Close all 9 friction points from the S13 newsletter dogfood (operator elected to fix F6-F9 rather than defer): - F1: namespace all subagent_type calls in newsletter.md to linkedin-thought-leadership:<name> (4 sites + canonical note) - F2: document agent invocation form + reload requirement in CLAUDE.md + README.md (reload itself is an operator action) - F3: add edition-config / edition-delingstekst / edition-HANDOVER templates under config/ + wire into Steps 0 and 8 + footer - F4: reconcile draft path to <serie>/NN-utkast.md (series root) - F5: de-hardcode series root (explicit arg / LTL_SERIES_ROOT / default) - F6: config-derive carousel editions (remove Seres CAROUSEL set); correct samle comment - F7: build-html.mjs exits non-zero when zero HTML produced - F8: guard parseDelingstekst (graceful ENOENT) + correct Step 8 wording - F9: relocate agents/README.md -> docs/agents-capability-matrix.md Re-tested: 87/87 plugin tests pass; build-html/build-linkedin behavior re-verified live. Per-item outcomes logged in dogfood-S13-friction.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
84 lines
3.4 KiB
JavaScript
84 lines
3.4 KiB
JavaScript
// build-linkedin.test.mjs — S2: edition-config.json generalization.
|
|
// Verifies the fasit assumption (5): changing values in the config changes
|
|
// POST.html output with NO code change. Regression: a config matching the old
|
|
// hardcoded Seres values reproduces the baseline strings.
|
|
import { describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { join, dirname } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { loadEditionConfig, editionPost, samlePost } from "../build-linkedin.mjs";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const fixturesDir = join(__dirname, "fixtures");
|
|
|
|
const meta = {
|
|
title: "Testtittel",
|
|
subtitle: "Undertittel",
|
|
lesetid: "5 min",
|
|
serie: "Test",
|
|
};
|
|
const body = "## Overskrift\n\nEn paragraf med tekst.";
|
|
const share = { share: "Delingstekst", hashtags: "#test", kommentar: "Kommentar" };
|
|
|
|
describe("build-linkedin edition-config", () => {
|
|
it("loadEditionConfig reads the Seres regression fixture", () => {
|
|
const cfg = loadEditionConfig(fixturesDir);
|
|
assert.equal(cfg.calendar["01"].dag, "Tirsdag 26.05.2026");
|
|
assert.equal(
|
|
cfg.coverCredit,
|
|
"Illustrasjon generert med Google Gemini (Nano Banana Pro)"
|
|
);
|
|
assert.ok(cfg.captions["06"].startsWith("Tolv grep"));
|
|
});
|
|
|
|
it("regression: Seres config reproduces baseline strings in POST.html", () => {
|
|
const cfg = loadEditionConfig(fixturesDir);
|
|
const html = editionPost("01", meta, body, share, cfg);
|
|
assert.ok(html.includes("Tirsdag 26.05.2026"), "calendar date present");
|
|
assert.ok(html.includes("Noen lover vekst"), "caption 01 present");
|
|
assert.ok(
|
|
html.includes("Illustrasjon generert med Google Gemini"),
|
|
"cover credit present"
|
|
);
|
|
assert.ok(html.includes("OpenAI-verdsettelse"), "freshness 01 present");
|
|
});
|
|
|
|
it("changing config values changes POST.html output (no code change)", () => {
|
|
const cfg = loadEditionConfig(fixturesDir);
|
|
const html1 = editionPost("01", meta, body, share, cfg);
|
|
|
|
const cfg2 = JSON.parse(JSON.stringify(cfg));
|
|
cfg2.captions["01"] = "EN HELT ANNEN CAPTION";
|
|
cfg2.calendar["01"].dag = "Mandag 01.01.2030";
|
|
const html2 = editionPost("01", meta, body, share, cfg2);
|
|
|
|
assert.notEqual(html1, html2, "different config → different output");
|
|
assert.ok(html2.includes("EN HELT ANNEN CAPTION"), "new caption present");
|
|
assert.ok(html2.includes("Mandag 01.01.2030"), "new date present");
|
|
assert.ok(!html2.includes("Noen lover vekst"), "old caption gone");
|
|
});
|
|
|
|
it("missing config degrades gracefully to empty defaults", () => {
|
|
const cfg = loadEditionConfig(join(fixturesDir, "does-not-exist"));
|
|
assert.deepEqual(cfg, {
|
|
calendar: {},
|
|
freshness: {},
|
|
coverCredit: "",
|
|
captions: {},
|
|
carousel: [],
|
|
});
|
|
// editionPost still renders without throwing (uses "—" fallbacks)
|
|
const html = editionPost("01", meta, body, share, cfg);
|
|
assert.ok(html.includes("Del 01"), "edition heading still rendered");
|
|
});
|
|
|
|
it("samlePost renders with config calendar and degrades gracefully", () => {
|
|
const cfg = loadEditionConfig(fixturesDir);
|
|
const html = samlePost(share, cfg);
|
|
assert.ok(html.includes("Mandag 01.06.2026"), "samle calendar from config");
|
|
|
|
const empty = loadEditionConfig(join(fixturesDir, "nope"));
|
|
const htmlEmpty = samlePost(share, empty);
|
|
assert.ok(htmlEmpty.includes("Samle-post"), "renders without throwing");
|
|
});
|
|
});
|