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>
This commit is contained in:
183
packages/schema/src/frontmatter.test.ts
Normal file
183
packages/schema/src/frontmatter.test.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user