Files
jacobh2 ae6db7e16f 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>
2026-09-19 12:27:29 +02:00

81 lines
4.0 KiB
TypeScript

/**
* Shared registration/onboarding steps for specs that need a brand-new,
* empty account rather than the shared demo workspace (`global-setup.ts`'s
* seeded data) — e.g. because the gesture under test needs a clean
* calendar, or because the demo user's own balance is deliberately drained
* (see `backend/scripts/seed_demo.py`'s "near-drained FP pool" for Alex,
* which a fresh drag-created period pinned to the logged-in parent would
* otherwise fail to fund).
*
* Every date here is derived from "today", never a hardcoded year.
*/
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { toIsoDate, addDays } from './dates'
export function uniqueEmail(tag: string): string {
return `e2e-${tag}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}@example.com`
}
export const ONBOARDING_PASSWORD = 'E2ePassOnboard123!'
/** Registers a brand-new account through the real UI and waits for the
* onboarding wizard's first step. */
export async function registerAndReachOnboarding(page: Page, email: string, displayName: string): Promise<void> {
await page.goto('/auth')
await page.getByRole('button', { name: 'Skapa konto' }).click()
await page.getByPlaceholder('Namn').fill(displayName)
await page.getByTestId('auth-email').fill(email)
await page.getByTestId('auth-password').fill(ONBOARDING_PASSWORD)
await page.getByTestId('auth-submit').click()
await expect(page.getByTestId('onboarding')).toBeVisible({ timeout: 15_000 })
await expect(page.getByTestId('onboarding-step-child')).toBeVisible()
}
/** Step 1 of the wizard: add the child, landing on step 2 (family). */
export async function fillChildStep(page: Page, childName: string): Promise<void> {
// Safely in the past relative to "today", regardless of when this runs.
const birthDate = toIsoDate(addDays(new Date(), -400))
await page.getByLabel('Barnets namn').fill(childName)
await page.getByTestId('birth-date-input').fill(birthDate)
await page.getByRole('button', { name: 'Lägg till barn' }).click()
await expect(page.getByTestId('onboarding-step-family')).toBeVisible()
}
/** 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.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()
}