Files
fusion/scripts/__tests__/plugin-authoring-docs.test.mjs
Fusion e7884370f2 fix(FN-3610): isolate test home for changed-package test runs
- Create a disposable HOME/USERPROFILE env for scripts/test-changed.mjs execution
- Run isolation guard checks with the same isolated env, including cache-hit no-op paths
- Clean up temp HOME after test execution to avoid residue
- Update test coverage and contributing docs for the shared isolation behavior

Fusion-Task-Id: FN-3610
2026-05-06 18:57:37 -07:00

88 lines
2.8 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const docPath = path.resolve(__dirname, "../../docs/PLUGIN_AUTHORING.md");
const doc = readFileSync(docPath, "utf8");
const expectedSections = [
"Getting Started",
"Plugin Manifest Reference",
"Plugin Settings Schema",
"Available Hooks and Signatures",
"Registering Tools",
"Registering Routes",
"Registering UI Slots",
"Registering Top-Level Dashboard Views",
"Registering Agent Runtimes",
"Plugin Context API Reference",
"Plugin Lifecycle States",
"Testing Plugins",
"Publishing Plugins",
"Example Plugins",
"Registering Skills",
"Registering Workflow Steps",
"Contributing Prompt Modifications",
"Plugin Binary Setup Hooks",
];
function slugifyHeading(text) {
return text
.trim()
.toLowerCase()
.replace(/[^a-z0-9\s-]/g, "")
.replace(/\s+/g, "-");
}
test("PLUGIN_AUTHORING headings are sequentially numbered 1..18 with expected titles", () => {
const headingMatches = [...doc.matchAll(/^##\s+(\d+)\.\s+(.+)$/gm)];
const numbered = headingMatches.map((m) => ({ number: Number(m[1]), title: m[2].trim() }));
assert.equal(numbered.length, expectedSections.length);
for (let i = 0; i < expectedSections.length; i += 1) {
assert.equal(numbered[i].number, i + 1);
assert.equal(numbered[i].title, expectedSections[i]);
}
});
test("PLUGIN_AUTHORING TOC includes top-level dashboard views and anchors align to headings", () => {
const tocMatch = doc.match(/## Table of Contents\n\n([\s\S]*?)\n---/);
assert.ok(tocMatch, "Table of Contents block should exist");
const tocLines = tocMatch[1]
.split("\n")
.map((line) => line.trim())
.filter(Boolean);
const tocEntries = tocLines.map((line) => {
const m = line.match(/^(\d+)\.\s+\[(.+)\]\(#(.+)\)$/);
assert.ok(m, `Invalid TOC line: ${line}`);
return {
number: Number(m[1]),
title: m[2],
anchor: m[3],
};
});
assert.equal(tocEntries.length, expectedSections.length);
for (let i = 0; i < expectedSections.length; i += 1) {
const sectionNumber = i + 1;
const expectedTitle = expectedSections[i];
const expectedAnchor = slugifyHeading(`${sectionNumber}. ${expectedTitle}`);
assert.equal(tocEntries[i].number, sectionNumber);
assert.equal(tocEntries[i].title, expectedTitle);
assert.equal(tocEntries[i].anchor, expectedAnchor);
}
const topLevelEntry = tocEntries.find((entry) => entry.number === 8);
assert.ok(topLevelEntry, "TOC should include section 8");
assert.equal(topLevelEntry.title, "Registering Top-Level Dashboard Views");
});