/e2e: Real-browser tests (TDD step 6)
SkillWeb & browsingStep 6 of the Weft TDD workflow. Use after /implement is green: writes *.browser.test.ts real-browser tests (Vitest browser mode + Playwright via vp run test:browser). Mandatory for every touched examples/* app; for package features only when behavior is browser-observable, otherwise records an explicit skip in specs.md.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the /e2e: Real-browser tests (TDD step 6) skill
What this skill tells your AI
The instructions your AI receives, as published by stefvw93/weft in .claude/skills/e2e/SKILL.md and read by ahel’s review.
Assert the feature's behavior in a real Chromium browser, or record an explicit, reasoned skip.
When to run
- Previous step:
/implement(vp run checkandvp run testgreen). - Next step:
/review-step. - Gate: every touched
examples/*app has a passing co-located*.browser.test.ts; package features either have browser coverage or an explicite2e: not applicable, <reason>line inspecs.md. Silent skips are forbidden.
Scope rule
-
examples/*app touched or created → mandatory. Every example must have at least one co-located*.browser.test.tsthat importsApp, mounts it in a real browser, and asserts the example's headline behavior. -
Package feature (
packages/*) → conditional. Required when behavior is browser-observable and jsdom cannot faithfully reproduce it: DOM rendering, hydration against a real parser, real event dispatch, layout. Pure type-level or logic-level features skip with a recorded reason inspecs.md:e2e: not applicable, <one-line reason>
Procedure
-
Decide scope per the rule above; record the skip in
specs.mdif not applicable, report it, and hand off. -
Write the test file:
*.browser.test.ts(or.tsx), co-located. Conventions (seee2e/specs.mdfor full detail):- Import test globals from
vite-plus/test, never fromvitestdirectly. - Example tests import
Appfrom the side-effect-freeapp.tsand mount it into their own container, with no dev server dependency. - Browser files are excluded from the default
vp run testand picked up only by the browser config.
- Import test globals from
-
Known pitfalls (each has bitten before):
- Post-mount render tick: the mounted tree is appended a tick after
mount's Effect resolves. Assert initial state withvi.waitFor, never synchronously. - Ref observers: to run an effect when a
ref's element mounts, fork theref.changesobserver withEffect.forkScoped, not bareEffect.forkChild. A bare fork binds to the transient component-body fiber and is interrupted under an isolatedmount(seeexamples/element-ref). - Missing example CSS: the test page has none of the example's
index.htmlCSS. Do not assert layout-derived pixel values.
- Post-mount render tick: the mounted tree is appended a tick after
-
Run:
vp run test:browser(packs first, then runs all*.browser.test.*in headless Chromium). Must be green. -
Hand off. Next step is
/review-step.
Rules
- Browser tests assert user-observable behavior, not implementation internals.
- A failing browser test that exposes a spec/mock problem triggers the pause rule: back up the cycle, don't patch around it.
Signals
- GitHub stars
- 44
- Forks
- 1
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
e2e-stefvw93- Source
- github.com/stefvw93/weft