文件
hyb-oa/server/tests/unit/scripts/check-wecom-approval-readability-gate.test.js
T

221 行
7.7 KiB
JavaScript

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);
});
});