test: require incremental pallet growth

This commit is contained in:
2026-09-04 15:30:59 +08:00
parent 7babcb9e0d
commit 9c96bdfaa8
3 changed files with 41 additions and 4 deletions
+1 -1
View File
@@ -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
@@ -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' } },
@@ -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,