2026-10-19 10:23:38 +08:00
|
|
|
import { beforeEach, expect, it, vi } from 'vitest'
|
|
|
|
|
import { shallowMount, flushPromises } from '@vue/test-utils'
|
|
|
|
|
import TripPickupPanel from './TripPickupPanel.vue'
|
|
|
|
|
import { commandPickupTask, commandPickupTrip, getPickupTasks, type PickupTask } from '../api/pickups'
|
|
|
|
|
import { getTrip } from '../api/trips'
|
|
|
|
|
import type { TripDetail } from '../tripTypes'
|
|
|
|
|
|
|
|
|
|
vi.mock('vue-router', () => ({ onBeforeRouteLeave: vi.fn() }))
|
|
|
|
|
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => true }) }))
|
|
|
|
|
vi.mock('element-plus', () => ({ ElMessage: { warning: vi.fn() }, ElMessageBox: { confirm: vi.fn().mockResolvedValue(true) } }))
|
|
|
|
|
vi.mock('../api/trips', () => ({ getTrip: vi.fn() }))
|
|
|
|
|
vi.mock('../api/pickups', () => ({ getPickupTasks: vi.fn(), commandPickupTask: vi.fn(), commandPickupTrip: vi.fn(), uploadPickupEvidence: vi.fn(), downloadPickupEvidence: vi.fn(), pickupStatusLabels: {} }))
|
|
|
|
|
const row: PickupTask = { customerId: 'C1', transferNo: 'WT-1', status: 'PICKED', evidence: [], lastlegOrderNo: 'LL-1', warehouseId: 'W1', pickupAddress: 'TEST Pickup Ave', contactName: '验收联系人', contactPhone: '0000000000', packageCount: 3, tripNo: 'TR-1', vehiclePlate: 'TEST-V1', driverName: '验收司机', driverPhone: '0000000000', plannedDepartureAt: null, actualPackages: 3, pickedAt: null, arrivedAt: null, remark: null }
|
|
|
|
|
const detail = (status: string) => ({ trip: { tripNo: 'TR-1', status, recordVersion: 2, vehicleId: 'V1', driverId: 'D1' } }) as TripDetail
|
|
|
|
|
function mount(status: string) {
|
|
|
|
|
return shallowMount(TripPickupPanel, { props: { detail: detail(status) }, global: { stubs: {
|
|
|
|
|
DataTable: { name: 'DataTable', props: ['data'], template: '<div><slot v-for="row in data" name="actions" :row="row"/></div>' },
|
|
|
|
|
ElButton: { props: ['disabled'], template: '<button :disabled="disabled"><slot/></button>' },
|
|
|
|
|
LoadErrorState: { name: 'LoadErrorState', emits: ['retry'], template: '<button @click="$emit(\'retry\')">重试读取</button>' },
|
|
|
|
|
} } })
|
|
|
|
|
}
|
|
|
|
|
beforeEach(() => { vi.clearAllMocks(); vi.mocked(getPickupTasks).mockResolvedValue([row]) })
|
|
|
|
|
|
2026-10-22 23:10:09 +08:00
|
|
|
it('unlocks parent actions and submits a fresh departure command after failure', async () => {
|
2026-10-19 10:23:38 +08:00
|
|
|
vi.mocked(commandPickupTrip).mockRejectedValueOnce(new Error('connection lost')).mockResolvedValueOnce(detail('IN_TRANSIT'))
|
|
|
|
|
const wrapper = mount('PLANNED'); await flushPromises()
|
|
|
|
|
await wrapper.findAll('button').find(button => button.text() === '确认取货发车')!.trigger('click'); await flushPromises()
|
2026-10-22 23:10:09 +08:00
|
|
|
expect(wrapper.emitted('locked')?.at(-1)).toEqual([false])
|
2026-10-19 10:23:38 +08:00
|
|
|
const body = vi.mocked(commandPickupTrip).mock.calls[0]![2]
|
2026-10-22 23:10:09 +08:00
|
|
|
await wrapper.findAll('button').find(button => button.text() === '确认取货发车')!.trigger('click'); await flushPromises()
|
|
|
|
|
expect(vi.mocked(commandPickupTrip).mock.calls[1]![2]).toEqual({ ...body, idempotencyKey: expect.any(String) }); expect(vi.mocked(commandPickupTrip).mock.calls[1]![2].idempotencyKey).not.toBe(body.idempotencyKey)
|
2026-10-19 10:23:38 +08:00
|
|
|
expect(wrapper.emitted('locked')?.at(-1)).toEqual([false])
|
|
|
|
|
wrapper.unmount()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('retries only reading after arrival committed but the trip refresh failed', async () => {
|
|
|
|
|
vi.mocked(commandPickupTask).mockResolvedValue([{ ...row, status: 'ARRIVED' }])
|
|
|
|
|
vi.mocked(getTrip).mockRejectedValueOnce(new Error('refresh lost')).mockResolvedValueOnce(detail('IN_TRANSIT'))
|
|
|
|
|
const wrapper = mount('IN_TRANSIT'); await flushPromises()
|
|
|
|
|
await wrapper.findAll('button').find(button => button.text() === '确认送仓')!.trigger('click'); await flushPromises()
|
|
|
|
|
expect(commandPickupTask).toHaveBeenCalledTimes(1)
|
|
|
|
|
wrapper.findComponent({ name: 'LoadErrorState' }).vm.$emit('retry'); await flushPromises()
|
|
|
|
|
expect(commandPickupTask).toHaveBeenCalledTimes(1)
|
|
|
|
|
expect(getTrip).toHaveBeenCalledTimes(2)
|
|
|
|
|
expect(wrapper.emitted('saved')).toHaveLength(1)
|
|
|
|
|
wrapper.unmount()
|
|
|
|
|
})
|