import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' import { selectCustomsFlow } from './phase3-customs.mjs' import { buildFinalizeResource } from './phase3-loading-finalize.mjs' function source(name) { return readFileSync(new URL(name, import.meta.url), 'utf8') } function assertOrder(value, snippets) { let cursor = -1 for (const snippet of snippets) { const next = value.indexOf(snippet) assert.ok(next > cursor, `${snippet} must appear after the previous production step`) cursor = next } } test('pairs customs source fixture with the matching loading container', () => { const resources = { orchestrationFixtures: { inboundMeasurement: { tenantId: 10001, orderId: 101, inboundId: 201 }, phase3Container: { tenantId: 10001, orderId: 102, inboundId: 202 }, }, phase3Loading: { tenantId: 10001, inboundId: 201, containerBookingId: 301 }, phase3ContainerLoading: { tenantId: 10001, inboundId: 202, containerBookingId: 302 }, } const selected = selectCustomsFlow(resources) assert.equal(selected.fixture.orderId, 101) assert.equal(selected.container.containerBookingId, 301) }) test('falls back to the matching container fixture without crossing source identities', () => { const resources = { orchestrationFixtures: { phase3Container: { tenantId: 10001, orderId: 102, inboundId: 202 } }, phase3Loading: { tenantId: 10001, inboundId: 201, containerBookingId: 301 }, phase3ContainerLoading: { tenantId: 10001, inboundId: 202, containerBookingId: 302 }, } const selected = selectCustomsFlow(resources) assert.equal(selected.fixture.orderId, 102) assert.equal(selected.container.containerBookingId, 302) }) test('records LOADING and a cleanup reason when finalize returns S0500', () => { const result = buildFinalizeResource( { inboundStatus: 'LOADING', inboundVersion: 5, finalStatus: 'COMPLETED' }, { summary: { processStatus: 'LOADING', version: 5 } }, { http: 200, body: { code: 'S0500' } }, ) assert.equal(result.finalStatus, 'LOADING') assert.equal(result.finalizeSucceeded, false) assert.match(result.notCleanedReason, /S0500/) }) test('records LOADED and clears the reason only after a real LOADED reread', () => { const result = buildFinalizeResource( { inboundStatus: 'LOADING', inboundVersion: 5, finalStatus: 'COMPLETED' }, { summary: { processStatus: 'LOADED', version: 6 } }, { http: 200, body: { code: '200' } }, ) assert.equal(result.finalStatus, 'LOADED') assert.equal(result.finalizeSucceeded, true) assert.equal(result.notCleanedReason, null) }) test('container loading follows push, claim, real pick, completed sequence', () => { const value = source('./phase3-container-loading.mjs') assert.match(value, /containerDetail\?\.planStatus === 'WAIT_LOADING'/) assertOrder(value, [ "pushed?.status === 'EDITING'", "claimedPlan?.status === 'EDITING'", "const pickResponse = await request", "finalPlan?.status === 'COMPLETED'", ]) }) test('bridge loading starts through a real PDA batch before preload confirmation', () => { const value = source('./phase3-loading.mjs') assertOrder(value, [ "pushedLoadingPlan?.status === 'EDITING'", "claimedPlan?.status === 'EDITING'", "const canonicalPick = await request", "pickedPlan?.status === 'COMPLETED'", "const confirming = await request", ]) assert.doesNotMatch(value, /关联柜次计划进入 LOADING/) })