Skip to content

fix(test): defuse the suite's landmines, and cover the dossier's untested modules - #1436

Merged
glennmichael123 merged 4 commits into
mainfrom
fix/test-landmines
Aug 31, 2026
Merged

fix(test): defuse the suite's landmines, and cover the dossier's untested modules#1436
glennmichael123 merged 4 commits into
mainfrom
fix/test-landmines

Conversation

@glennmichael123

@glennmichael123 glennmichael123 commented Aug 31, 2026

Copy link
Copy Markdown
Member

Three commits of test-suite health, all off the dossier's shortlist β€” the third one forced by the second stepping on the very landmine the first defuses.

Commit 1 β€” the three landmines

The node:fs mock that outlives its suite. test/dependency-file-parser.test.ts calls mock.module('node:fs', …) with bare mock functions. mock.module is process-global and permanent, so every file that runs afterwards inherits the mocks β€” and once afterEach resets them, existsSync returns undefined everywhere. That is precisely how #1434's decline test failed on CI while passing alone. The replacement functions now delegate to the real fs except while the suite has explicitly armed them.

The dead working directory. A suite that chdirs into a temp dir and deletes it leaves process.cwd() pointing at nothing; the next filesystem-touching suite fails with an ENOENT that looks like its own bug. test/preload.ts now carries the net: a global beforeEach that repairs cwd to the repo root only when it is dead.

The 0-byte test file. test/composer-constraint-updates.test.ts ran, passed, and asserted nothing. It now holds the suite its name promises: ^/~/exact constraints keep their shape, >=6.0,<7.0 moves only its floor, require-dev follows the same rules, an unknown package leaves the file untouched.

Commits 2+3 β€” the untested modules, and the README gap

src/utils/lock-file.ts β€” 188 lines, publicly re-exported, zero direct tests. Pure parts asserted directly; regenerateLockFile through its non-fatal contract: a machine without the manager gets a result object naming the failure, not an unhandled rejection (node fires error, Bun closes with a negative code β€” the test pins the contract, not the channel).

src/ai/providers/anthropic.ts β€” the gaps in its coverage are closed inside test/ai-provider.test.ts, at the fetch layer, through the real SDK: the remaining stop reasons (stop_sequence, max_tokens, unknown β†’ other), schema-constrained JSON parsing and its malformed-JSON AiProviderError, and the wire shape (system, tools mapped to input_schema, output_config, the 16000 max_tokens default) captured from the request body. The first attempt was a separate file owning its own mock.module('@anthropic-ai/sdk') β€” process-global, so under CI's file order it clobbered the existing fetch-stubbed tests, which began receiving the fake's canned response. Same landmine class commit 1 defuses; commit 3 removes it in favour of stubbing at the seam this suite already owns.

README β€” bun install is a hard prerequisite on a fresh clone (bun test otherwise fails with a hundred-plus phantom Cannot find package errors), and the git hooks declared in package.json do not install themselves β€” bunx bun-git-hooks activates them.

Tests

bun test: 2213 pass / 0 fail (up 19 net). The leak-order pair (dependency-file-parser β†’ cli-surface) run explicitly to confirm the delegation holds. Typecheck, pickier, check-docs green.

πŸ€– Generated with Claude Code

glennmichael123 and others added 3 commits August 31, 2026 19:45
… and un-strand two flags

Four review-side findings, the last of the sweep's low tier:

- reviewPullRequest now reads the ReviewSubmissionResult every provider
  already returned: a review that failed to post says so instead of
  claiming success (and records no state, so the next run does not skip
  a review nobody can see), and inline comments the platform dropped
  are counted in the status and warned about.
- prepareReview/renderFinding take the provider's reviewSuggestions
  capability: Bitbucket declares it false and was receiving literal
  suggestion fences promising a one-click apply it does not have; it
  now gets a plain code fence labelled as a suggested replacement.
- buddy review --auto passes skipIfReviewed, so the workflow that fires
  on every edited event stops re-reviewing the same head commit; a
  person at a terminal still always gets their review.
- buddy review --light --fix applies suggestions: the light branch
  returned before the fix block, so the flag worked everywhere except
  the one mode fast enough for a pre-commit hook.

The review-parity stub answered createReview with { id: 1 } β€” encoding
the defect that the result was ignored; it now returns what the
interface declares.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The node:fs module mock in dependency-file-parser leaked into every
  file that ran after it: mock.module is process-global and permanent,
  so once afterEach reset the mocks, existsSync returned undefined
  suite-wide β€” which is exactly how #1434's decline test failed on CI
  while passing alone. The mock now delegates to the real fs except
  while this suite has armed it.
- preload.ts gains a repair-only cwd net: a suite that chdirs into a
  temp directory and deletes it leaves process.cwd() dead, and every
  later filesystem-touching test fails with an unrelated ENOENT. A live
  cwd is never moved.
- test/composer-constraint-updates.test.ts was a 0-byte file that ran
  and asserted nothing β€” coverage in every listing, a test of nothing.
  It now holds the suite its name promises: caret, tilde, exact and
  compound constraints keep their shape, require-dev updates, and an
  unknown package leaves the file untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s not optional

- src/ai/providers/anthropic.ts was the one AI provider without a
  direct test (google and openai have them) β€” and it is the default
  when several keys are present. The SDK is faked at the module seam so
  complete() runs its real mapping: block collection, the stop-reason
  table (refusal preserved β€” it arrives as a successful response with
  empty content), usage with cache reads, schema-constrained JSON
  parsing, request passthrough, and the lazily built, reused client.
- src/utils/lock-file.ts: 188 lines, publicly re-exported, no direct
  test. The pure parts are asserted directly; regenerateLockFile is
  exercised through its non-fatal contract β€” a machine without the
  package manager gets a result object naming the failure, not an
  unhandled rejection (which channel reports it is platform-dependent:
  node fires 'error', Bun closes with a negative code).
- README: bun install is a hard prerequisite on a fresh clone (bun test
  otherwise fails with phantom module errors), and the declared git
  hooks do not install themselves β€” bunx bun-git-hooks activates them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@glennmichael123 glennmichael123 changed the title fix(test): defuse the suite's three landmines fix(test): defuse the suite's landmines, and cover the dossier's untested modules Aug 31, 2026
…h a second module mock

The new anthropic-provider file owned its own mock.module of the SDK β€”
process-global, so under CI's file order it clobbered ai-provider's
fetch-stubbed anthropic tests, which started receiving the fake's
canned response. The same landmine class this branch exists to defuse.

The genuinely new cases move into ai-provider.test.ts through the real
SDK: the remaining stop reasons (stop_sequence, max_tokens, unknown),
schema-constrained JSON parsing and its malformed-JSON failure, and the
wire shape (system, tools mapped to input_schema, output_config,
max_tokens default) captured from the request body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@glennmichael123
glennmichael123 merged commit b9d8492 into main Aug 31, 2026
10 checks passed
@glennmichael123
glennmichael123 deleted the fix/test-landmines branch August 31, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant