Skip to content

Testing rollout next steps implementation plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Finish the remaining high-value SDK test coverage work from the current worktree state, then harden the test system with enforceable coverage and verification gates.

Architecture: Keep the existing Vitest and layered PIXI mock foundation, then expand coverage in ROI order: missing manager logic, missing component logic, browser-specific utilities, and finally coverage ratcheting and CI readiness. Prefer small test files that mirror one source module or one focused behavior area.

Tech Stack: TypeScript, Vitest 4, V8 coverage, PIXI.js 8 mocks, Valtio, ESLint, Vite.


Current state summary

This plan starts from the actual repository state on March 10, 2026, not from the earlier design baseline.

  • Test infrastructure is already present in vitest.config.ts, test/setup.ts, test/mocks/*, and test/factories/*.
  • The worktree already has 25 test files and 650 passing tests.
  • AppService, Interaction, MapApplication, PathManager, ControlsManager, Robot, ChargingStation, and utility algorithms already have meaningful test coverage.
  • The largest remaining gaps are MapManager, RoomManager, many untested components, browser.ts, and hardening tasks such as non-zero coverage thresholds.

Constraints and execution rules

This plan follows the current repository rules and the current worktree state.

  • Preserve existing user changes in the dirty worktree.
  • Keep tests in test/ mirroring src/core/ paths.
  • Prefer splitting oversized test files by behavior area when it improves maintainability.
  • After each implementation slice, run npm test, npx tsc --noEmit, and npm run lint.
  • Before claiming hardening is complete, also run npm run test:coverage.
  • Do not introduce browser or E2E frameworks in this plan.

Task 1: Stabilize the in-progress test file split

This task closes the current dirty-worktree refactor before adding more surface area.

Files:

  • Modify: test/core/application/Interaction.test.ts
  • Modify: test/core/components/Robot.test.ts
  • Modify: test/core/managers/PathManager.test.ts
  • Modify: test/core/utils/algorithm-geometry.test.ts
  • Modify: test/core/utils/algorithm-outline.test.ts
  • Modify: test/core/utils/algorithm-room.test.ts
  • Modify: test/core/utils/algorithm-vector.test.ts
  • Delete: test/core/utils/index.test.ts
  • Create: test/core/application/Interaction-pointer.test.ts
  • Create: test/core/application/Interaction-gesture.test.ts
  • Create: test/core/application/Interaction-panzoom.test.ts
  • Create: test/core/application/Interaction-detect.test.ts
  • Create: test/core/application/interaction-test-setup.ts
  • Create: test/core/components/Robot-draw.test.ts
  • Create: test/core/components/Robot-movement.test.ts
  • Create: test/core/managers/PathManager-draw.test.ts
  • Create: test/core/managers/PathManager-operations.test.ts
  • Create: test/core/utils/utils-easing.test.ts
  • Create: test/core/utils/utils-precision.test.ts
  • Create: test/core/utils/utils-room.test.ts

Step 1: Review the split for duplication and ownership

Check that each new file owns one behavior cluster and that no assertions are duplicated across old and new files.

Step 2: Keep helper setup local and reusable

Move repeated Interaction setup into test/core/application/interaction-test-setup.ts only when it reduces noise.

Step 3: Remove the obsolete aggregate utility test file

Finish the migration away from test/core/utils/index.test.ts after its coverage has been preserved by the new focused utility test files.

Step 4: Run verification

Run:

bash
npm test
npx tsc --noEmit
npm run lint

Expected: all commands pass with no regression from the split.

Task 2: Add missing manager coverage for RoomManager

This task fills one of the two explicit manager gaps from the original phase plan.

Files:

  • Modify: src/core/managers/RoomManager.ts
  • Create: test/core/managers/RoomManager.test.ts

Step 1: Write failing tests for subscription-driven visibility behavior

Cover runtime reactions such as room visibility toggles, label visibility, and cleanup of subscriptions in destroy().

Step 2: Write failing tests for room data synchronization

Cover room collection updates, state-driven redraw decisions, and basic idempotency when repeated room updates arrive.

Step 3: Reuse existing factories and PIXI mocks

Build test fixtures from test/factories/map-data.ts, test/factories/config.ts, and test/factories/runtime.ts before creating new helpers.

Step 4: Implement only minimal test-support changes

If testability gaps exist, keep production edits small and avoid behavior changes beyond exposing stable seams.

Step 5: Run verification

Run:

bash
npm test -- RoomManager
npm test
npx tsc --noEmit
npm run lint

Expected: new RoomManager tests pass, and the full suite still passes.

Task 3: Add missing manager coverage for MapManager

This is the largest remaining high-value gap and the best next ROI item after RoomManager.

Files:

  • Modify: src/core/managers/MapManager.ts
  • Create: test/core/managers/MapManager.test.ts

Step 1: Identify a narrow first slice

Start with room detection flow, raster versus structured handling, and caching decisions. Do not try to cover every branch in the first pass.

Step 2: Mock robot-protocol decode boundaries deliberately

Use test/mocks/robot-protocol.ts and fixture builders so tests focus on manager orchestration rather than protocol internals.

Step 3: Add tests for cache reuse and redraw triggers

Cover cases where identical inputs skip unnecessary work and changed inputs cause the expected processing path.

Step 4: Add tests for structured versus raster dispatch

Verify that MapManager selects the correct pipeline and populates downstream data consistently.

Step 5: Run verification

Run:

bash
npm test -- MapManager
npm test
npx tsc --noEmit
npm run lint

Expected: the first focused MapManager slice lands without destabilizing the existing suite.

Task 4: Expand component coverage by priority

This task broadens Phase 4, but only for components with meaningful state or geometry logic.

Files:

  • Create: test/core/components/Path.test.ts
  • Create: test/core/components/RoomInfo.test.ts
  • Create: test/core/components/RoomLabel.test.ts
  • Create: test/core/components/VirtualWall.test.ts
  • Create: test/core/components/Carpet.test.ts
  • Optional create: additional focused component test files that map to the selected source modules

Step 1: Prioritize data-rich components

Implement coverage in this order: Path first, then room presentation components, then interactive control visuals.

Step 2: Test construction, updates, and destroy cleanup

Focus on input-to-render-state behavior, not PIXI internals.

Step 3: Avoid broad snapshot-style assertions

Use direct assertions on points, visibility, labels, transforms, and child management so failures stay easy to diagnose.

Step 4: Run verification

Run:

bash
npm test
npx tsc --noEmit
npm run lint

Expected: component coverage grows without requiring heavier PIXI mocks.

Task 5: Add browser utility coverage

This task closes the small but explicit browser-specific risk called out in the design record.

Files:

  • Create: test/core/utils/browser.test.ts
  • Modify: src/core/utils/browser.ts only if a small test seam is required

Step 1: Stub navigator inputs explicitly

Cover userAgent and deviceMemory branches with vi.stubGlobal() based tests.

Step 2: Verify environment assumptions

Make sure tests reset globals between cases so forked execution is not the only thing protecting isolation.

Step 3: Run verification

Run:

bash
npm test -- browser
npm test
npx tsc --noEmit
npm run lint

Expected: browser.ts no longer remains at zero coverage.

Task 6: Harden the test system gates

This task converts the current test suite from permissive to enforceable.

Files:

  • Modify: vitest.config.ts
  • Modify: package.json
  • Modify: eslint.config.js

Step 1: Set non-zero coverage thresholds

After Tasks 2 through 5 are complete, run npm run test:coverage and set thresholds in vitest.config.ts using the ratchet rule from the design doc.

Step 2: Extend lint coverage to test code

Update lint configuration so test files are included in normal verification. The current lint script only checks src.

Step 3: Keep thresholds realistic

Start with a floor that the current suite can satisfy comfortably, then ratchet up in later iterations rather than blocking progress on an overly aggressive first gate.

Step 4: Run verification

Run:

bash
npm run lint
npx tsc --noEmit
npm test
npm run test:coverage

Expected: all four commands pass with enforceable, non-zero thresholds.

Task 7: Update traceability and execution status

This task keeps the docs aligned with reality once implementation catches up.

Files:

  • Modify: docs/records/plans/2026-03-05-testing-infrastructure-design.md
  • Optional create: docs/records/bugs/2026-03-10-<topic>-bugfix.md if non-trivial defects are fixed during the rollout

Step 1: Update status language

Replace outdated statements such as "zero tests" and "Draft — pending approval" once the rollout milestone is complete.

Step 2: Record actual delivered phase status

Document which phases are complete, which are partial, and which hardening items remain open.

Step 3: Keep the record factual

Report actual commands, actual coverage, and actual remaining gaps instead of restating estimates.

Use this order to keep momentum and avoid mixing structural cleanup with new surface area.

  1. Finish Task 1.
  2. Implement Task 2.
  3. Implement Task 3.
  4. Implement Task 4.
  5. Implement Task 5.
  6. Implement Task 6.
  7. Close with Task 7.

Verification checklist

Use this checklist before calling the testing rollout complete.

  • npm test passes.
  • npx tsc --noEmit passes.
  • npm run lint passes for src and test.
  • npm run test:coverage passes with non-zero thresholds.
  • MapManager, RoomManager, and browser.ts are no longer uncovered.
  • The design record reflects the actual delivered state.

Next steps

If you want to execute this in the current session, the cleanest next move is to treat Task 1 plus Task 2 as the first batch. That closes the in-flight refactor and lands the smallest missing manager slice before tackling the much larger MapManager surface.

最后更新于: