文件
hyb-oa/scripts/qa/tests/prepare-local-e2e-accounts.test.mjs
wangsli 1f8d5b658a 完善借款、编号、付款与预算并发及验收(09-06-release-gate-integrity)
汇总已落盘的借款本金与还款、兼容历史编号的周期化编号、付款责任与回单核验、报销进度和排序、PWA/采购事务、错误原因与日期校验及ERP退役。
统一共享预算池锁序和锁后判断,恢复差旅原预算选择,补原因码固定夹具及反向完整性检查。
纳入配套迁移、测试、受管QA、分层验收合同、规约及任务记录;原始证据留在ignored artifacts。

关联任务:09-17-company-loan-principal-repayment、09-17-erp-exclusive-retirement、09-18-reimbursement-periodic-numbering、09-08-reimbursement-payment-closeout、09-18-local-concurrency-product-fixes、09-19-budget-pool-concurrency、09-05-error-explainability-payment-readiness。
预算补审由Claude定向验证2文件928项通过,原4446/28及r6结果仍仅对应各自历史输入;本轮未重跑测试。
完整新候选门禁、R1真实入口接入与12项公网义务仍开放。生产编号未启用、差旅仍冻结;不推送、不部署,不宣称发布资格。
2026-09-19 13:11:04 +08:00

43 行
2.2 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { prepareAccounts, localAccounts } from "../prepare-local-e2e-accounts.mjs";
const input = { origin: "http://127.0.0.1:12345", databaseName: "hyb_oa_webgate_synthetic", initialPassword: "Initial!synthetic-only-123456789" };
test("preparation refuses remote origins, wrong database and reused initial credentials before any request", async () => {
for (const change of [{ origin: "https://example.invalid" }, { origin: "http://127.0.0.1:1/api" },
{ databaseName: "production" }, { initialPassword: localAccounts[0].password }]) {
let calls = 0;
await assert.rejects(prepareAccounts({ ...input, ...change, fetchImpl: async () => { calls++; } }));
assert.equal(calls, 0);
}
});
test("all roles must really require change, reject old password and login again; receipts contain no credentials", async () => {
const calls = [];
const result = await prepareAccounts({ ...input, fetchImpl: async (url, request) => {
const step = calls.length % 4;
calls.push({ url, body: JSON.parse(request.body) });
assert.equal(request.redirect, "error");
assert.equal(new URL(url).pathname, step === 1 ? "/api/auth/change-password" : "/api/auth/login");
if (step === 1) assert.equal(request.headers.authorization, "Bearer synthetic");
return { status: step === 2 ? 401 : 200, json: async () => ({ data: { accessToken: "synthetic", mustChangePassword: step === 0 } }) };
} });
assert.equal(calls.length, localAccounts.length * 4);
assert.equal(result.accounts.length, 8);
assert.ok(!JSON.stringify(result).includes(input.initialPassword));
assert.ok(localAccounts.every(a => !JSON.stringify(result).includes(a.password)));
});
test("one false precondition stops before changing any further account", async () => {
for (const failingStep of [0, 1, 2, 3]) {
let calls = 0;
await assert.rejects(prepareAccounts({ ...input, fetchImpl: async () => {
const step = calls++;
return { status: step === failingStep ? 503 : step === 2 ? 401 : 200,
json: async () => ({ data: { accessToken: "synthetic", mustChangePassword: step === 0 } }) };
} }));
assert.equal(calls, failingStep + 1);
}
});