564 行
20 KiB
JavaScript
564 行
20 KiB
JavaScript
const {
|
|
buildInputs,
|
|
buildSecretCheck,
|
|
buildTimeWindow,
|
|
compareCallbackEvidence,
|
|
executeCompensationPoc,
|
|
parseArgs,
|
|
statusLabelFromSpStatus,
|
|
} = require("../../../src/scripts/check-wecom-approval-compensation-poc");
|
|
const {
|
|
fetchWecomApprovalInfoList,
|
|
maskApprovalIdentifier,
|
|
} = require("../../../src/services/integrations/wecomApproval");
|
|
const { clearWecomAppAccessTokenCache } = require("../../../src/services/integrations/wecomAccessToken");
|
|
|
|
const SENSITIVE_AGENT_CREDENTIAL = ["compensation", "agent", "credential", "should", "never", "leak"].join("-");
|
|
const SENSITIVE_CONTACT_CREDENTIAL = ["compensation", "contact", "credential", "unused"].join("-");
|
|
const SENSITIVE_CHECKIN_CREDENTIAL = ["compensation", "checkin", "credential", "unused"].join("-");
|
|
const SENSITIVE_HR_CREDENTIAL = ["compensation", "hr", "credential", "unused"].join("-");
|
|
const SENSITIVE_TEMPLATE_ID = ["tpl", "compensation", "full", "identifier", "must", "not", "leak"].join("-");
|
|
const SENSITIVE_SP_NO = ["sp", "compensation", "full", "identifier", "must", "not", "leak"].join("-");
|
|
const SENSITIVE_USER_ID = ["compensation", "userid", "full", "must", "not", "leak"].join("_");
|
|
const SENSITIVE_FORM_VALUE = "这里是审批表单值,报告不得输出";
|
|
|
|
function baseConfig(overrides = {}) {
|
|
return {
|
|
wecomCorpId: "corp-compensation",
|
|
wecomAgentId: "1000002",
|
|
wecomAgentSecret: SENSITIVE_AGENT_CREDENTIAL,
|
|
wecomContactSecret: SENSITIVE_CONTACT_CREDENTIAL,
|
|
wecomCheckinSecret: SENSITIVE_CHECKIN_CREDENTIAL,
|
|
wecomHrAssistantSecret: SENSITIVE_HR_CREDENTIAL,
|
|
wecomApprovalCallbackEvidenceFile: "/tmp/wacp3-test-evidence.jsonl",
|
|
wecomRequestTimeoutMs: 1000,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function baseOptions(overrides = {}) {
|
|
return {
|
|
live: true,
|
|
format: "json",
|
|
reportDir: "/tmp/wecom-approval-compensation-test",
|
|
startTime: "2026-05-19T00:00:00.000Z",
|
|
endTime: "2026-05-20T00:00:00.000Z",
|
|
templates: {
|
|
leave: SENSITIVE_TEMPLATE_ID,
|
|
missed_punch: "tpl-missed-punch",
|
|
},
|
|
size: 100,
|
|
maxPages: 10,
|
|
help: false,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function jsonResponse(payload, status = 200) {
|
|
return {
|
|
ok: status >= 200 && status < 300,
|
|
status,
|
|
json: async () => payload,
|
|
};
|
|
}
|
|
|
|
function detailSummary(spNo = SENSITIVE_SP_NO, overrides = {}) {
|
|
return {
|
|
spNoPrefix: maskApprovalIdentifier(spNo),
|
|
templateIdPrefix: maskApprovalIdentifier(SENSITIVE_TEMPLATE_ID),
|
|
spStatus: "2",
|
|
applyFieldCount: 3,
|
|
approvalNodeCount: 1,
|
|
notifyerCount: 1,
|
|
commentCount: 0,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("check-wecom-approval-compensation-poc", () => {
|
|
beforeEach(() => {
|
|
clearWecomAppAccessTokenCache();
|
|
});
|
|
|
|
it("parses CLI window, size and template filters", () => {
|
|
const options = parseArgs([
|
|
"--live",
|
|
"--format=json",
|
|
"--start-time=2026-05-19T00:00:00.000Z",
|
|
"--end-time=2026-05-20T00:00:00.000Z",
|
|
"--size=50",
|
|
"--template=leave:tpl-leave",
|
|
"--template=missed_punch:tpl-missed",
|
|
"--discover-template-ids",
|
|
"--discover-applicant-employee-no=SMOKE002",
|
|
]);
|
|
|
|
expect(options.live).toBe(true);
|
|
expect(options.format).toBe("json");
|
|
expect(options.size).toBe(50);
|
|
expect(options.discoverTemplateIds).toBe(true);
|
|
expect(options.discoverApplicantEmployeeNo).toBe("SMOKE002");
|
|
expect(options.templates).toEqual({
|
|
leave: "tpl-leave",
|
|
missed_punch: "tpl-missed",
|
|
});
|
|
expect(() => parseArgs(["--template=outing:tpl"])).toThrow(/unsupported target/);
|
|
expect(() => parseArgs(["--size=101"])).toThrow(/--size/);
|
|
});
|
|
|
|
it("builds a default 72-hour time window", () => {
|
|
const window = buildTimeWindow(baseOptions({ startTime: "", endTime: "" }), "2026-05-20T00:00:00.000Z");
|
|
|
|
expect(window.endTime - window.startTime).toBe(72 * 60 * 60);
|
|
expect(window.defaultWindowHours).toBe(72);
|
|
});
|
|
|
|
it("builds inputs from CLI first, then env, with masked template previews", () => {
|
|
const inputs = buildInputs(baseOptions({
|
|
templates: { leave: SENSITIVE_TEMPLATE_ID },
|
|
}), {
|
|
WECOM_APPROVAL_LEAVE_TEMPLATE_ID: "env-should-not-win",
|
|
WECOM_APPROVAL_MISSED_PUNCH_TEMPLATE_ID: "env-missed-template",
|
|
});
|
|
|
|
expect(inputs.find((item) => item.key === "leave")).toMatchObject({
|
|
templateSource: "cli",
|
|
templateIdPrefix: maskApprovalIdentifier(SENSITIVE_TEMPLATE_ID),
|
|
});
|
|
expect(inputs.find((item) => item.key === "missed_punch")).toMatchObject({
|
|
templateSource: "WECOM_APPROVAL_MISSED_PUNCH_TEMPLATE_ID",
|
|
templateIdPrefix: maskApprovalIdentifier("env-missed-template"),
|
|
});
|
|
});
|
|
|
|
it("documents WECOM_AGENT_SECRET as the only Secret source", () => {
|
|
const check = buildSecretCheck(baseConfig());
|
|
expect(check).toMatchObject({
|
|
status: "OK",
|
|
source: "WECOM_AGENT_SECRET",
|
|
endpoints: [
|
|
"POST /cgi-bin/oa/getapprovalinfo",
|
|
"POST /cgi-bin/oa/getapprovaldetail",
|
|
],
|
|
});
|
|
expect(check.noFallback).toEqual([
|
|
"WECOM_CONTACT_SECRET",
|
|
"WECOM_CHECKIN_SECRET",
|
|
"WECOM_HR_ASSISTANT_SECRET",
|
|
]);
|
|
expect(buildSecretCheck(baseConfig({ wecomAgentSecret: "" }))).toMatchObject({
|
|
status: "BLOCKED",
|
|
missing: ["WECOM_AGENT_SECRET"],
|
|
});
|
|
});
|
|
|
|
it("calls getapprovalinfo with template filter and redacts sp_no list", async () => {
|
|
const fetchImpl = vi.fn(async (url, init) => {
|
|
const urlText = String(url);
|
|
if (urlText.includes("/cgi-bin/gettoken")) {
|
|
expect(urlText).toContain("corpsecret=");
|
|
return jsonResponse({ errcode: 0, errmsg: "ok", access_token: "token-compensation", expires_in: 7200 });
|
|
}
|
|
expect(urlText).toContain("/cgi-bin/oa/getapprovalinfo");
|
|
expect(urlText).not.toContain(SENSITIVE_AGENT_CREDENTIAL);
|
|
const body = JSON.parse(init.body);
|
|
expect(body).toMatchObject({
|
|
starttime: 1779148800,
|
|
endtime: 1779235200,
|
|
size: 50,
|
|
filters: [{ key: "template_id", value: SENSITIVE_TEMPLATE_ID }],
|
|
});
|
|
return jsonResponse({
|
|
errcode: 0,
|
|
errmsg: "ok",
|
|
sp_no_list: [SENSITIVE_SP_NO],
|
|
next_cursor: "",
|
|
});
|
|
});
|
|
|
|
const result = await fetchWecomApprovalInfoList({
|
|
config: baseConfig(),
|
|
startTime: 1779148800,
|
|
endTime: 1779235200,
|
|
size: 50,
|
|
filters: [{ key: "template_id", value: SENSITIVE_TEMPLATE_ID }],
|
|
fetchImpl,
|
|
});
|
|
|
|
expect(result.ok).toBe(true);
|
|
expect(result.spNos).toEqual([SENSITIVE_SP_NO]);
|
|
expect(result.response.spNoPrefixes).toEqual([maskApprovalIdentifier(SENSITIVE_SP_NO)]);
|
|
expect(JSON.stringify(result.response)).not.toContain(SENSITIVE_SP_NO);
|
|
});
|
|
|
|
it("returns PARTIAL_COMPENSATION_NEEDS_CONFIG when template filters are missing", async () => {
|
|
const report = await executeCompensationPoc(baseOptions({
|
|
templates: {},
|
|
}), {
|
|
config: baseConfig(),
|
|
env: {},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
fetchApprovalInfoListImpl: vi.fn(),
|
|
fetchApprovalDetailImpl: vi.fn(),
|
|
readCallbackEvidenceImpl: vi.fn(async () => []),
|
|
});
|
|
|
|
expect(report.status).toBe("PARTIAL_COMPENSATION_NEEDS_CONFIG");
|
|
expect(report.configGaps.map((item) => item.id)).toContain("approval_compensation_pull");
|
|
expect(report.configGaps.map((item) => item.id)).not.toContain("approval_compensation_window_empty");
|
|
expect(report.checks.targets.every((item) => item.status === "NEEDS_CONFIG")).toBe(true);
|
|
});
|
|
|
|
it("returns PARTIAL_COMPENSATION_NEEDS_CONFIG in dry-run even when templates are configured", async () => {
|
|
const report = await executeCompensationPoc(baseOptions({ live: false }), {
|
|
config: baseConfig(),
|
|
env: {},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
readCallbackEvidenceImpl: vi.fn(async () => []),
|
|
});
|
|
|
|
expect(report.status).toBe("PARTIAL_COMPENSATION_NEEDS_CONFIG");
|
|
expect(report.configGaps.map((item) => item.id)).toContain("live_read");
|
|
expect(report.checks.targets.every((item) => item.status === "DRY_RUN_READY")).toBe(true);
|
|
});
|
|
|
|
it("auto-discovers missing template IDs by applicant creator without leaking full identifiers", async () => {
|
|
const discoveredLeaveTemplateId = "tpllv-auto-discovered-leave-sensitive";
|
|
const discoveredMissedTemplateId = "tplmp-auto-discovered-missed-sensitive";
|
|
const fetchApprovalInfoListImpl = vi.fn(async ({ filters }) => {
|
|
if (filters[0].key === "creator") {
|
|
return {
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
response: {
|
|
errcode: 0,
|
|
spNoCount: 2,
|
|
spNoPrefixes: [maskApprovalIdentifier("sp-discovery-leave"), maskApprovalIdentifier("sp-discovery-missed")],
|
|
},
|
|
spNos: ["sp-discovery-leave", "sp-discovery-missed"],
|
|
nextCursor: "",
|
|
};
|
|
}
|
|
return {
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
response: {
|
|
errcode: 0,
|
|
spNoCount: 1,
|
|
spNoPrefixes: [maskApprovalIdentifier(`${filters[0].value}-sp`)],
|
|
},
|
|
spNos: [`${filters[0].value}-sp`],
|
|
nextCursor: "",
|
|
};
|
|
});
|
|
const fetchApprovalDetailImpl = vi.fn(async ({ spNo }) => {
|
|
if (spNo === "sp-discovery-leave") {
|
|
return {
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
templateId: discoveredLeaveTemplateId,
|
|
spName: "OA-POC-请假-2026-05-19",
|
|
summary: detailSummary(spNo, { templateIdPrefix: maskApprovalIdentifier(discoveredLeaveTemplateId) }),
|
|
response: { errcode: 0, spStatus: "2" },
|
|
};
|
|
}
|
|
if (spNo === "sp-discovery-missed") {
|
|
return {
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
templateId: discoveredMissedTemplateId,
|
|
spName: "OA-POC-补卡-2026-05-19",
|
|
summary: detailSummary(spNo, { templateIdPrefix: maskApprovalIdentifier(discoveredMissedTemplateId) }),
|
|
response: { errcode: 0, spStatus: "2" },
|
|
};
|
|
}
|
|
return {
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
summary: detailSummary(spNo, {
|
|
templateIdPrefix: spNo.startsWith(discoveredLeaveTemplateId)
|
|
? maskApprovalIdentifier(discoveredLeaveTemplateId)
|
|
: maskApprovalIdentifier(discoveredMissedTemplateId),
|
|
}),
|
|
response: { errcode: 0, spStatus: "2" },
|
|
};
|
|
});
|
|
|
|
const report = await executeCompensationPoc(baseOptions({
|
|
templates: {},
|
|
discoverTemplateIds: true,
|
|
discoverApplicantEmployeeNo: "SMOKE002",
|
|
}), {
|
|
config: baseConfig(),
|
|
env: {},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
queryApplicantActorImpl: vi.fn(async () => ({
|
|
employeeNo: "SMOKE002",
|
|
status: "active",
|
|
archived: false,
|
|
wecomExternalUserId: SENSITIVE_USER_ID,
|
|
})),
|
|
fetchApprovalInfoListImpl,
|
|
fetchApprovalDetailImpl,
|
|
readCallbackEvidenceImpl: vi.fn(async () => [
|
|
{
|
|
callbackKind: "approval_status_change",
|
|
spStatus: "2",
|
|
statusLabel: "已通过",
|
|
spNoPrefix: maskApprovalIdentifier(`${discoveredLeaveTemplateId}-sp`),
|
|
},
|
|
{
|
|
callbackKind: "approval_status_change",
|
|
spStatus: "2",
|
|
statusLabel: "已通过",
|
|
spNoPrefix: maskApprovalIdentifier(`${discoveredMissedTemplateId}-sp`),
|
|
},
|
|
]),
|
|
});
|
|
|
|
expect(report.status).toBe("PASS_COMPENSATION_POC");
|
|
expect(fetchApprovalInfoListImpl.mock.calls[0][0].filters).toEqual([
|
|
{ key: "creator", value: SENSITIVE_USER_ID },
|
|
]);
|
|
expect(fetchApprovalInfoListImpl.mock.calls[1][0].filters).toEqual([
|
|
{ key: "template_id", value: discoveredLeaveTemplateId },
|
|
]);
|
|
expect(fetchApprovalInfoListImpl.mock.calls[2][0].filters).toEqual([
|
|
{ key: "template_id", value: discoveredMissedTemplateId },
|
|
]);
|
|
const serialized = JSON.stringify(report);
|
|
expect(serialized).not.toContain(discoveredLeaveTemplateId);
|
|
expect(serialized).not.toContain(discoveredMissedTemplateId);
|
|
expect(serialized).not.toContain(SENSITIVE_USER_ID);
|
|
expect(report.checks.templateDiscovery.discoveredTemplatePrefixes).toEqual({
|
|
leave: maskApprovalIdentifier(discoveredLeaveTemplateId),
|
|
missed_punch: maskApprovalIdentifier(discoveredMissedTemplateId),
|
|
});
|
|
});
|
|
|
|
it("pulls approval numbers and details, then passes when callback evidence matches", async () => {
|
|
const fetchApprovalInfoListImpl = vi.fn(async ({ filters }) => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
response: {
|
|
errcode: 0,
|
|
spNoCount: 1,
|
|
spNoPrefixes: [maskApprovalIdentifier(`${filters[0].value}-sp`)],
|
|
},
|
|
spNos: [`${filters[0].value}-sp`],
|
|
nextCursor: "",
|
|
}));
|
|
const fetchApprovalDetailImpl = vi.fn(async ({ spNo }) => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
summary: detailSummary(spNo, {
|
|
templateIdPrefix: spNo.startsWith(SENSITIVE_TEMPLATE_ID)
|
|
? maskApprovalIdentifier(SENSITIVE_TEMPLATE_ID)
|
|
: maskApprovalIdentifier("tpl-missed-punch"),
|
|
}),
|
|
response: {
|
|
errcode: 0,
|
|
spStatus: "2",
|
|
applyFieldCount: 3,
|
|
approvalNodeCount: 1,
|
|
commentCount: 0,
|
|
},
|
|
}));
|
|
const evidence = [
|
|
{
|
|
callbackKind: "approval_status_change",
|
|
approvalType: "leave",
|
|
spStatus: "2",
|
|
statusLabel: "已通过",
|
|
spNoPrefix: maskApprovalIdentifier(`${SENSITIVE_TEMPLATE_ID}-sp`),
|
|
templateIdPrefix: maskApprovalIdentifier(SENSITIVE_TEMPLATE_ID),
|
|
},
|
|
{
|
|
callbackKind: "approval_status_change",
|
|
approvalType: "missed_punch",
|
|
spStatus: "2",
|
|
statusLabel: "已通过",
|
|
spNoPrefix: maskApprovalIdentifier("tpl-missed-punch-sp"),
|
|
templateIdPrefix: maskApprovalIdentifier("tpl-missed-punch"),
|
|
},
|
|
];
|
|
|
|
const report = await executeCompensationPoc(baseOptions(), {
|
|
config: baseConfig(),
|
|
env: {},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
fetchApprovalInfoListImpl,
|
|
fetchApprovalDetailImpl,
|
|
readCallbackEvidenceImpl: vi.fn(async () => evidence),
|
|
});
|
|
|
|
expect(report.status).toBe("PASS_COMPENSATION_POC");
|
|
expect(fetchApprovalInfoListImpl).toHaveBeenCalledTimes(2);
|
|
expect(fetchApprovalDetailImpl).toHaveBeenCalledTimes(2);
|
|
expect(report.checks.callbackCompare.findings).toEqual([]);
|
|
});
|
|
|
|
it("returns PASS_WITH_FINDINGS for missing callback and status mismatch", async () => {
|
|
const report = await executeCompensationPoc(baseOptions(), {
|
|
config: baseConfig(),
|
|
env: {},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
fetchApprovalInfoListImpl: vi.fn(async () => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
response: { errcode: 0, spNoCount: 1 },
|
|
spNos: [SENSITIVE_SP_NO],
|
|
nextCursor: "",
|
|
})),
|
|
fetchApprovalDetailImpl: vi.fn(async ({ spNo }) => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
summary: detailSummary(spNo, { spStatus: "2" }),
|
|
response: { errcode: 0, spStatus: "2" },
|
|
})),
|
|
readCallbackEvidenceImpl: vi.fn(async () => [{
|
|
callbackKind: "approval_status_change",
|
|
spStatus: "3",
|
|
statusLabel: "已驳回",
|
|
spNoPrefix: maskApprovalIdentifier(SENSITIVE_SP_NO),
|
|
}]),
|
|
});
|
|
|
|
expect(report.status).toBe("PASS_WITH_FINDINGS");
|
|
expect(report.checks.callbackCompare.findings.map((item) => item.id)).toContain("callback_status_mismatch");
|
|
});
|
|
|
|
it("treats missing callback evidence after successful detail pull as findings", async () => {
|
|
const report = await executeCompensationPoc(baseOptions({
|
|
templates: { leave: SENSITIVE_TEMPLATE_ID, missed_punch: "tpl-missed-punch" },
|
|
}), {
|
|
config: baseConfig(),
|
|
env: {},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
fetchApprovalInfoListImpl: vi.fn(async () => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
response: { errcode: 0, spNoCount: 1 },
|
|
spNos: [SENSITIVE_SP_NO],
|
|
nextCursor: "",
|
|
})),
|
|
fetchApprovalDetailImpl: vi.fn(async ({ spNo }) => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
summary: detailSummary(spNo, { spStatus: "2" }),
|
|
response: { errcode: 0, spStatus: "2" },
|
|
})),
|
|
readCallbackEvidenceImpl: vi.fn(async () => []),
|
|
});
|
|
|
|
expect(report.status).toBe("PASS_WITH_FINDINGS");
|
|
expect(report.configGaps.map((item) => item.id)).not.toContain("callback_evidence_missing");
|
|
expect(report.checks.callbackCompare.findings.map((item) => item.id)).toContain("callback_missing_for_pulled_detail");
|
|
});
|
|
|
|
it("classifies WeCom API errors as BLOCKED_BY_EXTERNAL_CONFIG", async () => {
|
|
const report = await executeCompensationPoc(baseOptions({
|
|
templates: { leave: SENSITIVE_TEMPLATE_ID },
|
|
}), {
|
|
config: baseConfig(),
|
|
env: {},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
fetchApprovalInfoListImpl: vi.fn(async () => ({
|
|
ok: false,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
code: "wecom_approval_api_error",
|
|
message: "WeCom approval API errcode 48002",
|
|
response: { errcode: 48002, errmsg: "api forbidden" },
|
|
spNos: [],
|
|
})),
|
|
fetchApprovalDetailImpl: vi.fn(),
|
|
readCallbackEvidenceImpl: vi.fn(async () => []),
|
|
});
|
|
|
|
expect(report.status).toBe("SKIP");
|
|
expect(report.conclusion).toBe("BLOCKED_BY_EXTERNAL_CONFIG");
|
|
expect(report.mainBlockers[0]).toMatchObject({
|
|
reason: "wecom_approval_api_error",
|
|
});
|
|
});
|
|
|
|
it("compares callback evidence using redacted prefixes", () => {
|
|
const compare = compareCallbackEvidence([
|
|
{
|
|
details: [{
|
|
target: "leave",
|
|
spNoPrefix: "SPMATCH***",
|
|
spStatus: "2",
|
|
statusLabel: "已通过",
|
|
status: "OK",
|
|
}],
|
|
},
|
|
], {
|
|
eventCount: 2,
|
|
bySpNoPrefix: {
|
|
"SPMATCH***": [
|
|
{ spNoPrefix: "SPMATCH***", spStatus: "2", statusLabel: "已通过" },
|
|
{ spNoPrefix: "SPMATCH***", spStatus: "2", statusLabel: "已通过" },
|
|
],
|
|
"SPONLYCB***": [
|
|
{ spNoPrefix: "SPONLYCB***", spStatus: "2", statusLabel: "已通过" },
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(compare.status).toBe("FINDINGS");
|
|
expect(compare.findings.map((item) => item.id)).toEqual(expect.arrayContaining([
|
|
"callback_duplicate_for_pulled_detail",
|
|
"callback_not_in_compensation_window",
|
|
]));
|
|
});
|
|
|
|
it("redacts secrets, full identifiers and form values from reports", async () => {
|
|
const report = await executeCompensationPoc(baseOptions({
|
|
templates: { leave: SENSITIVE_TEMPLATE_ID },
|
|
}), {
|
|
config: baseConfig(),
|
|
env: {
|
|
WECOM_AGENT_SECRET: SENSITIVE_AGENT_CREDENTIAL,
|
|
},
|
|
generatedAt: "2026-05-20T00:00:00.000Z",
|
|
fetchApprovalInfoListImpl: vi.fn(async () => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
response: { errcode: 0, spNoCount: 1, spNoPrefixes: [maskApprovalIdentifier(SENSITIVE_SP_NO)] },
|
|
spNos: [SENSITIVE_SP_NO],
|
|
nextCursor: "",
|
|
})),
|
|
fetchApprovalDetailImpl: vi.fn(async ({ spNo }) => ({
|
|
ok: true,
|
|
tokenSource: "WECOM_AGENT_SECRET",
|
|
summary: detailSummary(spNo),
|
|
response: {
|
|
errcode: 0,
|
|
spStatus: "2",
|
|
applyFieldCount: 3,
|
|
approvalNodeCount: 1,
|
|
},
|
|
})),
|
|
readCallbackEvidenceImpl: vi.fn(async () => [{
|
|
callbackKind: "approval_status_change",
|
|
spStatus: "2",
|
|
statusLabel: "已通过",
|
|
spNoPrefix: maskApprovalIdentifier(SENSITIVE_SP_NO),
|
|
templateIdPrefix: maskApprovalIdentifier(SENSITIVE_TEMPLATE_ID),
|
|
}]),
|
|
});
|
|
const serialized = JSON.stringify(report);
|
|
|
|
expect(serialized).not.toContain(SENSITIVE_AGENT_CREDENTIAL);
|
|
expect(serialized).not.toContain(SENSITIVE_CONTACT_CREDENTIAL);
|
|
expect(serialized).not.toContain(SENSITIVE_CHECKIN_CREDENTIAL);
|
|
expect(serialized).not.toContain(SENSITIVE_HR_CREDENTIAL);
|
|
expect(serialized).not.toContain(SENSITIVE_SP_NO);
|
|
expect(serialized).not.toContain(SENSITIVE_TEMPLATE_ID);
|
|
expect(serialized).not.toContain(SENSITIVE_USER_ID);
|
|
expect(serialized).not.toContain(SENSITIVE_FORM_VALUE);
|
|
expect(statusLabelFromSpStatus("2")).toBe("已通过");
|
|
});
|
|
});
|