You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Centralizes the decisions we made during the Step 1-6 speedup and the Step 7
+ mutation/state-machine/property/IPC investigations into two canonical docs:
- docs/testing.md: the playbook. Test pyramid, decision table (when to use
which layer), anti-patterns with rationale (no `await sleep`, no synthetic
F-key for dialog tests, no direct atomic mutation in state-machine tests,
no `retries: 1` masking), and a per-feature checklist ("when you add X,
also add Y").
- docs/tooling/testing.md: the tools inventory. One paragraph per tool —
proptest, cargo-mutants, stryker, vitest mockIPC, pollUntil,
dispatchMenuCommand, virtual-mtp, the Docker SMB containers, the
checker, and the custom ESLint rules.
Plus per-module CLAUDE.md updates calling out the testing bar where it
matters most:
- write_operations/: state machine has 30+ tests, drive transitions via
public interface, run cargo-mutants after substantial changes
- indexing/: IndexPhase lifecycle tests need a dedicated mutex + tempdir
IndexStore; `Initializing` carries non-Clone owned state
- src/lib/ipc/: when to write an IPC contract test (destructive,
cross-window, many-arg surfaces) and when to skip (thin getters)
And process integration:
- AGENTS.md: link to docs/testing.md from the Testing section
- docs/maintenance.md: quarterly mutation sweep, per-release E2E health
check, per-release scan for new fixed sleeps in E2E specs, periodic
triage of the legacy `eslint-disable cmdr/no-arbitrary-sleep-in-e2e`
annotations
-**Fast checker total**: ~2m 30s baseline → **3m 13s** (+43s) — the regression is the new IPC contract tests
629
-
(+30s of Svelte vitest) and the +79 Rust tests (+1s). Net cost is well below what an equivalent E2E spec would add.
628
+
-**Fast checker total**: ~2m 30s baseline → **3m 13s** (+43s) — the regression is the new IPC contract tests (+30s of
629
+
Svelte vitest) and the +79 Rust tests (+1s). Net cost is well below what an equivalent E2E spec would add.
630
630
631
631
### Real bugs fixed
632
632
633
-
1.**file_viewer search-cancel was unobservable to the FE.**`search_cancel` nulled `session.search` immediately,
634
-
so the spawned thread's `SearchStatus::Cancelled` write was clobbered before the FE could see it. The FE
635
-
couldn't distinguish "search completed naturally with zero matches" from "search was cancelled mid-flight."
636
-
Fix: stop nulling on cancel; let the thread write `Cancelled` and the next `search_start` replaces it.
633
+
1.**file_viewer search-cancel was unobservable to the FE.**`search_cancel` nulled `session.search` immediately, so the
634
+
spawned thread's `SearchStatus::Cancelled` write was clobbered before the FE could see it. The FE couldn't
635
+
distinguish "search completed naturally with zero matches" from "search was cancelled mid-flight." Fix: stop nulling
636
+
on cancel; let the thread write `Cancelled` and the next `search_start` replaces it.
637
637
2.**Cancel-copy mid-operation rollback was lost on fast filesystems.** The Rust `Ok(())` arm in
638
-
`copy_files_with_progress` didn't check `OperationIntent` before committing the transaction, so a click during
639
-
the < 1 µs window between the last `is_cancelled` poll and loop exit landed as a no-op. Plus the Svelte
640
-
`TransferProgressDialog` left the Rollback button enabled during the `MIN_DISPLAY_MS = 400 ms` settle window
641
-
after `write-complete`, so clicks during settle were silent no-ops. Both fixed in Step 6d.
638
+
`copy_files_with_progress` didn't check `OperationIntent` before committing the transaction, so a click during the <
639
+
1 µs window between the last `is_cancelled` poll and loop exit landed as a no-op. Plus the Svelte
640
+
`TransferProgressDialog` left the Rollback button enabled during the `MIN_DISPLAY_MS = 400 ms` settle window after
641
+
`write-complete`, so clicks during settle were silent no-ops. Both fixed in Step 6d.
642
642
643
643
### Dead code removed
644
644
645
-
-`SmbVolume::ConnectionState::OsMount` variant — never written to the atomic, two unreachable `match` arms gone.
646
-
The OS-mount fallback the UI renders lives at the outer `SmbConnectionState` enriched by `enrich_smb_connection_state`
647
-
in `commands/volumes.rs`, not on this internal atomic.
645
+
-`SmbVolume::ConnectionState::OsMount` variant — never written to the atomic, two unreachable `match` arms gone. The
646
+
OS-mount fallback the UI renders lives at the outer `SmbConnectionState` enriched by `enrich_smb_connection_state` in
647
+
`commands/volumes.rs`, not on this internal atomic.
648
648
649
649
### Honest verdict per technique
650
650
651
-
-**Mutation testing (cargo-mutants + stryker)**: zero bugs, 55 tests added. Tools work but are too slow / noisy for
652
-
CI gating. Worth ad-hoc runs on numeric / state-machine modules. Don't wire into `check.sh`.
653
-
-**State-machine coverage**: 17 tests, 1 real bug (file_viewer search-cancel). Highest signal-to-noise of the test-quality push — the bug was a real silent UX failure, surfaced by writing the transition test.
651
+
-**Mutation testing (cargo-mutants + stryker)**: zero bugs, 55 tests added. Tools work but are too slow / noisy for CI
652
+
gating. Worth ad-hoc runs on numeric / state-machine modules. Don't wire into `check.sh`.
653
+
-**State-machine coverage**: 17 tests, 1 real bug (file_viewer search-cancel). Highest signal-to-noise of the
654
+
test-quality push — the bug was a real silent UX failure, surfaced by writing the transition test.
654
655
-**Property-based (proptest)**: 12 tests, 0 bugs. `proptest` added as a dev-dep, scoped to four targets
0 commit comments