Some checks failed
CI / typecheck + lint + boundaries + test + build (push) Has been cancelled
CI / Playwright e2e (push) Has been cancelled
CI / Storybook smoke tests + visual regression (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Coverage snapshot / snapshot (push) Has been cancelled
Release Please / release-please (push) Has been cancelled
Sentry PII guard (R31) / pii-guard (push) Has been cancelled
Extends 8111639 to cover __factories__, __seeds__, __contracts__, and
core-testing barrels.
87 lines
3.1 KiB
TypeScript
87 lines
3.1 KiB
TypeScript
import { it, expect, beforeEach, describe } from "vitest";
|
|
import { defineContractSuite } from "@repo/core-testing/contract";
|
|
import type { IHeaderRepository } from "../application/repositories/header.repository.interface";
|
|
import type { Header } from "../entities/models/header";
|
|
|
|
/**
|
|
* Known fixtures that every implementation's `buildSubject` must pre-seed.
|
|
* Exported so that test files can pass them to `MockHeaderRepository` or the
|
|
* Payload stub without duplicating definitions.
|
|
*/
|
|
export const CONTRACT_HEADER_SEED: Header = {
|
|
items: [
|
|
{ label: "Home", href: "/", external: false },
|
|
{ label: "Blog", href: "/blog", external: false },
|
|
{ label: "Docs", href: "/docs", external: true },
|
|
],
|
|
};
|
|
|
|
/**
|
|
* Contract for IHeaderRepository.
|
|
*
|
|
* Header is a singleton (Payload Global). The interface exposes only
|
|
* getHeader(). The contract verifies the shape, count, and order of items.
|
|
*/
|
|
export const headerRepositoryContract = defineContractSuite<IHeaderRepository>(
|
|
"IHeaderRepository",
|
|
({ buildSubject, getTracer }) => {
|
|
let repo: IHeaderRepository;
|
|
|
|
beforeEach(async () => {
|
|
repo = await buildSubject();
|
|
});
|
|
|
|
// --- getHeader ---
|
|
|
|
it("getHeader returns an object with an items array of the seeded length", async () => {
|
|
const header = await repo.getHeader();
|
|
expect(header).toBeDefined();
|
|
expect(header.items).toBeInstanceOf(Array);
|
|
expect(header.items).toHaveLength(3);
|
|
});
|
|
|
|
it("getHeader items appear in the seeded order with correct shape", async () => {
|
|
const header = await repo.getHeader();
|
|
expect(header.items[0]?.label).toBe("Home");
|
|
expect(header.items[0]?.href).toBe("/");
|
|
expect(header.items[0]?.external).toBe(false);
|
|
expect(header.items[1]?.label).toBe("Blog");
|
|
expect(header.items[1]?.href).toBe("/blog");
|
|
expect(header.items[1]?.external).toBe(false);
|
|
expect(header.items[2]?.label).toBe("Docs");
|
|
expect(header.items[2]?.href).toBe("/docs");
|
|
expect(header.items[2]?.external).toBe(true);
|
|
});
|
|
|
|
it("getHeader items have label, href, and external fields", async () => {
|
|
const header = await repo.getHeader();
|
|
for (const item of header.items) {
|
|
expect(typeof item.label).toBe("string");
|
|
expect(item.label.length).toBeGreaterThan(0);
|
|
expect(typeof item.href).toBe("string");
|
|
expect(item.href.length).toBeGreaterThan(0);
|
|
expect(typeof item.external).toBe("boolean");
|
|
}
|
|
});
|
|
|
|
it("getHeader logoId is string or undefined", async () => {
|
|
const header = await repo.getHeader();
|
|
expect(
|
|
header.logoId === undefined || typeof header.logoId === "string",
|
|
).toBe(true);
|
|
});
|
|
|
|
describe("span emission", () => {
|
|
it("getHeader emits header.getHeader span with op=repository", async () => {
|
|
if (!getTracer) return;
|
|
const tracer = getTracer();
|
|
tracer.reset();
|
|
await repo.getHeader();
|
|
const span = tracer.findSpan("header.getHeader");
|
|
expect(span).toBeDefined();
|
|
expect(span!.op).toBe("repository");
|
|
});
|
|
});
|
|
},
|
|
);
|