import { beforeEach, describe, expect, it, vi } from "vitest"; import { PERMS } from "@/lib/permission-slugs"; import type { HousekeepingCapabilityContext } from "../../foundation/contracts"; import { loadContentInboxItems } from "./inbox-production"; import { loadContentSearchCandidates } from "./search-production"; import { loadContentWidget } from "./widgets-production"; const { run } = vi.hoisted(() => ({ run: vi.fn() })); vi.mock("./queries/content-queries", () => ({ contentQuery: { run }, })); const context = { actor: { id: 42, username: "operator", rank: 7 }, isSuperAdmin: false, has: () => true, hasAny: () => true, hasAll: () => true, } satisfies HousekeepingCapabilityContext; function capability(granted: readonly string[]): HousekeepingCapabilityContext { const permissions = new Set(granted); return { ...context, has: (slug) => permissions.has(slug), hasAny: (...slugs) => slugs.some((slug) => permissions.has(slug)), hasAll: (...slugs) => slugs.every((slug) => permissions.has(slug)), }; } function result( routeId: string, total: number, items: readonly Record[] = [], ) { return { ok: true as const, data: { kind: routeId.split(".")[1], items, total, partialDependencies: [], }, correlationId: "provider-production", }; } describe("Content production providers", () => { beforeEach(() => { vi.clearAllMocks(); run.mockImplementation(async (_context, input) => result(input.routeId, input.routeId.includes("articles") ? 7 : 3), ); }); it("returns only truthful persisted counts from editorial and localization widgets", async () => { const signal = new AbortController().signal; await expect( loadContentWidget("editorial", context, signal), ).resolves.toEqual({ articles: 7 }); await expect( loadContentWidget("localization", context, signal), ).resolves.toEqual({ stores: 3 }); }); it("loads real search candidates from bounded query routes", async () => { run.mockImplementation(async (_context, input) => result(input.routeId, 1, [ { id: "9", title: "Launch", description: "Published", href: "/ase/content/editorial/articles/9", }, ]), ); const candidates = await loadContentSearchCandidates( "articles", context, "launch", 25, ); expect(candidates).toEqual([ expect.objectContaining({ id: "content.editorial.articles:9", href: "/ase/content/editorial/articles/9", }), ]); expect(run).toHaveBeenCalledWith( context, expect.objectContaining({ list: { search: "launch", pageSize: 25, offset: 0 }, }), ); }); it("builds publication inbox items only from real query rows", async () => { run.mockImplementation(async (_context, input) => result(input.routeId, 1, [ { id: "5", title: "Release", status: "published", updatedAt: new Date().toISOString(), href: "/ase/content/editorial/articles/5", }, ]), ); const items = await loadContentInboxItems( "publication", context, new AbortController().signal, ); expect(items).toEqual([]); }); it("loads only capability-matched media counts", async () => { const result = await loadContentWidget( "media", capability([PERMS.BANNERS_VIEW]), new AbortController().signal, ); expect(result).toEqual({ banners: 3 }); expect(run).toHaveBeenCalledTimes(1); expect(run).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ routeId: "content.media.banners" }), ); }); it("does not invent a zero when a widget dependency is unavailable", async () => { run.mockResolvedValueOnce({ ok: false, error: { code: "DEPENDENCY_UNAVAILABLE", messageKey: "dependency" }, correlationId: "unavailable", }); await expect( loadContentWidget("editorial", context, new AbortController().signal), ).rejects.toThrow("Content widget query unavailable"); }); it("emits only actionable publication statuses", async () => { run.mockResolvedValueOnce( result("content.editorial.articles", 2, [ { id: "draft", title: "Draft", status: "draft", updatedAt: new Date().toISOString(), href: "/ase/content/editorial/articles/draft", }, { id: "published", title: "Published", status: "published", updatedAt: new Date().toISOString(), href: "/ase/content/editorial/articles/published", }, ]), ); const items = await loadContentInboxItems( "publication", context, new AbortController().signal, ); expect(items.map((item) => item.itemId)).toEqual(["draft"]); expect(items[0]?.state).toBe("draft"); }); });