const fs = require("node:fs"); const os = require("node:os"); const path = require("node:path"); const { executeReadabilityGate, parseArgs, } = require("../../../src/scripts/check-wecom-approval-readability-gate"); const SENSITIVE_TEMPLATE_ID = "tpl_readability_full_identifier_must_not_leak"; const SENSITIVE_SP_NO = "SPREADABILITYFULLIDENTIFIERMUSTNOTLEAK"; const SENSITIVE_USER_ID = "readability_userid_full_must_not_leak"; const SENSITIVE_FORM_VALUE = "这里是表单值,不应出现在报告里"; function tempDir() { return fs.mkdtempSync(path.join(os.tmpdir(), "wread1-test-")); } function writeSummary(root, dirname, payload) { const dir = path.join(root, dirname); fs.mkdirSync(dir, { recursive: true }); const filePath = path.join(dir, "summary.json"); fs.writeFileSync(filePath, JSON.stringify(payload, null, 2)); return filePath; } function writeOkEvidence(root) { writeSummary(root, "wecom-approval-fixtures-20260519T053400Z", { status: "PASS_FIXTURE_CREATED", conclusion: "PASS_FIXTURE_CREATED", checks: { liveWrite: { createdTemplatePrefixes: { leave: "tpl-leav***", missed_punch: "tpl-miss***", }, submittedApprovalPrefixes: { leave: "SPLEAVE***", missed_punch: "SPMISS***", }, }, autoRerun: { status: "OK", }, }, rawShouldNotCopy: SENSITIVE_TEMPLATE_ID, }); writeSummary(root, "wecom-approval-callback-poc-20260519T092648Z", { status: "PASS_CALLBACK_EVENT_CONFIRMED", conclusion: "PASS_CALLBACK_EVENT_CONFIRMED", checks: { eventEvidence: { eventCount: 1, lastEvent: { approvalType: "missed_punch", statusLabel: "已通过", spNoPrefix: "SPMISS***", templateIdPrefix: "tpl-miss***", recordedAt: "2026-05-19T09:26:48.000Z", rawShouldNotCopy: SENSITIVE_SP_NO, }, }, }, }); writeSummary(root, "wecom-approval-compensation-poc-20260519T115944Z", { status: "PASS_WITH_FINDINGS", conclusion: "PASS_WITH_FINDINGS", checks: { templateDiscovery: { status: "OK", discovered: { leave: SENSITIVE_TEMPLATE_ID } }, targets: [ { target: "leave", status: "OK", detailCount: 1, statusSummary: { "审批中": 1 }, details: [{ spNoPrefix: "SPLEAVE***", rawShouldNotCopy: SENSITIVE_FORM_VALUE }], }, { target: "missed_punch", status: "OK", detailCount: 1, statusSummary: { "已通过": 1 }, details: [{ spNoPrefix: "SPMISS***" }], }, ], callbackCompare: { findings: [ { id: "callback_missing_for_pulled_detail", target: "leave", spNoPrefix: "SPLEAVE***" }, ], }, }, rawUserId: SENSITIVE_USER_ID, }); } describe("check-wecom-approval-readability-gate", () => { it("parses manual results and report options", () => { const options = parseArgs([ "--format=json", "--artifact-root=/tmp/wread1-artifacts", "--manual-result=leave:PASS_READABLE", "--manual-result=missed_punch:PASS_WITH_TEMPLATE_ADJUSTMENTS", "--manual-note=leave:卡片可读", "--confirmed-by=wangshunli", ]); expect(options.format).toBe("json"); expect(options.artifactRoot).toBe("/tmp/wread1-artifacts"); expect(options.manualResults).toEqual({ leave: "PASS_READABLE", missed_punch: "PASS_WITH_TEMPLATE_ADJUSTMENTS", }); expect(options.manualNotes.leave).toBe("卡片可读"); expect(options.confirmedBy).toBe("wangshunli"); expect(() => parseArgs(["--manual-result=leave:PASS"])).toThrow(/Unsupported manual result/); }); it("pauses for manual confirmation when existing evidence is available", async () => { const root = tempDir(); writeOkEvidence(root); const report = await executeReadabilityGate({ ...parseArgs(["--artifact-root", root]), reportDir: path.join(root, "out"), }, { generatedAt: "2026-05-20T00:00:00.000Z" }); expect(report.status).toBe("PAUSED_MANUAL_CONFIRMATION"); expect(report.checks.sampleEvidence.status).toBe("OK"); expect(report.checks.evidence.fixtures.status).toBe("OK"); expect(report.checks.evidence.compensation.status).toBe("OK"); expect(report.checks.manualResults.map((item) => item.status)).toEqual([ "PENDING_MANUAL_CONFIRMATION", "PENDING_MANUAL_CONFIRMATION", ]); }); it("accepts WACP3R compensation detail evidence when historical fixture artifacts are not persisted", async () => { const root = tempDir(); writeSummary(root, "wecom-approval-compensation-poc-20260519T115944Z", { status: "PASS_WITH_FINDINGS", conclusion: "PASS_WITH_FINDINGS", checks: { templateDiscovery: { status: "OK" }, targets: [ { target: "leave", status: "OK", details: [{ spNoPrefix: "SPLEAVE***" }], }, { target: "missed_punch", status: "OK", details: [{ spNoPrefix: "SPMISS***" }], }, ], callbackCompare: { findings: [] }, }, }); const report = await executeReadabilityGate(parseArgs(["--artifact-root", root]), { generatedAt: "2026-05-20T00:00:00.000Z", }); expect(report.status).toBe("PAUSED_MANUAL_CONFIRMATION"); expect(report.checks.sampleEvidence.status).toBe("OK"); expect(report.checks.sampleEvidence.reason).toBe("wacp3r_compensation_detail_evidence_available"); expect(report.checks.evidence.fixtures.status).toBe("MISSING"); }); it("returns PASS_WITH_TEMPLATE_ADJUSTMENTS when one template needs changes", async () => { const root = tempDir(); writeOkEvidence(root); const report = await executeReadabilityGate(parseArgs([ "--artifact-root", root, "--manual-result=leave:PASS_READABLE", "--manual-result=missed_punch:PASS_WITH_TEMPLATE_ADJUSTMENTS", "--manual-note=missed_punch:快捷按钮容易误点,需要提醒审批人点详情", "--confirmed-by=wangshunli", ]), { generatedAt: "2026-05-20T00:00:00.000Z" }); expect(report.status).toBe("PASS_WITH_TEMPLATE_ADJUSTMENTS"); expect(report.confirmedBy).toBe("wangshunli"); expect(report.checks.manualResults.find((item) => item.target === "missed_punch").note).toContain("快捷按钮"); }); it("asks for a fresh fixture when existing sample evidence is missing", async () => { const root = tempDir(); writeSummary(root, "wecom-approval-compensation-poc-20260519T115944Z", { status: "PASS_WITH_FINDINGS", checks: { targets: [] }, }); const report = await executeReadabilityGate(parseArgs(["--artifact-root", root]), { generatedAt: "2026-05-20T00:00:00.000Z", }); expect(report.status).toBe("PARTIAL_READABILITY_NEEDS_FRESH_FIXTURE"); expect(report.configGaps.map((item) => item.id)).toContain("readability_existing_sample"); }); it("does not leak full template, sp_no, userid or form values", async () => { const root = tempDir(); writeOkEvidence(root); const report = await executeReadabilityGate(parseArgs([ "--artifact-root", root, "--manual-result=leave:PASS_READABLE", "--manual-result=missed_punch:PASS_READABLE", "--manual-note=leave:不要泄露 SPREADABILITYFULLIDENTIFIERMUSTNOTLEAK", ]), { generatedAt: "2026-05-20T00:00:00.000Z" }); const serialized = JSON.stringify(report); expect(report.status).toBe("PASS_READABLE"); expect(serialized).not.toContain(SENSITIVE_TEMPLATE_ID); expect(serialized).not.toContain(SENSITIVE_SP_NO); expect(serialized).not.toContain(SENSITIVE_USER_ID); expect(serialized).not.toContain(SENSITIVE_FORM_VALUE); }); });