/*
Unit tests for article covering buildArticleNode. It also guards the documented public contract and regression-sensitive edge cases.
- Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only.
- RFC-1311: Compass header sweep — declares the article suite's contract for test-file scaffold coverage.
*/
import { describe, expect, it } from "vitest";
import { buildArticleNode } from "../article.ts";
import { createJsonLdContext } from "../context.ts";
import { makePage } from "../../tests/helpers.ts";
describe("buildArticleNode", () => {
it("returns null when page has no datePublished", () => {
const page = makePage();
const ctx = createJsonLdContext(page);
expect(buildArticleNode(ctx)).toBeNull();
});
it("builds Article/BlogPosting node with datePublished", () => {
const page = makePage({ datePublished: "2024-01-15" });
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node).not.toBeNull();
expect(node!["@type"]).toEqual(["Article", "BlogPosting"]);
expect(node!.datePublished).toBe("2024-01-15");
expect(node!.dateModified).toBe("2024-01-15");
expect(node!.headline).toBe("Test Heading");
expect(node!.inLanguage).toBe("de");
expect(node!.publisher).toEqual({ "@id": ctx.ids.organization });
});
it("uses dateModified when provided", () => {
const page = makePage({ datePublished: "2024-01-15", dateModified: "2024-06-01" });
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node!.dateModified).toBe("2024-06-01");
});
it("emits author as Person when author string is present", () => {
const page = makePage({ datePublished: "2024-01-15", author: "Jane Doe" });
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node!.author).toEqual({ "@type": "Person", name: "Jane Doe" });
});
it("emits structured author from authorRecord", () => {
const page = makePage({
datePublished: "2024-01-15",
authorRecord: { name: "Jane Doe", contactUrl: "https://example.com/contact" },
});
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node!.author).toEqual({
"@type": "Person",
name: "Jane Doe",
url: "https://example.com/contact",
});
});
it("emits keywords as comma-separated string", () => {
const page = makePage({ datePublished: "2024-01-15", keywords: ["foo", "bar"] });
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node!.keywords).toBe("foo, bar");
});
it("emits image from primaryImage", () => {
const page = makePage({
datePublished: "2024-01-15",
primaryImage: { url: "https://example.com/img.jpg" },
});
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node!.image).toBe("https://example.com/img.jpg");
});
it("uses page URL as mainEntityOfPage for ratgeber depth-1", () => {
const page = makePage({
datePublished: "2024-01-15",
surfaceId: "ratgeber",
depth: 1,
url: "https://example.com/de/ratgeber/article/",
});
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node!.mainEntityOfPage).toBe("https://example.com/de/ratgeber/article/");
});
it("uses webpage @id as mainEntityOfPage for non-ratgeber pages", () => {
const page = makePage({ datePublished: "2024-01-15" });
const ctx = createJsonLdContext(page);
const node = buildArticleNode(ctx);
expect(node!.mainEntityOfPage).toEqual({ "@id": ctx.webpageId });
});
});