Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

pi/agent/skillz/ims-process-review/scripts/ims.test.mjs

Raw
import assert from "node:assert/strict";
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { test } from "node:test";
import {
	applyPlan,
	applyReplacements,
	assertEquivalentStorage,
	checkPolicy,
	createSnapshot,
	parseBaseline,
	parseCli,
	parseDate,
	parseHeaderHtml,
	parseReportHtml,
	readPlan,
	selectWorklist,
	validatePlan,
} from "./ims.mjs";

const reportHtml = `
<table><tbody>
<tr><th>Prozess</th><th>Document Owner</th><th>Risk Owner</th><th>Asset Owner</th><th>Klassifizierung</th><th>Status</th><th>Geprüft von</th><th>Geprüft am</th><th>Freigegeben von</th><th>Freigegeben am</th></tr>
<tr>
<td><a href="/wiki/spaces/RD/pages/101/Alpha">Alpha &amp; Beta</a></td>
<td><a data-account-id="owner-1">Kathi Borrmann</a></td><td>Risk</td><td>Asset</td><td>Intern</td><td>Prüfung</td>
<td><a data-account-id="oliver">Oliver Krylow</a></td><td>20.08.2026</td><td>Release</td><td>21.08.2026</td>
</tr>
<tr>
<td data-content-id="102"><a href="/wiki/spaces/GA/pages/102/Draft">Draft</a></td>
<td><a data-account-id="oliver">Oliver Krylow</a></td><td>Risk</td><td>Asset</td><td>Intern</td><td>Entwurf</td>
<td></td><td></td><td></td><td></td>
</tr>
<tr>
<td><a href="/wiki/spaces/isp/pages/103/Old">Old</a></td>
<td><a data-account-id="oliver">Oliver Krylow</a></td><td>Risk</td><td>Asset</td><td>Intern</td><td>Freigegeben</td>
<td><a data-account-id="oliver">Oliver Krylow</a></td><td>25.08.2025</td><td>Release</td><td>26.08.2025</td>
</tr>
</tbody></table>`;

test("parses IMS report rows and entities", () => {
	const rows = parseReportHtml(reportHtml);
	assert.equal(rows.length, 3);
	assert.deepEqual(rows[0], {
		id: "101",
		title: "Alpha & Beta",
		href: "/wiki/spaces/RD/pages/101/Alpha",
		area: "RD",
		documentOwner: "Kathi Borrmann",
		documentOwnerIds: ["owner-1"],
		riskOwner: "Risk",
		riskOwnerIds: [],
		assetOwner: "Asset",
		assetOwnerIds: [],
		classification: "Intern",
		status: "Prüfung",
		reviewer: "Oliver Krylow",
		reviewerIds: ["oliver"],
		reviewedAt: "20.08.2026",
		releasedBy: "Release",
		releasedAt: "21.08.2026",
	});
	assert.equal(rows[1].id, "102");
});

test("builds distinct reviewer and owner worklists with RD first", () => {
	const rows = parseReportHtml(reportHtml);
	const reviewer = selectWorklist(rows, { mode: "reviewer", person: "ignored", accountId: "oliver", area: "all", today: "2026-08-27" });
	assert.deepEqual(reviewer.candidates.map((row) => [row.id, row.reasons]), [["101", ["awaiting-review"]]]);

	const owner = selectWorklist(rows, { mode: "owner", person: "ignored", accountId: "oliver", area: "all", today: "2026-08-27" });
	assert.deepEqual(owner.candidates.map((row) => row.id), ["103", "102"]);
	assert.deepEqual(owner.candidates[0].reasons, ["self-reviewer", "annual-review-due"]);
	assert.deepEqual(owner.candidates[1].reasons, ["draft", "missing-reviewer"]);

	const nearName = [{ ...rows[1], documentOwner: "Max Anna Meyer", documentOwnerIds: [] }];
	assert.equal(selectWorklist(nearName, { mode: "owner", person: "Anna Meyer", area: "all", today: "2026-08-27" }).roleMatchCount, 0);
});

test("rejects impossible German calendar dates", () => {
	assert.equal(parseDate("31.02.2026"), undefined);
	assert.equal(parseDate("2026-02-29"), undefined);
	assert.equal(parseDate("29.02.2024")?.toISOString(), "2024-02-29T00:00:00.000Z");
	assert.equal(parseDate("2024-02-29")?.toISOString(), "2024-02-29T00:00:00.000Z");
});

test("parses the policy baseline and detects version changes", async () => {
	const baseline = parseBaseline(`
- Instruction page: \`540606500\`, version \`24\`, [Instructions](https://site.example/wiki/x/a)
- Announcement: \`1437532339\`, version \`1\`, [Announcement](https://site.example/wiki/x/b)
- Worklist report: \`899153943\`, [Report](https://site.example/wiki/x/c)
`);
	assert.equal(baseline.baseUrl, "https://site.example");
	const client = {
		async get(requestPath) {
			return { version: { number: requestPath.includes("blogposts") ? 2 : 24 } };
		},
	};
	const result = await checkPolicy(client, baseline);
	assert.equal(result.changed, true);
	assert.deepEqual(result.sources.map((source) => source.changed), [false, true]);
});

test("extracts row and matrix IMS headers", () => {
	const rows = `<table><tr><th>Status:</th><td>Prüfung</td></tr><tr><td>Geprüft von</td><td>Marcus Storre</td></tr></table>`;
	assert.deepEqual(parseHeaderHtml(rows), { Status: "Prüfung", "Geprüft von": "Marcus Storre" });
	const matrix = `<table><tr><th>Document Owner</th><th>Risk Owner</th></tr><tr><td>Oliver Krylow</td><td>Marcus Storre</td></tr></table>`;
	assert.deepEqual(parseHeaderHtml(matrix), { "Document Owner": "Oliver Krylow", "Risk Owner": "Marcus Storre" });
});

test("check-plan is read-only and apply requires the separate mutation gate", () => {
	assert.equal(parseCli(["check-plan", "plan.json"]).allowMutation, false);
	assert.throws(() => parseCli(["apply", "plan.json", "--expected-version", "7", "--plan-sha256", "a".repeat(64)]), /--allow-mutation/);
	assert.throws(() => parseCli(["apply", "plan.json", "--expected-version", "7", "--allow-mutation"]), /--plan-sha256/);
});

test("locks the exact validated plan bytes", (t) => {
	const dir = mkdtempSync(path.join(tmpdir(), "ims-plan-test-"));
	t.after(() => rmSync(dir, { recursive: true, force: true }));
	const file = path.join(dir, "plan.json");
	writeFileSync(file, JSON.stringify({
		pageId: "123",
		expectedVersion: 7,
		operations: [{ kind: "page", versionComment: "geprüft", replacements: [{ from: "old", to: "new" }], expect: { contains: ["new"] } }],
	}));
	const first = readPlan(file);
	writeFileSync(file, `${first.source}\n`);
	const second = readPlan(file);
	assert.notEqual(first.sha256, second.sha256);
	assert.deepEqual(first.plan, second.plan);
});

test("rejects plan and replacement shapes that could silently broaden a write", () => {
	assert.throws(() => validatePlan({ pageId: "x", expectedVersion: 1, operations: [] }), /pageId/);
	assert.throws(() => validatePlan({ pageId: "1", expectedVersion: 1, operations: [{ kind: "page", versionComment: "x", replacements: [] }] }), /lacks replacements/);
	assert.throws(() => validatePlan({ pageId: "1", expectedVersion: 1, operations: [{ kind: "page", versionComment: "x", replacements: [{ from: "a", to: "b" }], expect: { contains: "b" } }] }), /expect.contains/);
	assert.throws(() => validatePlan({ pageId: "1", expectedVersion: 1, operations: [{ kind: "page", versionComment: "x", replacements: [{ from: "a", to: "b" }] }] }), /at least one expectation/);
	assert.throws(() => validatePlan({ pageId: "1", expectedVersion: 1, operations: [
		{ kind: "page", versionComment: "x", replacements: [{ from: "a", to: "b" }], expect: { contains: ["b"] } },
		{ kind: "inline-comment", target: "b", text: "fix" },
	] }), /must precede/);
	assert.throws(() => applyReplacements("one old", [{ from: "old", to: "new", count: 2 }]), /found 1/);
	assert.throws(
		() => applyReplacements('<ac:inline-comment-marker ac:ref="marker">old</ac:inline-comment-marker>', [{ from: '<ac:inline-comment-marker ac:ref="marker">old</ac:inline-comment-marker>', to: "new" }]),
		/inline-comment markers/,
	);
});

test("accepts server-only storage attributes but rejects semantic drift", () => {
	const expected = '<p><ac:link><ri:user ri:account-id="person" /></ac:link>Hello</p>';
	const normalized = '<p data-local-id="server"><ac:link ac:local-id="server"><ri:user ri:account-id="person" /></ac:link>Hello</p>';
	assert.doesNotThrow(() => assertEquivalentStorage(expected, normalized));
	assert.throws(() => assertEquivalentStorage(expected, normalized.replace("person", "other")), /differs/);
	assert.throws(() => assertEquivalentStorage("<p>Hello <strong>world</strong></p>", "<p>Hello<strong>world</strong></p>"), /differs/);

	const links = '<p><ac:link><ri:page ri:space-key="RD" ri:content-title="Rules" /></ac:link>One <ac:link><ri:page ri:space-key="GA" ri:content-title="Rules" /></ac:link>Two</p>';
	const swapped = links.replace('ri:space-key="RD"', 'ri:space-key="TEMP"').replace('ri:space-key="GA"', 'ri:space-key="RD"').replace('ri:space-key="TEMP"', 'ri:space-key="GA"');
	assert.throws(() => assertEquivalentStorage(links, swapped), /differs/);
});

test("applies a version-gated page plan and emits an exact receipt", async () => {
	let page = {
		id: "123",
		title: "Process",
		status: "current",
		spaceId: "space-1",
		version: { number: 3, message: "before" },
		body: { storage: { value: '<table><tr><th>Status</th><td>Prüfung</td></tr></table><p><ac:inline-comment-marker ac:ref="keep">Old</ac:inline-comment-marker></p>' } },
		_links: { webui: "/wiki/spaces/RD/pages/123/Process" },
	};
	let mutations = 0;
	const client = {
		async get(requestPath) {
			assert.match(requestPath, /pages\/123\?body-format=storage/);
			return structuredClone(page);
		},
		async mutate(method, requestPath, body) {
			mutations += 1;
			assert.equal(method, "PUT");
			assert.equal(requestPath, "wiki/api/v2/pages/123");
			assert.equal(body.spaceId, "space-1");
			page = {
				...page,
				version: structuredClone(body.version),
				body: { storage: { value: body.body.value.replace("<p>", '<p data-local-id="server">') } },
			};
			return structuredClone(page);
		},
	};
	const plan = validatePlan({
		pageId: "123",
		expectedVersion: 3,
		operations: [{
			kind: "page",
			versionComment: "Rechtschreibkorrektur",
			replacements: [{ from: "Old", to: "New" }],
			expect: { contains: ["New"], notContains: ["Old"] },
		}],
	});
	const receipt = await applyPlan(plan, client, "https://site.example");
	assert.equal(mutations, 1);
	assert.deepEqual(receipt, {
		pageId: "123",
		initialVersion: 3,
		operations: [{ kind: "page", version: 4, versionComment: "Rechtschreibkorrektur", validation: "passed" }],
		inlineComments: [],
		validation: "passed",
		url: "https://site.example/wiki/spaces/RD/pages/123/Process",
		finalVersion: 4,
		versionComment: "Rechtschreibkorrektur",
		header: { Status: "Prüfung" },
	});
});

test("stops before mutation on version drift", async () => {
	let mutations = 0;
	const client = {
		async get() {
			return { id: "123", version: { number: 8 }, body: { storage: { value: "old" } } };
		},
		async mutate() {
			mutations += 1;
		},
	};
	const plan = validatePlan({ pageId: "123", expectedVersion: 7, operations: [{ kind: "page", versionComment: "x", replacements: [{ from: "old", to: "new" }], expect: { contains: ["new"] } }] });
	await assert.rejects(applyPlan(plan, client, "https://site.example"), /version drift/);
	assert.equal(mutations, 0);
});

test("creates and verifies an inline comment and its page marker", async () => {
	let storage = "<p>Before exact target after</p>";
	const page = (representation) => ({
		id: "123",
		title: "Process",
		status: "current",
		version: { number: 5, message: "before" },
		body: representation === "storage"
			? { storage: { value: storage } }
			: { atlas_doc_format: { value: JSON.stringify({ type: "doc", content: [{ type: "paragraph", content: [{ type: "text", text: "Before exact " }, { type: "text", text: "target after" }] }] }) } },
		_links: { webui: "/wiki/pages/123" },
	});
	let comment;
	const client = {
		async get(requestPath) {
			if (requestPath.includes("inline-comments/c1")) return structuredClone(comment);
			if (requestPath.includes("/inline-comments?")) return { results: [{ id: "c1" }] };
			if (requestPath.includes("atlas_doc_format")) return page("atlas_doc_format");
			return page("storage");
		},
		async mutate(method, requestPath, body) {
			assert.equal(method, "POST");
			assert.equal(requestPath, "wiki/api/v2/inline-comments");
			assert.equal(body.inlineCommentProperties.textSelection, "exact target");
			storage = storage.replace("exact target", '<ac:inline-comment-marker ac:ref="marker-1">exact target</ac:inline-comment-marker>');
			comment = {
				id: "c1",
				pageId: "123",
				resolutionStatus: "open",
				body: { storage: { value: "<p>Pr&uuml;fung n&ouml;tig</p>" } },
				properties: { inlineOriginalSelection: "exact target", inlineMarkerRef: "marker-1" },
			};
			return { id: "c1" };
		},
	};
	const plan = validatePlan({
		pageId: "123",
		expectedVersion: 5,
		operations: [{ kind: "inline-comment", target: "exact target", text: "Prüfung nötig" }],
	});
	const receipt = await applyPlan(plan, client, "https://site.example");
	assert.equal(receipt.validation, "passed");
	assert.deepEqual(receipt.inlineComments, [{ id: "c1", target: "exact target", markerRef: "marker-1", validation: "passed" }]);
	assert.match(storage, /inline-comment-marker/);
});

test("rejects a snapshot changed during supplementary reads", async () => {
	let storageReads = 0;
	const client = {
		async get(requestPath) {
			if (requestPath.endsWith("?body-format=storage")) {
				storageReads += 1;
				return { id: "123", title: "Process", version: { number: storageReads === 1 ? 9 : 10 }, body: { storage: { value: "<p>Storage</p>" } } };
			}
			if (requestPath.endsWith("?body-format=view")) return { id: "123", version: { number: 9 }, body: { view: { value: "<p>View</p>" } } };
			return { results: [] };
		},
	};
	await assert.rejects(createSnapshot(client, "123", "https://site.example"), /changed during snapshot/);
});

test("captures one version-consistent page snapshot", async () => {
	const client = {
		async get(requestPath) {
			if (requestPath.endsWith("?body-format=storage")) return {
				id: "123",
				title: "Process",
				version: { number: 9, message: "x" },
				body: { storage: { value: "<p>Storage</p>" } },
				_links: { webui: "/wiki/pages/123" },
			};
			if (requestPath.endsWith("?body-format=view")) return {
				id: "123",
				version: { number: 9 },
				body: { view: { value: "<table><tr><th>Status</th><td>Entwurf</td></tr></table>" } },
			};
			if (requestPath.includes("/labels")) return [{ results: [{ name: "ims-dokument" }] }];
			if (requestPath.includes("/inline-comments")) return { results: [{ id: "i1" }] };
			if (requestPath.includes("/footer-comments")) return { results: [{ id: "f1" }] };
			if (requestPath.includes("/attachments")) return { results: [{ id: "a1" }] };
			throw new Error(`Unexpected path: ${requestPath}`);
		},
	};
	const snapshot = await createSnapshot(client, "123", "https://site.example");
	assert.equal(snapshot.url, "https://site.example/wiki/pages/123");
	assert.deepEqual(snapshot.header, { Status: "Entwurf" });
	assert.deepEqual(snapshot.labels, [{ name: "ims-dokument" }]);
	assert.equal(snapshot.body.storage, "<p>Storage</p>");
	assert.match(snapshot.body.storageSha256, /^[0-9a-f]{64}$/);
});