44 lines
2.8 KiB
JavaScript
44 lines
2.8 KiB
JavaScript
import test from 'node:test'
|
|||
|
|
import assert from 'node:assert/strict'
|
||
|
|
import { ensureAppointmentDeparture } from './phase4-overseas-inbound-operations.mjs'
|
||
|
|
|
||
|
|
const producer = { marker: 'RUN', carrierScheduleQueryId: '10', tenantId: '20', containerBookingId: '30', containerNo: 'BOX' }
|
||
|
|
function fixture(fault = '', departed = false) {
|
||
|
|
const calls = [], task = { id: '10', customerId: fault === 'foreign-customer' ? 'OTHER' : '20',
|
||
|
|
containerBookingId: '30', trackingNo: 'BOX', version: '0', latestActualNode: departed ? 'DEPARTED_ORIGIN_PORT' : null }
|
||
|
|
const context = { marker: 'RUN', createdResources: {}, async checkpoint() {}, addStep() {},
|
||
|
|
async request(method, path, body) {
|
||
|
|
calls.push({ method, path, body })
|
||
|
|
if (method === 'POST') {
|
||
|
|
if (fault === 'unknown') throw Error('unknown write result')
|
||
|
|
assert.equal(body.expectedVersion, Number(task.version))
|
||
|
|
task.version = String(Number(task.version) + 1); task.latestActualNode = body.standardNode; task.latestActualAt = body.actualAt
|
||
|
|
}
|
||
|
|
const data = path.includes('/last-leg/orders/') ? { order: { customerId: '20', sourceContainerBookingId: '30',
|
||
|
|
containerNode: task.latestActualNode, manualNodeOverride: false } } : { query: { query: structuredClone(task) } }
|
||
|
|
return { http: 200, body: { code: '200', data } }
|
||
|
|
} }
|
||
|
|
return { context, calls }
|
||
|
|
}
|
||
|
|
test('appointment source advances native container shipping and proves Lastleg consumption before appointment writes', async () => {
|
||
|
|
const { context, calls } = fixture()
|
||
|
|
assert.equal((await ensureAppointmentDeparture(context, producer, '40')).status, 'CONSUMED')
|
||
|
|
assert.deepEqual(calls.filter(call => call.method === 'POST').map(call => call.body.standardNode),
|
||
|
|
['DEPARTED_WAREHOUSE', 'AT_ORIGIN_PORT', 'LOADED_ON_VESSEL', 'DEPARTED_ORIGIN_PORT'])
|
||
|
|
assert.ok(calls.filter(call => call.method === 'POST').every(call => call.path.startsWith('/api/platform/v1/carrier-schedule-queries/10/manual-nodes')))
|
||
|
|
})
|
||
|
|
test('already departed source is reused without adding shipping nodes', async () => {
|
||
|
|
const { context, calls } = fixture('', true)
|
||
|
|
await ensureAppointmentDeparture(context, producer, '40')
|
||
|
|
assert.ok(calls.every(call => call.method === 'GET'))
|
||
|
|
})
|
||
|
|
test('foreign source and unknown write stop without further mutation', async () => {
|
||
|
|
const foreign = fixture('foreign-customer')
|
||
|
|
await assert.rejects(ensureAppointmentDeparture(foreign.context, producer, '40'), /身份/)
|
||
|
|
assert.ok(foreign.calls.every(call => call.method === 'GET'))
|
||
|
|
const unknown = fixture('unknown')
|
||
|
|
await assert.rejects(ensureAppointmentDeparture(unknown.context, producer, '40'), /unknown/)
|
||
|
|
assert.equal(unknown.calls.filter(call => call.method === 'POST').length, 1)
|
||
|
|
assert.equal(unknown.context.createdResources.appointmentDeparturePrerequisite.commands[0].status, 'UNKNOWN_RESULT')
|
||
|
|
})
|