This commit is contained in:
2026-10-21 16:58:38 +08:00
parent e2f99b4f4b
commit c510cc4e2e
15 changed files with 481 additions and 23 deletions
@@ -1,9 +1,10 @@
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import ElementPlus, { ElSelect, ElTag } from 'element-plus'
import { flushPromises, mount } from '@vue/test-utils'
import { beforeEach, expect, it, vi } from 'vitest'
import DispatchesView from './DispatchesView.vue'
import QueryToolbar from '@/shared/components/QueryToolbar.vue'
import DataTable from '@/shared/components/DataTable.vue'
import RowActions from '@/shared/components/RowActions.vue'
import { getDispatch, getDispatchBolPdf, listDispatches } from '../api/dispatches'
import { command, detail, listRow, page } from '../dispatchTestFixtures'
@@ -110,6 +111,117 @@ it('shows four working phases and uses server stage counts instead of current pa
await tabs[2]!.trigger('click'); await flushPromises()
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ stage: 'DELIVERING' })); expect(wrapper.find('[aria-label="装车前审核分区"]').exists()).toBe(false); wrapper.unmount()
})
it.each([0, 1, 2])('preserves section %s and its query after clearing the active dispatch filter', async index => {
const wrapper = mount(DispatchesView, options); await flushPromises()
const sectionValues = ['VEHICLE_INFO', 'DISPATCH_REVIEW', 'LOADING_REVIEW']
const sectionSelector = '[aria-label="装车前审核分区"]'
await wrapper.get(sectionSelector).findAll('button')[index]!.trigger('click'); await flushPromises()
const toolbar = wrapper.getComponent(QueryToolbar)
await toolbar.findAll('button').find(button => button.text() === '高级筛选')!.trigger('click')
toolbar.findAllComponents(ElSelect).find(select => select.props('placeholder') === '单据范围')!.vm.$emit('update:modelValue', '')
await flushPromises()
expect(wrapper.get(sectionSelector).findAll('button').map(button => button.text())).toEqual(['车辆信息', '调度审核', '理货员审核'])
expect(wrapper.get(sectionSelector).findAll('button')[index]!.attributes('aria-selected')).toBe('true')
await toolbar.findAll('button').find(button => button.text() === '查询')!.trigger('click'); await flushPromises()
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ status: 'ACTIVE', beforeLoadingSection: sectionValues[index] }))
const nextIndex = (index + 1) % 3
await wrapper.get(sectionSelector).findAll('button')[nextIndex]!.trigger('click'); await flushPromises()
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ status: 'ACTIVE', beforeLoadingSection: sectionValues[nextIndex] }))
await toolbar.findAll('button').find(button => button.text() === '重置')!.trigger('click'); await flushPromises()
expect(wrapper.get(sectionSelector).findAll('button')).toHaveLength(3)
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ status: 'ACTIVE', beforeLoadingSection: sectionValues[nextIndex] }))
await wrapper.get('[aria-label="排车执行阶段"]').findAll('button')[1]!.trigger('click'); await flushPromises()
expect(wrapper.find(sectionSelector).exists()).toBe(false)
expect(vi.mocked(listDispatches).mock.calls.at(-1)?.[0]).not.toHaveProperty('beforeLoadingSection')
wrapper.unmount()
})
it.each([
['WAIT_DEPARTURE', 'BEFORE_LOADING', '装车前'],
['DELIVERING', 'DELIVERING', '派送中'],
['DELIVERED', 'DELIVERED', '派送完成'],
] as const)('queries %s through server pagination and selects the corresponding stage', async (vehicleStatus, stage, label) => {
const wrapper = mount(DispatchesView, options); await flushPromises()
await wrapper.get('[aria-label="排车执行阶段"]').findAll('button')[3]!.trigger('click'); await flushPromises()
const table = wrapper.getComponent(DataTable)
table.vm.$emit('update:page', 3); await flushPromises()
const result = { ...page([listRow({ stage })]), total: 21, pages: 3 }
vi.mocked(listDispatches).mockResolvedValueOnce(result)
const toolbar = wrapper.getComponent(QueryToolbar)
const select = toolbar.findAllComponents(ElSelect).find(item => item.props('placeholder') === '车辆状态')!
select.vm.$emit('update:modelValue', vehicleStatus); select.vm.$emit('change', vehicleStatus); await flushPromises()
await toolbar.findAll('button').find(button => button.text() === '查询')!.trigger('click'); await flushPromises()
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ page: 1, size: 10, stage, status: 'ACTIVE' }))
expect(vi.mocked(listDispatches).mock.calls.at(-1)?.[0]).not.toHaveProperty('vehicleStatus')
expect(wrapper.get('[aria-label="排车执行阶段"] [aria-selected="true"]').text()).toContain(label)
expect(table.props('total')).toBe(21)
expect(table.props('data')).toEqual(result.records)
expect(wrapper.find('[aria-label="装车前审核分区"]').exists()).toBe(stage === 'BEFORE_LOADING')
wrapper.unmount()
})
it('keeps waiting vehicles in the current loading phase and synchronizes an active status when changing phases', async () => {
const wrapper = mount(DispatchesView, options); await flushPromises()
const tabs = wrapper.get('[aria-label="排车执行阶段"]').findAll('button')
await tabs[1]!.trigger('click'); await flushPromises()
const toolbar = wrapper.getComponent(QueryToolbar)
toolbar.vm.$emit('search', { vehicleStatus: 'WAIT_DEPARTURE', status: 'ACTIVE' }); await flushPromises()
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ stage: 'LOADING' }))
expect(vi.mocked(listDispatches).mock.calls.at(-1)?.[0]).not.toHaveProperty('beforeLoadingSection')
await tabs[2]!.trigger('click'); await flushPromises()
expect(toolbar.props('modelValue').vehicleStatus).toBe('DELIVERING')
await tabs[0]!.trigger('click'); await flushPromises()
expect(toolbar.props('modelValue').vehicleStatus).toBe('WAIT_DEPARTURE')
wrapper.unmount()
})
it('shows trip progress independently of master vehicle status and leaves cancelled vehicles without progress', async () => {
const records = [
listRow({ dispatchNo: 'PC-WAIT', stage: 'BEFORE_LOADING' }),
listRow({ dispatchNo: 'PC-LOADING', stage: 'LOADING' }),
listRow({ dispatchNo: 'PC-DELIVERING', stage: 'DELIVERING' }),
listRow({ dispatchNo: 'PC-DELIVERED', stage: 'DELIVERED' }),
listRow({ dispatchNo: 'PC-CANCELLED', status: 'CANCELLED' }),
]
for (const row of records) row.resources.vehicle!.vehicleStatus = 'MAINTENANCE'
vi.mocked(listDispatches).mockResolvedValueOnce(page(records))
const wrapper = mount(DispatchesView, options); await flushPromises()
const toolbar = wrapper.getComponent(QueryToolbar)
expect(toolbar.props('fields').map(field => field.key)).toEqual(['dispatchNo', 'vehiclePlate', 'vehicleStatus'])
expect(toolbar.props('fields').find(field => field.key === 'vehicleStatus')?.options?.map(option => option.label)).toEqual(['待发车', '配送中', '已送达'])
expect(wrapper.getComponent(DataTable).props('columns').some(column => column.key === 'vehicleStatus' && column.label === '车辆状态')).toBe(true)
expect(wrapper.findAllComponents(ElTag).map(tag => tag.text())).toEqual(['待发车', '待发车', '配送中', '已送达'])
expect(wrapper.text()).toContain('已取消')
expect(wrapper.text()).not.toContain('维修中')
wrapper.unmount()
})
it.each(['CANCELLED', 'ALL'])('retains advanced %s lookup and resets its hidden value', async status => {
const wrapper = mount(DispatchesView, options); await flushPromises()
const toolbar = wrapper.getComponent(QueryToolbar)
toolbar.vm.$emit('search', { status: 'ACTIVE', vehicleStatus: 'WAIT_DEPARTURE' }); await flushPromises()
await toolbar.findAll('button').find(button => button.text() === '高级筛选')!.trigger('click')
const select = toolbar.findAllComponents(ElSelect).find(item => item.props('placeholder') === '单据范围')!
select.vm.$emit('update:modelValue', status); select.vm.$emit('change', status); await flushPromises()
await toolbar.findAll('button').find(button => button.text() === '查询')!.trigger('click'); await flushPromises()
expect(toolbar.props('modelValue').vehicleStatus).toBe('')
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ status }))
expect(vi.mocked(listDispatches).mock.calls.at(-1)?.[0]).not.toHaveProperty('beforeLoadingSection')
await toolbar.findAll('button').find(button => button.text().startsWith('收起筛选'))!.trigger('click')
expect(toolbar.props('fields').some(field => field.key === 'status')).toBe(false)
expect(toolbar.text()).toContain(status === 'CANCELLED' ? '高级筛选 · 已取消' : '高级筛选 · 全部单据')
await toolbar.findAll('button').find(button => button.text() === '重置')!.trigger('click'); await flushPromises()
expect(toolbar.props('modelValue')).toMatchObject({ status: 'ACTIVE', vehicleStatus: '' })
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ page: 1, status: 'ACTIVE', beforeLoadingSection: 'VEHICLE_INFO' }))
wrapper.unmount()
})
it('returns to active dispatches when selecting vehicle progress from cancelled lookup', async () => {
const wrapper = mount(DispatchesView, options); await flushPromises()
const toolbar = wrapper.getComponent(QueryToolbar)
toolbar.vm.$emit('search', { status: 'CANCELLED', vehicleStatus: '' }); await flushPromises()
const select = toolbar.findAllComponents(ElSelect).find(item => item.props('placeholder') === '车辆状态')!
select.vm.$emit('update:modelValue', 'DELIVERING'); select.vm.$emit('change', 'DELIVERING'); await flushPromises()
await toolbar.findAll('button').find(button => button.text() === '查询')!.trigger('click'); await flushPromises()
expect(listDispatches).toHaveBeenLastCalledWith(expect.objectContaining({ status: 'ACTIVE', stage: 'DELIVERING' }))
expect(toolbar.props('modelValue')).toMatchObject({ status: 'ACTIVE', vehicleStatus: 'DELIVERING' })
wrapper.unmount()
})
it('queries the current review queue without offering historical result filters', async () => {
const wrapper = mount(DispatchesView, options); await flushPromises()
await wrapper.get('[aria-label="装车前审核分区"]').findAll('button')[1]!.trigger('click'); await flushPromises()