import { test, expect } from '@playwright/test'; import { loadFixture, probeReadiness, readinessMessage } from './helpers'; import { ensureLoggedIn, awaitSession } from './flow'; declare const require: (id: string) => any; test.use({ ignoreHTTPSErrors: true }); test.beforeAll(async () => { const readiness = await probeReadiness(); expect(readiness.ok, readinessMessage(readiness)).toBe(true); }); function loadFixtureOrSkip() { try { return loadFixture(); } catch (err) { test.skip(true, `run provision first: cargo run -p provision -- bootstrap --password-file (${(err as Error).message})`); throw new Error('unreachable'); } } test('happy path: sign in, dashboard, refresh, logout', async ({ page }) => { const fixture = loadFixtureOrSkip(); const { authenticator } = require('otplib'); const totpCode = (secret: string) => authenticator.generate(secret); await page.goto('/'); await expect(page.getByRole('link', { name: /sign in/i }).first()).toBeVisible(); await ensureLoggedIn(page, fixture, totpCode); await page.goto('/dashboard'); const session = await awaitSession(page); expect(session.subject).toBe(fixture.email); expect(session.scope).toContain('demo.read'); expect(session.token_type).toBe('DPoP'); expect(session.cnf?.jkt).toBeTruthy(); const config = await (await page.request.get('/api/config')).json(); expect(session.client_id).toBeTruthy(); expect(session.client_id).toBe(config.client_id); await expect(page.getByText(fixture.email).first()).toBeVisible({ timeout: 20_000 }); await page.getByRole('button', { name: 'Refresh' }).click(); const afterRefresh = await awaitSession(page); expect(afterRefresh.subject).toBe(fixture.email); await page.getByRole('button', { name: 'Log out' }).click(); await expect.poll(async () => (await page.request.get('/api/session')).status()).toBe(401); await expect(page.getByRole('link', { name: /sign in/i }).first()).toBeVisible(); });