Files
sass-mohfarawati/tests/integration/portfolio.test.ts
T
MOH 0a5f77d8de REFACTORED - migrate the data layer from Prisma to Drizzle (unify the stack)
- Add lib/db (Drizzle schema: 7 tables + 6 enums + relations, postgres.js client),
  drizzle.config.ts, lib/db/enums.ts (Prisma-compatible enum objects)
- Rewrite all 14 app consumers + 4 admin components to Drizzle
- Move the test DB layer to Drizzle + in-process PGlite; convert all 8 integration
  test files + factories (371 tests green)
- Remove Prisma: deps, prisma/ schema+migrations, lib/prisma.ts, Dockerfile prisma
  generate; wire db:generate/migrate/push/studio to drizzle-kit; update Makefile
- Preserve the old seed as scripts/legacy-prisma-seed.cjs (needs a Drizzle rewrite)
2026-08-07 14:18:41 +02:00

143 lines
5.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
getActivePortfolioCategories,
getActivePortfolioCategoryBySlug,
getAdminPortfolioCategories,
getAdminPortfolioProjectById,
getAdminPortfolioProjects,
getPublishedPortfolioProjectBySlug,
getPublishedPortfolioProjects,
} from "@/lib/portfolio";
import { eq } from "drizzle-orm";
import { db } from "@/lib/db";
import { category, mediaUsage, portfolioAsset, portfolioProject, portfolioSection } from "@/lib/db/schema";
import {
createAsset,
createCategory,
createMediaAsset,
createProject,
createSection,
} from "@/tests/helpers/factories";
describe("categories", () => {
it("lists admin categories with project counts, ordered", async () => {
const a = await createCategory({ slug: "a", sortOrder: 2 });
await createCategory({ slug: "b", sortOrder: 1 });
await createProject({ categoryId: a.id });
const categories = await getAdminPortfolioCategories();
expect(categories.map((c) => c.slug)).toEqual(["b", "a"]); // sortOrder asc
expect(categories.find((c) => c.slug === "a")?.projectCount).toBe(1);
expect(categories.find((c) => c.slug === "b")?.projectCount).toBe(0);
});
it("returns only active categories publicly", async () => {
await createCategory({ slug: "on", isActive: true });
await createCategory({ slug: "off", isActive: false });
const active = await getActivePortfolioCategories();
expect(active.map((c) => c.slug)).toEqual(["on"]);
});
it("finds an active category by slug and ignores inactive ones", async () => {
await createCategory({ slug: "visible", isActive: true });
await createCategory({ slug: "hidden", isActive: false });
expect((await getActivePortfolioCategoryBySlug("visible"))?.slug).toBe("visible");
expect(await getActivePortfolioCategoryBySlug("hidden")).toBeNull();
});
});
describe("admin projects", () => {
it("filters by status and category", async () => {
const cat = await createCategory();
await createProject({ categoryId: cat.id, slug: "pub", isPublished: true });
await createProject({ categoryId: cat.id, slug: "draft", isPublished: false });
const published = await getAdminPortfolioProjects({ status: "published" });
expect(published.map((p) => p.slug)).toEqual(["pub"]);
const drafts = await getAdminPortfolioProjects({ status: "draft" });
expect(drafts.map((p) => p.slug)).toEqual(["draft"]);
const byCategory = await getAdminPortfolioProjects({ categoryId: cat.id });
expect(byCategory.length).toBe(2);
});
it("maps localized content and nested sections/assets", async () => {
const project = await createProject({ slug: "mapped" });
await createSection(project.id, { titleEn: "Intro" });
await createAsset(project.id, { altEn: "Cover" });
const detail = await getAdminPortfolioProjectById(project.id);
expect(detail?.title.en).toBe("Title");
expect(detail?.sections[0].title.en).toBe("Intro");
expect(detail?.assets[0].alt.en).toBe("Cover");
});
it("attaches media bindings to a project fetched by id", async () => {
const project = await createProject();
const cover = await createMediaAsset();
await db.insert(mediaUsage).values({
assetId: cover.id,
usageType: "PORTFOLIO_COVER",
entityType: "portfolio-project",
entityId: project.id,
fieldKey: "cover",
});
const detail = await getAdminPortfolioProjectById(project.id);
expect(detail?.coverMediaAssetId).toBe(cover.id);
});
it("returns null for a missing project id", async () => {
expect(await getAdminPortfolioProjectById("missing")).toBeNull();
});
});
describe("published projects", () => {
it("returns only published projects in active categories", async () => {
const activeCat = await createCategory({ isActive: true });
const inactiveCat = await createCategory({ isActive: false });
await createProject({ categoryId: activeCat.id, slug: "shown", isPublished: true });
await createProject({ categoryId: activeCat.id, slug: "hidden-draft", isPublished: false });
await createProject({ categoryId: inactiveCat.id, slug: "hidden-cat", isPublished: true });
const projects = await getPublishedPortfolioProjects();
expect(projects.map((p) => p.slug)).toEqual(["shown"]);
});
it("filters published projects by category slug", async () => {
const catA = await createCategory({ slug: "cat-a", isActive: true });
const catB = await createCategory({ slug: "cat-b", isActive: true });
await createProject({ categoryId: catA.id, slug: "in-a", isPublished: true });
await createProject({ categoryId: catB.id, slug: "in-b", isPublished: true });
const projects = await getPublishedPortfolioProjects({ categorySlug: "cat-a" });
expect(projects.map((p) => p.slug)).toEqual(["in-a"]);
});
it("finds a published project by slug and hides drafts", async () => {
await createProject({ slug: "live", isPublished: true });
await createProject({ slug: "wip", isPublished: false });
expect((await getPublishedPortfolioProjectBySlug("live"))?.slug).toBe("live");
expect(await getPublishedPortfolioProjectBySlug("wip")).toBeNull();
});
});
describe("referential integrity", () => {
it("restricts deleting a category that still has projects", async () => {
const cat = await createCategory();
await createProject({ categoryId: cat.id });
await expect(db.delete(category).where(eq(category.id, cat.id))).rejects.toThrow();
});
it("cascades section and asset deletion when a project is removed", async () => {
const project = await createProject();
await createSection(project.id);
await createAsset(project.id);
await db.delete(portfolioProject).where(eq(portfolioProject.id, project.id));
expect(await db.$count(portfolioSection)).toBe(0);
expect(await db.$count(portfolioAsset)).toBe(0);
});
});