Files
2026-06-06 10:40:48 +08:00

169 lines
6.5 KiB
JavaScript

#!/usr/bin/env node
/**
* PR-1 Freeze Architecture Test
*
* Run: node --test test/architecture/freeze.test.mjs
*
* Tests:
* 1. architecture-freeze-v2.md exists
* 2. Document contains core/adapter/legacy/experimental sections
* 3. Document contains 90-day legacy policy
* 4. check-deprecations output includes replacement info
* 5. check-deprecations output includes migration window
* 6. production-check still passes
* 7. guard still passes
* 8. baseline still passes
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { existsSync, readFileSync, statSync } from "node:fs";
import { join } from "node:path";
import { execSync, spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
const __dirname = join(fileURLToPath(import.meta.url), "..", "..", "..");
const ROOT = __dirname;
const SCRIPTS = join(ROOT, "scripts");
const DOCS = join(ROOT, "docs");
// ─── Helpers ──────────────────────────────────────────
function getFileSize(path) {
try { return statSync(path).size; } catch { return 0; }
}
describe("PR-1: Freeze Architecture", () => {
// ─── Test 1 ──────────────────────────────────────────
it("architecture-freeze-v2.md exists and is non-empty", () => {
const path = join(DOCS, "architecture-freeze-v2.md");
assert.ok(existsSync(path), `Missing: ${path}`);
const size = getFileSize(path);
assert.ok(size > 1000, `File too small: ${size} bytes (expected >1000)`);
});
// ─── Test 2 ──────────────────────────────────────────
it("document contains core / adapter / legacy / experimental sections", () => {
const content = readFileSync(join(DOCS, "architecture-freeze-v2.md"), "utf8");
const required = [
"Core Module",
"Adapter Module",
"Legacy Module",
"Experimental Module",
];
for (const section of required) {
assert.ok(content.includes(section),
`Missing section: "${section}"`);
}
});
// ─── Test 3 ──────────────────────────────────────────
it("document contains 90-day legacy migration policy", () => {
const content = readFileSync(join(DOCS, "architecture-freeze-v2.md"), "utf8");
assert.ok(content.includes("90-day") || content.includes("90-Day") ||
content.includes("90 day") || content.includes("Migration Window"),
"Missing 90-day migration policy reference");
assert.ok(content.includes("2026-09-04"),
"Missing removal target date 2026-09-04");
});
// ─── Test 4 ──────────────────────────────────────────
it("check-deprecations output includes replacement info", { timeout: 30000 }, () => {
const result = spawnSync("node", [join(SCRIPTS, "check-deprecations.mjs")], {
cwd: ROOT,
encoding: "utf8",
timeout: 25000,
maxBuffer: 1024 * 1024,
});
const output = result.stdout + result.stderr;
console.log(output.slice(-1000));
// Deprecation check always exits 0 (never blocks on deprecation count)
assert.equal(result.status, 0, `Script crashed (exit ${result.status})`);
// Must contain replacement info in enhanced output
assert.ok(
output.includes("Replacement:") || output.includes("replacement"),
"Missing replacement info in deprecation output"
);
});
// ─── Test 5 ──────────────────────────────────────────
it("check-deprecations output includes migration window", { timeout: 30000 }, () => {
const result = spawnSync("node", [join(SCRIPTS, "check-deprecations.mjs")], {
cwd: ROOT,
encoding: "utf8",
timeout: 25000,
maxBuffer: 1024 * 1024,
});
const output = result.stdout + result.stderr;
// Must contain migration window
assert.ok(
output.includes("Migration Window") || output.includes("migrationWindow") ||
output.includes("Migration Timeline") || output.includes("Removal Target"),
"Missing migration window info in deprecation output"
);
});
// ─── Test 6 ──────────────────────────────────────────
it("production-check still passes after freeze", { timeout: 120000 }, () => {
const result = spawnSync("bash", [join(SCRIPTS, "production-check.sh")], {
cwd: ROOT,
encoding: "utf8",
timeout: 110000,
maxBuffer: 2 * 1024 * 1024,
});
const output = result.stdout + result.stderr;
console.log(output.slice(-800));
assert.equal(result.status, 0,
`Production check failed after freeze (exit ${result.status}):\n${output.slice(-500)}`);
assert.ok(output.includes("PRODUCTION CHECK PASSED") ||
output.includes("Overall:"),
"Production check summary not found");
});
// ─── Test 7 ──────────────────────────────────────────
it("architecture guard still passes after freeze", { timeout: 60000 }, () => {
const result = spawnSync("bash", [join(SCRIPTS, "guard-all.sh")], {
cwd: ROOT,
encoding: "utf8",
timeout: 55000,
maxBuffer: 1024 * 1024,
});
const output = result.stdout + result.stderr;
console.log(output.slice(-500));
assert.equal(result.status, 0,
`Guard failed after freeze (exit ${result.status}):\n${output.slice(-300)}`);
});
// ─── Test 8 ──────────────────────────────────────────
it("baseline tests still pass after freeze", { timeout: 60000 }, () => {
const result = spawnSync("node", ["--test", "test/baseline/test-*.test.mjs"], {
cwd: ROOT,
encoding: "utf8",
timeout: 55000,
maxBuffer: 2 * 1024 * 1024,
shell: true,
});
const output = result.stdout + result.stderr;
assert.equal(result.status, 0,
`Baseline tests failed after freeze (exit ${result.status})`);
assert.ok(output.includes("fail 0") || !output.includes("fail"),
"Baseline tests have failures");
});
});