From 3dcebc47372eb74304e6b9f28a39588587e63f22 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Thu, 27 Aug 2026 16:34:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/multi-plan-receiving.test.mjs | 79 +++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 tests/multi-plan-receiving.test.mjs diff --git a/tests/multi-plan-receiving.test.mjs b/tests/multi-plan-receiving.test.mjs new file mode 100644 index 0000000..bc7eb96 --- /dev/null +++ b/tests/multi-plan-receiving.test.mjs @@ -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/) +})