154 lines
4.6 KiB
JavaScript
154 lines
4.6 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { resolveLinkedArticles, validateLinkedArticles } from "../src/_utils/linked-articles.js";
|
|
import { filters } from "../src/_filters/index.js";
|
|
import configureEleventy from "../eleventy.config.js";
|
|
|
|
test("Linked articles: accepts an article's list when every name identifies another post", () => {
|
|
assert.doesNotThrow(() => {
|
|
validateLinkedArticles([
|
|
{
|
|
inputPath: "src/posts/2026-10-06-terminal-preview-demo.md",
|
|
data: {
|
|
title: "Terminal Preview Demo",
|
|
linkedArticles: ["Markdown Preview Demo"]
|
|
}
|
|
},
|
|
{
|
|
inputPath: "src/posts/2026-10-05-markdown-preview-demo.md",
|
|
data: { title: "Markdown Preview Demo" }
|
|
}
|
|
]);
|
|
});
|
|
});
|
|
|
|
test("Linked articles: rejects a non-list frontmatter value", () => {
|
|
assert.throws(
|
|
() => {
|
|
validateLinkedArticles([
|
|
{
|
|
inputPath: "src/posts/2026-10-06-terminal-preview-demo.md",
|
|
data: {
|
|
title: "Terminal Preview Demo",
|
|
linkedArticles: "Markdown Preview Demo"
|
|
}
|
|
},
|
|
{
|
|
inputPath: "src/posts/2026-10-05-markdown-preview-demo.md",
|
|
data: { title: "Markdown Preview Demo" }
|
|
}
|
|
]);
|
|
},
|
|
/must define 'linkedArticles' as a YAML list/
|
|
);
|
|
});
|
|
|
|
test("Linked articles: rejects empty and unknown article names", () => {
|
|
const posts = [
|
|
{
|
|
inputPath: "src/posts/2026-10-06-terminal-preview-demo.md",
|
|
data: { title: "Terminal Preview Demo", linkedArticles: [""] }
|
|
},
|
|
{
|
|
inputPath: "src/posts/2026-10-05-markdown-preview-demo.md",
|
|
data: { title: "Markdown Preview Demo" }
|
|
}
|
|
];
|
|
|
|
assert.throws(() => validateLinkedArticles(posts), /non-empty article titles/);
|
|
|
|
posts[0].data.linkedArticles = ["Missing Dispatch"];
|
|
assert.throws(() => validateLinkedArticles(posts), /links to unknown article 'Missing Dispatch'/);
|
|
});
|
|
|
|
test("Linked articles: rejects self-references and duplicate navigation targets", () => {
|
|
const posts = [
|
|
{
|
|
inputPath: "src/posts/2026-10-06-terminal-preview-demo.md",
|
|
data: {
|
|
title: "Terminal Preview Demo",
|
|
linkedArticles: ["Terminal Preview Demo"]
|
|
}
|
|
},
|
|
{
|
|
inputPath: "src/posts/2026-10-05-markdown-preview-demo.md",
|
|
data: { title: "Markdown Preview Demo" }
|
|
}
|
|
];
|
|
|
|
assert.throws(() => validateLinkedArticles(posts), /cannot link to itself/);
|
|
|
|
posts[0].data.linkedArticles = ["Markdown Preview Demo", "Markdown Preview Demo"];
|
|
assert.throws(() => validateLinkedArticles(posts), /cannot contain duplicate article titles/);
|
|
});
|
|
|
|
test("Linked articles: the Eleventy posts collection rejects invalid frontmatter", () => {
|
|
const collections = new Map();
|
|
configureEleventy({
|
|
setUseGitIgnore() {},
|
|
addPassthroughCopy() {},
|
|
addPlugin() {},
|
|
setLibrary() {},
|
|
addFilter() {},
|
|
addCollection(name, callback) {
|
|
collections.set(name, callback);
|
|
},
|
|
setServerOptions() {}
|
|
});
|
|
|
|
assert.throws(
|
|
() => {
|
|
collections.get("posts")({
|
|
getFilteredByGlob() {
|
|
return [
|
|
{
|
|
inputPath: "src/posts/2026-10-06-terminal-preview-demo.md",
|
|
data: {
|
|
title: "Terminal Preview Demo",
|
|
linkedArticles: ["Missing Dispatch"]
|
|
}
|
|
}
|
|
];
|
|
}
|
|
});
|
|
},
|
|
/links to unknown article 'Missing Dispatch'/
|
|
);
|
|
});
|
|
|
|
test("Linked articles: resolves named posts in the frontmatter order for navigation", () => {
|
|
const posts = [
|
|
{
|
|
url: "/dispatches/terminal-preview-demo/",
|
|
data: { title: "Terminal Preview Demo" }
|
|
},
|
|
{
|
|
url: "/dispatches/markdown-preview-demo/",
|
|
data: { title: "Markdown Preview Demo" }
|
|
}
|
|
];
|
|
|
|
assert.deepEqual(
|
|
resolveLinkedArticles(posts, ["Markdown Preview Demo", "Terminal Preview Demo"]),
|
|
[posts[1], posts[0]]
|
|
);
|
|
});
|
|
|
|
test("Linked articles: exposes navigation resolution to Nunjucks", () => {
|
|
assert.strictEqual(filters.resolveLinkedArticles, resolveLinkedArticles);
|
|
});
|
|
|
|
test("Linked articles: post layout renders Other Articles at the top of dispatch telemetry", () => {
|
|
const postLayout = fs.readFileSync(
|
|
path.resolve("src/_includes/layouts/post.njk"),
|
|
"utf-8"
|
|
);
|
|
|
|
assert.match(
|
|
postLayout,
|
|
/{% set linkedPosts = collections\.posts \| resolveLinkedArticles\(linkedArticles\) %}[\s\S]*?<div[^>]+class="sidebar-heading">OTHER ARTICLES<\/div>[\s\S]*?<nav[^>]+aria-label="Other Articles">[\s\S]*?href="{{ linkedPost\.url }}"/
|
|
);
|
|
});
|