ae6db7e16f
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>
81 lines
4.0 KiB
TypeScript
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()
|
|
}
|