/** * Image cache service tests * * TRACES: UR-007 | DR-016 */ import { describe, it, expect, beforeEach, vi } from "vitest"; import { getCacheStats, setCacheLimit, clearCache, deleteItemCache, formatBytes, gbToBytes, bytesToGb, } from "./imageCache"; vi.mock("@tauri-apps/api/core", () => ({ invoke: vi.fn(async (command: string, args?: any) => { if (command === "thumbnail_get_cached") { return null; // No cached image } if (command === "thumbnail_get_stats") { return { totalSizeBytes: 1024 * 1024, itemCount: 10, limitBytes: 1024 * 1024 * 1024, }; } if (command === "thumbnail_set_limit") { return undefined; } if (command === "thumbnail_clear_cache") { return undefined; } if (command === "thumbnail_delete_item") { return undefined; } if (command === "thumbnail_save") { return undefined; } return null; }), convertFileSrc: vi.fn((path: string) => `asset://path/${path}`), })); describe("image cache service", () => { beforeEach(() => { vi.clearAllMocks(); }); describe("cache statistics", () => { it("should get cache statistics", async () => { const stats = await getCacheStats(); expect(stats).toHaveProperty("totalSizeBytes"); expect(stats).toHaveProperty("itemCount"); expect(stats).toHaveProperty("limitBytes"); expect(typeof stats.totalSizeBytes).toBe("number"); expect(typeof stats.itemCount).toBe("number"); }); it("should set cache limit", async () => { const limit = 1024 * 1024 * 1024 * 5; // 5GB await setCacheLimit(limit); const { invoke } = await import("@tauri-apps/api/core"); const invokeSpy = vi.mocked(invoke); const setLimitCall = invokeSpy.mock.calls.find((call) => call[0] === "thumbnail_set_limit"); expect(setLimitCall).toBeDefined(); expect(setLimitCall![1]).toHaveProperty("limitBytes", limit); }); }); describe("cache clearing", () => { it("should clear all cached thumbnails", async () => { await clearCache(); const { invoke } = await import("@tauri-apps/api/core"); const invokeSpy = vi.mocked(invoke); expect(invokeSpy).toHaveBeenCalledWith("thumbnail_clear_cache"); }); it("should delete cache for specific item", async () => { await deleteItemCache("item-456"); const { invoke } = await import("@tauri-apps/api/core"); const invokeSpy = vi.mocked(invoke); const deleteCall = invokeSpy.mock.calls.find((call) => call[0] === "thumbnail_delete_item"); expect(deleteCall).toBeDefined(); expect(deleteCall![1]).toHaveProperty("itemId", "item-456"); }); }); describe("byte formatting", () => { it("should format bytes", () => { expect(formatBytes(512)).toContain("B"); expect(formatBytes(512)).not.toContain("KB"); }); it("should format kilobytes", () => { expect(formatBytes(1024)).toContain("KB"); }); it("should format megabytes", () => { expect(formatBytes(1024 * 1024)).toContain("MB"); }); it("should format gigabytes", () => { expect(formatBytes(1024 * 1024 * 1024)).toContain("GB"); }); it("should format with correct precision", () => { const result = formatBytes(1024 * 1.5); expect(result).toMatch(/\d+\.\d+ KB/); }); }); describe("unit conversion", () => { it("should convert gigabytes to bytes", () => { const bytes = gbToBytes(1); expect(bytes).toBe(1024 * 1024 * 1024); }); it("should convert bytes to gigabytes", () => { const gb = bytesToGb(1024 * 1024 * 1024); expect(gb).toBe(1); }); it("should handle fractional conversions", () => { const bytes = gbToBytes(0.5); expect(bytes).toBe(512 * 1024 * 1024); const gb = bytesToGb(512 * 1024 * 1024); expect(gb).toBe(0.5); }); }); });