import { beforeEach, describe, expect, it, vi } from "vitest"; const findMany = vi.hoisted(() => vi.fn()); vi.mock("@/lib/prisma", () => ({ prisma: { websiteWordfilter: { findMany } }, })); vi.mock("@/env", () => ({ env: { OPENAI_API_KEY: undefined, }, })); import { isAllowed, moderateOrThrow, reloadWordFilter } from "./moderation"; beforeEach(() => { findMany.mockReset(); reloadWordFilter(); }); describe("moderation", () => { it("allows clean text", async () => { findMany.mockResolvedValue([{ word: "badword" }]); const result = await isAllowed("hello world"); expect(result).toEqual({ ok: true }); }); it("blocks text containing a filtered word", async () => { findMany.mockResolvedValue([{ word: "badword" }]); const result = await isAllowed("this contains badword here"); expect(result).toEqual({ ok: false, reason: 'Blocked by word filter: "badword"', }); }); it("allows empty text", async () => { const result = await isAllowed(""); expect(result).toEqual({ ok: true }); }); it("caches the word list and respects TTL", async () => { findMany.mockResolvedValue([{ word: "first" }]); await isAllowed("test"); await isAllowed("test"); expect(findMany).toHaveBeenCalledTimes(1); }); it("moderateOrThrow throws on blocked content", async () => { findMany.mockResolvedValue([{ word: "bad" }]); await expect(moderateOrThrow("this is bad")).rejects.toThrow( "Blocked by word filter", ); }); it("moderateOrThrow resolves on clean content", async () => { findMany.mockResolvedValue([{ word: "bad" }]); await expect(moderateOrThrow("clean text")).resolves.toBeUndefined(); }); });