test(maestro): a test runner and a reachable pure core for the SPA #44

Merged
naps62-yolo merged 1 commits from lithuanians into main 2026-08-22 14:16:40 +01:00
Collaborator

The browser app had no tests and no way to run any. package.json shipped dev/build/preview/typecheck; CI installed Node and pnpm and then never ran anything with them — not even typecheck. And its densest logic was module-private, so a runner alone would not have reached it.

Four pure modules extracted from DOM-heavy ones, rather than just exporting in place — attach.ts imports xterm's CSS at module level, which a node test cannot load:

new module was buried in what it holds
tree.ts catalog.ts directory grouping: buildTree, mergeLinear, compareNodes
keys.ts attach.ts terminal escape encoding: toCtrl, applyModsToChar, cursorSeq
paths.ts dirAutocomplete.ts splitPath, longestCommonPrefix
html.ts four places one escapeHtml, replacing copies in catalog.ts, spawn.ts, types.ts and attach.ts (esc)

CatalogStore gains an injectable socket factory, scheduler and refetch, so the reducer and the backoff schedule are drivable without a server. snapshot() now returns a copy — it returned the live object while SessionAdded/Removed/Updated mutated it in place, so listeners could not diff and every single event rebuilt the entire tree.

36 tests across 6 files, including the backoff doubling/cap, reset-on-open, Lagged-triggers-refetch, and that hydrate re-issues ids rather than trusting stored ones.

New web CI job — typecheck, test, build. That is the first CI signal the SPA has ever had.

Two constraints worth naming:

  • vitest is pinned to 2.x. 4.x requires vite >= 6 and this repo is on vite 5; bumping vite is a separate decision, not something to smuggle into a test-infrastructure PR.
  • I did not fix the two-uncoordinated-channels problem for session death (the row updates from WS, the pane from ws.onclose, nothing reconciles them). It needs a design call, and this PR is already the infrastructure one.
Verification
pnpm -C web typecheck   clean
pnpm -C web test        36 passed (6 files)
pnpm -C web build       ✓ built, 32 modules
pnpm -C web install --frozen-lockfile   already up to date
cargo test --all        300 passed, 0 failed

Fifth of nine from the architecture review (#40–#43 merged).

The browser app had **no tests and no way to run any**. `package.json` shipped `dev`/`build`/`preview`/`typecheck`; CI installed Node and pnpm and then never ran anything with them — not even `typecheck`. And its densest logic was module-private, so a runner alone would not have reached it. **Four pure modules extracted** from DOM-heavy ones, rather than just `export`ing in place — `attach.ts` imports xterm's CSS at module level, which a node test cannot load: | new module | was buried in | what it holds | |---|---|---| | `tree.ts` | `catalog.ts` | directory grouping: `buildTree`, `mergeLinear`, `compareNodes` | | `keys.ts` | `attach.ts` | terminal escape encoding: `toCtrl`, `applyModsToChar`, `cursorSeq` | | `paths.ts` | `dirAutocomplete.ts` | `splitPath`, `longestCommonPrefix` | | `html.ts` | four places | one `escapeHtml`, replacing copies in `catalog.ts`, `spawn.ts`, `types.ts` and `attach.ts` (`esc`) | `CatalogStore` gains an injectable socket factory, scheduler and refetch, so the reducer and the backoff schedule are drivable without a server. `snapshot()` now returns a copy — it returned the live object while `SessionAdded`/`Removed`/`Updated` mutated it in place, so listeners could not diff and every single event rebuilt the entire tree. 36 tests across 6 files, including the backoff doubling/cap, reset-on-open, Lagged-triggers-refetch, and that `hydrate` re-issues ids rather than trusting stored ones. **New `web` CI job** — typecheck, test, build. That is the first CI signal the SPA has ever had. Two constraints worth naming: - vitest is pinned to **2.x**. 4.x requires vite >= 6 and this repo is on vite 5; bumping vite is a separate decision, not something to smuggle into a test-infrastructure PR. - I did *not* fix the two-uncoordinated-channels problem for session death (the row updates from WS, the pane from `ws.onclose`, nothing reconciles them). It needs a design call, and this PR is already the infrastructure one. <details> <summary>Verification</summary> ``` pnpm -C web typecheck clean pnpm -C web test 36 passed (6 files) pnpm -C web build ✓ built, 32 modules pnpm -C web install --frozen-lockfile already up to date cargo test --all 300 passed, 0 failed ``` </details> Fifth of nine from the architecture review (#40–#43 merged).
naps62-yolo added 1 commit 2026-08-22 14:08:39 +01:00
test(maestro): give the SPA a test runner and a reachable pure core
ci / rust (pull_request) Successful in 2m28s
ci / web (pull_request) Successful in 23s
ci / web (push) Successful in 26s
ci / rust (push) Successful in 1m38s
031c80a40b
The browser app had no tests and no way to run any: package.json shipped
dev/build/preview/typecheck, and CI installed Node and pnpm but never ran
anything with them. Its densest logic was module-private, so even with a
runner none of it was reachable.

Extracts four pure modules out of DOM-heavy ones — tree.ts (directory
grouping), keys.ts (terminal escape encoding), paths.ts (completion
arithmetic), html.ts (one escaper, replacing four copies). Extraction
rather than `export` because attach.ts imports xterm's CSS at module
level, which a node test cannot load.

CatalogStore takes an injectable socket factory, scheduler and refetch, so
the reducer and the backoff schedule run without a server. snapshot() now
returns a copy: it returned the live object while events mutated it in
place, so listeners could not diff and every event rebuilt the whole tree.

36 tests across 6 files, and a `web` CI job running typecheck, test and
build. vitest is pinned to 2.x — 4.x requires vite >= 6 and this is vite 5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
naps62-yolo left a comment
Author
Collaborator

Reviewed 031c80a40b9891b999de00d5405b6dd67865b405. No findings.

Reviewed `031c80a40b9891b999de00d5405b6dd67865b405`. No findings. <!-- agent-meta: {"model":"gpt-5.6","session":"01a02996"} -->
naps62-yolo merged commit 031c80a40b into main 2026-08-22 14:16:40 +01:00
naps62-yolo deleted branch lithuanians 2026-08-22 14:16:40 +01:00
This repo is archived. You cannot comment on pull requests.