import ElementPlus from 'element-plus' import { createPinia, setActivePinia } from 'pinia' import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { useAuthStore } from '@/core/auth/auth' import { useAccessPreviewStore } from '@/core/access/accessPreview' import RowActions from '@/shared/components/RowActions.vue' import type { DataTableColumn } from '@/shared/components/DataTable.vue' import { listLocalLooseboardOrders, listUsTruckOrders } from '../api/platformOverseasBusiness' import { overseasBusinessPermissions as permissions } from '../permissions' import type { LocalLooseboardOrder, LocalTransportOrder } from '../types' import TransportOrdersView from './TransportOrdersView.vue' const routing = vi.hoisted(() => ({ push: vi.fn(), route: { query: {} } })) vi.mock('vue-router', () => ({ useRoute: () => routing.route, useRouter: () => ({ push: routing.push }) })) vi.mock('../api/platformOverseasBusiness', () => ({ listLocalLooseboardOrders: vi.fn(), listUsTruckOrders: vi.fn() })) vi.mock('@/modules/overseas-master-data', () => ({ inquiryReturnTarget: () => null, TransportRouteDialog: { template: '
' }, routeLocation: (name: string) => ({ name }) })) function order(): LocalLooseboardOrder { return { id: '9007199254741001', orderNo: 'LB-TEST', customerId: '9007199254741999', fleetArrangement: null, palletRequired: 'YES', transportType: 'WAREHOUSE_TO_WAREHOUSE', productName: '测试货物', estimatedPalletCount: 2, origin: 'LA', destination: 'ONT', originContactName: '发货人', originContactPhone: '10001', destinationContactName: '收货人', destinationContactPhone: '10002', pickupAt: null, deliveryAt: null, packageCount: 20, totalWeightKg: '100', totalVolumeCbm: '2', budgetAmount: '500', currency: 'USD', status: 'PENDING_ACCEPTANCE', version: 1, createdAt: '2026-10-20T08:00:00', updatedAt: '2026-10-20T08:00:00', } } function mountList(domain: 'truck' | 'looseboard', edit = false) { const pinia = createPinia(); setActivePinia(pinia) const auth = useAuthStore(); auth.token = 'test-token'; auth.user = { id: '7', name: '操作员', account: 'tester', roles: [] } auth.permissions = [permissions.truckList, permissions.looseboardList, ...(edit ? [permissions.looseboardEdit] : [])] useAccessPreviewStore().initializeAfterLogin() return mount(TransportOrdersView, { props: { domain }, global: { plugins: [pinia, ElementPlus], stubs: { DataTable: { name: 'DataTable', props: ['data', 'columns'], template: '
{{ column.prop ? row[column.prop] : \'\' }}
' }, AppDialog: true, } } }) } enableAutoUnmount(afterEach) beforeEach(() => { vi.clearAllMocks() vi.mocked(listLocalLooseboardOrders).mockResolvedValue({ records: [order()], total: 1, page: 1, size: 20, pages: 1 }) vi.mocked(listUsTruckOrders).mockResolvedValue({ records: [], total: 0, page: 1, size: 20, pages: 0 }) }) describe('transport document entry', () => { it('lets list-only users open looseboard details without edit permission', async () => { const wrapper = mountList('looseboard'); await flushPromises() const actions = wrapper.findComponent(RowActions) expect(actions.text()).toContain('详情') expect(actions.text()).not.toContain('编辑') actions.vm.$emit('action', 'detail'); await flushPromises() expect(routing.push).toHaveBeenCalledWith({ name: 'overseas-business-looseboard-detail', params: { orderId: 'LB-TEST' }, query: { customerId: '9007199254741999' } }) }) it('lets authorized users complete missing receiving information before review', async () => { const wrapper = mountList('looseboard', true); await flushPromises() const actions = wrapper.findComponent(RowActions) expect(actions.text()).toContain('编辑') actions.vm.$emit('action', 'edit'); await flushPromises() expect(routing.push).toHaveBeenCalledWith({ name: 'overseas-business-looseboard-edit', params: { orderId: 'LB-TEST' }, query: { customerId: '9007199254741999' } }) }) it('keeps truck mode on its own list API', async () => { mountList('truck'); await flushPromises() expect(listUsTruckOrders).toHaveBeenCalledOnce() expect(listLocalLooseboardOrders).not.toHaveBeenCalled() }) it('displays truck pallet counts instead of the unused package count', async () => { const truck: LocalTransportOrder = { id: '9007199254741001', customerId: '9007199254741999', orderNo: 'TR-TEST', fleetArrangement: null, vehicleType: 'PALLET_15', origin: 'LA', destination: 'ONT', palletCount: 3, packageCount: 0, receivedPalletCount: 0, allocatedPalletCount: 0, shippedPalletCount: 0, totalWeightKg: '100', totalVolumeCbm: '2', budgetAmount: '500', currency: 'USD', originContactName: null, originContactPhone: null, destinationContactName: null, destinationContactPhone: null, pickupAt: null, deliveryAt: null, status: 'PENDING_REVIEW', version: 1, createdAt: '', updatedAt: '', } vi.mocked(listUsTruckOrders).mockResolvedValue({ records: [truck], total: 1, page: 1, size: 20, pages: 1 }) const wrapper = mountList('truck'); await flushPromises() const columns = wrapper.findComponent({ name: 'DataTable' }).props('columns') as DataTableColumn[] expect(columns.find(column => column.key === 'palletCount')).toMatchObject({ label: '托数', prop: 'palletCount' }) expect(columns.some(column => column.key === 'packageCount')).toBe(false) expect(wrapper.get('[data-column="palletCount"]').text()).toBe('3') const actions = wrapper.findComponent(RowActions) expect(actions.text()).toContain('详情') expect(actions.text()).not.toContain('审核') expect(actions.text()).not.toContain('编辑') }) it('preserves looseboard package counts and forecast pallet counts', async () => { const wrapper = mountList('looseboard'); await flushPromises() const columns = wrapper.findComponent({ name: 'DataTable' }).props('columns') as DataTableColumn[] expect(columns.find(column => column.key === 'packageCount')).toMatchObject({ label: '件数', prop: 'packageCount' }) expect(columns.find(column => column.key === 'estimatedPalletCount')).toMatchObject({ label: '预计托数', prop: 'estimatedPalletCount' }) expect(wrapper.get('[data-column="packageCount"]').text()).toBe('20') expect(wrapper.get('[data-column="estimatedPalletCount"]').text()).toBe('2') }) })