169 lines
6.5 KiB
JavaScript
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");
|
|
});
|
|
});
|