汇总已落盘的借款本金与还款、兼容历史编号的周期化编号、付款责任与回单核验、报销进度和排序、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项公网义务仍开放。生产编号未启用、差旅仍冻结;不推送、不部署,不宣称发布资格。
48 行
2.7 KiB
JavaScript
48 行
2.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import test from 'node:test';
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
const source = readFileSync(path.join(root, 'server/scripts/regression-workflow-actions.sh'), 'utf8');
|
|
function checkResponse(context, code, details, candidate = source) {
|
|
const directory = mkdtempSync(path.join(os.tmpdir(), 'hyb-payment-profile-'));
|
|
context.after(() => rmSync(directory, { recursive: true, force: true }));
|
|
writeFileSync(path.join(directory, 'pay-ok-pay.json'), JSON.stringify({ error: { code: 'VALID_001', details } }));
|
|
// Execute the candidate's real shell assertions. No app, database, or HTTP tools are started.
|
|
const helpers = ['assert_status', 'assert_error_code', 'assert_error_detail'].map(name => {
|
|
const start = candidate.indexOf(name + '() {');
|
|
assert.ok(start >= 0);
|
|
const end = candidate.indexOf('\n}\n', start);
|
|
assert.ok(end > start);
|
|
return candidate.slice(start, end + 3);
|
|
}).join('\n');
|
|
const start = candidate.indexOf('if [[', candidate.indexOf('\npay_ok_status='));
|
|
const end = candidate.indexOf(' echo "[19/23] batch-required profile:', start);
|
|
assert.ok(start >= 0 && end > start);
|
|
const script = 'set -euo pipefail\n' + helpers + '\n' + candidate.slice(start, end) + '\nfi\n';
|
|
return spawnSync('bash', ['-c', script], {
|
|
env: { PATH: process.env.PATH, TMP_DIR: directory, PAYMENT_BATCH_ENABLED: 'true', pay_ok_status: String(code) },
|
|
encoding: 'utf8', timeout: 10000,
|
|
});
|
|
}
|
|
|
|
test('configured batch mode accepts only the exact batch-required refusal', context => {
|
|
const valid = { payment: 'payment_batch_v1_required', reasonCode: 'reimbursement.payment_payment_batch_v1_required' };
|
|
assert.equal(checkResponse(context, 409, valid).status, 0);
|
|
for (const code of [200, 400, 403, 500]) assert.notEqual(checkResponse(context, code, valid).status, 0);
|
|
assert.notEqual(checkResponse(context, 409, { payment: 'some_other_reason' }).status, 0);
|
|
});
|
|
|
|
test('choosing the branch from the observed response is detected as a false-green mutation', context => {
|
|
const before = 'if [[ "${PAYMENT_BATCH_ENABLED:-false}" == "true" ]]; then';
|
|
assert.ok(source.includes(before));
|
|
const mutant = source.replace(before, 'if [[ "$pay_ok_status" == "409" ]]; then');
|
|
const verify = candidate => assert.notEqual(checkResponse(context, 200, {}, candidate).status, 0);
|
|
verify(source);
|
|
assert.throws(() => verify(mutant), assert.AssertionError);
|
|
});
|