Files
admin-web/src/modules/ocean-bookings/api/platformOceanBookings.test.ts
T

58 lines
3.9 KiB
TypeScript
Raw Normal View History

2026-08-08 13:32:27 +08:00
import { describe, expect, it, vi } from 'vitest'
2026-08-14 18:50:11 +08:00
import { createOceanBooking, listOceanBookings, listWarehouseLogisticsChannels, performOceanBookingAction, releaseOceanBooking, requestOceanBookingChange } from './platformOceanBookings'
2026-08-08 13:32:27 +08:00
import { http } from '@/shared/api/http'
2026-08-10 09:12:06 +08:00
const detailResponse = (version = 0) => ({
oceanBooking: {
id: 123, bookingNo: 'OB123', status: 'DRAFT', version, customerId: 456, customerName: '客户',
containers: [],
},
parties: [], containerRequirements: [], containerAllocations: [], histories: [],
})
describe('ocean bookings api', () => {
it('normalizes pagination and long ids', async () => {
vi.spyOn(http, 'get').mockResolvedValueOnce({ code: '200', message: 'ok', data: { records: [{ id: 123, customerId: 456, containers: [] }], page: '2', size: '20', total: '21', pages: '2' } })
const result = await listOceanBookings({ page: 1, size: 10 })
expect(result.page).toBe(2)
expect(result.total).toBe(21)
expect(result.records[0]?.id).toBe('123')
expect(result.records[0]?.customerId).toBe('456')
})
it('uses version zero for create and extracts the id from the returned Detail', async () => {
const post = vi.spyOn(http, 'post').mockResolvedValue({ code: '200', message: 'ok', data: detailResponse() })
2026-08-14 19:59:32 +08:00
const created = await createOceanBooking({ expectedVersion: 0, data: { customerId: null, customerName: null, channelCode: 'SEA', warehouseId: '8', warehouseName: '义乌仓', serviceTerm: null, freightTerm: null, parties: [], containerRequirements: [] } })
const sentPayload = post.mock.calls[0]?.[1] as { expectedVersion: number; data: Record<string, unknown> }
expect(sentPayload).toMatchObject({ expectedVersion: 0, data: { customerId: null, customerName: null, serviceTerm: null, freightTerm: null } })
expect(sentPayload).not.toMatchObject({ data: { customerId: '', customerName: '' } })
for (const releaseOnlyField of ['billOfLadingNo', 'vesselName', 'voyageNo', 'estimatedSailingAt', 'estimatedArrivalAt']) {
expect(sentPayload.data).not.toHaveProperty(releaseOnlyField)
}
2026-08-10 09:12:06 +08:00
expect(post.mock.calls[0]?.[2]).toMatchObject({ headers: { 'Idempotency-Key': expect.any(String) } })
expect(created.id).toBe('123')
expect(created.version).toBe(0)
})
it('uses action and change-specific request contracts', async () => {
const post = vi.spyOn(http, 'post').mockResolvedValue({ code: '200', message: 'ok', data: detailResponse(4) })
await performOceanBookingAction('123', 'confirm', { expectedVersion: 3, reason: 'ok' })
expect(post.mock.calls[0]?.[0]).toContain('/123/confirm')
expect(post.mock.calls[0]?.[1]).toEqual({ expectedVersion: 3, reason: 'ok' })
await requestOceanBookingChange('123', { expectedVersion: 4, vesselName: 'VESSEL', voyageNo: 'V001', reason: '调整船期' })
expect(post.mock.calls[1]?.[0]).toContain('/123/change-request')
expect(post.mock.calls[1]?.[1]).toMatchObject({ expectedVersion: 4, vesselName: 'VESSEL', voyageNo: 'V001', reason: '调整船期' })
await releaseOceanBooking('123', { expectedVersion: 4, billOfLadingNo: 'BL-1', vesselName: 'VESSEL', voyageNo: 'V001', estimatedSailingAt: '2026-08-12T10:00:00', estimatedArrivalAt: '2026-09-01T10:00:00' })
expect(post.mock.calls[2]?.[0]).toContain('/123/release')
expect(post.mock.calls[2]?.[1]).toMatchObject({ billOfLadingNo: 'BL-1', vesselName: 'VESSEL', voyageNo: 'V001', estimatedSailingAt: '2026-08-12T10:00:00', estimatedArrivalAt: '2026-09-01T10:00:00' })
2026-08-10 09:12:06 +08:00
})
2026-08-14 18:50:11 +08:00
it('loads warehouse-scoped logistics channels from the booking contract', async () => {
vi.spyOn(http, 'get').mockResolvedValue({ code: '200', message: 'ok', data: [{ channelCode: 'SEA_FCL', channelName: '海运整箱' }] })
await expect(listWarehouseLogisticsChannels('8')).resolves.toEqual([{ channelCode: 'SEA_FCL', channelName: '海运整箱' }])
expect(http.get).toHaveBeenCalledWith('/platform/v1/ocean-bookings/channels', { params: { originWarehouseId: '8' } })
})
2026-08-10 09:12:06 +08:00
})