v0.2.0: Git-native architecture (#1)
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import * as os from "node:os";
|
||||
import { StructuralVerification } from "../verification/structural.js";
|
||||
|
||||
describe("StructuralVerification", () => {
|
||||
let tempDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "ci-structural-test-"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
function setupProjectStructure(hasPhaseDir = true, hasPlan = true, hasCIConfig = true, hasSpec = true) {
|
||||
if (hasPhaseDir) {
|
||||
const phaseDir = path.join(tempDir, ".planning", "phases", "phase-1");
|
||||
fs.mkdirSync(phaseDir, { recursive: true });
|
||||
if (hasPlan) {
|
||||
fs.writeFileSync(path.join(phaseDir, "PLAN.md"), "# Plan\n\nTasks:\n- [ ] Task 1\n- [ ] Task 2\n");
|
||||
}
|
||||
}
|
||||
if (hasCIConfig) {
|
||||
const ciDir = path.join(tempDir, ".ci");
|
||||
fs.mkdirSync(ciDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(ciDir, "config.json"), JSON.stringify({ autonomy: { level: "full" } }, null, 2));
|
||||
}
|
||||
if (hasSpec) {
|
||||
const specDir = path.join(tempDir, ".ci");
|
||||
if (!fs.existsSync(specDir)) fs.mkdirSync(specDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(specDir, "specification.md"), "# Project\n## Objective\nBuild a REST API for task management\n\n## Requirements\n- User auth\n- CRUD\n");
|
||||
}
|
||||
}
|
||||
|
||||
it("passes when all structural elements exist", async () => {
|
||||
setupProjectStructure(true, true, true, true);
|
||||
const verifier = new StructuralVerification();
|
||||
const result = await verifier.verify(tempDir, 1);
|
||||
|
||||
expect(result.layer).toBe(1);
|
||||
expect(result.name).toBe("Structural");
|
||||
expect(result.checks.length).toBeGreaterThan(0);
|
||||
|
||||
const phaseDirCheck = result.checks.find((c) => c.name === "Phase directory exists");
|
||||
expect(phaseDirCheck?.status).toBe("pass");
|
||||
|
||||
const planCheck = result.checks.find((c) => c.name === "PLAN.md exists");
|
||||
expect(planCheck?.status).toBe("pass");
|
||||
|
||||
const configCheck = result.checks.find((c) => c.name === "CI config valid");
|
||||
expect(configCheck?.status).toBe("pass");
|
||||
|
||||
const specCheck = result.checks.find((c) => c.name === "Specification exists");
|
||||
expect(specCheck?.status).toBe("pass");
|
||||
});
|
||||
|
||||
it("fails when phase directory is missing", async () => {
|
||||
setupProjectStructure(false, false, true, true);
|
||||
const verifier = new StructuralVerification();
|
||||
const result = await verifier.verify(tempDir, 1);
|
||||
|
||||
const phaseDirCheck = result.checks.find((c) => c.name === "Phase directory exists");
|
||||
expect(phaseDirCheck?.status).toBe("fail");
|
||||
});
|
||||
|
||||
it("fails when PLAN.md is missing", async () => {
|
||||
setupProjectStructure(true, false, true, true);
|
||||
const verifier = new StructuralVerification();
|
||||
const result = await verifier.verify(tempDir, 1);
|
||||
|
||||
const planCheck = result.checks.find((c) => c.name === "PLAN.md exists");
|
||||
expect(planCheck?.status).toBe("fail");
|
||||
});
|
||||
|
||||
it("fails when CI config has invalid JSON", async () => {
|
||||
const ciDir = path.join(tempDir, ".ci");
|
||||
fs.mkdirSync(ciDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(ciDir, "config.json"), "not valid json{{{");
|
||||
fs.mkdirSync(path.join(tempDir, ".planning", "phases", "phase-1"), { recursive: true });
|
||||
|
||||
const verifier = new StructuralVerification();
|
||||
const result = await verifier.verify(tempDir, 1);
|
||||
|
||||
const configCheck = result.checks.find((c) => c.name === "CI config valid");
|
||||
expect(configCheck?.status).toBe("fail");
|
||||
});
|
||||
|
||||
it("detects TODO/FIXME patterns in source files", async () => {
|
||||
const srcDir = path.join(tempDir, "src");
|
||||
fs.mkdirSync(srcDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(srcDir, "app.ts"), "export function main() { /* TODO: implement */ }");
|
||||
fs.mkdirSync(path.join(tempDir, ".planning", "phases", "phase-1"), { recursive: true });
|
||||
fs.writeFileSync(path.join(tempDir, ".planning", "phases", "phase-1", "PLAN.md"), "# Plan");
|
||||
const ciDir = path.join(tempDir, ".ci");
|
||||
fs.mkdirSync(ciDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(ciDir, "config.json"), "{}");
|
||||
fs.writeFileSync(path.join(ciDir, "specification.md"), "# Test\n## Objective\nBuild it");
|
||||
|
||||
const verifier = new StructuralVerification();
|
||||
const result = await verifier.verify(tempDir, 1);
|
||||
|
||||
const stubsCheck = result.checks.find((c) => c.name === "No stubs/TODOs");
|
||||
expect(stubsCheck?.status).toMatch(/warning|fail/);
|
||||
});
|
||||
|
||||
it("reports duration", async () => {
|
||||
setupProjectStructure(true, true, true, true);
|
||||
const verifier = new StructuralVerification();
|
||||
const result = await verifier.verify(tempDir, 1);
|
||||
expect(result.duration_ms).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user