The morph-survival of every interactive behavior should be a structural property of the e2e suite, not an opt-in @morph tag on a handful of scenarios. Right now exactly one scenario uses navigate via Ema (the toc-spy morph test from #663); every other scenario opens via page.goto (fresh full reload), so the morph code path is uncovered for those behaviors. This is how the toc-spy bug (#667) and the Stork theme-mirror-after-morph bug (PR #672 review thread) both shipped — the regression was invisible to the existing tests.
Shape
Add a third value to EMANOTE_MODE: morph (alongside live and static). It spawns the live backend (same as live), but the When I open \"{string}\" step performs an Ema-internal route switch instead of a fresh page.goto:
- Before each scenario, navigate to
/ via page.goto (priming) and wait for window.ema.ready.
When I open \"/foo\" → await window.ema.switchRoute('/foo') + wait for EMAHotReload.
Subsequent I open calls in the same scenario become additional morph navs. Every behavior assertion implicitly runs against "the page that landed via morph, not via fresh load" — exactly the path that's been silently uncovered.
A just e2e-morph recipe wires it; CI runs all three modes (static, live, morph).
Wrinkles to handle
- The existing
@morph-gated Before hook (tests/support/hooks.ts) needs mode === \"static\" instead of mode !== \"live\" for the skip predicate, so morph-mode runs them.
- The
\"navigate via Ema\" without @morph\" fail-fast hook should suppress in morph mode (every step morphs there; the check is meaningless).
- The
morph mode is incompatible with static (no WS) — MODE=morph requires the live backend; that constraint is already satisfied by piggybacking on the live setup.
Why a separate PR
Building this surfaces N broken behaviors (Stork is the first; toc-spy was the second; there may be more once everything's exercised). Each fix needs its own test + commit + review cycle. Bundling that with the infrastructure makes for a sprawling PR; landing the infrastructure first (with one targeted bug fix where necessary) makes the breakages discoverable as separate, focused follow-ups.
The targeted fix for the Stork bug ships in PR #672 with a single @morph-tagged scenario; the broader auto-morph infrastructure is what this issue tracks.
The morph-survival of every interactive behavior should be a structural property of the e2e suite, not an opt-in
@morphtag on a handful of scenarios. Right now exactly one scenario usesnavigate via Ema(the toc-spy morph test from #663); every other scenario opens viapage.goto(fresh full reload), so the morph code path is uncovered for those behaviors. This is how the toc-spy bug (#667) and the Stork theme-mirror-after-morph bug (PR #672 review thread) both shipped — the regression was invisible to the existing tests.Shape
Add a third value to
EMANOTE_MODE:morph(alongsideliveandstatic). It spawns the live backend (same aslive), but theWhen I open \"{string}\"step performs an Ema-internal route switch instead of a freshpage.goto:/viapage.goto(priming) and wait forwindow.ema.ready.When I open \"/foo\"→await window.ema.switchRoute('/foo')+ wait forEMAHotReload.Subsequent
I opencalls in the same scenario become additional morph navs. Every behavior assertion implicitly runs against "the page that landed via morph, not via fresh load" — exactly the path that's been silently uncovered.A
just e2e-morphrecipe wires it; CI runs all three modes (static,live,morph).Wrinkles to handle
@morph-gatedBeforehook (tests/support/hooks.ts) needsmode === \"static\"instead ofmode !== \"live\"for the skip predicate, so morph-mode runs them.\"navigate via Ema\" without @morph\"fail-fast hook should suppress in morph mode (every step morphs there; the check is meaningless).morphmode is incompatible withstatic(no WS) —MODE=morphrequires the live backend; that constraint is already satisfied by piggybacking on thelivesetup.Why a separate PR
Building this surfaces N broken behaviors (Stork is the first; toc-spy was the second; there may be more once everything's exercised). Each fix needs its own test + commit + review cycle. Bundling that with the infrastructure makes for a sprawling PR; landing the infrastructure first (with one targeted bug fix where necessary) makes the breakages discoverable as separate, focused follow-ups.
The targeted fix for the Stork bug ships in PR #672 with a single
@morph-tagged scenario; the broader auto-morph infrastructure is what this issue tracks.