This commit is contained in:
2026-08-27 16:34:45 +08:00
parent 3fdfcb659a
commit 3dcebc4737
+79
View File
@@ -0,0 +1,79 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { normalizeReceivingCandidate, normalizeReceivingSession } from '../src/api/receiving-adapter.js'
import { receiving, receivingPhase, receivingProgress, resetReceivingSession, setCurrentReceiving } from '../src/stores/receiving.js'
const read = (path) => readFile(new URL(path, import.meta.url), 'utf8')
const inbounds = Array.from({ length: 15 }, (_, index) => ({
inboundCode: `NYEXX260827${String(index + 1).padStart(4, '0')}`,
destinationType: index % 2 === 0 ? 'FBA' : 'OVERSEAS',
fbaWarehouseCode: index % 2 === 0 ? 'ABE3' : null,
destinationWarehouseCode: index % 2 === 0 ? 'ABE3' : 'US-LAX-01',
plannedPalletCount: 1,
totalPackages: 4,
receivedPackages: index === 0 ? 4 : 0,
pendingPackages: index === 0 ? 0 : 4
}))
test('one container candidate aggregates fifteen independent one-inbound plans', () => {
const candidate = normalizeReceivingCandidate({
containerNo: 'C10000000', status: 'WAIT_SIGN', planCount: 15, inboundCodeCount: 15,
destinationCodes: ['ABE3', 'US-LAX-01'], plannedPalletCount: 15,
totalPackages: 60, receivedPackages: 0, currentAccount: false
})
assert.deepEqual(candidate, {
containerNo: 'C10000000', status: 'WAIT_SIGN', planCount: 15, inboundCodeCount: 15,
destinationCodes: ['ABE3', 'US-LAX-01'], plannedPalletCount: 15,
totalPackages: 60, receivedPackages: 0, currentAccount: false
})
assert.equal(candidate.planCount, candidate.inboundCodeCount)
})
test('current recovery retains all independent-plan inbound facts while progress remains container-level', () => {
const session = normalizeReceivingSession({
containerNo: 'C10000000', status: 'RECEIVING', totalPackages: 60,
receivedPackages: 4, pendingPackages: 56, photos: [], inbounds
})
setCurrentReceiving(session)
assert.equal(receivingPhase(), 'receive')
assert.deepEqual(receivingProgress(), { total: 60, received: 4, pending: 56, percent: 7 })
assert.equal(receiving.current.inbounds.length, 15)
assert.equal(receiving.current.inbounds[0].inboundCode, 'NYEXX2608270001')
assert.equal(receiving.current.inbounds[14].inboundCode, 'NYEXX2608270015')
resetReceivingSession()
})
test('container UI locks and signs once across independent plans, then renders only the scan-matched inbound', async () => {
const [operation, summary, inboundApi] = await Promise.all([
read('../src/pages/operation/operation.vue'),
read('../src/components/ReceivingSessionSummary.vue'),
read('../src/api/inbound.js')
])
assert.match(operation, /item\.inboundCodeCount[\s\S]*item\.planCount[\s\S]*item\.totalPackages/)
assert.match(summary, /inboundCodeCount[\s\S]*plannedPalletCount[\s\S]*totalPackages/)
assert.doesNotMatch(operation, /v-for="[^"]*inbound[^"]*"/)
assert.match(operation, /v-if="activeInbound"[\s\S]*activeInbound\.inboundCode[\s\S]*activeInbound\.pendingPackages/)
assert.match(operation, /resolveCurrentCarton\(cartonMark\)/)
assert.doesNotMatch(operation, /cartonMark\.split|\.split\([^\n]*['"]#['"]/)
assert.match(inboundApi, /\$\{RECEIVING_BASE\}\/\$\{encodeURIComponent\(containerNo\)\}\/prepare/)
assert.match(inboundApi, /current\('\/sign'\)/)
assert.match(operation, /prepareReceivingContainer\(this\.selected\.containerNo, \{ idempotencyKey: key\.value \}\)/)
assert.match(operation, /getCurrentReceiving\(\)[\s\S]*applyCurrentReceiving\(current\)/)
for (const forbidden of ['customerId', 'planNo', 'allocationId', 'warehouseId', 'locationId']) {
assert.doesNotMatch(inboundApi, new RegExp(forbidden))
}
})
test('PDA does not infer container eligibility from partial plan workflow states', async () => {
const operation = await read('../src/pages/operation/operation.vue')
for (const internalStatus of ['PENDING_ASSIGNMENT', 'INBOUND_PLANNED', 'PDA_PENDING', 'ASSIGNED', 'PICKING']) {
assert.doesNotMatch(operation, new RegExp(internalStatus))
}
assert.match(operation, /listReceivingCandidates\(\)/)
assert.match(operation, /statusLabel\(status\)[\s\S]*WAIT_SIGN[\s\S]*SIGNED[\s\S]*RECEIVING[\s\S]*COMPLETED/)
})