The walking-skeleton happy path now drives the real S-12 flow: after submit, a behandelaar logs in to the behandel portal (medewerker realm), finds the registration in the werkbak by its reference, and clicks Goedkeuren — replacing the temporary domain admin endpoint. Treat the behandel origin as secure too, for its PKCE login. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
81 lines
4.3 KiB
TypeScript
81 lines
4.3 KiB
TypeScript
import { expect, test } from '@playwright/test';
|
|
|
|
// Walking-skeleton happy path (S-08d + S-09 + S-09b + S-12): a zorgprofessional logs in via mock
|
|
// DigiD and submits through the self-service portal → BFF → domain; the entry appears in the openbaar
|
|
// register as INGEDIEND; a behandelaar then logs in to the behandel portal, finds the registration in
|
|
// the werkbak, and approves it (goedkeuren); the decision completes the Flowable Beoordelen task and
|
|
// flows via the ACL → NRC → event-subscriber → projection, and the openbaar register shows INGESCHREVEN.
|
|
test('DigiD submit → public INGEDIEND → behandelaar goedkeurt → public INGESCHREVEN', async ({ page }) => {
|
|
// Visiting the guarded page redirects to the Keycloak (mock DigiD) login.
|
|
await page.goto('/');
|
|
|
|
// Keycloak's default login form (stable ids across themes).
|
|
await page.locator('#username').fill('jan-burger');
|
|
await page.locator('#password').fill('test123');
|
|
await page.locator('#kc-login').click();
|
|
|
|
// Back on the portal, authenticated.
|
|
await expect(page.getByRole('heading', { name: /Zelfservice/i })).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: /indienen/i }).click();
|
|
|
|
// The BFF accepted it and the page shows the confirmation with the reference.
|
|
const confirmation = page.getByText(/ontvangen/i);
|
|
await expect(confirmation).toBeVisible();
|
|
const reference = (await confirmation.textContent())?.match(/Referentie:\s*([0-9a-fA-F-]+)/)?.[1];
|
|
expect(reference, 'the confirmation shows a registration reference').toBeTruthy();
|
|
|
|
// The openbaar register (anonymous, its own origin) shows the submitted entry once the projection
|
|
// catches up. The projection updates asynchronously (NRC → event-subscriber), and the register loads
|
|
// on open, so reload until *this* submission's row appears. We poll on the reference cell (not a
|
|
// generic INGEDIEND cell): the shared verify stack already holds INGEDIEND rows from earlier checks,
|
|
// so a status-only poll would short-circuit on a stale row before our row is projected.
|
|
await page.goto('http://openbaar/');
|
|
await expect(page.getByRole('heading', { name: /Openbaar BIG-register/i })).toBeVisible();
|
|
|
|
// #78: the reference shown in the public register must be the exact one the citizen saw on the
|
|
// submit confirmation — no mismatch between the two portals.
|
|
await expect
|
|
.poll(async () => {
|
|
await page.reload();
|
|
return page.getByRole('cell', { name: reference }).count();
|
|
}, { timeout: 30_000, intervals: [1_000, 2_000, 3_000, 5_000] })
|
|
.toBeGreaterThan(0);
|
|
await expect(page.getByRole('row', { name: reference }).getByRole('cell', { name: 'INGEDIEND' }))
|
|
.toBeVisible();
|
|
|
|
// A behandelaar picks the registration up in the behandel-portal werkbak and approves it
|
|
// (goedkeuren) — the S-12 flow that replaces the temporary admin endpoint. Navigating here switches
|
|
// to the medewerker realm (a different Keycloak realm than the citizen's digid session).
|
|
await page.goto('http://behandel/');
|
|
await page.locator('#username').fill('merel-behandelaar');
|
|
await page.locator('#password').fill('test123');
|
|
await page.locator('#kc-login').click();
|
|
|
|
await expect(page.getByRole('heading', { name: /Werkbak/i })).toBeVisible();
|
|
|
|
// The registration parks at the Beoordelen user task only after the worker has opened its zaak, so
|
|
// it appears in the werkbak asynchronously — reload until this reference's row shows up. Target the
|
|
// decide button by reference (not a generic "Goedkeuren"): the shared verify stack holds other open
|
|
// tasks, so a positional match could act on someone else's registration.
|
|
const goedkeuren = page.getByRole('button', { name: `Goedkeuren ${reference}` });
|
|
await expect
|
|
.poll(async () => {
|
|
await page.reload();
|
|
return goedkeuren.count();
|
|
}, { timeout: 30_000, intervals: [1_000, 2_000, 3_000, 5_000] })
|
|
.toBeGreaterThan(0);
|
|
|
|
await goedkeuren.click();
|
|
|
|
// The approval flows back to the projection; back on the openbaar register *our* row (matched by
|
|
// its reference) now shows INGESCHREVEN.
|
|
await page.goto('http://openbaar/');
|
|
await expect
|
|
.poll(async () => {
|
|
await page.reload();
|
|
return page.getByRole('row', { name: reference }).getByRole('cell', { name: 'INGESCHREVEN' }).count();
|
|
}, { timeout: 30_000, intervals: [1_000, 2_000, 3_000, 5_000] })
|
|
.toBeGreaterThan(0);
|
|
});
|