Commit 26baabe
refactor(tests): adopt libtest-mimic and custom snapshot_test crate (#339)
## Why
Before this PR, both `e2e_snapshots` and `plan_snapshots` used `harness
= false` with a hand-rolled `fn main()` that:
- Parsed one positional arg as a substring filter (`args().nth(1)`), and
nothing else — no `--list`, no `--exact`, no `--ignored`, no
`--test-threads`.
- Iterated fixtures sequentially in a single thread, regardless of
machine parallelism.
- Printed fixture names to stdout as progress, mixed into `insta`'s own
stderr diff output, with no structured "passed / failed / filtered out"
summary.
Two problems fall out of that:
- **AI-agent friction.** Agents (Claude Code, Cursor, etc.) drive tests
through `cargo test` and expect the built-in harness contract: filter a
subset with `--exact`, enumerate with `--list`, read the standard "N
passed; M failed" summary to know what happened. Custom output and
missing flags force the agent to grep through ad-hoc progress prints or
re-run the full suite just to isolate one fixture. Moving to
`libtest-mimic` removes that friction — the harness behaves exactly like
a normal Rust test binary.
- **No parallelism.** `plan_snapshots` in particular is CPU-bound and
embarrassingly parallel per fixture, but the old harness ran it
single-threaded. `libtest-mimic` runs fixtures in parallel by default
(via `available_parallelism()`), using the hardware the CI already pays
for. (E2E tests spawn PTY children and send signals; on Linux we pin
them back to single-threaded — see the "Platform-specific fixes" section
below.)
## Summary
Two-part migration of the e2e and plan snapshot test harnesses:
### 1. Adopt `libtest-mimic` for proper `cargo test` integration
Migrating to `libtest-mimic` gives:
- Proper `cargo test` flag support: `--filter`, `--list`, `--exact`,
`--ignored`, `--test-threads`
- Standard test runner output formatting (`running N tests` / `test X
... ok` / `test result: ok. ... passed; ... failed`)
- Parallel fixture execution by default
### 2. Replace `insta` with a custom `snapshot_test` crate
Created `crates/snapshot_test` with two methods that return `Result<(),
String>` — containing a unified diff — so failures integrate cleanly
with `libtest-mimic::Failed`:
- `check_snapshot(name, actual)` — compares raw text
- `check_json_snapshot(name, comment, value)` — serializes to pretty
JSON, prepends `// {comment}` header, writes to `.jsonc`
Key behaviors:
- Drops the `insta` dependency and its transitive deps
- Unified diff appears directly in the `failures:` section of test
output (see
[`crates/snapshot_test/README.md`](crates/snapshot_test/README.md) for
why `insta` didn't fit)
- Plan JSON snapshots now use `.jsonc` extension with `// run ...`
command headers (e.g. `// run build --recursive`); e2e snapshots keep
`.snap`
- Existing `insta` YAML headers stripped from all 310 snapshot files
- `UPDATE_SNAPSHOTS=1` env var accepts new output in-place (replaces
`INSTA_UPDATE`)
- Snapshot directories excluded from `oxfmt` via `.oxfmtrc.json` to
prevent trailing-comma insertion in `.jsonc` files
### Platform-specific fixes
- **Windows**: CRLF line endings are normalized to LF when reading
snapshot files
- **Linux**: e2e tests forced to single-threaded (`test_threads = 1`),
matching the pre-PR custom-harness behavior. `libtest-mimic` defaults to
`available_parallelism()`, which caused PTY/signal-routing races in the
`ctrl-c` test. macOS and Windows keep parallel execution.
## Test plan
- [x] `cargo test -p vite_task_plan --test plan_snapshots` — 45 tests
pass
- [x] `cargo test -p vite_task_bin --test e2e_snapshots` — 36 tests pass
- [x] `cargo test -- --list` lists all fixture names
- [x] `cargo test -- --exact <name>` filters correctly
- [x] Tampered `.snap`/`.jsonc` file produces a unified diff in the
failure message, pointing to the `.snap.new` / `.jsonc.new` file
- [x] `UPDATE_SNAPSHOTS=1` accepts new output in-place and clears `.new`
files
- [x] CI stability: 5 consecutive green runs across Linux, macOS (arm64
+ x86_64), Windows, and musl
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent b2e2e2c commit 26baabe
373 files changed
Lines changed: 835 additions & 2730 deletions
File tree
- crates
- snapshot_test
- src
- vite_task_bin
- tests/e2e_snapshots
- fixtures
- associate-existing-cache/snapshots
- builtin-different-cwd/snapshots
- cache-disabled/snapshots
- cache-miss-command-change/snapshots
- cache-miss-reasons/snapshots
- cache-subcommand/snapshots
- cache-task-select/snapshots
- colon-in-name/snapshots
- concurrent-execution/snapshots
- ctrl-c/snapshots
- error_cycle_dependency/snapshots
- exit-codes/snapshots
- filter-unmatched/snapshots
- glob-base-test/snapshots
- grouped-stdio/snapshots
- individual-cache-for-adt-args/snapshots
- individual-cache-for-env/snapshots
- input-cache-test/snapshots
- input-glob-meta-in-path/snapshots
- input-negative-glob-subpackage/snapshots
- input-read-write-not-cached/snapshots
- interleaved-stdio/snapshots
- labeled-stdio/snapshots
- malformed-fspy-path/snapshots
- parallel-execution/snapshots
- pass-args-to-task/snapshots
- signal-exit/snapshots
- summary-output/snapshots
- task-list/snapshots
- task-no-trailing-newline/snapshots
- task-select-truncate/snapshots
- task-select/snapshots
- topological-execution-order/snapshots
- vite-task-smoke/snapshots
- workspace-root-self-reference/snapshots
- vite_task_plan
- tests/plan_snapshots
- fixtures
- additional-env/snapshots
- cache-cli-override/snapshots
- cache-keys/snapshots
- cache-scripts-default/snapshots
- cache-scripts-enabled/snapshots
- cache-scripts-error-non-root/snapshots
- cache-scripts-task-override/snapshots
- cache-sharing/snapshots
- cache-subcommand/snapshots
- cache-tasks-disabled/snapshots
- cache-true-no-force-enable/snapshots
- cd-in-scripts/snapshots
- comprehensive-task-graph/snapshots
- conflict-test/snapshots
- cycle-dependency/snapshots
- dependency-both-topo-and-explicit/snapshots
- duplicate-package-names/snapshots
- empty-package-test/snapshots
- explicit-deps-workspace/snapshots
- extra-args-not-forwarded-to-depends-on/snapshots
- filter-workspace/snapshots
- input-trailing-slash/snapshots
- input-workspace-base/snapshots
- nested-cache-override/snapshots
- nested-tasks/snapshots
- package-self-dependency/snapshots
- parallel-and-concurrency/snapshots
- pnpm-workspace-packages-optional/snapshots
- recursive-topological-workspace/snapshots
- script-conflict/snapshots
- script-hooks-disabled/snapshots
- script-hooks-nested-run/snapshots
- script-hooks-task-no-hook/snapshots
- script-hooks/snapshots
- shell-fallback/snapshots
- synthetic-cache-disabled/snapshots
- synthetic-in-subpackage/snapshots
- transitive-skip-intermediate/snapshots
- vpr-shorthand/snapshots
- workspace-root-cd-no-skip/snapshots
- workspace-root-depends-on-passthrough/snapshots
- workspace-root-multi-command/snapshots
- workspace-root-mutual-recursion/snapshots
- workspace-root-no-package-json/snapshots
- workspace-root-self-reference/snapshots
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
4 | 8 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
50 | | - | |
| 50 | + | |
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
48 | | - | |
| 48 | + | |
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| |||
0 commit comments