Skip to content

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

  1. runDemoWalk({ browser, page }, personas, story, { device }) — one shared page when E2E_DEMO is unset; N isolated contexts when on. device is desktop · tablet · mobile (or E2E_DEMO_DEVICE). Pass only the personas the story needs.
  2. 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.
  3. Current action. demoAnnounce(page, 'Submitting') before a goto or click that should show in the banner.
  4. Pace visible fields. fillField / fillTypedValue / fillShown / demoClick. Product form helpers should call these.
  5. Storyboard stills. Pass shot on the teaching click, fill, or demoPoint so 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-frame demoScreenshot hides the pointer on stills only. Do not screenshot after demoFocus and hope the cursor is already on the next control. Iterate on stills before you pay for video (E2E_DEMO=1). See Best practices.
  6. 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.

Released under the MIT License.