Skip to content

N3: [Minor] Test infrastructure — silentLogger / poll-loop / drain helpers + missing test cases #77

Description

@curtyo18

Summary

Test-suite-level housekeeping, all from the 2026-05-17 full-repo review. None are individually critical; bundled because they share one PR's worth of structural cleanup.

Helpers to extract

  • packages/engine/src/scan/orchestrator.test.ts:55, 75, 90, 108, 138, 164, 197, 231const writes: string[] = [] declared in 8 tests but never asserted on; exists only to silence the logger. Extract silentLogger() from a test helper, or pass a noop writer.
  • packages/engine/src/api/server.test.ts:40-50, 78-82, 129-134, 159-164, 611-616, 732-737, 898-903, 1067-1072, 1159-1164, 2095-2100for (let i = 0; i < 50; i++) { fetch...; await sleep(50); } polling loop duplicated in 10+ tests. Extract waitForScanStatus(handle, scanId, target, opts) so tests express intent rather than mechanism, with a deterministic timeout/error.
  • packages/engine/src/scan/walker.test.ts:138, 158, 176for await (const _ of walk(...)) { void _ } drain pattern duplicated three times. Small await drain(asyncIterable) helper.
  • packages/engine/src/organize/applier.test.ts:14-17, move-cross-drive.test.ts:14-17, undo.test.ts:4-7 — three vi.mock(...) calls that just re-export the actual module so a later vi.spyOn can override. Worth a single inline comment on the first occurrence explaining the Vitest-specific idiom; without it the next reader will think these mocks do something.

Missing test cases

  • packages/engine/src/rules/matcher.test.ts — no test exercises backslash paths or Windows-cased **/Downloads/** glob. Add one. (Pairs with M20; can ship as part of this issue or as part of the M20 fix.)
  • packages/engine/src/rules/template.test.ts — no test for filenames containing / or \ (legal on Linux for / if escaped in stored names; NTFS has separate constraints). Add hostile-filename tests.
  • packages/engine/src/throttle/scheduler.test.ts — no test for an hour-boundary crossing inside a single start()/advanceTimersByTime run. (Pairs with M15; can ship there.)
  • packages/engine/src/scan/metadata-video.test.ts:48-80 — writes a #!/bin/sh shim with mode 0o755; fails on Windows (README primary target). Guard with it.skipIf(process.platform === 'win32') or provide a .bat shim.
  • packages/engine/src/scan/walker.test.ts:76-83 — "reports size and mtime" test asserts inside for await; with zero entries it passes with no assertions. Collect into array, assert length first.

Background

From the 2026-05-17 multi-agent full-repo review. Per standards/test-patterns.md: "Verbose/slop tests" and "Tests that don't assert" — each item picks up one of those rules.

Acceptance criteria

Helpers

  • silentLogger() exported from a test-helpers module (e.g., packages/engine/src/test-helpers/log.ts). Used in orchestrator.test.ts. The writes: string[] = [] shim is deleted.
  • waitForScanStatus(handle, scanId, target, opts?: { timeoutMs?: number, intervalMs?: number }) exported from test-helpers. Throws a clear "timed out waiting for scan X to reach status Y after Z ms" error. Used everywhere the polling loop currently appears.
  • drain(asyncIterable) helper. Used at the three sites.
  • One inline comment on the first vi.mock(actual) site explaining the spy-prep idiom.

Tests

  • Windows backslash path test in matcher.test.ts.
  • Hostile filename test in template.test.ts.
  • Hour-boundary crossing test in scheduler.test.ts (if not covered by M15).
  • Windows skip in metadata-video.test.ts.
  • walker.test.ts:76-83 collects entries into array and asserts length first.

Files affected (likely)

  • packages/engine/src/test-helpers/ (new directory)
  • packages/engine/src/scan/orchestrator.test.ts
  • packages/engine/src/api/server.test.ts
  • packages/engine/src/scan/walker.test.ts
  • packages/engine/src/rules/matcher.test.ts
  • packages/engine/src/rules/template.test.ts
  • packages/engine/src/throttle/scheduler.test.ts
  • packages/engine/src/scan/metadata-video.test.ts

Suggested approach

Helpers first (drop-in replacements, no behavior change), then missing-test cases. The Windows-skip / it.skipIf cases are smallest.

Out of scope

  • Adopting a different test framework
  • Increasing coverage to a target threshold

References

  • Standards: standards/test-patterns.md
  • Code: paths above

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions