import { describe, expect, it, vi } from "vitest"; const drizzleMocks = vi.hoisted(() => ({ eq: vi.fn((column: unknown, value: unknown) => ({ column, value })), })); vi.mock("drizzle-orm", async (importOriginal) => ({ ...(await importOriginal()), eq: drizzleMocks.eq, })); import { HousekeepingUserPreferences } from "@/lib/db"; import { createDrizzleHousekeepingPreferencesStorage } from "@/lib/housekeeping-preferences-repository"; import { createHousekeepingPreferencesRepository, type HousekeepingPreferencesStorage, } from "./repository"; import { defaultHousekeepingPreferences } from "./schema"; describe("housekeeping preferences repository", () => { it("returns a fresh default when no row exists", async () => { const storage: HousekeepingPreferencesStorage = { findByUserId: vi.fn().mockResolvedValue(null), upsert: vi.fn(), }; const repository = createHousekeepingPreferencesRepository(storage); expect(await repository.read(42)).toEqual(defaultHousekeepingPreferences()); expect(storage.findByUserId).toHaveBeenCalledWith(42); }); it("reads validated JSON and writes the schema-versioned payload through the injected adapter", async () => { const value = { ...defaultHousekeepingPreferences(), pinnedRouteIds: ["people.users"], }; const storage: HousekeepingPreferencesStorage = { findByUserId: vi.fn().mockResolvedValue({ schemaVersion: 1, payload: JSON.stringify(value), }), upsert: vi.fn(), }; const repository = createHousekeepingPreferencesRepository(storage); expect(await repository.read(42)).toEqual(value); await repository.upsert(42, value); expect(storage.upsert).toHaveBeenCalledWith({ userId: 42, schemaVersion: 1, payload: JSON.stringify(value), }); }); it("returns a fresh default for malformed or incompatible stored values", async () => { const storage: HousekeepingPreferencesStorage = { findByUserId: vi .fn() .mockResolvedValueOnce({ schemaVersion: 1, payload: "{broken" }) .mockResolvedValueOnce({ schemaVersion: 2, payload: "{}" }) .mockResolvedValueOnce({ schemaVersion: 1, payload: JSON.stringify({ schemaVersion: 1 }), }), upsert: vi.fn(), }; const repository = createHousekeepingPreferencesRepository(storage); await expect(repository.read(42)).resolves.toEqual( defaultHousekeepingPreferences(), ); await expect(repository.read(42)).resolves.toEqual( defaultHousekeepingPreferences(), ); await expect(repository.read(42)).resolves.toEqual( defaultHousekeepingPreferences(), ); }); it("preserves genuine storage failures instead of treating them as corrupt preferences", async () => { const storage: HousekeepingPreferencesStorage = { findByUserId: vi .fn() .mockRejectedValue(new Error("database unavailable")), upsert: vi.fn(), }; await expect( createHousekeepingPreferencesRepository(storage).read(42), ).rejects.toThrow("database unavailable"); }); it("uses the preferences table and user ID for the typed Drizzle read and upsert", async () => { const limit = vi.fn().mockResolvedValue([]); const where = vi.fn().mockReturnValue({ limit }); const from = vi.fn().mockReturnValue({ where }); const select = vi.fn().mockReturnValue({ from }); const onDuplicateKeyUpdate = vi.fn().mockResolvedValue(undefined); const values = vi.fn().mockReturnValue({ onDuplicateKeyUpdate }); const insert = vi.fn().mockReturnValue({ values }); const storage = createDrizzleHousekeepingPreferencesStorage({ select, insert, } as never); const value = defaultHousekeepingPreferences(); await storage.findByUserId(42); await storage.upsert({ userId: 42, schemaVersion: 1, payload: JSON.stringify(value), }); expect(select).toHaveBeenCalledWith({ schemaVersion: HousekeepingUserPreferences.schemaVersion, payload: HousekeepingUserPreferences.payload, }); expect(from).toHaveBeenCalledWith(HousekeepingUserPreferences); expect(drizzleMocks.eq).toHaveBeenCalledWith( HousekeepingUserPreferences.userId, 42, ); expect(where).toHaveBeenCalledWith({ column: HousekeepingUserPreferences.userId, value: 42, }); expect(values).toHaveBeenCalledWith({ userId: 42, schemaVersion: 1, payload: JSON.stringify(value), }); expect(onDuplicateKeyUpdate).toHaveBeenCalledWith({ set: expect.objectContaining({ schemaVersion: 1, payload: JSON.stringify(value), updatedAt: expect.any(Date), }), }); }); });