import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { dirname, resolve } from 'node:path' import test from 'node:test' import { fileURLToPath } from 'node:url' const here = dirname(fileURLToPath(import.meta.url)) const read = (name) => readFileSync(resolve(here, name), 'utf8') const readFirstlegTest = (name) => readFileSync(resolve(here, '../../firstleg/src/test/java/com/baiyue/firstleg/portschedule/service', name), 'utf8') test('current-marker departure batch separates domestic customs evidence from post-departure destination documents', () => { const customs = read('phase3-customs.mjs') const documents = read('phase3-container-documents.mjs') const outbound = read('phase3-outbound-dispatch.mjs') assert.doesNotMatch(customs, /DESTINATION_CLEARANCE|DELIVERY_ORDER|PICKUP_ORDER/) for (const type of ['DESTINATION_CLEARANCE', 'DELIVERY_ORDER']) assert.match(documents, new RegExp(type)) assert.doesNotMatch(documents, /PICKUP_ORDER/) for (const evidence of ['上传', '回读', '完成']) assert.match(documents, new RegExp(evidence)) assert.match(customs, /整柜聚合回显国内报关资料与真实PDA照片证据/) assert.match(customs, /photos\.length >= 5/) assert.match(customs, /\/customs\/loading-plans/) assert.match(customs, /complete-all-buy/) assert.match(customs, /国内报关资料与PDA证据必须完成后才允许进入出仓确认/) assert.match(outbound, /CUSTOMS_CLEARANCE/) assert.match(outbound, /拖车与独立船期仅作聚合参考且不参与出仓门禁/) assert.match(outbound, /\$\{BASE\}\/\$\{encodeURIComponent\(containerBookingId\)\}\/confirm/) assert.match(outbound, /confirm-dispatch 幂等重放/) assert.match(outbound, /相同 Idempotency-Key 不同请求拒绝/) assert.match(outbound, /实际DEPARTED_WAREHOUSE节点产生后撤销精确返回A0409/) assert.doesNotMatch(outbound, /\/confirm-dispatch|\/reverse-dispatch|\/check-gate\?/) }) test('outbound-created query supports automated or manual carrier then reaches PICKUP_READY PDA candidate', () => { const query = read('phase3-carrier-schedule-queries.mjs') const nodes = read('phase4-carrier-nodes.mjs') const pda = read('phase4-overseas-pda.mjs') assert.match(query, /出仓自动建任务兼容自动船司与未知船司人工处理/) assert.match(query, /manualCarrier && task\?\.status === 'MANUAL_REQUIRED'/) assert.match(nodes, /'DISCHARGED_FROM_VESSEL', 'PICKUP_READY'/) assert.match(nodes, /const pickupReadyIndex = STANDARD_NODES\.indexOf\('PICKUP_READY'\)/) assert.match(nodes, /createdResources\.phase4CarrierPickupReady/) assert.match(nodes, /重复当前实际节点精确返回A0409/) assert.match(nodes, /更早实际节点精确返回A0409/) assert.match(nodes, /operation claim零残留/) assert.match(nodes, /task、node、history零漂移/) assert.match(nodes, /actualProgressSnapshot/) assert.match(pda, /convertReceivingContainers\(context, producers\)/) assert.match(pda, /last-leg\/orders\/container-summaries/) assert.match(pda, /last-leg\/inbound-plans\/convert-container/) assert.match(pda, /Number\(summary\?\.missingInboundCodeCount\) === 0/) assert.doesNotMatch(pda, /summary\?\.eligible/) assert.match(pda, /item\?\.shippingReady !== false/) assert.match(pda, /nonBlank\(item\?\.resourceKey\)/) assert.match(pda, /targetCorrelated/) assert.match(pda, /deploymentBlocker: true/) assert.doesNotMatch(pda, /addCoverageGap\([^\n]*PICKUP_READY/) }) test('demo package locks provider failure retry and refuses stray facts on failed calls', () => { const scheduler = readFirstlegTest('CarrierScheduleQuerySchedulerTest.java') const service = readFirstlegTest('CarrierScheduleQueryServiceTest.java') assert.match(scheduler, /retryableProviderResultCannotAdvanceEvenWhenItCarriesStrayFacts/) assert.match(scheduler, /verify\(service, never\(\)\)\.applyProviderObservation/) assert.match(scheduler, /completeScheduledAttempt\(1L, "RETRYABLE_FAILURE", "HTTP_503", "unavailable"\)/) assert.match(service, /retryableFailureUsesFifteenThenThirtyMinutesAndStopsAfterThreeCallsInTheSlot/) assert.match(service, /containsExactly\(1, 2, 3\)/) assert.match(service, /retryThatWouldReachTheNextSlotWaitsForTheSlotInstead/) }) test('demo package exposes the stable Admin task, node, exception and history DTO contract', () => { const nodes = read('phase4-carrier-nodes.mjs') assert.match(nodes, /trackingType === 'CONTAINER_NO'/) assert.match(nodes, /validContainerNo\(task\?\.trackingNo\)/) assert.match(nodes, /Array\.isArray\(detail\?\.nodes\)/) assert.match(nodes, /nodes\.every\(validNode\)/) assert.match(nodes, /exceptions\.every\(validException\)/) assert.match(nodes, /histories\.every\(validHistory\)/) assert.match(nodes, /!Object\.hasOwn\(detail \|\| \{\}, 'attempts'\)/) })