4.1 KiB
Operator Regression Testing
Blacksite editor operators and modal tools must preserve the authored scene across preview,
commit, cancellation, validation failure, and undo/redo. Tests share
operators::test_harness::OperatorInvariantHarness so a new tool proves the same contract instead
of inventing local assertions.
Required invariants
Every production operator test must cover the paths it exposes:
| Path | Required proof |
|---|---|
| Commit | Expected authored projection, exact undo-group delta, dirty state, stable operator ID, committed phase |
| Zero-history commit | Authored projection and prior dirty state remain unchanged |
| Cancel or commit failure | Exact authored projection restored, no new history, prior dirty state, stable operator ID, terminal canceled/blocked phase |
| Blocked start | Commit closure never runs; authored state, history, and dirty state are unchanged |
| Preview failure | Cancel finalizer runs, authored state is restored, and helpers are removed |
| Preview helpers | No helper component remains after commit or cancel |
| Undoable commit | assert_undo_redo_round_trip restores both initial and committed semantic projections |
| Continuous edit | The entire interaction creates one history command, not one per frame or target |
The harness intentionally fails with the invariant name in the assertion message. Tests may add domain assertions, but should not replace these shared lifecycle checks.
Adding a tool test
- Build a minimal
WorldwithActiveOperator,EditorHistory, andSceneIo. Add tool-specific selection/resources andSelectedEntitywhen history helpers update selection. - Capture
OperatorInvariantHarnessimmediately before starting the operation. - Run the real dispatch path or production finalizer used by the input system. Do not duplicate its state transition in the test.
- Call
assert_committed,assert_canceled, orassert_blockedwith the expected authored and undo deltas, thenassert_statuswith the stable operator ID and terminal phase. - For helpers, call
assert_no_helpers::<ToolHelper>. For undoable work, project the meaningful state throughassert_undo_redo_round_trip; useassert_projection_unchangedfor no-op paths.
Do not satisfy a lifecycle test by constructing an EditorCommand and checking only its label.
The test must mutate a world and prove restoration.
Current coverage
| Workflow | Coverage |
|---|---|
Generic EditorOperator |
Commit cleanup, preview/commit failure rollback, blocked no-op, terminal ID/phase |
| Palette and registered commands | Typed immediate commit versus modal preview ownership; Enter/click/Escape dismissal cannot be overwritten by stale window state; failed CSG start terminates |
| Selection and scene commands | Atomic Group Selection across repeated undo/redo; spawned group actors have an immediate Bevy visibility hierarchy; grouped Reset Lighting and Project Sun history |
| Asset workflows | Asset/sub-asset placement; material/texture group assignment; audio/animation assignment and incompatible targets |
| Viewport material drop | Exact renderer slot/primitive/brush-face preview, cancel, commit, cleanup, undo, and redo |
| Draw Brush and CSG | Modal cancel; decomposed commit; CSG validation/read-only block, cancel, grouped commit, and deleted-brush restoration |
| Brush clip and element gizmo | Production finalizers, geometry round trip, Escape rollback, and helper cleanup |
| Terrain sculpt and paint | Multi-dab grouped commit, no-op release, commit failure rollback, cancel, clean-view interruption, and resource cleanup |
| Physics placement | Prerequisite block, no-op commit, exact cancel, real settle commit, multi-selection grouping, helper cleanup, undo, and redo |
| Transform gizmo finalization | Actual tracker finalizer, continuous multi-target grouping, no-op release, and missing-primary survivor rollback |
The shared harness covers formal operators and multi-frame modal paths. Atomic inspector and history
mutations that do not own ActiveOperator use focused typed history tests with equivalent semantic
projection and undo/redo assertions.