Files
stargue-publishing-engine/packages/schema/src/frontmatter.test.ts
Angelo B. J. Luidens e529651de1 Stage 1 complete: shared packages with full test coverage
- packages/schema: 15 Vitest tests (6 valid + 6 invalid frontmatter + 3 round-trip)
- packages/sanitize: fail-closed remark plugin + 12 private fixtures + 6 clean fixtures, 20 tests
- packages/observability: Pino + correlation IDs + redaction; 5 tests with 100-log validation
- packages/linkedin-client: Posts API client + token store; 10 tests; AES-256-GCM substituted for libsodium crypto_secretbox (Bun ESM bug, see docs/deferred-gates.md D-001)

50/50 tests pass across 4 packages. All Stage 1 DoDs verified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 12:50:03 -04:00

184 lines
4.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
NoteFrontmatterSchema,
PublishFrontmatterSchema,
parseFrontmatter,
} from "./frontmatter";
const baseTimestamps = {
created: "2026-04-01T10:00:00+00:00",
updated: "2026-04-26T14:00:00+00:00",
};
describe("PublishFrontmatterSchema — 6 valid cases", () => {
it("accepts a minimal published blog post", () => {
const parsed = PublishFrontmatterSchema.parse({
status: "published",
outlets: [
{ outlet: "stargue.com", status: "published", published_url: "https://stargue.com/blog/post" },
],
category: "blog",
});
expect(parsed.language).toBe("en");
expect(parsed.canonical).toBe("stargue.com");
expect(parsed.sanitize).toBe(true);
expect(parsed.version).toBe(1);
});
it("accepts a draft with no outlets yet", () => {
const parsed = PublishFrontmatterSchema.parse({
status: "draft",
outlets: [],
category: "research",
});
expect(parsed.scheduled).toBeNull();
});
it("accepts a queued post with future scheduled time", () => {
const parsed = PublishFrontmatterSchema.parse({
status: "queued",
outlets: [
{ outlet: "linkedin.member", status: "queued", published_url: null },
],
scheduled: "2026-05-01T08:30:00-04:00",
category: "blog",
});
expect(parsed.scheduled).toBe("2026-05-01T08:30:00-04:00");
});
it("accepts multi-outlet partial publish", () => {
const parsed = PublishFrontmatterSchema.parse({
status: "partial",
outlets: [
{ outlet: "stargue.com", status: "published", published_url: "https://stargue.com/x" },
{ outlet: "linkedin.org", status: "failed", published_url: null },
],
category: "case-study",
slug: "x",
});
expect(parsed.outlets).toHaveLength(2);
});
it("accepts non-English language with explicit canonical", () => {
const parsed = PublishFrontmatterSchema.parse({
status: "published",
language: "pap",
canonical: "stargue.com",
outlets: [
{ outlet: "stargue.com", status: "published", published_url: "https://stargue.com/pap/x" },
],
category: "blog",
});
expect(parsed.language).toBe("pap");
});
it("accepts sanitize=false explicit override", () => {
const parsed = PublishFrontmatterSchema.parse({
status: "ready",
outlets: [],
category: "white-paper",
sanitize: false,
version: 3,
});
expect(parsed.sanitize).toBe(false);
expect(parsed.version).toBe(3);
});
});
describe("PublishFrontmatterSchema — 6 invalid cases", () => {
it("rejects unknown status", () => {
expect(() =>
PublishFrontmatterSchema.parse({
status: "drafted",
outlets: [],
category: "blog",
}),
).toThrow();
});
it("rejects unknown outlet", () => {
expect(() =>
PublishFrontmatterSchema.parse({
status: "published",
outlets: [
{ outlet: "facebook", status: "published", published_url: "https://fb.com/x" },
],
category: "blog",
}),
).toThrow();
});
it("rejects unknown language", () => {
expect(() =>
PublishFrontmatterSchema.parse({
status: "draft",
language: "fr",
outlets: [],
category: "blog",
}),
).toThrow();
});
it("rejects malformed scheduled timestamp (no offset)", () => {
expect(() =>
PublishFrontmatterSchema.parse({
status: "queued",
outlets: [],
scheduled: "2026-05-01T08:30:00",
category: "blog",
}),
).toThrow();
});
it("rejects negative version", () => {
expect(() =>
PublishFrontmatterSchema.parse({
status: "draft",
outlets: [],
category: "blog",
version: -1,
}),
).toThrow();
});
it("rejects unknown category", () => {
expect(() =>
PublishFrontmatterSchema.parse({
status: "draft",
outlets: [],
category: "newsletter",
}),
).toThrow();
});
});
describe("NoteFrontmatterSchema — round-trip", () => {
it("round-trips a full vault note frontmatter", () => {
const input = {
...baseTimestamps,
tags: ["MOC"],
publish: {
status: "published",
outlets: [
{ outlet: "stargue.com", status: "published", published_url: "https://stargue.com/x" },
],
category: "blog",
},
};
const parsed = NoteFrontmatterSchema.parse(input);
expect(parsed.publish?.status).toBe("published");
expect(parsed.publish?.canonical).toBe("stargue.com");
});
it("accepts a note without publish block (private vault notes)", () => {
const parsed = parseFrontmatter({ ...baseTimestamps, tags: null });
expect(parsed.publish).toBeUndefined();
});
it("rejects a note missing required timestamps", () => {
expect(() =>
NoteFrontmatterSchema.parse({ tags: [] }),
).toThrow();
});
});