import test from 'node:test' import assert from 'node:assert/strict' import { CARRIER_EXCEPTION_CODES, carrierExceptionShapeErrors, carrierExceptionTransitionErrors, captureCarrierExceptionEvidence } from './phase3-carrier-schedule-queries.mjs' const fixture = () => ({ marker: 'current', queryId: '2105227585104384001', detail: { query: { query: { id: '2105227585104384001', customerId: '0', oceanBookingId: '2105227599885111297', containerBookingId: '2105227585104384002', latestStandardNode: 'IN_TRANSIT', latestActualAt: '2026-10-02T09:00:00' } }, nodes: [{ id: 'actual', standardNode: 'IN_TRANSIT', actualAt: '2026-10-02T09:00:00' }, { id: 'estimated', standardNode: 'ARRIVED_DESTINATION_PORT', estimatedAt: '2026-10-20T09:00:00' }], exceptions: [], histories: [], } }) const fact = (code, active = true, sequence = 1) => ({ id: `210522758510438401${sequence}`, providerCode: 'TEST_PROVIDER', providerEventId: `${code}-${active}`, providerStatus: active ? 'HOLD' : 'RELEASE', exceptionCode: code, active, observedAt: '2026-10-02T10:00:00', locationCode: 'USLAX', locationName: 'Los Angeles', sourceReference: 'controlled-provider', rawPayloadHash: (active ? 'a' : 'b').repeat(64), createdAt: '2026-10-02T10:00:01' }) function append(before, value) { const after = structuredClone(before) after.detail.exceptions.push(value) after.detail.histories.push({ id: value.id, action: 'EXCEPTION_OBSERVED', reason: value.exceptionCode }) return after } for (const code of CARRIER_EXCEPTION_CODES) { test(`${code}: append and release retain original exception and both normal time facts`, () => { const before = fixture(), active = fact(code), released = fact(code, false, 2) const after = append(before, active) assert.deepEqual(carrierExceptionTransitionErrors(before, after, { kind: 'APPEND', expected: active }), []) assert.deepEqual(carrierExceptionTransitionErrors(after, append(after, released), { kind: 'RELEASE', expected: released }), []) assert.deepEqual(carrierExceptionTransitionErrors(after, structuredClone(after), { kind: 'REPLAY', expected: active }), []) assert.deepEqual(carrierExceptionTransitionErrors(after, structuredClone(after), { kind: 'CONFLICT', expected: { ...active, rawPayloadHash: 'c'.repeat(64) } }), []) }) } test('replay/conflict fail on changed fact, extra history, missing original event or wrong payload hash', () => { const original = fact('CUSTOMS_HOLD'), before = append(fixture(), original) for (const mutate of [ value => { value.detail.exceptions[0].active = false }, value => { value.detail.histories.push({ id: 'extra', action: 'EXCEPTION_OBSERVED' }) }, value => { value.detail.nodes[1].estimatedAt = '2026-10-21T09:00:00' }, value => { value.detail.query.query.latestStandardNode = 'PICKUP_READY' }, value => { value.marker = 'other' }, ]) { const after = structuredClone(before); mutate(after) assert.ok(carrierExceptionTransitionErrors(before, after, { kind: 'REPLAY', expected: original }).length) } assert.ok(carrierExceptionTransitionErrors(fixture(), fixture(), { kind: 'REPLAY', expected: original }).length) assert.ok(carrierExceptionTransitionErrors(before, before, { kind: 'CONFLICT', expected: original }).length) }) test('release replacing the active row, deleting original history or absent estimated baseline is rejected', () => { const active = fact('TERMINAL_HOLD'), release = fact('TERMINAL_HOLD', false, 2) const before = append(fixture(), active) for (const mutate of [ value => { value.detail.exceptions.shift() }, value => { value.detail.histories.shift() }, value => { value.detail.nodes.pop() }, ]) { const after = append(before, release); mutate(after) assert.ok(carrierExceptionTransitionErrors(before, after, { kind: 'RELEASE', expected: release }).length) } const empty = fixture(); empty.detail.nodes.pop() assert.ok(carrierExceptionTransitionErrors(empty, append(empty, active), { kind: 'APPEND', expected: active }).length) }) test('reject customs declaration codes, duplicate supplier event, malformed hash and absent source fields', () => { for (const mutate of [ value => { value.detail.exceptions[0].exceptionCode = 'INSPECTION' }, value => { value.detail.exceptions.push({ ...value.detail.exceptions[0], id: '2105227585104384019' }) }, value => { value.detail.exceptions[0].rawPayloadHash = 'bad' }, value => { value.detail.exceptions[0].providerCode = '' }, value => { value.detail.nodes[0].standardNode = 'CUSTOMS_HOLD' }, ]) { const value = append(fixture(), fact('UNKNOWN_HOLD')); mutate(value) assert.ok(carrierExceptionShapeErrors(value.detail).length) } }) test('provider DTO permits absent location and source reference; supplied values still match exactly', () => { const active = { ...fact('UNKNOWN_HOLD'), locationCode: null, locationName: null, sourceReference: null } const before = fixture(), after = append(before, structuredClone(active)) assert.deepEqual(carrierExceptionShapeErrors(after.detail), []) assert.deepEqual(carrierExceptionTransitionErrors(before, after, { kind: 'APPEND', expected: active }), []) after.detail.exceptions[0].sourceReference = 'changed' assert.ok(carrierExceptionTransitionErrors(before, after, { kind: 'APPEND', expected: active }).length) }) test('real API checkpoint uses only original detail GET and rejects another marker before any call', async () => { const before = fixture(), calls = [], original = globalThis.fetch const context = { marker: 'current', options: { gateway: 'https://offline.invalid' }, token: 'offline', apiSuccess: (_module, _name, response) => response.body.data, assert: (_module, _name, _response, passed) => assert.ok(passed) } const resource = { queryId: before.queryId, marker: 'current', ownedByModule: true, triggerSource: 'OUTBOUND_CONFIRM' } globalThis.fetch = async (url, options) => { calls.push({ url, method: options.method }); return new Response(JSON.stringify({ code: '200', data: before.detail })) } try { const captured = await captureCarrierExceptionEvidence(context, resource) assert.deepEqual(captured.detail, before.detail) assert.deepEqual(calls.map(item => item.method), ['GET']) assert.ok(calls[0].url.endsWith(`/api/platform/v1/carrier-schedule-queries/${before.queryId}`)) await assert.rejects(captureCarrierExceptionEvidence(context, { ...resource, marker: 'other' }), /current-marker/) assert.equal(calls.length, 1) } finally { globalThis.fetch = original } })