import { describe, expect, it } from "vitest"; import { countMediaUsageReferences, createMediaAsset, deleteEntityMediaUsages, getAdminMediaAssets, getMediaAssetById, getMediaOptions, getPortfolioMediaBindings, replaceEntityMediaUsages, } from "@/lib/media"; import { db } from "@/lib/db"; import { mediaUsage } from "@/lib/db/schema"; import { createMediaAsset as seedAsset } from "@/tests/helpers/factories"; describe("createMediaAsset / getMediaAssetById", () => { it("creates and reads back an asset with usages", async () => { const created = await createMediaAsset({ source: "EXTERNAL", kind: "IMAGE", url: "https://cdn/x.png", fileName: "x.png", label: "X", }); const found = await getMediaAssetById(created.id); expect(found?.url).toBe("https://cdn/x.png"); expect(found?.usages).toEqual([]); }); it("returns null for a missing asset", async () => { expect(await getMediaAssetById("nope")).toBeNull(); }); }); describe("getMediaOptions", () => { it("filters by kind", async () => { await seedAsset({ kind: "IMAGE" }); await seedAsset({ kind: "DOCUMENT" }); const images = await getMediaOptions({ kind: "IMAGE" }); expect(images.every((a) => a.kind === "IMAGE")).toBe(true); const all = await getMediaOptions(); expect(all.length).toBe(2); }); }); describe("getAdminMediaAssets", () => { it("returns newest first with usage details", async () => { const a = await seedAsset(); await createMediaUsageFor(a.id); const list = await getAdminMediaAssets(); expect(list.length).toBe(1); expect(list[0].usages.length).toBe(1); }); }); describe("replaceEntityMediaUsages", () => { it("replaces existing usages transactionally", async () => { const a1 = await seedAsset(); const a2 = await seedAsset(); await replaceEntityMediaUsages({ entityType: "portfolio-project", entityId: "p1", usages: [{ assetId: a1.id, usageType: "PORTFOLIO_COVER", fieldKey: "cover" }], }); expect(await countMediaUsageReferences(a1.id)).toBe(1); await replaceEntityMediaUsages({ entityType: "portfolio-project", entityId: "p1", usages: [{ assetId: a2.id, usageType: "PORTFOLIO_COVER", fieldKey: "cover" }], }); expect(await countMediaUsageReferences(a1.id)).toBe(0); expect(await countMediaUsageReferences(a2.id)).toBe(1); }); it("clears usages when given an empty list", async () => { const a1 = await seedAsset(); await replaceEntityMediaUsages({ entityType: "portfolio-project", entityId: "p2", usages: [{ assetId: a1.id, usageType: "PORTFOLIO_ASSET", fieldKey: "a" }], }); await replaceEntityMediaUsages({ entityType: "portfolio-project", entityId: "p2", usages: [] }); expect(await countMediaUsageReferences(a1.id)).toBe(0); }); }); describe("deleteEntityMediaUsages", () => { it("removes only the target entity's usages", async () => { const a1 = await seedAsset(); await replaceEntityMediaUsages({ entityType: "portfolio-project", entityId: "keep", usages: [{ assetId: a1.id, usageType: "PORTFOLIO_ASSET", fieldKey: "a" }], }); await replaceEntityMediaUsages({ entityType: "portfolio-project", entityId: "drop", usages: [{ assetId: a1.id, usageType: "PORTFOLIO_ASSET", fieldKey: "b" }], }); await deleteEntityMediaUsages("portfolio-project", "drop"); expect(await countMediaUsageReferences(a1.id)).toBe(1); }); }); describe("getPortfolioMediaBindings", () => { it("routes usages into cover / section / asset buckets", async () => { const cover = await seedAsset(); const section = await seedAsset(); const asset = await seedAsset(); await db.insert(mediaUsage).values([ { assetId: cover.id, usageType: "PORTFOLIO_COVER", entityType: "portfolio-project", entityId: "proj", fieldKey: "cover" }, { assetId: section.id, usageType: "PORTFOLIO_SECTION", entityType: "portfolio-project", entityId: "proj", fieldKey: "sec_1" }, { assetId: asset.id, usageType: "PORTFOLIO_ASSET", entityType: "portfolio-project", entityId: "proj", fieldKey: "ast_1" }, ]); const bindings = await getPortfolioMediaBindings("proj"); expect(bindings.coverAssetId).toBe(cover.id); expect(bindings.sectionAssetIds.sec_1).toBe(section.id); expect(bindings.assetIds.ast_1).toBe(asset.id); }); it("returns empty bindings for an unknown project", async () => { const bindings = await getPortfolioMediaBindings("missing"); expect(bindings).toEqual({ coverAssetId: null, sectionAssetIds: {}, assetIds: {} }); }); }); async function createMediaUsageFor(assetId: string) { await db.insert(mediaUsage).values({ assetId, usageType: "GENERIC", entityType: "e", entityId: "1", fieldKey: "f" }); }