test: cover concurrent inbound hold

This commit is contained in:
2026-09-07 12:16:19 +08:00
parent c6b598daa7
commit 0aecc90d11
2 changed files with 32 additions and 0 deletions
@@ -32,6 +32,8 @@ test('入库扣货模块覆盖隔离、幂等、冲突、候选门禁和统一
assert.match(source, /上传本轮扣货关联凭证/)
assert.match(source, /尚未进入不可变历史的凭证禁止下载/)
assert.match(source, /进入不可变历史后的扣货凭证可下载且内容一致/)
assert.match(source, /同版本并发扣货恰好一个成功一个冲突/)
assert.match(source, /并发验收最终恢复未扣货且历史完整/)
assert.match(source, /summary\?\.holdFlag/)
assert.match(source, /summary\?\.currentHoldReason/)
assert.doesNotMatch(source, /\.holdCargo\b|\.holdReason\b|\bholdCargo\s*:|\bholdReason\s*:/)
@@ -313,4 +313,34 @@ export async function run(context) {
rows(finalCandidates).some((row) => id(row?.inboundId) === inboundId),
`inboundId=${inboundId}, candidates=${rows(finalCandidates).map((row) => id(row?.inboundId)).join(',') || 'empty'}`,
OPTIONS)
const concurrentReasons = [`${context.marker} 并发扣货A`, `${context.marker} 并发扣货B`]
const concurrentResponses = await Promise.all(concurrentReasons.map((concurrentReason, index) =>
write(context, holdPath, { expectedVersion: releasedVersion, reason: concurrentReason },
`${context.marker}-inbound-hold-race-${index}`.slice(0, 128))))
const concurrentCodes = concurrentResponses.map(code).sort()
context.assert(MODULE, '同版本并发扣货恰好一个成功一个冲突', null,
JSON.stringify(concurrentCodes) === JSON.stringify(['200', 'A0409']),
`codes=${concurrentCodes.join(',')}`, OPTIONS)
const concurrentSnapshotResponse = await context.request('GET', holdPath)
const concurrentSnapshot = context.apiSuccess(MODULE, '回查并发扣货后的唯一快照',
concurrentSnapshotResponse, evidence(concurrentSnapshotResponse), OPTIONS)
context.assert(MODULE, '并发扣货只递增一次版本并新增一条历史', concurrentSnapshotResponse,
concurrentSnapshot?.holdFlag === true
&& concurrentReasons.includes(concurrentSnapshot?.currentHoldReason)
&& Number(concurrentSnapshot?.version) === releasedVersion + 1
&& historyRows(concurrentSnapshot).length === releasedHistorySize + 1,
`version=${concurrentSnapshot?.version}, history=${concurrentSnapshot?.history?.length ?? 'missing'}, reason=${concurrentSnapshot?.currentHoldReason || 'missing'}`,
OPTIONS)
const cleanupResponse = await write(context, releasePath,
{ expectedVersion: Number(concurrentSnapshot?.version), reason: `${context.marker} 并发验收恢复` },
`${context.marker}-inbound-race-cleanup`.slice(0, 128))
const cleanup = context.apiSuccess(MODULE, '并发验收后解除扣货恢复订单', cleanupResponse,
evidence(cleanupResponse), OPTIONS)
context.assert(MODULE, '并发验收最终恢复未扣货且历史完整', cleanupResponse,
cleanup?.holdFlag === false && cleanup?.currentHoldReason == null
&& Number(cleanup?.version) === releasedVersion + 2
&& historyRows(cleanup).length === releasedHistorySize + 2,
`version=${cleanup?.version}, history=${cleanup?.history?.length ?? 'missing'}`, OPTIONS)
}