This commit is contained in:
2026-10-20 14:25:01 +08:00
parent 5679b156ca
commit 03b1e7163e
23 changed files with 425 additions and 54 deletions
@@ -6,7 +6,7 @@ import DispatchesView from './DispatchesView.vue'
import QueryToolbar from '@/shared/components/QueryToolbar.vue'
import RowActions from '@/shared/components/RowActions.vue'
import { getDispatch, getDispatchBolPdf, listDispatches } from '../api/dispatches'
import { detail, listRow, page } from '../dispatchTestFixtures'
import { command, detail, listRow, page } from '../dispatchTestFixtures'
import type { DispatchPage } from '../dispatchContracts'
import { useDispatchCommandRecovery } from '../dispatchCommandRecovery'
const identity = vi.hoisted(() => ({ id: '' }))
@@ -69,3 +69,45 @@ it('navigates by the business number without arranging a separate trip', async (
it('reads one BOL on demand and preserves popup failure handling', async () => {
vi.stubGlobal('open', vi.fn().mockReturnValue(null)); const wrapper = mount(DispatchesView, options); await flushPromises(); wrapper.findAllComponents(RowActions).find(entry => entry.props('moreLabel') === '更多操作 · PC/1')!.vm.$emit('action', 'bol'); await flushPromises(); expect(getDispatchBolPdf).not.toHaveBeenCalled(); wrapper.unmount()
})
it.each(['saved', 'rejected'] as const)('refreshes list actions after workflow %s without retaining a stale submit button', async event => {
vi.mocked(listDispatches).mockResolvedValueOnce(page([listRow({ actions: { SUBMIT_REVIEW: { allowed: true, blockCode: null, blockReason: null } } })]))
const wrapper = mount(DispatchesView, options); await flushPromises()
const row = wrapper.findAllComponents(RowActions).find(entry => entry.props('moreLabel') === '更多操作 · PC/1')!
expect(row.props('actions')).toContainEqual(expect.objectContaining({ key: 'SUBMIT_REVIEW' }))
row.vm.$emit('action', 'SUBMIT_REVIEW'); await flushPromises()
vi.mocked(listDispatches).mockResolvedValueOnce(page([listRow({ recordVersion: 1, actions: { SUBMIT_REVIEW: { allowed: false, blockCode: 'ALREADY_SUBMITTED', blockReason: '审核已提交' } } })]))
const dialog = wrapper.getComponent({ name: 'DispatchWorkflowDialog' })
if (event === 'rejected') dialog.vm.$emit('rejected', { message: '本轮审核已经提交', code: 'A0409', requestId: 'list-reject-request' })
else dialog.vm.$emit('saved')
dialog.vm.$emit('update:modelValue', false); await flushPromises()
expect(listDispatches).toHaveBeenCalledTimes(2)
expect(row.props('actions')).not.toContainEqual(expect.objectContaining({ key: 'SUBMIT_REVIEW' }))
if (event === 'rejected') {
expect(wrapper.text()).toContain('本轮审核已经提交')
expect(wrapper.text()).toContain('A0409')
expect(wrapper.text()).toContain('list-reject-request')
}
expect(wrapper.text()).not.toContain('结果尚待核对')
wrapper.unmount()
})
it('describes a proven command awaiting its GET as completed instead of unknown', async () => {
const recovery = useDispatchCommandRecovery(() => identity.id)
recovery.begin('PC/1', 'SUBMIT_REVIEW', { recordVersion: 0, idempotencyKey: 'known-key' })
recovery.pending.value!.attempted = true
recovery.pending.value!.result = command('SUBMIT_REVIEW', 'known-key')
const wrapper = mount(DispatchesView, options); await flushPromises()
expect(wrapper.text()).toContain('操作已完成,页面资料待刷新')
expect(wrapper.text()).not.toContain('结果尚待核对')
await wrapper.findAll('button').find(button => button.text() === '刷新页面资料')!.trigger('click')
expect(wrapper.getComponent({ name: 'DispatchWorkflowDialog' }).props()).toMatchObject({ modelValue: true, action: 'SUBMIT_REVIEW', dispatchNo: 'PC/1' })
wrapper.unmount()
})
it('clears an earlier input rejection after the corrected workflow succeeds', async () => {
const wrapper = mount(DispatchesView, options); await flushPromises()
const dialog = wrapper.getComponent({ name: 'DispatchWorkflowDialog' })
dialog.vm.$emit('rejected', { message: '请补齐本趟资料', code: 'A0400' }); await flushPromises()
expect(wrapper.text()).toContain('请补齐本趟资料')
dialog.vm.$emit('saved'); await flushPromises()
expect(wrapper.text()).not.toContain('请补齐本趟资料')
wrapper.unmount()
})