import { afterEach, beforeEach, expect, it, vi } from 'vitest' import { shallowMount, flushPromises, type VueWrapper } from '@vue/test-utils' import VehicleFulfillmentTable from './VehicleFulfillmentTable.vue' import * as api from '../api/vehicleFulfillment' const permissions = vi.hoisted(() => ({ allowed: true })) vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => permissions.allowed }) })) vi.mock('../api/vehicleFulfillment', () => ({ listVehicleDeliveries: vi.fn(), listVehicleAssignmentChanges: vi.fn() })) const wrappers: VueWrapper[] = [] const result = (number: string) => ({ records: [{ deliveryNo: number }], page: 1, size: 10, total: 1, pages: 1 }) function mount(kind: 'deliveries' | 'changes' = 'deliveries') { const wrapper = shallowMount(VehicleFulfillmentTable, { props: { vehicleId: '900719925474099301', kind }, global: { stubs: { DataTable: { name: 'DataTable', props: ['data','columns','page','pageSize','total','loading'], emits: ['update:page','update:pageSize'], template: '
' }, ElButton: { template: '' }, LoadErrorState: { name: 'LoadErrorState', props: ['message'], template: '

{{ message }}

' }, ApiErrorMeta: true, } } }); wrappers.push(wrapper); return wrapper } beforeEach(() => { vi.clearAllMocks(); permissions.allowed = true vi.mocked(api.listVehicleDeliveries).mockResolvedValue(result('DL-1') as Awaited>) vi.mocked(api.listVehicleAssignmentChanges).mockResolvedValue({ records: [], page: 1, size: 10, total: 0, pages: 0 }) }) afterEach(() => { wrappers.splice(0).forEach(w => w.unmount()) }) it('loads only its displayed projection once and does not fetch per-row details', async () => { const wrapper = mount(); await flushPromises() expect(api.listVehicleDeliveries).toHaveBeenCalledExactlyOnceWith('900719925474099301',1,10) expect(api.listVehicleAssignmentChanges).not.toHaveBeenCalled() expect(wrapper.findComponent({ name: 'DataTable' }).props('data')).toEqual(result('DL-1').records) }) it('does not call either endpoint without the required viewing permissions', async () => { permissions.allowed = false; const wrapper = mount(); await flushPromises() expect(api.listVehicleDeliveries).not.toHaveBeenCalled(); expect(api.listVehicleAssignmentChanges).not.toHaveBeenCalled() expect(wrapper.text()).toContain('暂无派送记录查看权限') }) it('changing vehicle from a later page resets pagination and sends one scoped request', async () => { const wrapper = mount(); await flushPromises() wrapper.findComponent({ name: 'DataTable' }).vm.$emit('update:page', 3); await flushPromises() vi.mocked(api.listVehicleDeliveries).mockClear() await wrapper.setProps({ vehicleId: '900719925474099302' }); await flushPromises() expect(api.listVehicleDeliveries).toHaveBeenCalledExactlyOnceWith('900719925474099302',1,10) }) it('a late response for the previous vehicle cannot replace the new vehicle records', async () => { let resolveOld!: (value: Awaited>) => void vi.mocked(api.listVehicleDeliveries).mockImplementationOnce(() => new Promise(resolve => { resolveOld=resolve })) const wrapper = mount() await wrapper.setProps({ vehicleId: '900719925474099302' }); await flushPromises() resolveOld(result('DL-OLD') as Awaited>); await flushPromises() expect(wrapper.findComponent({ name: 'DataTable' }).props('data')).toEqual(result('DL-1').records) }) it('changes use the history endpoint and do not reveal current customer delivery data', async () => { mount('changes'); await flushPromises() expect(api.listVehicleAssignmentChanges).toHaveBeenCalledExactlyOnceWith('900719925474099301',1,10) expect(api.listVehicleDeliveries).not.toHaveBeenCalled() }) it('failed reads show an error and clear stale rows instead of showing unrelated prior data', async () => { const wrapper = mount(); await flushPromises() vi.mocked(api.listVehicleDeliveries).mockRejectedValueOnce(new Error('读取失败')) await wrapper.find('button').trigger('click'); await flushPromises() expect(wrapper.findComponent({ name: 'DataTable' }).props('data')).toEqual([]) expect(wrapper.findComponent({ name: 'LoadErrorState' }).exists()).toBe(true) })