import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs"; import os from "node:os"; import path from "node:path"; import test from "node:test"; import { coveragePlan, verifyLocalCoverage, verifyPostDeployCoverage } from "../full-local-coverage.mjs"; const candidate = { commit: "a".repeat(40), digest: "b".repeat(64) }; function report(rows, executed = false) { return { errors: [], suites: rows.map(row => ({ file: row.file, specs: [{ ...row, tests: [{ projectName: "", repeatEachIndex: 0, ...(executed ? { expectedStatus: "passed", status: "expected", results: [{ status: "passed", retry: 0 }] } : {}) }] }] })) }; } function fixture(context) { const root = mkdtempSync(path.join(os.tmpdir(), "hyb-coverage-")); context.after(() => rmSync(root, { recursive: true, force: true })); const rows = ["local", "live", "frozen", "protection"].map(name => ({ file: `client/tests/e2e/${name}.spec.ts`, id: name, title: name, projectName: "", repeatEachIndex: 0 })); for (const row of rows) { mkdirSync(path.dirname(path.join(root, row.file)), { recursive: true }); writeFileSync(path.join(root, row.file), row.title); } const contract = { schemaVersion: 1, approvalReference: "synthetic", exceptions: rows.slice(1, 3).map(row => ({ ...row, kind: row.id === "live" ? "post-deploy" : "frozen", reason: "synthetic", entry: "synthetic", responsibilityRole: "synthetic", namedOwner: null, requiredEvidence: "synthetic", sourceSha256: createHash("sha256").update(row.title).digest("hex"), replacementFile: rows[3].file, replacementTitle: rows[3].title })) }; const discovery = report(rows); const plan = () => coveragePlan(root, discovery, contract, candidate); return { root, rows, contract, discovery, plan }; } test("全发现分层,本地通过仍保留公网必跑且不能获得交付资格", context => { const f = fixture(context), p = f.plan(); assert.equal(p.status, "PASS"); assert.equal(p.totalCases, 4); assert.equal(p.localCases.length, 2); const r = verifyLocalCoverage(p, report(p.localCases, true), candidate); assert.equal(r.status, "PASS"); assert.equal(r.deliveryStatus, "INCOMPLETE"); assert.equal(r.normalReleaseEligible, false); assert.deepEqual(r.obligations.map(row => row.status), ["NOT_RUN_LOCAL", "FROZEN_PROTECTION_PASS"]); }); for (const mutation of ["missing-file", "new-file", "new-live-case", "identity-drift", "duplicate", "source-drift", "no-protection", "unknown-exception", "missing-reason"]) test(`发现/归属反例:${mutation}`, context => { const f = fixture(context); if (mutation === "missing-file") f.discovery.suites.pop(); if (mutation === "new-file") writeFileSync(path.join(f.root, "client/tests/e2e/new.spec.ts"), "new"); if (mutation === "new-live-case") f.discovery.suites[1].specs.push({ ...f.discovery.suites[1].specs[0], id: "new-live", title: "new-live" }); if (mutation === "identity-drift") f.discovery.suites[1].specs[0].id = "drift"; if (mutation === "duplicate") f.discovery.suites.push(f.discovery.suites[0]); if (mutation === "source-drift") writeFileSync(path.join(f.root, f.rows[1].file), "changed"); if (mutation === "no-protection") f.contract.exceptions[1].replacementTitle = "missing"; if (mutation === "unknown-exception") f.contract.exceptions[1].kind = "ignore"; if (mutation === "missing-reason") delete f.contract.exceptions[0].reason; assert.equal(f.plan().status, "FAIL"); }); for (const mutation of ["missing", "unexpected", "duplicate", "skipped", "failed", "timedOut", "interrupted", "retry", "expected-failure", "fake-pass", "candidate", "errors", "title-drift"]) test(`本地结果反例:${mutation}`, context => { const f = fixture(context), p = f.plan(), r = report(p.localCases, true); let current = candidate; const row = r.suites[0].specs[0].tests[0]; if (mutation === "missing") r.suites.pop(); if (mutation === "unexpected") r.suites.push(report([f.rows[1]], true).suites[0]); if (mutation === "duplicate") r.suites.push(r.suites[0]); if (["skipped", "failed", "timedOut", "interrupted"].includes(mutation)) row.results[0].status = mutation; if (mutation === "retry") row.results.push({ status: "passed", retry: 1 }); if (mutation === "expected-failure") row.expectedStatus = "failed"; if (mutation === "fake-pass") { r.passed = true; delete row.results; } if (mutation === "candidate") current = { ...candidate, digest: "c".repeat(64) }; if (mutation === "errors") r.errors.push({ message: "synthetic" }); if (mutation === "title-drift") r.suites[0].specs[0].title = "changed"; assert.equal(verifyLocalCoverage(p, r, current).status, "FAIL"); }); test("公网只接受同候选 live 逐项结果,不接受本地或布尔通过", context => { const f = fixture(context), p = f.plan(); const good = { profile: "post-deploy-live", mode: "live", candidate, deployedCandidate: candidate, report: report([f.rows[1]], true) }; assert.equal(verifyPostDeployCoverage(p, good).status, "PASS"); for (const bad of [{ passed: true }, { ...good, profile: "full-local" }, { ...good, mode: "local" }, { ...good, deployedCandidate: { ...candidate, commit: "c".repeat(40) } }, { ...good, candidate: { ...candidate, digest: "d".repeat(64) } }, { ...good, report: report(p.localCases, true) }]) assert.equal(verifyPostDeployCoverage(p, bad).status, "FAIL"); });