From f1af749616ab7196ac2aeed9c3c8f2d875eabd29 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Tue, 25 Aug 2026 14:18:13 +0800 Subject: [PATCH] test: target dynamic loading detail precisely --- ...e3-loading-dynamic-final-contract.test.mjs | 6 ++++++ .../admin-test-env-modules/phase3-loading.mjs | 19 ++++++++++++++++--- .../phase3-producer-chain-contract.test.mjs | 4 ++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/scripts/admin-test-env-modules/phase3-loading-dynamic-final-contract.test.mjs b/scripts/admin-test-env-modules/phase3-loading-dynamic-final-contract.test.mjs index e11b400de..1d99d7a3f 100644 --- a/scripts/admin-test-env-modules/phase3-loading-dynamic-final-contract.test.mjs +++ b/scripts/admin-test-env-modules/phase3-loading-dynamic-final-contract.test.mjs @@ -56,6 +56,7 @@ test('HTTP chain refreshes after stale inventory and keeps one stable PDA identi 'PDA 原子批次完成拣货并等待人工确认', '五类装柜证据完整且铅封号持久化', 'LOADING 阶段向同一 PDA task 增加入库单', + '动态新增计划明细按 inboundDetailId 唯一定位', '增量保持稳定四元身份、LOADING 不回退并撤回最终完成门禁', '增量后旧 inventory token 明确 A0409 并要求刷新', '增量旧 token 冲突后 plan/task/items 零写入', @@ -71,6 +72,11 @@ test('HTTP chain refreshes after stale inventory and keeps one stable PDA identi '报关与最终完成前保持 LOADING 且不提前写 COMPLETE_LOADING', ]) assert.match(loading, /String\(staleIncrementBatch\.body\?\.message \|\| ''\)\.includes\('库存已变化,请刷新后重试'\)/) + assert.match(loading, /incrementalPlanItems = \(incrementedPlan\?\.items \|\| \[\]\)\.filter[\s\S]*id\(item\?\.inboundDetailId\) === id\(dynamicCandidate\.inboundDetailId\)/) + assert.match(loading, /reassignedPlanItems = \(reassignedPlan\?\.items \|\| \[\]\)\.filter[\s\S]*id\(item\?\.inboundDetailId\) === id\(dynamicCandidate\.inboundDetailId\)/) + assert.match(loading, /重新加入动态明细仍按 inboundDetailId 唯一定位/) + assert.doesNotMatch(loading, /incrementedPlan\?\.items\?\.find\?\.\(\(item\) => id\(item\?\.inboundId\) === incrementalInboundId\)/) + assert.doesNotMatch(loading, /reassignedPlan\?\.items\?\.find\?\.\(\(item\) => id\(item\?\.inboundId\) === incrementalInboundId\)/) assert.match(loading, /id\(incrementedTask\?\.loadingPlanId\) === loadingPlanId/) assert.match(loading, /id\(incrementedTask\?\.containerBookingId\) === containerBookingId/) assert.match(loading, /const taskDetailPath = `\$\{pdaBase\}\/tasks\/\$\{canonicalTaskId\}\?warehouseId=/) diff --git a/scripts/admin-test-env-modules/phase3-loading.mjs b/scripts/admin-test-env-modules/phase3-loading.mjs index 4a27a4019..9059f6a91 100644 --- a/scripts/admin-test-env-modules/phase3-loading.mjs +++ b/scripts/admin-test-env-modules/phase3-loading.mjs @@ -1160,9 +1160,15 @@ export async function run(context) { inboundId: incrementalInboundId, inboundDetailId: id(dynamicCandidate.inboundDetailId), packageCount: 1, expectedVersion: Number(planBeforeIncrement?.version), operationId: `${context.marker}-dynamic-assign`.slice(0, 128), - }) + }) const incrementedPlan = context.apiSuccess(MODULE, 'LOADING 阶段向同一 PDA task 增加入库单', incrementResponse, '', OPTIONS) - const incrementalPlanItem = incrementedPlan?.items?.find?.((item) => id(item?.inboundId) === incrementalInboundId) + const incrementalPlanItems = (incrementedPlan?.items || []).filter((item) => + id(item?.inboundId) === incrementalInboundId + && id(item?.inboundDetailId) === id(dynamicCandidate.inboundDetailId)) + const incrementalPlanItem = incrementalPlanItems.length === 1 ? incrementalPlanItems[0] : null + context.assert(MODULE, '动态新增计划明细按 inboundDetailId 唯一定位', incrementResponse, + incrementalPlanItems.length === 1 && id(incrementalPlanItem?.inboundDetailId) === id(dynamicCandidate.inboundDetailId), + `inboundId=${incrementalInboundId}, inboundDetailId=${id(dynamicCandidate.inboundDetailId)}, matches=${incrementalPlanItems.length}, planItemId=${id(incrementalPlanItem?.id) || 'missing'}`, OPTIONS) const preservedRemarkItem = incrementedPlan?.items?.find?.((item) => id(item?.id) === id(assignedItem.id)) const incrementedTaskResponse = await context.request('GET', taskDetailPath) const incrementedTask = context.apiSuccess(MODULE, '增量后回查稳定 PDA 四元身份', incrementedTaskResponse, '', OPTIONS) @@ -1228,7 +1234,14 @@ export async function run(context) { }) const reassignedPlan = context.apiSuccess(MODULE, '删除后重新加入同一动态入库单', reassignResponse, '', OPTIONS) let effectiveDynamicPlan = reassignedPlan - let reassignedPlanItem = reassignedPlan?.items?.find?.((item) => id(item?.inboundId) === incrementalInboundId) + const reassignedPlanItems = (reassignedPlan?.items || []).filter((item) => + id(item?.inboundId) === incrementalInboundId + && id(item?.inboundDetailId) === id(dynamicCandidate.inboundDetailId)) + let reassignedPlanItem = reassignedPlanItems.length === 1 ? reassignedPlanItems[0] : null + context.assert(MODULE, '重新加入动态明细仍按 inboundDetailId 唯一定位', reassignResponse, + reassignedPlanItems.length === 1 + && id(reassignedPlanItem?.inboundDetailId) === id(dynamicCandidate.inboundDetailId), + `inboundId=${incrementalInboundId}, inboundDetailId=${id(dynamicCandidate.inboundDetailId)}, matches=${reassignedPlanItems.length}, planItemId=${id(reassignedPlanItem?.id) || 'missing'}`, OPTIONS) context.assert(MODULE, '动态增量 fixture 至少保留两件可用数量供调整与最小已拣门禁', dynamicCandidatesResponse, Number(dynamicCandidate?.availablePackageCount) >= 2, `availablePackageCount=${dynamicCandidate?.availablePackageCount ?? 'missing'}`, OPTIONS) diff --git a/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs b/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs index 2f019a12c..51e47e9e6 100644 --- a/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs +++ b/scripts/admin-test-env-modules/phase3-producer-chain-contract.test.mjs @@ -454,6 +454,10 @@ test('phase3 loading proves mixed-line rollback across task, all items and opera test('phase3 loading proves stale inventory zero-write and defers final completion audit', () => { const loading = source('./phase3-loading.mjs') assert.match(loading, /taskItemsSignature\(afterStaleTask\) === taskItemsSignature\(beforeMutationTask\)/) + assert.match(loading, /动态新增计划明细按 inboundDetailId 唯一定位/) + assert.match(loading, /重新加入动态明细仍按 inboundDetailId 唯一定位/) + assert.equal((loading.match(/id\(item\?\.inboundDetailId\) === id\(dynamicCandidate\.inboundDetailId\)/g) || []).length, 2) + assert.doesNotMatch(loading, /items\?\.find\?\.\(\(item\) => id\(item\?\.inboundId\) === incrementalInboundId\)/) assertOrder(loading, [ '旧 token 冲突对任务、明细、已拣数量和操作历史零写入', '库存变化后刷新 PDA 实时库存快照',