fix: prevent node:fs mock pollution in directory injector tests

Move mock.module() calls from top-level to beforeEach and restore in
afterEach to prevent readFileSync mock from leaking into other test
files. Use dynamic import with cache-busting query to get fresh modules.
This commit is contained in:
YeonGyu-Kim 2026-02-14 16:19:40 +09:00
parent f27733eae2
commit 945329e261
2 changed files with 84 additions and 34 deletions

View File

@ -1,34 +1,59 @@
import { beforeEach, describe, expect, it, mock } from "bun:test"
import { beforeEach, afterEach, describe, expect, it, mock, afterAll } from "bun:test"
const readFileSyncMock = mock((_: string, __: string) => "# AGENTS")
const realNodeFs = await import("node:fs")
const realFinder = await import("./finder")
const realStorage = await import("./storage")
const originalReadFileSync = realNodeFs.readFileSync
const readFileSyncMock = mock((filePath: string, encoding?: string) => {
if (String(filePath).endsWith("AGENTS.md")) {
return "# AGENTS"
}
return originalReadFileSync(filePath as never, encoding as never)
})
const findAgentsMdUpMock = mock((_: { startDir: string; rootDir: string }) => [] as string[])
const resolveFilePathMock = mock((_: string, path: string) => path)
const loadInjectedPathsMock = mock((_: string) => new Set<string>())
const saveInjectedPathsMock = mock((_: string, __: Set<string>) => {})
mock.module("node:fs", () => ({
readFileSync: readFileSyncMock,
}))
afterAll(() => {
mock.module("node:fs", () => ({ ...realNodeFs }))
mock.module("./finder", () => ({ ...realFinder }))
mock.module("./storage", () => ({ ...realStorage }))
})
mock.module("./finder", () => ({
findAgentsMdUp: findAgentsMdUpMock,
resolveFilePath: resolveFilePathMock,
}))
mock.module("./storage", () => ({
loadInjectedPaths: loadInjectedPathsMock,
saveInjectedPaths: saveInjectedPathsMock,
}))
const { processFilePathForAgentsInjection } = await import("./injector")
let processFilePathForAgentsInjection: typeof import("./injector").processFilePathForAgentsInjection
describe("processFilePathForAgentsInjection", () => {
beforeEach(() => {
beforeEach(async () => {
readFileSyncMock.mockClear()
findAgentsMdUpMock.mockClear()
resolveFilePathMock.mockClear()
loadInjectedPathsMock.mockClear()
saveInjectedPathsMock.mockClear()
mock.module("node:fs", () => ({
...realNodeFs,
readFileSync: readFileSyncMock,
}))
mock.module("./finder", () => ({
findAgentsMdUp: findAgentsMdUpMock,
resolveFilePath: resolveFilePathMock,
}))
mock.module("./storage", () => ({
loadInjectedPaths: loadInjectedPathsMock,
saveInjectedPaths: saveInjectedPathsMock,
}))
;({ processFilePathForAgentsInjection } = await import(`./injector?${Date.now()}`))
})
afterEach(() => {
mock.module("node:fs", () => ({ ...realNodeFs }))
mock.module("./finder", () => ({ ...realFinder }))
mock.module("./storage", () => ({ ...realStorage }))
})
it("does not save when all discovered paths are already cached", async () => {

View File

@ -1,34 +1,59 @@
import { beforeEach, describe, expect, it, mock } from "bun:test"
import { beforeEach, afterEach, describe, expect, it, mock, afterAll } from "bun:test"
const readFileSyncMock = mock((_: string, __: string) => "# README")
const realNodeFs = await import("node:fs")
const realFinder = await import("./finder")
const realStorage = await import("./storage")
const originalReadFileSync = realNodeFs.readFileSync
const readFileSyncMock = mock((filePath: string, encoding?: string) => {
if (String(filePath).endsWith("README.md")) {
return "# README"
}
return originalReadFileSync(filePath as never, encoding as never)
})
const findReadmeMdUpMock = mock((_: { startDir: string; rootDir: string }) => [] as string[])
const resolveFilePathMock = mock((_: string, path: string) => path)
const loadInjectedPathsMock = mock((_: string) => new Set<string>())
const saveInjectedPathsMock = mock((_: string, __: Set<string>) => {})
mock.module("node:fs", () => ({
readFileSync: readFileSyncMock,
}))
afterAll(() => {
mock.module("node:fs", () => ({ ...realNodeFs }))
mock.module("./finder", () => ({ ...realFinder }))
mock.module("./storage", () => ({ ...realStorage }))
})
mock.module("./finder", () => ({
findReadmeMdUp: findReadmeMdUpMock,
resolveFilePath: resolveFilePathMock,
}))
mock.module("./storage", () => ({
loadInjectedPaths: loadInjectedPathsMock,
saveInjectedPaths: saveInjectedPathsMock,
}))
const { processFilePathForReadmeInjection } = await import("./injector")
let processFilePathForReadmeInjection: typeof import("./injector").processFilePathForReadmeInjection
describe("processFilePathForReadmeInjection", () => {
beforeEach(() => {
beforeEach(async () => {
readFileSyncMock.mockClear()
findReadmeMdUpMock.mockClear()
resolveFilePathMock.mockClear()
loadInjectedPathsMock.mockClear()
saveInjectedPathsMock.mockClear()
mock.module("node:fs", () => ({
...realNodeFs,
readFileSync: readFileSyncMock,
}))
mock.module("./finder", () => ({
findReadmeMdUp: findReadmeMdUpMock,
resolveFilePath: resolveFilePathMock,
}))
mock.module("./storage", () => ({
loadInjectedPaths: loadInjectedPathsMock,
saveInjectedPaths: saveInjectedPathsMock,
}))
;({ processFilePathForReadmeInjection } = await import(`./injector?${Date.now()}`))
})
afterEach(() => {
mock.module("node:fs", () => ({ ...realNodeFs }))
mock.module("./finder", () => ({ ...realFinder }))
mock.module("./storage", () => ({ ...realStorage }))
})
it("does not save when all discovered paths are already cached", async () => {