Files
healer-man/src/game/runewakerInstancePipeline.test.ts
T
2026-08-14 15:56:39 -04:00

90 lines
3.2 KiB
TypeScript

import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
const projectRoot = process.cwd();
const pipelineRoot = path.join(projectRoot, "scripts", "runewaker-pipeline");
const scripts = [
"lib/recipe.mjs",
"lib/wdb.mjs",
"discover-instances.mjs",
"inspect-wdb.mjs",
"scaffold-instance.mjs",
"refresh-population.mjs",
"build-environment.mjs",
"build-population.mjs",
"extract-mechanics.mjs",
"validate-instance.mjs",
"cli.mjs",
];
describe("generic RuneWaker instance pipeline", () => {
it("keeps every JavaScript pipeline entry point syntactically valid", () => {
for (const script of scripts) {
expect(() => execFileSync(process.execPath, ["--check", path.join(pipelineRoot, script)], {
cwd: projectRoot,
stdio: "pipe",
})).not.toThrow();
}
});
it("documents the offline boundary and all import stages", () => {
const guide = readFileSync(path.join(pipelineRoot, "INSTANCE_IMPORT_GUIDE.md"), "utf8");
for (const stage of [
"discover",
"scaffold",
"environment",
"refresh",
"actors",
"population",
"mechanics",
"validate",
]) {
expect(guide).toContain(stage);
}
expect(guide).toContain("SQL Server is used only by the explicit `refresh` command");
expect(guide).toContain("Simulation state stays outside React scene components");
});
it("limits SQL restore access to the explicit refresh command", () => {
const cli = readFileSync(path.join(pipelineRoot, "cli.mjs"), "utf8");
const refresh = readFileSync(path.join(pipelineRoot, "refresh-population.ps1"), "utf8");
const offlineScripts = [
"build-environment.mjs",
"build-population.mjs",
"extract-mechanics.mjs",
].map((name) => readFileSync(path.join(pipelineRoot, name), "utf8")).join("\n");
expect(cli).toContain('command === "refresh"');
expect(refresh).toContain("SET READ_ONLY WITH ROLLBACK IMMEDIATE");
expect(refresh).toContain("DROP DATABASE");
expect(refresh).toContain("[Parameter(Mandatory = $true)][int]$ZoneId");
expect(offlineScripts).not.toMatch(/SqlConnection|RESTORE DATABASE|ROM_Global\.bak/);
});
it("records a reviewed, non-executable mechanics audit for Forsaken Abbey", () => {
const report = JSON.parse(readFileSync(path.join(
projectRoot,
"src/assets/game/dungeons/forsaken-abbey/mechanics-audit.json",
), "utf8"));
expect(report.status).toBe("review-required");
expect(report.luaSources).toHaveLength(3);
expect(report.bossRows).toHaveLength(8);
expect(report.templateCandidates).toHaveLength(31);
expect(report.safety).toMatchObject({
executableMechanicsGenerated: false,
runtimeSqlDependency: false,
});
});
it("passes the packaged Forsaken Abbey validation gate", () => {
const report = JSON.parse(readFileSync(path.join(
projectRoot,
"src/assets/game/dungeons/forsaken-abbey/instance-validation-report.json",
), "utf8"));
expect(report.status).toBe("green");
expect(report.errors).toEqual([]);
expect(report.checks.every((check: { passed: boolean }) => check.passed)).toBe(true);
});
});