Files
admin-web/src/modules/appointment-calendar/workApi.test.ts
T

51 lines
4.1 KiB
TypeScript

import { beforeEach, expect, it, vi } from 'vitest'
import { http } from '@/shared/api/http'
import { getWorkCalendar, getWorkSummary, getWorkItems, getWorkDetail, submitWorkCommand } from './workApi'
import { getCargoVerification, saveCargoVerification } from './cargoVerificationApi'
import { workCalendar, workDetail, workItem, workSummary } from './work.test-support'
vi.mock('@/shared/api/http', () => ({ http: { get: vi.fn(), post: vi.fn() }, unwrapApiResponse: <T>(value: { data: T }) => value.data }))
beforeEach(() => vi.clearAllMocks())
it('uses inclusive calendar dates and repeated type parameters with no duplicate API prefix', async () => {
vi.mocked(http.get).mockResolvedValue({ data: workCalendar })
const signal = new AbortController().signal
await getWorkCalendar({ from: '2026-10-01', to: '2026-10-31', flow: 'DIRECT', types: ['PICKUP', 'EMPTY_RETURN'] }, signal)
const [path, config] = vi.mocked(http.get).mock.calls[0]!
expect(path).toBe('/platform/v1/last-leg/appointment-work/calendar')
expect(config?.params.getAll('types')).toEqual(['PICKUP', 'EMPTY_RETURN'])
expect(config?.params.get('to')).toBe('2026-10-31'); expect(config?.signal).toBe(signal)
})
it('keeps global summary free of month, flow, types and page parameters', async () => {
vi.mocked(http.get).mockResolvedValue({ data: workSummary })
expect(await getWorkSummary()).toEqual(workSummary)
expect(http.get).toHaveBeenCalledExactlyOnceWith('/platform/v1/last-leg/appointment-work/summary', { signal: undefined })
})
it('preserves server totals, null work dates and long string identities', async () => {
vi.mocked(http.get).mockResolvedValue({ data: { records: [workItem()], page: '2', size: '8', total: '35', pages: '5' } })
const result = await getWorkItems({ view: 'UNDATED', page: 2, size: 8 })
expect(result.total).toBe(35); expect(result.records[0]!.calendarDate).toBeNull()
expect(result.records[0]!.containers[0]!.containerBookingId).toBe('9007199254740993')
const params = vi.mocked(http.get).mock.calls[0]![1]?.params as URLSearchParams
expect([...params.keys()]).toEqual(['view', 'page', 'size'])
})
it('encodes stable keys and forwards the immutable versioned command', async () => {
vi.mocked(http.get).mockResolvedValue({ data: workDetail() }); vi.mocked(http.post).mockResolvedValue({ data: { item: workItem(), affectedWorkItemKeys: [] } })
await getWorkDetail('work/ORDER:1')
const command = { command: 'CONFIRM_ROUTE' as const, expectedVersion: 3, idempotencyKey: 'same-command', payload: { flow: 'DIRECT' as const, reason: null } }
await submitWorkCommand('work/ORDER:1', command)
expect(http.post).toHaveBeenCalledWith('/platform/v1/last-leg/appointment-work/items/work%2FORDER%3A1/commands', command)
})
it('does not turn upstream failures into an empty calendar or zero summary', async () => {
vi.mocked(http.get).mockRejectedValue(new Error('unavailable'))
await expect(getWorkSummary()).rejects.toThrow('unavailable')
await expect(getWorkCalendar({ from: '2026-10-01', to: '2026-10-31' })).rejects.toThrow('unavailable')
})
it('scopes cargo verification to its explicit customer and never coerces unknown allocation to zero', async () => {
const source = { sourceKey: 'BOOKING:B/1', customerId: '9007199254740995', destinationKey: 'FBA:ONT8' }
vi.mocked(http.get).mockResolvedValue({ data: { availablePackages: null, sourceChanged: true } })
const context = await getCargoVerification(source); expect(context.availablePackages).toBeNull()
expect(http.get).toHaveBeenCalledWith('/platform/v1/last-leg/appointment-planning/sources/BOOKING%3AB%2F1/cargo-verification', { params: { customerId: source.customerId, destinationKey: source.destinationKey } })
const request = { destinationKey: source.destinationKey, expectedSourceVersion: null, expectedVersion: 0, packageCount: null, shipmentReferences: ['FBA-TEST'], remark: null, idempotencyKey: 'verify-1' }
vi.mocked(http.post).mockResolvedValue({ data: { version: 1 } }); await saveCargoVerification(source, request)
expect(http.post).toHaveBeenCalledWith(expect.stringContaining('/cargo-verification'), request, { params: { customerId: source.customerId } })
})