diff --git a/tests/e2e/catalogus.spec.ts b/tests/e2e/catalogus.spec.ts index bb6e85f..5acd400 100644 --- a/tests/e2e/catalogus.spec.ts +++ b/tests/e2e/catalogus.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { loginMedewerker } from './medewerker-login'; +import { loginMedewerker } from './keycloak-login'; // S-15a walking skeleton: a beheerder logs in to the beheer portal (medewerker realm) and sees the // read-only ZTC catalogus. The verify stack seeds and publishes the BIG-REGISTRATIE zaaktype (the diff --git a/tests/e2e/default-fill.spec.ts b/tests/e2e/default-fill.spec.ts index 637fe57..c9bf4e2 100644 --- a/tests/e2e/default-fill.spec.ts +++ b/tests/e2e/default-fill.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { loginMedewerker } from './medewerker-login'; +import { loginMedewerker } from './keycloak-login'; // S-15b: a beheerder edits the ACL default-fill in the beheer portal and gets a saved confirmation. // Runs against the shared verify stack; it edits + saves (the ACL store is in-memory, ADR-0026) and diff --git a/tests/e2e/medewerker-login.spec.ts b/tests/e2e/keycloak-login.spec.ts similarity index 92% rename from tests/e2e/medewerker-login.spec.ts rename to tests/e2e/keycloak-login.spec.ts index b4e83bb..6580c31 100644 --- a/tests/e2e/medewerker-login.spec.ts +++ b/tests/e2e/keycloak-login.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { OTP_PERIOD_MS, nextUnusedCounter } from './medewerker-login'; +import { OTP_PERIOD_MS, nextUnusedCounter } from './keycloak-login'; // Pure check of the TOTP counter guard in loginMedewerker — no browser, no stack. Keycloak refuses // a code it has already accepted (its otpPolicyCodeReusable defaults to false), so two logins as diff --git a/tests/e2e/medewerker-login.ts b/tests/e2e/keycloak-login.ts similarity index 78% rename from tests/e2e/medewerker-login.ts rename to tests/e2e/keycloak-login.ts index 53ba23a..3b7f003 100644 --- a/tests/e2e/medewerker-login.ts +++ b/tests/e2e/keycloak-login.ts @@ -4,6 +4,9 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; import type { Page } from '@playwright/test'; +// Every portal login in the suite goes through this module — citizen realms (mock DigiD) and the +// medewerker realm alike — so the shared Keycloak form handling lives in exactly one place. + // The medewerker realm enforces MFA (S-15c), so a staff login is two steps: password, then a TOTP // code. The realm export seeds every medewerker with this fixture secret — Keycloak HMACs the raw // secret bytes — so the e2e can compute a valid code instead of enrolling an authenticator. @@ -42,10 +45,24 @@ function spendCounter(username: string): number { return counter; } -export async function loginMedewerker(page: Page, username: string): Promise { +/** + * Fill Keycloak's login form. Every portal is guarded, so the first navigation redirects here; the + * form ids are stable across themes. + */ +async function submitPassword(page: Page, username: string): Promise { await page.locator('#username').fill(username); await page.locator('#password').fill('test123'); await page.locator('#kc-login').click(); +} + +/** A citizen login on a mock-DigiD realm — no second factor (ADR-0031). */ +export async function loginBurger(page: Page, username: string): Promise { + await submitPassword(page, username); +} + +/** A staff login on the medewerker realm: password, then the enforced TOTP second factor. */ +export async function loginMedewerker(page: Page, username: string): Promise { + await submitPassword(page, username); // Keycloak's conditional-OTP step. Wait out the rest of the window if the counter we may spend is // still in the future; its lookAheadWindow would accept the code a moment early, but only by one diff --git a/tests/e2e/registration.spec.ts b/tests/e2e/registration.spec.ts index a7a9c0e..f02ae1a 100644 --- a/tests/e2e/registration.spec.ts +++ b/tests/e2e/registration.spec.ts @@ -1,5 +1,5 @@ import { expect, request, test } from '@playwright/test'; -import { loginMedewerker } from './medewerker-login'; +import { loginBurger, loginMedewerker } from './keycloak-login'; // Walking-skeleton happy path (S-08d + S-09 + S-09b + S-12 + S-10a + S-19b-2): a zorgprofessional // logs in via mock DigiD and submits through the self-service portal → BFF → domain; the entry @@ -23,9 +23,7 @@ test('DigiD submit → public INGEDIEND → documenten → behandelaar goedkeurt // checks submit as jan-burger (bsn 123456782) before the e2e runs on the shared stack, and // resume-on-load (S-26) would otherwise restore one of those on login — so each self-service spec // uses a dedicated citizen no other actor touches. - await page.locator('#username').fill('emma-burger'); - await page.locator('#password').fill('test123'); - await page.locator('#kc-login').click(); + await loginBurger(page, 'emma-burger'); // Back on the portal, authenticated. await expect(page.getByRole('heading', { name: /Zelfservice/i })).toBeVisible(); diff --git a/tests/e2e/resume.spec.ts b/tests/e2e/resume.spec.ts index cf749e0..fd1b14e 100644 --- a/tests/e2e/resume.spec.ts +++ b/tests/e2e/resume.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from '@playwright/test'; +import { loginBurger } from './keycloak-login'; // S-26: a zorgprofessional submits, then reloads the self-service portal. On load the portal asks the // BFF for the caller's current open registration (owner-scoped by the DigiD token's bsn) and restores @@ -9,9 +10,7 @@ test('DigiD submit → reload → self-service restores the existing registratio // Its own DigiD user (like every self-service spec): on the shared verify stack, resume-on-load // (S-26) restores any open registration for the bsn, so each spec uses a dedicated citizen that no // other spec or verify-* check touches. This one in particular leaves an open registration. - await page.locator('#username').fill('sanne-burger'); - await page.locator('#password').fill('test123'); - await page.locator('#kc-login').click(); + await loginBurger(page, 'sanne-burger'); await expect(page.getByRole('heading', { name: /Zelfservice/i })).toBeVisible(); await page.getByRole('button', { name: /indienen/i }).click(); diff --git a/tests/e2e/withdrawal.spec.ts b/tests/e2e/withdrawal.spec.ts index a13d8f1..d9b2b33 100644 --- a/tests/e2e/withdrawal.spec.ts +++ b/tests/e2e/withdrawal.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from '@playwright/test'; +import { loginBurger } from './keycloak-login'; // S-11 (Flow 3): a zorgprofessional logs in via mock DigiD, submits a registration, then withdraws // it ("trek aanvraag in") from the self-service portal. The withdrawal goes portal → BFF (owner- @@ -10,9 +11,7 @@ test('DigiD submit → trek aanvraag in → self-service confirms ingetrokken', // Its own DigiD user — isolated from the verify-* checks (jan-burger/123456782) so resume-on-load // (S-26) can't restore someone else's registration on the shared stack. - await page.locator('#username').fill('lars-burger'); - await page.locator('#password').fill('test123'); - await page.locator('#kc-login').click(); + await loginBurger(page, 'lars-burger'); await expect(page.getByRole('heading', { name: /Zelfservice/i })).toBeVisible();