2026-09-10 14:14:24 +08:00
|
|
|
|
import ElementPlus from 'element-plus'
|
|
|
|
|
|
import { flushPromises, mount } from '@vue/test-utils'
|
|
|
|
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
|
|
import { listOceanBookingLinkCandidates } from '@/modules/ocean-bookings'
|
|
|
|
|
|
import { linkContainerOceanBooking } from '../api/platformContainerLoading'
|
|
|
|
|
|
import type { ContainerBookingResource } from '../types'
|
|
|
|
|
|
import OceanBookingLinkDialog from './OceanBookingLinkDialog.vue'
|
2026-10-20 10:11:31 +08:00
|
|
|
|
import AppDialog from '@/shared/components/AppDialog.vue'
|
2026-09-10 14:14:24 +08:00
|
|
|
|
|
|
|
|
|
|
vi.mock('@/modules/ocean-bookings', () => ({ listOceanBookingLinkCandidates: vi.fn() }))
|
|
|
|
|
|
vi.mock('../api/platformContainerLoading', () => ({ linkContainerOceanBooking: vi.fn() }))
|
|
|
|
|
|
|
|
|
|
|
|
const container = {
|
2026-10-12 11:45:00 +08:00
|
|
|
|
id: '9001', cabinetNo: 'CAB-1', containerNo: null, planId: '7001', planStatus: 'EDITING',
|
2026-09-10 19:25:11 +08:00
|
|
|
|
sourceType: 'SIMULATION', warehouseId: '8', warehouseName: '义乌仓', channelGroupCode: 'MATSON_CLX', channelCode: null, channelName: null,
|
2026-09-15 10:38:03 +08:00
|
|
|
|
oceanBookingId: null, billOfLadingNo: null, vesselName: null, voyageNo: null, containerType: '40HQ',
|
2026-09-10 14:14:24 +08:00
|
|
|
|
shippingCompanyId: null, shippingCompanyName: null, departurePortCode: null, departurePortName: null,
|
|
|
|
|
|
destinationPortCode: null, destinationPortName: null, destinationWarehouseCode: null, destinationWarehouseName: null,
|
2026-09-15 10:38:03 +08:00
|
|
|
|
capacityCbm: 68, maxWeightKg: 19500, terminalTruckingCompanyId: null, terminalTruckingCompany: null,
|
2026-09-10 14:14:24 +08:00
|
|
|
|
loadingAt: null, estimatedSailingAt: null, actualSailingAt: null, estimatedPortArrivalAt: null,
|
|
|
|
|
|
actualPortArrivalAt: null, estimatedWarehouseArrivalAt: null, actualWarehouseArrivalAt: null, version: 7,
|
|
|
|
|
|
} satisfies ContainerBookingResource
|
|
|
|
|
|
|
|
|
|
|
|
const candidate = {
|
2026-09-18 09:59:12 +08:00
|
|
|
|
oceanBookingId: '101', bookingNo: 'OB-101', billOfLadingNo: 'BL-101', requirementId: '202', containerType: '40HQ', capacityCbm: 68,
|
2026-09-15 10:38:03 +08:00
|
|
|
|
maxWeightKg: 19500, requiredQuantity: 2, allocatedQuantity: 1, remainingQuantity: 1,
|
2026-09-10 14:14:24 +08:00
|
|
|
|
customerName: '测试客户', warehouseName: '义乌仓', channelName: '美森正班',
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
describe('OceanBookingLinkDialog', () => {
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
|
vi.mocked(listOceanBookingLinkCandidates).mockReset().mockResolvedValue({ records: [candidate], page: 1, size: 200, total: 1, pages: 1 })
|
|
|
|
|
|
vi.mocked(linkContainerOceanBooking).mockReset().mockResolvedValue({ ...container, oceanBookingId: '101', oceanBookingRequirementId: '202', version: 8 } as never)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
it('loads matching released-booking requirements when opened', async () => {
|
|
|
|
|
|
const wrapper = mount(OceanBookingLinkDialog, { props: { modelValue: true, container }, global: { plugins: [ElementPlus] } })
|
|
|
|
|
|
await flushPromises()
|
2026-10-20 10:11:31 +08:00
|
|
|
|
expect(wrapper.findComponent(AppDialog).props('title')).toBe('关联已放舱订舱 · CAB-1')
|
|
|
|
|
|
const identity = wrapper.findAllComponents({ name: 'ElFormItem' }).find(field => field.props('label') === '柜次号')!
|
|
|
|
|
|
expect(identity.text()).toContain('CAB-1')
|
|
|
|
|
|
expect(identity.find('input').exists()).toBe(false)
|
2026-09-15 10:38:03 +08:00
|
|
|
|
expect(listOceanBookingLinkCandidates).toHaveBeenCalledExactlyOnceWith({ warehouseId: '8', channelGroupCode: 'MATSON_CLX', containerType: '40HQ', page: 1, size: 200 })
|
2026-09-18 09:59:12 +08:00
|
|
|
|
expect((wrapper.vm as unknown as { candidates: Array<{ label: string }> }).candidates[0]?.label).toContain('OB-101 · 提单号 BL-101 · 40HQ × 1')
|
2026-09-10 14:14:24 +08:00
|
|
|
|
wrapper.unmount()
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
it.each([
|
|
|
|
|
|
[' mscu1234567 ', 'MSCU1234567'],
|
|
|
|
|
|
['', null],
|
|
|
|
|
|
])('normalizes and submits the optional real container number %#', async (input, expected) => {
|
|
|
|
|
|
const wrapper = mount(OceanBookingLinkDialog, { props: { modelValue: true, container }, global: { plugins: [ElementPlus] } })
|
|
|
|
|
|
await flushPromises()
|
|
|
|
|
|
const vm = wrapper.vm as unknown as { candidateKey: string; containerNo: string; save: () => Promise<void> }
|
|
|
|
|
|
vm.candidateKey = '101:202'
|
|
|
|
|
|
vm.containerNo = input
|
2026-10-20 10:11:31 +08:00
|
|
|
|
await wrapper.findComponent(AppDialog).find('button[aria-label="展开全屏"]').trigger('click')
|
|
|
|
|
|
expect(vm.containerNo).toBe(input)
|
|
|
|
|
|
expect(linkContainerOceanBooking).not.toHaveBeenCalled()
|
2026-09-10 14:14:24 +08:00
|
|
|
|
await vm.save()
|
|
|
|
|
|
expect(linkContainerOceanBooking).toHaveBeenCalledExactlyOnceWith('9001', {
|
|
|
|
|
|
oceanBookingId: '101', requirementId: '202', containerNo: expected, expectedVersion: 7,
|
|
|
|
|
|
})
|
|
|
|
|
|
expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual([false])
|
|
|
|
|
|
expect(wrapper.emitted('linked')).toHaveLength(1)
|
|
|
|
|
|
wrapper.unmount()
|
|
|
|
|
|
})
|
2026-09-16 16:17:41 +08:00
|
|
|
|
|
|
|
|
|
|
it('prefills and preserves a real container number recorded before booking linkage', async () => {
|
|
|
|
|
|
const existingContainer = { ...container, containerNo: 'MSCU6639870' }
|
|
|
|
|
|
const wrapper = mount(OceanBookingLinkDialog, {
|
|
|
|
|
|
props: { modelValue: true, container: existingContainer },
|
|
|
|
|
|
global: { plugins: [ElementPlus] },
|
|
|
|
|
|
})
|
|
|
|
|
|
await flushPromises()
|
|
|
|
|
|
const vm = wrapper.vm as unknown as { candidateKey: string; containerNo: string; save: () => Promise<void> }
|
|
|
|
|
|
expect(vm.containerNo).toBe('MSCU6639870')
|
|
|
|
|
|
|
|
|
|
|
|
vm.candidateKey = '101:202'
|
|
|
|
|
|
await vm.save()
|
|
|
|
|
|
|
|
|
|
|
|
expect(linkContainerOceanBooking).toHaveBeenCalledExactlyOnceWith('9001', {
|
|
|
|
|
|
oceanBookingId: '101', requirementId: '202', containerNo: 'MSCU6639870', expectedVersion: 7,
|
|
|
|
|
|
})
|
|
|
|
|
|
wrapper.unmount()
|
|
|
|
|
|
})
|
2026-09-10 14:14:24 +08:00
|
|
|
|
})
|