import { beforeEach, describe, expect, it, vi } from 'vitest' import { http } from '@/shared/api/http' import { getCarrierScheduleQuery, listCarrierScheduleQueries } from './platformCarrierScheduleQueries' vi.mock('@/shared/api/http', async () => { const actual = await vi.importActual('@/shared/api/http') return { ...actual, http: { get: vi.fn() } } }) const query = { id: 9007199254740993n, queryNo: 'CSQ-1', customerId: 101, oceanBookingId: 202, containerBookingId: 303, carrierCode: 'COSCO', trackingType: 'CONTAINER_NO', trackingNo: 'CSNU1234567', status: 'MANUAL_REQUIRED', triggerSource: 'OUTBOUND_CONFIRM', latestStandardNode: 'DEPARTED_WAREHOUSE', latestNodeObservedAt: '2026-08-20T10:00:00', accessMode: 'DYNAMIC_IFRAME', lastErrorCode: 'DYNAMIC_IFRAME_REQUIRED', lastErrorMessage: '必须人工查询', resultPortScheduleId: 404, version: '3', } describe('platformCarrierScheduleQueries', () => { beforeEach(() => vi.clearAllMocks()) it('filters by real booking/container relations and preserves long ids as strings', async () => { vi.mocked(http.get).mockResolvedValue({ code: '200', data: { records: [{ query, expired: true }], page: '1', size: '200', total: '1', pages: '1' } }) const result = await listCarrierScheduleQueries({ page: 1, size: 200, oceanBookingId: '202', containerBookingId: '303' }) expect(vi.mocked(http.get)).toHaveBeenCalledWith('/platform/v1/carrier-schedule-queries', { params: { page: 1, size: 200, oceanBookingId: '202', containerBookingId: '303' } }) expect(result.records[0]).toMatchObject({ query: { id: '9007199254740993', customerId: '101', oceanBookingId: '202', containerBookingId: '303', resultPortScheduleId: '404', accessMode: 'DYNAMIC_IFRAME', triggerSource: 'OUTBOUND_CONFIRM', latestStandardNode: 'DEPARTED_WAREHOUSE', latestNodeObservedAt: '2026-08-20T10:00:00', lastErrorCode: 'DYNAMIC_IFRAME_REQUIRED', lastErrorMessage: '必须人工查询', version: 3 }, expired: true }) }) it('normalizes standard node facts and immutable business history', async () => { vi.mocked(http.get).mockResolvedValue({ code: '200', data: { query: { query: { ...query, status: 'ARRIVED', latestStandardNode: 'ARRIVED' }, expired: false }, nodes: [{ id: 1, providerCode: 'COSCO', providerNodeCode: 'ARR', standardNode: 'ARRIVED', nodeSequence: '50', observedAt: '2026-08-20T12:00:00', estimatedAt: null, actualAt: '2026-08-20T11:55:00', locationCode: 'USLAX', locationName: 'Los Angeles', sourceReference: 'provider-event-1', rawPayloadHash: 'a'.repeat(64), createdAt: '2026-08-20T12:01:00' }], histories: [{ id: 2, action: 'NODE_OBSERVED', fromVersion: '1', toVersion: '2', reason: 'ARRIVED', operatorId: 808 }] } }) const result = await getCarrierScheduleQuery('9007199254740993') expect(vi.mocked(http.get)).toHaveBeenCalledWith('/platform/v1/carrier-schedule-queries/9007199254740993') expect(result.nodes[0]).toMatchObject({ id: '1', standardNode: 'ARRIVED', nodeSequence: 50, actualAt: '2026-08-20T11:55:00', locationCode: 'USLAX' }) expect(result.histories[0]).toMatchObject({ id: '2', action: 'NODE_OBSERVED', fromVersion: 1, toVersion: 2, operatorId: '808' }) }) it('preserves nullable DTO fields instead of fabricating false or zero values', async () => { vi.mocked(http.get).mockResolvedValue({ code: '200', data: { query: { query: { ...query, containerBookingId: null, resultPortScheduleId: null, latestStandardNode: null, latestNodeObservedAt: null, stoppedAt: null, stopReason: null }, expired: true }, nodes: [{ id: 1, providerCode: 'FIRSTLEG', providerNodeCode: 'OUTBOUND_CONFIRM', standardNode: 'DEPARTED_WAREHOUSE', nodeSequence: 10, observedAt: '2026-08-20T10:00:00', estimatedAt: null, actualAt: null, locationCode: null, locationName: null, sourceReference: null, rawPayloadHash: 'b'.repeat(64), createdAt: null }], histories: [{ id: 2, action: 'AUTO_CREATE', fromVersion: null, toVersion: 0, reason: null, operatorId: null, operatorName: null, createdAt: null }] } }) const result = await getCarrierScheduleQuery('9007199254740993') expect(result.query.query).toMatchObject({ containerBookingId: null, resultPortScheduleId: null, latestStandardNode: null, latestNodeObservedAt: null, stoppedAt: null, stopReason: null }) expect(result.nodes[0]).toMatchObject({ estimatedAt: null, actualAt: null, locationCode: null, locationName: null, sourceReference: null, createdAt: null }) expect(result.histories[0]).toMatchObject({ fromVersion: null, operatorId: null, operatorName: null, createdAt: null }) }) })