Skip to content

Commit f68cc67

Browse files
Brian M HuntBrian M Hunt
authored andcommitted
docs: add browser test runner plan + promote plans/ in AGENTS
- Add plans/browser-test-runner.md documenting the /tests page: context, two-phase iframe scheduling, bundling flow, files, verification, and known gaps. - Promote the plans/ directory in AGENTS.md: add a "Before you start" checklist at the top of the agent-context section so the plans/ convention is not buried after Release Process. - Enrich the Plans section with explicit triggers (when to write one, when to skip) so future agents don't have to infer scope.
1 parent c5bd8d7 commit f68cc67

2 files changed

Lines changed: 150 additions & 3 deletions

File tree

AGENTS.md

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ Two things shape the coverage/safety bar here more than any specific rule:
1717

1818
Together: coverage and signal are expensive to lose and cheap to keep. When a change trades either away, say so explicitly and justify the delta.
1919

20+
## Before you start (checklist)
21+
22+
1. **Check `plans/` first.** A significant change (new page, new build step, new CI workflow, new top-level concept, multi-commit refactor) needs a plan file in [`plans/`](plans/) *before implementation* — see the [Plans](#plans) section below. If the task matches an existing plan, read it; if not and the scope is significant, draft one and get alignment.
23+
2. **Check verified-behaviors.** If the change touches a package with `verified-behaviors.json`, the behaviors are a contract — preserve them unless the plan explicitly calls for a revision.
24+
3. **Run `bun run verify`** before any commit. It's the safety net.
25+
2026
## Project Structure
2127

2228
Monorepo with Bun workspaces.
@@ -156,9 +162,27 @@ long-lived publish token.
156162

157163
## Plans
158164

159-
Significant changes should have a plan file in `plans/` before implementation
160-
begins. Plans document the context, approach, and verification steps. Review
161-
existing plans in that directory for format examples.
165+
Significant changes need a plan file in [`plans/`](plans/) **before
166+
implementation begins**. Plans document the context, approach, architecture,
167+
files touched, and verification steps. Existing plans are the format reference
168+
— match their shape.
169+
170+
**Write a plan when the change is any of:**
171+
172+
- a new top-level page, route, or site feature (e.g. `/playground`, `/tests`)
173+
- a new build, bundling, or release step
174+
- a new CI workflow or check
175+
- a new cross-package concept (e.g. verified-behaviors, defineOption)
176+
- a refactor touching 5+ files across packages
177+
- anything you'd describe to a teammate as "this is a project, not a fix"
178+
179+
**Skip a plan for:** bug fixes, single-file edits, doc tweaks, dependency
180+
bumps, comment cleanup, test additions to an existing spec.
181+
182+
If unsure, check `plans/` for precedent — the existing plans span docs
183+
migrations, build modernization, playground, test runner, agent-verified
184+
behaviors, and more. If nothing comparable is there, the change probably
185+
deserves a plan.
162186

163187
## Agent-First Documentation
164188

plans/browser-test-runner.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Plan: Live browser test runner at /tests
2+
3+
## Context
4+
5+
TKO specs run under Vitest + happy-dom in CI (`bun run test`). That
6+
covers DOM semantics reachable from a JS implementation of the
7+
DOM, but misses anything that depends on a real browser: system
8+
focus routing, layout, rendering, intersection, CSSOM, and per-
9+
engine DOM quirks across Chromium / WebKit / Firefox.
10+
11+
A live browser runner at `/tests` on `tko.io` closes that gap by
12+
running the same Mocha specs inside real iframes. It serves two
13+
audiences:
14+
15+
1. **Contributors** — open `/tests` in any browser, get real-
16+
browser pass/fail without installing anything. Double as a
17+
reproducible bug harness.
18+
2. **Agents** — Playwright or similar hits `/tests`, parses the
19+
stats chips, and knows whether a change holds up under real
20+
layout/focus/rendering. Complements verified-behaviors.json
21+
as an additional correctness signal.
22+
23+
Test environments are additive: Vitest+happy-dom stays, browser
24+
runner expands coverage. Neither replaces the other.
25+
26+
## Approach
27+
28+
Astro page at `tko.io/src/pages/tests.astro` drives two modes via
29+
`?suite=`:
30+
31+
- **source** (default) — run specs from the checkout, bundled
32+
per-spec into ESM chunks. One iframe per spec.
33+
- **build** — load a published `@tko/build.*` bundle from
34+
jsDelivr, run all specs in one iframe against that CDN
35+
artifact. Proves the shipped build is green.
36+
37+
Each spec executes inside a `tests-frame.html` iframe harness
38+
and posts pass/fail/pending/end events to the parent page. The
39+
parent aggregates into a TKO-driven view model (suite tree,
40+
stats chips, progress bar).
41+
42+
## Architecture
43+
44+
```
45+
┌───────────────────────────────────────────────────────────┐
46+
│ /tests page (TKO view model) │
47+
│ ┌─────────────────────────────────────────────────────┐ │
48+
│ │ suite tree (per-spec file, running/pass/fail state) │ │
49+
│ └─────────────────────────────────────────────────────┘ │
50+
│ │
51+
│ Phase 1: parallel (pool=4) hidden iframes │
52+
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ 1×1 offscreen │
53+
│ │spec │ │spec │ │spec │ │spec │ no focus needed │
54+
│ └─────┘ └─────┘ └─────┘ └─────┘ │
55+
│ │
56+
│ Phase 2: serial iframe in bottom-right workarea │
57+
│ ┌─────────────────┐ real layout box │
58+
│ │ focus-spec here │ sole system focus │
59+
│ └─────────────────┘ hasfocus/.focus/activeElement │
60+
│ │
61+
│ postMessage(pass/fail/pending/end) → parent │
62+
└───────────────────────────────────────────────────────────┘
63+
```
64+
65+
### Why two phases
66+
67+
Chromium grants system focus to one iframe at a time and denies
68+
it to off-screen / zero-area iframes. Specs that assert on
69+
`hasfocus`, `.focus()`, `document.activeElement`, or `focusin` /
70+
`focusout` can't run in parallel in hidden iframes — they need a
71+
real visible layout box and sole focus. A `needsFocus` flag
72+
(grep-based in the bundler) routes those specs serially through
73+
a visible workarea.
74+
75+
### Bundling
76+
77+
`tko.io/scripts/bundle-tests.mjs` (esbuild) produces:
78+
79+
- `public/tests/build-bundle.js` — all `builds/**/spec/*` specs
80+
that only depend on `ko.*` globals, bundled into one script
81+
for build mode. Specs with relative imports are excluded.
82+
- `public/tests/source/setup.js` — classic-script IIFE that
83+
exposes `globalThis.ko`, chai/sinon, punctuation filters,
84+
mocha-test-helpers, and the focus/sinon polyfills.
85+
- `public/tests/source/<slug>.js` — one ESM module per spec
86+
for source mode.
87+
- `public/tests/source/manifest.json` — per-spec metadata
88+
(slug, suite name, needsFocus) the parent uses to schedule.
89+
90+
`prebuild` runs the bundler so the dev server and production
91+
build both serve fresh output.
92+
93+
## Files
94+
95+
| File | Role |
96+
|------|------|
97+
| `tko.io/src/pages/tests.astro` | `/tests` page — TKO VM, suite tree, schedulers |
98+
| `tko.io/public/tests-frame.html` | Per-spec iframe harness |
99+
| `tko.io/scripts/bundle-tests.mjs` | Discover specs, emit bundles + manifest |
100+
| `builds/knockout/helpers/browser-setup.js` | Globals, focus polyfill, sinon restore, ctx-arg shim |
101+
| `tko.io/package.json` | `prebuild` invokes the bundler |
102+
| `tko.io/.gitignore` | Ignores generated `public/tests/` |
103+
104+
## Verification
105+
106+
1. `cd tko.io && bun run dev`
107+
2. Visit `http://localhost:4321/tests` — source mode should
108+
reach 2708/0/42 in ~5-6s.
109+
3. Switch to `/tests?suite=build&pkg=knockout&ver=latest`
110+
build-mode suite runs against the published CDN bundle.
111+
4. `?grep=<pattern>` — filter specs by file/slug (both modes).
112+
5. CI: `bun run verify` still green under Vitest+happy-dom; the
113+
browser runner is an additive signal, not a replacement.
114+
115+
## What's not there yet
116+
117+
| Gap | What's needed |
118+
|-----|---------------|
119+
| **CI smoke** | Playwright job hitting `/tests` on every PR |
120+
| **Firefox / WebKit coverage** | Playwright per-engine; today only Chromium is exercised interactively |
121+
| **Flaky focus detection** | Track focus-phase retries; flag specs that pass only after retry |
122+
| **Build-mode spec coverage** | 60+ specs currently excluded because they have relative imports — rewrite to use `ko.*` globals so build mode covers them |
123+
| **Differential result** | Surface specs that pass under happy-dom but fail in a real browser (and vice versa) as a report |

0 commit comments

Comments
 (0)