9.4 KiB
issue, issue_title
| issue | issue_title |
|---|---|
| 35 | Align #21 test files with updated mock-cleanup and node:* default-export rules |
Align #21 test files with updated mock-cleanup and node:* default-export rules
Problem Statement
Two AGENTS.md testing rules were added during the #21 retro, but the three test files that were written as part of #21 still violate them:
vi.fn()stubs are reset viavi.clearAllMocks()inafterEachrather than via explicit.mockReset()(or.mockClear()) calls on named module-scope references inbeforeEach.vi.restoreAllMocks()only handlesvi.spyOn()spies —vi.clearAllMocks()is the wrong hook forvi.fn()stubs, and reset-in-afterEachfires after the test body has already completed, so a leaked state from test N can pollute test N+1 beforeafterEachruns.tests/external-directory.test.tsmocksnode:oswithout adefaultexport, creating a latent "No default export defined on the mock" failure for any future import path that uses the default form of that module.
Goals
- Replace
vi.clearAllMocks()inafterEachwith explicitbeforeEach+.mockReset()(or.mockClear()where the default implementation must be preserved) on named stub references in the three affected test files. - Add the
defaultmirror export to thenode:osmock factory intests/external-directory.test.ts. - Pass
npx vitest runandnpm run buildwith no regressions.
Non-Goals
- Changes to production source files.
- Extending test coverage beyond what is needed for the cleanup.
- Updating any other test files that were not written in #21.
- Schema, config, or documentation changes.
Background
Affected files
All four files were created in #21. No permission surface or runtime behavior is involved — this is test-infrastructure hygiene.
| File | Violation |
|---|---|
tests/bash-filter.test.ts |
vi.clearAllMocks() in afterEach; two vi.fn() stubs (compileWildcardPatterns, findCompiledWildcardMatch) cleaned up globally rather than individually |
tests/permission-prompts.test.ts |
vi.clearAllMocks() in afterEach; mockedFormatToolInput reset globally |
tests/tool-input-preview.test.ts |
vi.clearAllMocks() in afterEach; mockedStringify reset globally |
tests/external-directory.test.ts |
node:os mock factory missing default key; vi.restoreAllMocks() in afterEach is correct as-is (no vi.fn() stubs to clean up there) |
Current pattern (all three mock-cleanup files)
afterEach(() => {
vi.clearAllMocks(); // wrong hook for vi.fn() stubs
vi.restoreAllMocks(); // correct for vi.spyOn() spies
});
Target pattern
beforeEach(() => {
mockedX.mockReset(); // or mockClear() when default implementation must survive
});
afterEach(() => {
vi.restoreAllMocks(); // unchanged
});
compileWildcardPatterns nuance in bash-filter.test.ts
The vi.mock() factory for wildcard-matcher supplies a non-trivial default implementation for compileWildcardPatterns (it transforms the patterns object into a compiled array).
Several tests assert .toHaveBeenCalledWith(...) on that function but rely on the default implementation being in place.
mockReset() would wipe the implementation and cause those tests to fail.
mockClear() clears call history while preserving the implementation — it is the correct choice here.
findCompiledWildcardMatch has no default implementation and each test that needs a return value calls .mockReturnValue() explicitly, so mockReset() is safe.
A module-scope vi.mocked() reference should be extracted for compileWildcardPatterns so it can be addressed explicitly in beforeEach.
Design Overview
No new types, modules, or config changes. All changes are confined to four test files.
tests/bash-filter.test.ts
- Extract
const mockedCompilePatterns = vi.mocked(compileWildcardPatterns);at module scope. beforeEach: callmockedCompilePatterns.mockClear()andmockedFindMatch.mockReset().afterEach: keep onlyvi.restoreAllMocks().- Remove
vi.clearAllMocks().
tests/permission-prompts.test.ts
beforeEach: callmockedFormatToolInput.mockReset(). (mockedFormatToolInputis already module-scope.)afterEach: keep onlyvi.restoreAllMocks().- Remove
vi.clearAllMocks().
tests/tool-input-preview.test.ts
beforeEach: callmockedStringify.mockReset(). (mockedStringifyis already module-scope.)afterEach: keep onlyvi.restoreAllMocks().- Remove
vi.clearAllMocks().
tests/external-directory.test.ts
Replace the node:os mock factory:
// Before
vi.mock("node:os", () => ({
homedir: vi.fn(() => "/mock/home"),
}));
// After
vi.mock("node:os", () => {
const homedir = vi.fn(() => "/mock/home");
return {
homedir,
default: { homedir },
};
});
No beforeEach changes are needed here — homedir is not referenced by a module-scope vi.mocked() variable, and the afterEach vi.restoreAllMocks() is correct as-is.
Module-Level Changes
| File | Change |
|---|---|
tests/bash-filter.test.ts |
Extract mockedCompilePatterns; add beforeEach with mockClear/mockReset; replace afterEach body |
tests/permission-prompts.test.ts |
Add beforeEach with mockReset; replace afterEach body |
tests/tool-input-preview.test.ts |
Add beforeEach with mockReset; replace afterEach body |
tests/external-directory.test.ts |
Refactor node:os mock factory to include default key |
No source files, schemas, config, or documentation are modified.
TDD Order
Because this issue is a test-file refactor with no production code changes, each cycle is: verify tests still pass (green) → make the change → verify still green → commit.
- Verify baseline:
npx vitest runpasses for all four test files. Commit message: (no commit — baseline only) - Refactor
tests/bash-filter.test.ts: extractmockedCompilePatterns, addbeforeEachwithmockClear/mockReset, dropvi.clearAllMocks(). Commit message:test: use beforeEach mockReset/mockClear in bash-filter tests (#35) - Refactor
tests/permission-prompts.test.ts: addbeforeEachwithmockReset, dropvi.clearAllMocks(). Commit message:test: use beforeEach mockReset in permission-prompts tests (#35) - Refactor
tests/tool-input-preview.test.ts: addbeforeEachwithmockReset, dropvi.clearAllMocks(). Commit message:test: use beforeEach mockReset in tool-input-preview tests (#35) - Refactor
tests/external-directory.test.ts: extracthomedirinto a named variable and return it with adefaultmirror in thenode:osmock factory. Commit message:test: add default export to node:os mock in external-directory tests (#35) - Final verification:
npx vitest runandnpm run buildboth pass. Commit message: (included in step 5 commit or a follow-up if build reveals type issues)
Risks and Mitigations
| Risk | Mitigation |
|---|---|
mockReset() on compileWildcardPatterns wipes the default implementation, breaking tests that rely on it |
Use mockClear() for that stub; confirmed safe because it only clears call history |
Removing vi.clearAllMocks() leaves state leak between tests if a stub is missed |
The beforeEach hooks are exhaustive — every vi.fn() in each file is listed; run npx vitest run after each file change to confirm |
| Could this silently weaken a permission? | No. No production code or policy logic is modified. These are test-only changes. |
default key addition to node:os mock could break existing tests that rely on named imports only |
Adding default is purely additive; tests using import { homedir } from "node:os" are unaffected |
Open Questions
- None. The changes are fully specified by the issue and the AGENTS.md rules.