MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-2645

(motir-core) E2E flake, 3rd occurrence — `signIn()` returns while the post-auth redirect is still in flight, so the caller's next `page.goto` is aborted by a navigation to /dashboard

Done
Description

Repo: motir-core. One PR. The shared sign-in helper reports success too early, so the very next page.goto(...) in a spec is aborted by the tail of the auth redirect. Three occurrences, three different specs, two lanes, all on innocent diffs.

The signature

Error: page.goto: Navigation to "http://localhost:3200/items" is interrupted by
another navigation to "http://localhost:3200/dashboard"

  235 |     await page.context().clearCookies();
  236 |     await signIn(page, VIEWER_EMAIL, VIEWER_PASSWORD);
> 237 |     await page.goto('/items');

_helpers/shell-session.ts's signIn() (and signUp()) end at await page.waitForURL('**/dashboard'). That resolves on the FIRST URL match — but the post-auth router.replace can still have a second client-side navigation to /dashboard in flight, and it aborts the caller's explicit goto.

Two failure shapes, same cause — the duration is not the tell, the phrase interrupted by another navigation inside the call log is:

  • fast (~2–5s) when the goto is bare — reads as an instant error;
  • a long timeout when the goto sits inside a toPass({timeout: 90_000}) retry wrapper — reads as a 90s hang.

Occurrences

#datePRspeclane
12026-07-28#1640acceptance-augment-replan.spec.ts:196acceptance-video
22026-08-01#1772collab-at-scale.spec.ts:352 (via warmIssueRoutes)collab-at-scale
32026-08-10#2025acceptance-quick-view-edit.spec.ts:237acceptance-video 3/4

Occurrence 3's spec landed on 2026-08-07 (MOTIR-2560 / #2017) — i.e. the shape is being copied into new specs faster than it is being worked around, which is the argument for fixing the helper rather than each caller.

What it is, and what it is not

Not a product regression. Occurrence 3's proof was structural and took one command: the spec did not exist on the branch at all (ls tests/e2e/acceptance-quick-view-edit.spec.ts → No such file). PR CI checks out the branch merged with main, so a spec that arrived on main after your last merge can red-light your PR while being absent from your tree.

Do this

Fix it once, in the helper — not in each caller, and not with a sleep.

  1. signIn() / signUp() must not return until the auth redirect has SETTLED: after waitForURL('**/dashboard'), also await an authoritative dashboard signal (a heading / a data-testid the dashboard owns) so no further navigation is queued.
  2. Sweep the callers that already work around it, so the workaround does not outlive the cause.
  3. A page.goto immediately after signIn must be safe by construction — that is the property under test.

Acceptance criteria

  1. signIn() and signUp() return only after the dashboard has settled, and the wait is on an authoritative signal — no waitForTimeout (CLAUDE.md § E2E forbids a sleep as synchronisation).
  2. A test proves the property is real by FAILING against the current helper: sign in, goto another route immediately, assert it lands. Falsifiable, not tautological.
  3. All three specs above pass unmodified — the fix is in the helper, so no caller edit is needed to make them green.
  4. The three occurrences are named in the PR body with their run ids, so the next triager can match the signature instead of re-deriving it.

Out of scope

MOTIR-2617's rank=popular webServer-degradation mode and MOTIR-1565's sign-up-404 mode. Both are different failures on adjacent surfaces; do not fold them in. In particular this one is not capacity — it reproduces on a healthy server and is a genuine ordering bug in the helper.