Files
ForgeFlow/tests/ipc-contract.test.mjs
NuklearRabbitandClaude Opus 5 d77643c058 refactor(renderer): move diff rendering into its own module
views.js sat at the project's 750-line limit, so the diff cap in the previous
commit pushed it over and every further change would have meant shaving
comments elsewhere. That is the file asking for decomposition, which is what the
architecture audit says to do.

Diff rendering is self-contained: the line cap, the line classifier and the
change-map illustration depend on nothing in views.js beyond ui and escapeHtml.
They now live in src/renderer/diff-view.js and are registered in index.html and
in the three renderer file lists that scan the bridge surface, so anything added
there is covered by the existing contract tests.

views.js drops from 755 to 714 lines and no source file exceeds 750 again. The
nested ternary that classified a diff line became a named function with guard
clauses on the way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 14:51:31 +02:00

50 lines
2.0 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
async function rendererSource() {
return (await Promise.all(["app.js", "diff-view.js", "views.js", "dialogs.js", "operations.js", "actions/shell.js", "actions/inventory.js", "actions/deployment-profile.js", "actions/deployment-operation.js", "actions/setup-and-settings.js", "actions/recovery.js", "actions/command.js", "events.js"].map((file) => readFile(new URL(`../src/renderer/${file}`, import.meta.url), "utf8")))).join("\n");
}
test("every preload invoke channel has a registered IPC handler", async () => {
const preload = await readFile(
new URL("../preload.cjs", import.meta.url),
"utf8",
);
const ipc = (await Promise.all(["ipc.cjs", "ipc/repository-handlers.cjs", "ipc/deployment-handlers.cjs", "ipc/operations-handlers.cjs"].map((file) => readFile(new URL(`../src/main/${file}`, import.meta.url), "utf8")))).join("\n");
const invokes = [...preload.matchAll(/invoke\(\s*['"]([^'"]+)['"]/g)].map(
(match) => match[1],
);
const handlers = new Set(
[...ipc.matchAll(/register\(\s*['"]([^'"]+)['"]/g)].map(
(match) => match[1],
),
);
assert.ok(invokes.length > 40, "expected the complete renderer API surface");
assert.deepEqual(
invokes.filter((channel) => !handlers.has(channel)),
[],
);
});
test("every renderer bridge call is exposed by the preload contract", async () => {
const renderer = await rendererSource();
const preload = await readFile(
new URL("../preload.cjs", import.meta.url),
"utf8",
);
const calls = new Set(
[...renderer.matchAll(/window\.forgeflow\.([A-Za-z0-9_]+)\s*\(/g)].map(
(match) => match[1],
),
);
const exposed = new Set(
[...preload.matchAll(/^\s+([A-Za-z0-9_]+):/gm)].map((match) => match[1]),
);
assert.ok(calls.size > 40, "expected the complete renderer bridge surface");
assert.deepEqual(
[...calls].filter((method) => !exposed.has(method)),
[],
);
});