Redesign the setup flow and consolidate the CSS into one primitives layer
Onboarding asks explicitly for one or two parents and shows one card per parent for balances; the balance form is per parent with inline validation; the partner can be filled from the FK deduction or added from it. Settings and Dashboard reuse the same form. CSS: bare buttons carry no colour any more; buttons, cards, choice cards, fields, alerts, badges, eyebrow and modal chrome are defined once in primitives.css. Media queries live only in responsive.css. A style guard test blocks hex, !important and stray media queries. Bilingual fixes: calendar selects size by content, header no longer wraps. Vitest is capped at four workers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -36,12 +36,31 @@ export function calendarDayCell(page: Page, isoDate: string) {
|
||||
* cells entirely, which reads as a click on the anchor date. Moving in
|
||||
* several steps per cell, with a short pause between cells, is what
|
||||
* reliably fires a `pointerenter` on each one.
|
||||
*
|
||||
* The whole dragged range is scrolled into view ONCE, before the drag
|
||||
* starts — never mid-drag. A default-viewport (1280×720) run of a 6-row
|
||||
* month puts the trailing week's cells below the fold (`getBoundingClientRect`
|
||||
* still reports their real, off-screen `y`); moving the mouse to those
|
||||
* coordinates without scrolling first sends it past the bottom of the
|
||||
* actually-rendered viewport, where there is no element to receive
|
||||
* `pointerenter` at all — the browser just stops delivering the event, and
|
||||
* the drag's `dragCurrent` freezes on the last on-screen cell it entered
|
||||
* while still climbing toward the target. Scrolling once up front (via the
|
||||
* last, typically lowest, target date) keeps every waypoint's precomputed
|
||||
* center valid for the whole gesture; scrolling again after `mouse.down()`
|
||||
* would invalidate the coordinates of any cell already computed and risk
|
||||
* disrupting the in-progress native pointer sequence.
|
||||
*/
|
||||
export async function dragSelectDates(page: Page, isoDates: string[]): Promise<void> {
|
||||
if (isoDates.length < 2) {
|
||||
throw new Error('dragSelectDates needs at least two dates to actually drag across')
|
||||
}
|
||||
|
||||
const lastDate = isoDates[isoDates.length - 1]
|
||||
if (lastDate) {
|
||||
await calendarDayCell(page, lastDate).scrollIntoViewIfNeeded()
|
||||
}
|
||||
|
||||
const centerOf = async (isoDate: string): Promise<{ x: number; y: number }> => {
|
||||
const box = await calendarDayCell(page, isoDate).boundingBox()
|
||||
if (!box) throw new Error(`calendar day cell not visible for ${isoDate} — is it in the current month view?`)
|
||||
|
||||
@@ -43,12 +43,38 @@ export async function fillChildStep(page: Page, childName: string): Promise<void
|
||||
await expect(page.getByTestId('onboarding-step-family')).toBeVisible()
|
||||
}
|
||||
|
||||
/** From step 2 (family), keeps the default "solo" planning mode, continues
|
||||
* to step 3 (balances) and skips it — landing on the Dashboard with the
|
||||
* statutory-assumption balance (no manual fetch, no drained pool). */
|
||||
/** From step 2 (family) — "Bara jag" is selected by default, so this just
|
||||
* continues to step 3 (balances) and presses "Klar" without filling
|
||||
* anything in — landing on the Dashboard with the statutory-assumption
|
||||
* balance (no manual fetch, no drained pool). */
|
||||
export async function continueSoloAndSkipBalances(page: Page): Promise<void> {
|
||||
await page.getByRole('button', { name: 'Fortsätt' }).click()
|
||||
await expect(page.getByTestId('onboarding-step-balances')).toBeVisible()
|
||||
await page.getByRole('button', { name: 'Hoppa över för nu' }).click()
|
||||
await page.getByTestId('onboarding-finish').click()
|
||||
await expect(page.getByTestId('dashboard')).toBeVisible({ timeout: 15_000 })
|
||||
}
|
||||
|
||||
/** From step 2 (family), selects "Vi är två föräldrar", fills in the other
|
||||
* parent's name and continues — landing on step 3 (balances) with both
|
||||
* parents' cards visible. */
|
||||
export async function chooseTwoParents(page: Page, partnerName: string): Promise<void> {
|
||||
await page.getByTestId('onboarding-family-couple').click()
|
||||
await page.getByLabel('Den andra förälderns namn').fill(partnerName)
|
||||
await page.getByRole('button', { name: 'Fortsätt' }).click()
|
||||
await expect(page.getByTestId('onboarding-step-balances')).toBeVisible()
|
||||
}
|
||||
|
||||
/** In step 3 (balances), opens "Ange själv" on the parent card matching
|
||||
* `name` and fills in + saves the three balance fields shown there. */
|
||||
export async function enterBalancesFor(
|
||||
page: Page,
|
||||
name: string,
|
||||
balances: { sjukpenning: number; lagsta: number; dubbeldagar: number },
|
||||
): Promise<void> {
|
||||
const card = page.getByTestId('onboarding-parent-card').filter({ hasText: name })
|
||||
await card.getByRole('button', { name: 'Ange själv' }).click()
|
||||
await page.getByLabel(/Sjukpenningnivå/).fill(String(balances.sjukpenning))
|
||||
await page.getByLabel(/Lägstanivå/).fill(String(balances.lagsta))
|
||||
await page.getByLabel(/Dubbeldagar/).fill(String(balances.dubbeldagar))
|
||||
await page.getByRole('button', { name: 'Spara' }).click()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user