diff --git a/src/hooks/directory-readme-injector/injector.test.ts b/src/hooks/directory-readme-injector/injector.test.ts index 775d8a89..932fb77e 100644 --- a/src/hooks/directory-readme-injector/injector.test.ts +++ b/src/hooks/directory-readme-injector/injector.test.ts @@ -1,53 +1,67 @@ -import { beforeEach, describe, expect, it, mock } from "bun:test" +import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test" +import { mkdirSync, rmSync, writeFileSync } from "node:fs" +import { tmpdir } from "node:os" +import { join } from "node:path" -const readFileSyncMock = mock((_: string, __: string) => "# README") const findReadmeMdUpMock = mock((_: { startDir: string; rootDir: string }) => [] as string[]) const resolveFilePathMock = mock((_: string, path: string) => path) const loadInjectedPathsMock = mock((_: string) => new Set()) const saveInjectedPathsMock = mock((_: string, __: Set) => {}) -mock.module("node:fs", () => ({ - readFileSync: readFileSyncMock, -})) - -mock.module("./finder", () => ({ - findReadmeMdUp: findReadmeMdUpMock, - resolveFilePath: resolveFilePathMock, -})) - -mock.module("./storage", () => ({ - loadInjectedPaths: loadInjectedPathsMock, - saveInjectedPaths: saveInjectedPathsMock, -})) - -const { processFilePathForReadmeInjection } = await import("./injector") - describe("processFilePathForReadmeInjection", () => { + let testRoot = "" + beforeEach(() => { - readFileSyncMock.mockClear() findReadmeMdUpMock.mockClear() resolveFilePathMock.mockClear() loadInjectedPathsMock.mockClear() saveInjectedPathsMock.mockClear() + + testRoot = join( + tmpdir(), + `directory-readme-injector-${Date.now()}-${Math.random().toString(16).slice(2)}` + ) + mkdirSync(testRoot, { recursive: true }) + }) + + afterEach(() => { + mock.restore() + rmSync(testRoot, { recursive: true, force: true }) }) it("does not save when all discovered paths are already cached", async () => { //#given const sessionID = "session-1" - const cachedDirectory = "/repo/src" + const repoRoot = join(testRoot, "repo") + const readmePath = join(repoRoot, "src", "README.md") + const cachedDirectory = join(repoRoot, "src") + mkdirSync(join(repoRoot, "src"), { recursive: true }) + writeFileSync(readmePath, "# README") + loadInjectedPathsMock.mockReturnValueOnce(new Set([cachedDirectory])) - findReadmeMdUpMock.mockReturnValueOnce(["/repo/src/README.md"]) + findReadmeMdUpMock.mockReturnValueOnce([readmePath]) const truncator = { truncate: mock(async () => ({ result: "trimmed", truncated: false })), } + mock.module("./finder", () => ({ + findReadmeMdUp: findReadmeMdUpMock, + resolveFilePath: resolveFilePathMock, + })) + mock.module("./storage", () => ({ + loadInjectedPaths: loadInjectedPathsMock, + saveInjectedPaths: saveInjectedPathsMock, + })) + + const { processFilePathForReadmeInjection } = await import("./injector") + //#when await processFilePathForReadmeInjection({ - ctx: { directory: "/repo" } as never, + ctx: { directory: repoRoot } as never, truncator: truncator as never, sessionCaches: new Map(), - filePath: "/repo/src/file.ts", + filePath: join(repoRoot, "src", "file.ts"), sessionID, output: { title: "Result", output: "", metadata: {} }, }) @@ -59,19 +73,36 @@ describe("processFilePathForReadmeInjection", () => { it("saves when a new path is injected", async () => { //#given const sessionID = "session-2" + const repoRoot = join(testRoot, "repo") + const readmePath = join(repoRoot, "src", "README.md") + const injectedDirectory = join(repoRoot, "src") + mkdirSync(join(repoRoot, "src"), { recursive: true }) + writeFileSync(readmePath, "# README") + loadInjectedPathsMock.mockReturnValueOnce(new Set()) - findReadmeMdUpMock.mockReturnValueOnce(["/repo/src/README.md"]) + findReadmeMdUpMock.mockReturnValueOnce([readmePath]) const truncator = { truncate: mock(async () => ({ result: "trimmed", truncated: false })), } + mock.module("./finder", () => ({ + findReadmeMdUp: findReadmeMdUpMock, + resolveFilePath: resolveFilePathMock, + })) + mock.module("./storage", () => ({ + loadInjectedPaths: loadInjectedPathsMock, + saveInjectedPaths: saveInjectedPathsMock, + })) + + const { processFilePathForReadmeInjection } = await import("./injector") + //#when await processFilePathForReadmeInjection({ - ctx: { directory: "/repo" } as never, + ctx: { directory: repoRoot } as never, truncator: truncator as never, sessionCaches: new Map(), - filePath: "/repo/src/file.ts", + filePath: join(repoRoot, "src", "file.ts"), sessionID, output: { title: "Result", output: "", metadata: {} }, }) @@ -80,28 +111,44 @@ describe("processFilePathForReadmeInjection", () => { expect(saveInjectedPathsMock).toHaveBeenCalledTimes(1) const saveCall = saveInjectedPathsMock.mock.calls[0] expect(saveCall[0]).toBe(sessionID) - expect((saveCall[1] as Set).has("/repo/src")).toBe(true) + expect((saveCall[1] as Set).has(injectedDirectory)).toBe(true) }) it("saves once when cached and new paths are mixed", async () => { //#given const sessionID = "session-3" - loadInjectedPathsMock.mockReturnValueOnce(new Set(["/repo/already-cached"])) - findReadmeMdUpMock.mockReturnValueOnce([ - "/repo/already-cached/README.md", - "/repo/new-dir/README.md", - ]) + const repoRoot = join(testRoot, "repo") + const cachedReadmePath = join(repoRoot, "already-cached", "README.md") + const newReadmePath = join(repoRoot, "new-dir", "README.md") + mkdirSync(join(repoRoot, "already-cached"), { recursive: true }) + mkdirSync(join(repoRoot, "new-dir"), { recursive: true }) + writeFileSync(cachedReadmePath, "# README") + writeFileSync(newReadmePath, "# README") + + loadInjectedPathsMock.mockReturnValueOnce(new Set([join(repoRoot, "already-cached")])) + findReadmeMdUpMock.mockReturnValueOnce([cachedReadmePath, newReadmePath]) const truncator = { truncate: mock(async () => ({ result: "trimmed", truncated: false })), } + mock.module("./finder", () => ({ + findReadmeMdUp: findReadmeMdUpMock, + resolveFilePath: resolveFilePathMock, + })) + mock.module("./storage", () => ({ + loadInjectedPaths: loadInjectedPathsMock, + saveInjectedPaths: saveInjectedPathsMock, + })) + + const { processFilePathForReadmeInjection } = await import("./injector") + //#when await processFilePathForReadmeInjection({ - ctx: { directory: "/repo" } as never, + ctx: { directory: repoRoot } as never, truncator: truncator as never, sessionCaches: new Map(), - filePath: "/repo/new-dir/file.ts", + filePath: join(repoRoot, "new-dir", "file.ts"), sessionID, output: { title: "Result", output: "", metadata: {} }, }) @@ -109,6 +156,6 @@ describe("processFilePathForReadmeInjection", () => { //#then expect(saveInjectedPathsMock).toHaveBeenCalledTimes(1) const saveCall = saveInjectedPathsMock.mock.calls[0] - expect((saveCall[1] as Set).has("/repo/new-dir")).toBe(true) + expect((saveCall[1] as Set).has(join(repoRoot, "new-dir"))).toBe(true) }) })