import { describe, expect, it, vi, beforeEach } from "vitest"; import { RecordingTracer } from "@repo/core-testing/instrumentation"; import { ArticlesRepository } from "@/infrastructure/repositories/articles.repository"; import { articlesRepositoryContract } from "@/__contracts__/articles-repository.contract"; import { stubPayloadConfig } from "@repo/core-testing/payload/stub-config"; // --------------------------------------------------------------------------- // In-memory Payload stub used by both the contract suite and impl-specific tests // --------------------------------------------------------------------------- function buildPayloadStub() { const store = new Map>(); return { create: vi.fn( async ({ data, }: { collection: string; data: Record; overrideAccess?: boolean; }) => { // Payload assigns an id; here we require the data to carry one // (the repository passes `id` via the mapped domain object implicitly // through the Article — we expose the mapped doc back from createArticle). // The stub returns the data as-is so the mapDoc function can work. const doc = { id: `stub-${store.size + 1}`, ...data }; store.set(String(doc.id), doc); return doc; }, ), find: vi.fn( async ({ where, limit, }: { collection: string; where?: { slug?: { equals: string }; status?: { equals: string }; author?: { equals: string }; }; limit?: number; page?: number; overrideAccess?: boolean; }) => { let docs = Array.from(store.values()); if (where?.slug) { docs = docs.filter((d) => d.slug === where.slug?.equals); } if (where?.status) { docs = docs.filter((d) => d.status === where.status?.equals); } if (where?.author) { docs = docs.filter((d) => d.author === where.author?.equals); } if (limit !== undefined) { docs = docs.slice(0, limit); } return { docs }; }, ), findByID: vi.fn( async ({ id }: { collection: string; id: string; overrideAccess?: boolean }) => { const doc = store.get(String(id)); if (!doc) { const err = Object.assign(new Error(`Not found: ${id}`), { status: 404 }); throw err; } return doc; }, ), update: vi.fn( async ({ id, data, }: { collection: string; id: string; data: Record; overrideAccess?: boolean; }) => { const existing = store.get(String(id)); if (!existing) { const err = Object.assign(new Error(`Not found: ${id}`), { status: 404 }); throw err; } const updated = { ...existing, ...data }; store.set(String(id), updated); return updated; }, ), }; } vi.mock("payload", () => ({ getPayload: vi.fn(), })); // --------------------------------------------------------------------------- // Contract suite // --------------------------------------------------------------------------- describe("ArticlesRepository", () => { describe("contract", () => { const tracer = new RecordingTracer(); articlesRepositoryContract.run( async () => { const stub = buildPayloadStub(); const { getPayload } = await import("payload"); (getPayload as ReturnType).mockResolvedValue(stub); return new ArticlesRepository(stubPayloadConfig, tracer); }, { tracer: () => tracer }, ); }); // ------------------------------------------------------------------------- // Impl-specific tests: Payload doc → domain mapping // ------------------------------------------------------------------------- describe("Payload doc → domain mapping", () => { beforeEach(() => { vi.clearAllMocks(); }); it("maps a Payload doc to a domain Article on getArticleBySlug", async () => { const { getPayload } = await import("payload"); const findMock = vi.fn().mockResolvedValue({ docs: [ { id: "p-123", title: "Hello", slug: "hello", content: { type: "doc", children: [] }, status: "published", author: "u1", createdAt: "2026-05-04T12:00:00.000Z", updatedAt: "2026-05-04T12:00:00.000Z", }, ], }); (getPayload as ReturnType).mockResolvedValue({ find: findMock, }); const repo = new ArticlesRepository(stubPayloadConfig); const result = await repo.getArticleBySlug("hello"); expect(findMock).toHaveBeenCalledWith({ collection: "articles", where: { slug: { equals: "hello" } }, limit: 1, overrideAccess: true, }); expect(result?.id).toBe("p-123"); expect(result?.slug).toBe("hello"); expect(result?.status).toBe("published"); expect(result?.authorId).toBe("u1"); expect(result?.createdAt).toBeInstanceOf(Date); }); it("returns undefined when slug is not found", async () => { const { getPayload } = await import("payload"); (getPayload as ReturnType).mockResolvedValue({ find: vi.fn().mockResolvedValue({ docs: [] }), }); const repo = new ArticlesRepository(stubPayloadConfig); const result = await repo.getArticleBySlug("missing"); expect(result).toBeUndefined(); }); }); });