Writing a walk
Prefer one lift call. Do not copy multi-window boilerplate into a spec.
ts
test('advisor sees the new player', async ({ browser, page }) => {
test.setTimeout(demoTimeout(180_000));
await runDemoWalk({ browser, page }, ['ADMIN', 'ADVISOR'], async (walk) => {
const admin = walk.page.ADMIN;
const advisor = walk.page.ADVISOR;
await demoFocus(admin, '1 / 3', 'Admin signs in', 'On the sign-in form');
await demoClick(admin, admin.getByRole('button', { name: 'Sign in' }), {
shot: 'admin_sign_in',
});
// login + product helpers
await demoFocus(advisor, '3 / 3', 'Advisor first login', 'On the sign-in form');
});
});Recipe
runDemoWalk({ browser, page }, personas, story, { device })— one shared page whenE2E_DEMOis unset; N isolated contexts when on.deviceisdesktop·tablet·mobile(orE2E_DEMO_DEVICE). Pass only the personas the story needs.- Chapter = window comes forward.
demoFocus(walk.page.ADVISOR, '2 / 5', title, note)at every persona switch. That updates the HUD chip on the shared-page stills path too. Number chapters consecutively. - Current action.
demoAnnounce(page, 'Submitting')before a goto or click that should show in the banner. - Pace visible fields.
fillField/fillTypedValue/fillShown/demoClick. Product form helpers should call these. - Storyboard stills. Pass
shoton the teaching click, fill, ordemoPointso CI captures the same beat the video clicks on (pointer + one held ring). Video does not recapture that PNG and does not hold the ring. The ring pulses, then the click, then a short pause. Rest-framedemoScreenshothides the pointer on stills only. Do not screenshot afterdemoFocusand hope the cursor is already on the next control. Iterate on stills before you pay for video (E2E_DEMO=1). See Best practices. - Shared-page re-auth. After a logout on the fast path,
resumeOnSharedPage(walk, () => loginAs(...)).
demoTimeout(fastMs) is 15 minutes on the demo path (override the second argument if needed).
What stays in your app
Login labels, inbox readers, and domain form helpers. This package does not know your /login button names unless you write that helper.