test(acceptance): reuse fixed customers and align native fulfillment flows

This commit is contained in:
2026-10-23 04:48:02 +08:00
parent b92f7fe991
commit 139f6b1932
51 changed files with 1076 additions and 228 deletions
@@ -9,6 +9,7 @@ function fixture(fault = '') {
tripNo: 'TR-1', bookingNo: 'BK-1', status: 'CONFIRMED_ORIGINAL_ORDER', createRequest: { cargo, expectedPalletCount: 2 } } }
const booking = { bookingNo: 'BK-1', tripNo: 'TR-1', customerId: '101', status: 'CONFIRMED', recordVersion: 1, cargo }
const pallets = [], calls = [], snapshots = []; let incomingWrites = 0, receiptWrites = 0, palletized = false
const cartons = [1, 2, 3].map(index => ({ cartonMark: `BX-${index}`, transferItemId: '81', status: 'EXPECTED' }))
const source = () => ({ incomingNo: 'IN-1', warehouseId: fault === 'warehouse' ? '99' : '42', destinationKey: cargo.destinationKey,
status: palletized ? 'WAIT_CUSTOMER_CONFIRMATION' : 'WAIT_PDA_RECEIVING', receiptHash: 'hash',
receivedPackages: fault === 'quantity' ? 4 : 3,
@@ -27,15 +28,30 @@ function fixture(fault = '') {
if (fault === 'replay' && incomingWrites > 1) data.booking.incomingNo = 'IN-2'
} else if (path.endsWith('/fulfillment')) data = { preview: { tripRecordVersion: 2, recordVersion: 2, incoming: source() } }
else if (path.endsWith('/pallets/drafts')) {
assert.equal(token, 'pda'); assert.equal(body.cartonCount, pallets.length ? 1 : 2)
pallets.push({ id: String(pallets.length + 1), cartonCount: body.cartonCount, status: 'DRAFT' })
assert.equal(token, 'pda'); assert.deepEqual(Object.keys(body), ['idempotencyKey'])
pallets.push({ id: String(pallets.length + 1), cartonCount: 0, status: 'DRAFT' })
data = { pallets }
} else if (path.endsWith('/generate')) {
const pallet = pallets.find(p => path.includes(`/pallets/${p.id}/`))
Object.assign(pallet, { palletNo: `P-${pallet.id}`, warehousePalletId: String(70 + Number(pallet.id)) })
Object.assign(pallet, { palletNo: `P-${pallet.id}`, warehousePalletId: String(70 + Number(pallet.id)), status: 'GENERATED' })
data = { pallets }
} else if (path.endsWith('/bind')) data = { pallets }
} else if (path.endsWith('/bind')) { pallets.find(p => path.includes(`/pallets/${p.id}/`)).status = 'BOUND'; data = { pallets } }
else if (path.endsWith('/cartons/count')) {
assert.equal(token, 'pda'); assert.equal(body.forecastPackageCount, 3)
assert.equal(body.boxes.length, 3)
assert.ok(pallets.every(row => row.status === 'BOUND'))
if (fault !== 'uncounted') {
for (const input of body.boxes) Object.assign(cartons.find(box => box.cartonMark === input.cartonMark), input, { status: 'COUNTED' })
for (const pallet of pallets) {
const boxes = body.boxes.filter(box => box.transferPalletId === pallet.id)
Object.assign(pallet, { cartonCount: boxes.length, volumeCbm: boxes.reduce((sum, box) => sum + box.length * box.width * box.height / 1000000, 0),
grossWeightKg: boxes.reduce((sum, box) => sum + box.weight, 0) })
}
}
data = { pallets, cartons }
}
else if (path.endsWith('/palletize')) {
assert.ok(cartons.every(box => box.status === 'COUNTED'))
assert.deepEqual(body.photoFileIds, ['9'])
palletized = true; pallets.forEach(p => { p.status = 'COMPLETED' })
data = { status: 'WAIT_CUSTOMER_CONFIRMATION', pallets }
@@ -45,7 +61,9 @@ function fixture(fault = '') {
assert.equal(body.unitPrice, 25)
data = { tripRecordVersion: 3, booking: { ...booking, status: 'RECEIVED', incomingNo: 'IN-1',
receipt: { source: { ...source(), status: 'READY_FOR_DISPATCH' } } }, replayed: receiptWrites > 1 }
} else throw Error(`Unexpected ${method} ${path}`)
} else if (method === 'GET' && path.includes('/warehouse-transfers/')) data = { operatingWarehouseId: '42', packageCount: 3,
items: [{ id: '81', skuCode: 'DECLARED-SKU' }], cartons, pallets }
else throw Error(`Unexpected ${method} ${path}`)
if (path.includes('/warehouse-transfers/')) data.transferNo = fault === 'wrong incoming' ? 'OTHER' : 'IN-1'
return { http: 200, body: { code: '200', data: structuredClone(data) }, requestId: 'req', traceId: 'trace' }
},
@@ -56,7 +74,9 @@ function fixture(fault = '') {
} }
return { context, calls, snapshots, counts: () => ({ incomingWrites, receiptWrites }),
args: { demand, tripProof, pdaToken: 'pda', measurements: [2, 1].map(cartonCount => ({ cartonCount, lengthCm: 100, widthCm: 100,
heightCm: 90, volumeCbm: 0.9, grossWeightKg: 40 })) } }
heightCm: 90, volumeCbm: 0.9, grossWeightKg: 40,
boxes: cartonCount === 2 ? [{ length: 100, width: 100, height: 45, weight: 20, quantity: 1 }, { length: 100, width: 100, height: 45, weight: 20, quantity: 1 }]
: [{ length: 100, width: 100, height: 90, weight: 40, quantity: 1 }] })) } }
}
test('original looseboard booking receives two pallets three boxes and confirms once with replay', async () => {
@@ -69,7 +89,19 @@ test('original looseboard booking receives two pallets three boxes and confirms
await assert.rejects(receiveLooseboardPool(f.context, f.args))
})
for (const fault of ['network', 'replay', 'warehouse', 'quantity', 'file', 'disk', 'wrong incoming']) {
for (const native of [true, false]) test(`native Long receipt versions remain bounded: ${native ? 'encoded strings' : 'invalid unsafe value'}`, async () => {
const f = fixture(), request = f.context.request
f.context.request = async (...args) => {
const response = await request(...args)
response.body.data = JSON.parse(JSON.stringify(response.body.data, (key, value) =>
/^(recordVersion|tripRecordVersion)$/.test(key) ? native ? String(value) : '9007199254740992' : value))
return response
}
if (native) assert.equal((await receiveLooseboardPool(f.context, f.args)).status, 'RECEIVED_READY_FOR_DISPATCH')
else { await assert.rejects(receiveLooseboardPool(f.context, f.args), /来货前/); assert.equal(f.counts().incomingWrites, 0) }
})
for (const fault of ['network', 'replay', 'warehouse', 'quantity', 'file', 'disk', 'wrong incoming', 'uncounted']) {
test(`receipt stops on ${fault} before operational confirmation`, async () => {
const f = fixture(fault)
await assert.rejects(receiveLooseboardPool(f.context, f.args))
@@ -77,6 +109,7 @@ for (const fault of ['network', 'replay', 'warehouse', 'quantity', 'file', 'disk
assert.equal(f.counts().receiptWrites, 0)
if (fault === 'network') assert.equal(f.counts().incomingWrites, 1)
if (fault === 'disk') assert.equal(f.calls.length, 0)
if (fault === 'uncounted') assert.equal(f.calls.some(call => call.path.endsWith('/palletize')), false)
})
}