repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
pi/agent/skillz/ims-process-review/scripts/ims.test.mjs
Rawimport 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,
plainTextFromHtml,
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 & 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("decodes Confluence named entities in text and comments", () => {
assert.equal(plainTextFromHtml("<p>Seite ‚Continuous Integration‘ verlinken</p>"), "Seite ‚Continuous Integration‘ verlinken");
assert.equal(plainTextFromHtml("<p>01.–04.09.2026</p>"), "01.–04.09.2026");
});
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: "", to: "new" }], expect: { contains: ["new"] } }] }), /invalid replacement/);
assert.throws(() => validatePlan({ pageId: "1", expectedVersion: 1, operations: [{ kind: "page", versionComment: "x", initializeStorage: "<p>new</p>", replacements: [{ from: "x", to: "y" }], expect: { contains: ["new"] } }] }), /invalid empty-page initialization/);
assert.throws(() => validatePlan({ pageId: "1", expectedVersion: 1, operations: [{ kind: "add-label", name: "ims-dokument", expectedBefore: [] }] }), /must add ims-dokument/);
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/);
const pageLink = '<ac:link><ri:page ri:space-key="RD" ri:content-title="Rules" ri:version-at-save="15" /><ac:link-body>Rules</ac:link-body></ac:link>';
const refreshed = pageLink.replace('ri:version-at-save="15"', 'ri:version-at-save="16"');
assert.doesNotThrow(() => assertEquivalentStorage(pageLink, refreshed));
assert.throws(() => assertEquivalentStorage(pageLink, refreshed.replace('ri:content-title="Rules"', 'ri:content-title="Other"')), /differs/);
assert.throws(() => assertEquivalentStorage(pageLink, refreshed.replace('ri:space-key="RD"', 'ri:space-key="GA"')), /differs/);
assert.throws(() => assertEquivalentStorage(pageLink, refreshed.replace('ri:version-at-save="16"', '')), /differs/);
assert.throws(() => assertEquivalentStorage(pageLink, refreshed.replace('<ac:link-body>Rules', '<ac:link-body>Other')), /differs/);
assert.throws(() => assertEquivalentStorage(pageLink, refreshed.replace('<ac:link-body>Rules', '<ac:link-body><ac:inline-comment-marker ac:ref="new">Rules</ac:inline-comment-marker>')), /differs/);
assert.throws(() => assertEquivalentStorage(pageLink.replace('<ac:link><ri:page', '<ri:attachment><ri:page').replace('</ac:link>', '</ri:attachment>'), refreshed.replace('<ac:link><ri:page', '<ri:attachment><ri:page').replace('</ac:link>', '</ri:attachment>')), /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|view)/);
if (requestPath.endsWith("body-format=view")) return {
...structuredClone(page),
body: { view: { value: '<table><tr><th>Document Owner</th><th>Status</th></tr><tr><td><a href="/wiki/people/oliver">Oliver Krylow</a></td><td>Prüfung</td></tr></table>' } },
};
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: { "Document Owner": "Oliver Krylow", Status: "Prüfung" },
});
});
test("bootstraps only an empty IMS page, validates its rendered header, then adds its label", async () => {
const header = {
"Document Owner": "Oliver Krylow", "Risk Owner": "Steffen Kröger", "Asset Owner": "Steffen Kröger",
Klassifizierung: "Vertraulich", "Geprüft von": "Normen Rachel", "Geprüft am": "",
"Freigegeben von": "Steffen Kröger", "Freigegeben am": "", Status: "Entwurf",
};
const storage = '<ac:structured-macro ac:name="details"><table><tr><th>Document Owner</th><th>Risk Owner</th><th>Asset Owner</th><th>Klassifizierung</th></tr><tr><td>Oliver Krylow</td><td>Steffen Kröger</td><td>Steffen Kröger</td><td>Vertraulich</td></tr></table></ac:structured-macro>' +
'<ac:structured-macro ac:name="details"><table><tr><th>Geprüft von</th><th>Geprüft am</th><th>Freigegeben von</th><th>Freigegeben am</th><th>Status</th></tr><tr><td>Normen Rachel</td><td></td><td>Steffen Kröger</td><td></td><td>Entwurf</td></tr></table></ac:structured-macro>';
const plan = validatePlan({ pageId: "123", expectedVersion: 1, operations: [
{ kind: "page", versionComment: "inhaltliche Bearbeitung", initializeStorage: storage, expectHeader: header, expect: { contains: ["Entwurf"] } },
{ kind: "add-label", name: "ims-dokument", expectedBefore: [] },
] });
let page = { id: "123", title: "Penetrationstests", status: "current", spaceId: "space-1", version: { number: 1, message: "" }, body: { storage: { value: "" } } };
let labels = [];
const writes = [];
const client = {
async get(requestPath) {
if (requestPath.includes("/labels?")) return { results: structuredClone(labels) };
if (requestPath.endsWith("body-format=view")) return { ...page, body: { view: { value: page.body.storage.value } } };
return structuredClone(page);
},
async mutate(method, requestPath, body) {
writes.push(method);
if (method === "POST") {
assert.equal(requestPath, "wiki/rest/api/content/123/label");
assert.deepEqual(body, [{ prefix: "global", name: "ims-dokument" }]);
labels = body;
return labels;
}
assert.equal(requestPath, "wiki/api/v2/pages/123");
page = { ...page, version: body.version, body: { storage: { value: body.body.value } } };
return structuredClone(page);
},
};
const receipt = await applyPlan(plan, client, "https://site.example");
assert.deepEqual(writes, ["PUT", "POST"]);
assert.deepEqual(receipt.header, header);
assert.deepEqual(receipt.operations.map((operation) => operation.validation), ["passed", "passed"]);
assert.equal(receipt.finalVersion, 2);
page = { ...page, version: { number: 1 }, body: { storage: { value: " " } } };
labels = [];
writes.length = 0;
await assert.rejects(applyPlan(plan, client, "https://site.example"), /not empty/);
assert.deepEqual(writes, []);
page = { ...page, body: { storage: { value: "" } } };
writes.length = 0;
const invalidHeaderClient = { ...client, async get(requestPath) {
if (requestPath.endsWith("body-format=view")) return { ...page, body: { view: { value: page.body.storage.value.replace("Normen Rachel", "Other Reviewer") } } };
return client.get(requestPath);
} };
await assert.rejects(applyPlan(plan, invalidHeaderClient, "https://site.example"), /rendered IMS header validation failed/);
assert.deepEqual(writes, ["PUT"]);
});
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");
if (requestPath.includes("body-format=view")) return { id: "123", version: { number: 5 }, body: { view: { value: "<p>Before exact target after</p>" } } };
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üfung nö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: "/spaces/RD/pages/123", base: "https://site.example/wiki" },
};
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/spaces/RD/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}$/);
});