From 9c96bdfaa842a71cc68ca76c7ee5834300e0c479 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 4 Sep 2026 15:30:59 +0800 Subject: [PATCH] test: require incremental pallet growth --- scripts/README.md | 2 +- ...tion-test-env-acceptance.contract.test.mjs | 30 ++++++++++++++++++- .../pallet-location-test-env-acceptance.mjs | 13 ++++++-- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/scripts/README.md b/scripts/README.md index 4dd6b2a24..6ed0c980d 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -126,7 +126,7 @@ node --env-file="$env:USERPROFILE\.codex\chongchong-global-test-acceptance.env" ## 订单测量与连续库位扩展矩阵 -部署完成后,可用独立入口串行执行订单创建、审核建入库单、称重确认、库位指引、删除释放、补传复用、测量提交/审核至 `WAIT_SPLIT`。默认固定“义乌仓”并执行 5 个确定性场景:单图单槽、单图两预留槽、实测体积跨档、两图逐次扩容、三图连续扩容。每票使用独立订单、入库单、库位块和 reservation,最后额外验证跨票不串数据。 +部署完成后,可用独立入口串行执行订单创建、审核建入库单、称重确认、库位指引、删除释放、补传复用、测量提交/审核至 `WAIT_SPLIT`。默认固定“义乌仓”并执行 5 个确定性场景:单图单槽、单图两预留槽、实测体积跨档、两图逐次扩容、小体积订单三图 `1→2→3` 连续扩容。每票使用独立订单、入库单、库位块和 reservation,最后额外验证跨票不串数据。 ```powershell node --env-file="$env:USERPROFILE\.codex\chongchong-global-test-acceptance.env" scripts/pallet-location-test-env-acceptance.mjs diff --git a/scripts/pallet-location-test-env-acceptance.contract.test.mjs b/scripts/pallet-location-test-env-acceptance.contract.test.mjs index 5d1141170..579099afd 100644 --- a/scripts/pallet-location-test-env-acceptance.contract.test.mjs +++ b/scripts/pallet-location-test-env-acceptance.contract.test.mjs @@ -18,8 +18,10 @@ test('pallet location matrix declares deterministic one, two, and three-image sc assert.match(source, /--verify-pallet-location-guide', 'true'/) assert.match(source, /--wait-split-package-count', '18'/) assert.match(source, /--wait-split-package-count', '12'/) - assert.match(source, /--wait-split-package-count', '61'/) + assert.match(source, /--route-mode', 'random', '--wait-split-random-value', '2'/) assert.match(source, /第3张确认后扩容只追加且既有槽身份不漂移/) + assert.match(source, /beforeSlots=1, afterSlots=2/) + assert.match(source, /beforeSlots=2, afterSlots=3/) }) test('matrix options select known scenarios without duplicate or unknown names', () => { @@ -77,6 +79,32 @@ test('scenario inspection detects naturally observed shared A0 from evidence wit assert.equal(inspectScenarioReport(scenario, report, 1).resources.sharedOverflowObserved, true) }) +test('three-image scenario rejects a no-op growth assertion even when the base step passed', () => { + const scenario = PALLET_LOCATION_SCENARIOS.at(-1) + const report = { + success: true, + createdResources: { + inboundMeasurement: { palletCount: 3, processStatus: 'WAIT_SPLIT' }, + inboundMeasurementLocationGuide: { + blockId: '1', reservationId: '2', locationId: '3', deleteSucceeded: true, slotReused: true, + }, + }, + steps: [ + { name: '删除只解绑图片且原 reservation/location 变为 RESERVED_EMPTY', passed: true }, + { name: '替代图片按新 resultId 复用原空槽', passed: true }, + { name: '固定客户第 1 单停在待分柜', passed: true }, + { name: '报告敏感信息扫描', passed: true }, + { name: '第2张确认后扩容只追加且既有槽身份不漂移', passed: true, + evidence: 'beforeSlots=3, afterSlots=3' }, + { name: '第3张确认后扩容只追加且既有槽身份不漂移', passed: true, + evidence: 'beforeSlots=3, afterSlots=3' }, + ], + } + const inspected = inspectScenarioReport(scenario, report, 0) + assert.equal(inspected.assertions.requiredStepEvidence, false) + assert.deepEqual(inspected.mismatchedStepEvidence, scenario.requiredSteps) +}) + test('cross-scenario inspection permits shared A0 location but rejects shared reservation or block', () => { const results = [ { resources: { inboundId: '1', blockId: '11', reservationId: '21', locationId: 'A0' } }, diff --git a/scripts/pallet-location-test-env-acceptance.mjs b/scripts/pallet-location-test-env-acceptance.mjs index ba3dc874d..39cd89d68 100644 --- a/scripts/pallet-location-test-env-acceptance.mjs +++ b/scripts/pallet-location-test-env-acceptance.mjs @@ -37,13 +37,17 @@ export const PALLET_LOCATION_SCENARIOS = Object.freeze([ }, { name: 'three-image-incremental-growth', - description: '61 箱、3 张称重图,验证连续两次增托与既有槽身份稳定', + description: '小体积订单上传 3 张称重图,强制验证库位块 1→2→3 连续扩容', expectedPalletCount: 3, - args: ['--wait-split-package-count', '61', '--wait-split-random-value', '1'], + args: ['--route-mode', 'random', '--wait-split-random-value', '2'], requiredSteps: [ '第2张确认后扩容只追加且既有槽身份不漂移', '第3张确认后扩容只追加且既有槽身份不漂移', ], + requiredStepEvidence: [ + { name: '第2张确认后扩容只追加且既有槽身份不漂移', pattern: /beforeSlots=1, afterSlots=2/ }, + { name: '第3张确认后扩容只追加且既有槽身份不漂移', pattern: /beforeSlots=2, afterSlots=3/ }, + ], }, ]) @@ -91,6 +95,9 @@ export function inspectScenarioReport(scenario, report, exitCode = 0) { const stepByName = new Map(steps.map((step) => [step.name, step])) const requiredSteps = [...COMMON_REQUIRED_STEPS, ...(scenario.requiredSteps || [])] const missingOrFailedSteps = requiredSteps.filter((name) => stepByName.get(name)?.passed !== true) + const mismatchedStepEvidence = (scenario.requiredStepEvidence || []) + .filter(({ name, pattern }) => !pattern.test(String(stepByName.get(name)?.evidence || ''))) + .map(({ name }) => name) const measurement = report?.createdResources?.inboundMeasurement || {} const guide = report?.createdResources?.inboundMeasurementLocationGuide || {} const guideEvidence = steps @@ -102,6 +109,7 @@ export function inspectScenarioReport(scenario, report, exitCode = 0) { childExitCode: exitCode === 0, childReportSuccess: report?.success === true, requiredSteps: missingOrFailedSteps.length === 0, + requiredStepEvidence: mismatchedStepEvidence.length === 0, expectedPalletCount: Number(measurement.palletCount) === scenario.expectedPalletCount, waitSplitReached: measurement.processStatus === 'WAIT_SPLIT', locationIdentityRecorded: Boolean(guide.blockId && guide.reservationId && guide.locationId), @@ -117,6 +125,7 @@ export function inspectScenarioReport(scenario, report, exitCode = 0) { passed, assertions, missingOrFailedSteps, + mismatchedStepEvidence, summary: report?.summary || null, resources: { marker: report?.marker || null,