dedup-scan-cache.spec.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { beforeEach, expect, test, vi } from "vitest"
  2. vi.mock("@/commands/fs", () => ({
  3. readFile: vi.fn(),
  4. writeFile: vi.fn(),
  5. fileExists: vi.fn(),
  6. }))
  7. import { readFile, writeFile, fileExists } from "@/commands/fs"
  8. import {
  9. loadDedupScanCache,
  10. removeGroupFromDedupScanCache,
  11. saveDedupScanCache,
  12. } from "./dedup-scan-cache"
  13. const mockedReadFile = vi.mocked(readFile)
  14. const mockedWriteFile = vi.mocked(writeFile)
  15. const mockedFileExists = vi.mocked(fileExists)
  16. beforeEach(() => {
  17. vi.clearAllMocks()
  18. })
  19. test("removeGroupFromDedupScanCache drops matching group and rewrites file", async () => {
  20. mockedFileExists.mockResolvedValue(true)
  21. mockedReadFile.mockResolvedValue(
  22. JSON.stringify({
  23. version: 1,
  24. projectId: "p1",
  25. scannedAt: 100,
  26. scannedPageCount: 4,
  27. modelId: "openai/gpt-4",
  28. groups: [
  29. {
  30. group: { slugs: ["alpha", "beta"], reason: "same", confidence: "high" },
  31. canonicalSlug: "alpha",
  32. skipped: false,
  33. },
  34. {
  35. group: { slugs: ["gamma", "delta"], reason: "same", confidence: "medium" },
  36. canonicalSlug: "gamma",
  37. skipped: false,
  38. },
  39. ],
  40. }),
  41. )
  42. const removed = await removeGroupFromDedupScanCache("/Project", ["beta", "alpha"])
  43. expect(removed).toBe(true)
  44. expect(mockedWriteFile).toHaveBeenCalledTimes(1)
  45. const written = JSON.parse(String(mockedWriteFile.mock.calls[0]?.[1]))
  46. expect(written.groups).toHaveLength(1)
  47. expect(written.groups[0].group.slugs).toEqual(["gamma", "delta"])
  48. })
  49. test("removeGroupFromDedupScanCache is a no-op when group absent", async () => {
  50. mockedFileExists.mockResolvedValue(true)
  51. mockedReadFile.mockResolvedValue(
  52. JSON.stringify({
  53. version: 1,
  54. projectId: "p1",
  55. scannedAt: 100,
  56. scannedPageCount: 2,
  57. groups: [
  58. {
  59. group: { slugs: ["gamma", "delta"], reason: "same", confidence: "low" },
  60. canonicalSlug: "gamma",
  61. skipped: false,
  62. },
  63. ],
  64. }),
  65. )
  66. const removed = await removeGroupFromDedupScanCache("/Project", ["alpha", "beta"])
  67. expect(removed).toBe(false)
  68. expect(mockedWriteFile).not.toHaveBeenCalled()
  69. })
  70. test("save + load round-trip keeps modelId", async () => {
  71. mockedFileExists.mockResolvedValue(true)
  72. let stored = ""
  73. mockedWriteFile.mockImplementation(async (_path, content) => {
  74. stored = String(content)
  75. })
  76. mockedReadFile.mockImplementation(async () => stored)
  77. await saveDedupScanCache("/Project", {
  78. version: 1,
  79. projectId: "p1",
  80. scannedAt: 1,
  81. scannedPageCount: 0,
  82. modelId: "x/y",
  83. groups: [],
  84. })
  85. const loaded = await loadDedupScanCache("/Project")
  86. expect(loaded?.modelId).toBe("x/y")
  87. })