Files
agentic-dev/packages/media/src/__contracts__/media-repository.contract.ts

97 lines
3.5 KiB
TypeScript

import { it, expect, beforeEach, describe } from "vitest";
import { defineContractSuite } from "@repo/core-testing/contract";
import type { IMediaRepository } from "../application/repositories/media.repository.interface.js";
import { mediaFactory } from "../__factories__/media.factory.js";
export const mediaRepositoryContract =
defineContractSuite<IMediaRepository>(
"IMediaRepository",
({ buildSubject, getTracer }) => {
let repo: IMediaRepository;
beforeEach(async () => {
mediaFactory.reset();
repo = await buildSubject();
});
// --- getMedia ---
it("getMedia returns undefined for a missing id", async () => {
const result = await repo.getMedia("does-not-exist");
expect(result).toBeUndefined();
});
// --- listMedia ---
it("listMedia returns empty array when no media exists", async () => {
const result = await repo.listMedia();
expect(result).toHaveLength(0);
});
// --- deleteMedia ---
it("deleteMedia removes the item so getMedia returns undefined", async () => {
const seed = mediaFactory.build({ id: "contract-1" });
// @ts-expect-error _store is a test helper on MockMediaRepository
if (typeof repo._store === "function") {
// @ts-expect-error _store is a test helper
await repo._store(seed);
}
await repo.deleteMedia("contract-1");
const result = await repo.getMedia("contract-1");
expect(result).toBeUndefined();
});
it("listMedia with limit returns at most limit items", async () => {
// Only verifiable on mock; for real impl this checks the interface
const result = await repo.listMedia({ limit: 0 });
expect(Array.isArray(result)).toBe(true);
});
it("listMedia with offset skips items", async () => {
const result = await repo.listMedia({ offset: 100 });
expect(Array.isArray(result)).toBe(true);
});
it("getMedia returns undefined for empty string id", async () => {
const result = await repo.getMedia("");
expect(result).toBeUndefined();
});
describe("span emission (R50)", () => {
it("getMedia emits media.getMedia span with id attribute", async () => {
if (!getTracer) return;
const tracer = getTracer();
tracer.reset();
await repo.getMedia("nonexistent");
const span = tracer.findSpan("media.getMedia");
expect(span).toBeDefined();
expect(span!.op).toBe("repository");
expect(span!.attributes.id).toBe("nonexistent");
});
it("listMedia emits media.listMedia span with op=repository", async () => {
if (!getTracer) return;
const tracer = getTracer();
tracer.reset();
await repo.listMedia({ limit: 10 });
const span = tracer.findSpan("media.listMedia");
expect(span).toBeDefined();
expect(span!.op).toBe("repository");
expect(span!.attributes.limit).toBe(10);
});
it("deleteMedia emits media.deleteMedia span with id attribute", async () => {
if (!getTracer) return;
const tracer = getTracer();
tracer.reset();
await repo.deleteMedia("nonexistent");
const span = tracer.findSpan("media.deleteMedia");
expect(span).toBeDefined();
expect(span!.op).toBe("repository");
expect(span!.attributes.id).toBe("nonexistent");
});
});
},
);