import * as fs from "node:fs"; import * as path from "node:path"; import * as os from "node:os"; import { VerificationPipeline } from "../verification/index.js"; describe("E2E Verification Pipeline", () => { let tempDir: string; beforeEach(() => { tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-e2e-test-")); }); afterEach(() => { fs.rmSync(tempDir, { recursive: true, force: true }); }); it("passes all 4 layers on a clean project", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "app.ts"), "export function main() { return 1; }"); fs.writeFileSync(path.join(tempDir, "package.json"), JSON.stringify({ name: "test-project", version: "1.0.0", devDependencies: { jest: "^29.0.0" }, scripts: { test: "echo 'no tests yet'" }, })); fs.writeFileSync(path.join(tempDir, "tsconfig.json"), JSON.stringify({ compilerOptions: { target: "ES2022", module: "Node16", strict: true, outDir: "dist" }, include: ["src"], })); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\ndist\n"); const ciDir = path.join(tempDir, ".ciagent"); fs.mkdirSync(ciDir, { recursive: true }); fs.writeFileSync(path.join(ciDir, "ROADMAP.md"), "# Roadmap\n\n| 1 | Init | complete | setup |\n"); fs.writeFileSync(path.join(ciDir, "REQUIREMENTS.md"), "# Requirements\n\n| REQ-01 | Must work | P0 | 1 | covered |\n"); fs.writeFileSync(path.join(ciDir, "config.json"), JSON.stringify({ autonomy: { level: "full" } })); fs.writeFileSync(path.join(ciDir, "PROJECT.md"), "# Test\n\n## Requirements\n\n- [ ] Must work\n"); const pipeline = new VerificationPipeline(tempDir); const result = await pipeline.run(1); expect(result.all_passed).toBe(true); expect(result.structural.passed).toBe(true); expect(result.behavioral.passed).toBe(true); expect(result.security.passed).toBe(true); expect(result.quality.passed).toBe(true); }); it("fails security layer on hardcoded password", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "app.ts"), 'export const password = "secret123";'); fs.writeFileSync(path.join(tempDir, "package.json"), JSON.stringify({ name: "test", version: "1.0.0" })); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n"); const pipeline = new VerificationPipeline(tempDir); const result = await pipeline.run(1); expect(result.security.passed).toBe(false); }); it("fails quality layer on P0 finding (empty catch)", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "app.ts"), 'try { work(); } catch(e) {}\nexport function main() { return 1; }'); fs.writeFileSync(path.join(tempDir, "package.json"), JSON.stringify({ name: "test", version: "1.0.0" })); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n"); const pipeline = new VerificationPipeline(tempDir); const result = await pipeline.run(1); expect(result.quality.passed).toBe(false); }); });