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
@@ -1,7 +1,7 @@
import { flushPromises, mount } from '@vue/test-utils'
import { beforeEach, expect, it, vi } from 'vitest'
import WorkSharedTripForm from './WorkSharedTripForm.vue'
import { getDispatch, useDispatchCommandRecovery, type DispatchDetail } from '@/modules/overseas-warehouse'
import { getDispatch, useDispatchCommandRecovery, type CommandResult, type DispatchDetail } from '@/modules/overseas-warehouse'
import type { LeaveGuard } from './useWorkDraft'
const access = vi.hoisted(() => ({ allowed: true }))
const identity = vi.hoisted(() => ({ id: '' }))
@@ -35,3 +35,46 @@ it('retries lookup as a read and keeps the original detail navigation', async ()
vi.mocked(getDispatch).mockRejectedValueOnce(new Error('lookup failed')); const wrapper = render(); await flushPromises(); await wrapper.get('[role="alert"] button').trigger('click'); await flushPromises(); expect(getDispatch).toHaveBeenCalledTimes(2)
await button(wrapper, '查看原排车单').trigger('click'); expect(wrapper.emitted('external')).toEqual([['/overseas-warehouse/dispatches/DS-60']]); wrapper.unmount()
})
it.each([false, true])('refreshes the original add-cargo gate after a rejection and preserves its message when GET fails: %s', async readFails => {
const wrapper = render(); await flushPromises(); await button(wrapper, '选择同仓未安排货物').trigger('click')
if (readFails) vi.mocked(getDispatch).mockRejectedValueOnce(new Error('read unavailable'))
else vi.mocked(getDispatch).mockResolvedValueOnce(detail('DS-60', false))
const dialog = wrapper.getComponent({ name: 'DispatchWorkflowDialog' })
dialog.vm.$emit('rejected', { message: '来源已变化,请重新核对', code: 'A0409' })
dialog.vm.$emit('update:modelValue', false); await flushPromises()
expect(getDispatch).toHaveBeenCalledTimes(2)
expect(wrapper.emitted('updated')).toHaveLength(1)
expect(wrapper.text()).toContain('来源已变化,请重新核对')
expect(button(wrapper, '选择同仓未安排货物').attributes('disabled')).toBeDefined()
expect(wrapper.text()).not.toContain('原排车请求尚未核对')
if (!readFails) expect(wrapper.text()).toContain('货物已开始真实拣货')
wrapper.unmount()
})
it('offers read refresh for proven add-cargo success while retaining the exact original command', async () => {
const recovery = useDispatchCommandRecovery(() => identity.id)
recovery.begin('DS-60', 'ADD_CARGO', { recordVersion: 0, idempotencyKey: 'known-key', cargo: [], batchAllocations: [] })
recovery.pending.value!.attempted = true
const completed: CommandResult = {
dispatchNo: 'DS-60', action: 'ADD_CARGO', idempotencyKey: 'known-key', recordVersion: 1, status: 'ACTIVE', stage: 'BEFORE_LOADING',
occurredAt: '2026-10-20T00:00:00Z', effect: 'APPLIED', counts: { itemCount: 1, palletCount: 1, packageCount: 60, pickedPackageCount: 0, shippedPackageCount: 0 },
replayed: false, alreadyArranged: false, result: { dispatchNo: 'DS-60', changedItemIds: [] },
}
recovery.pending.value!.result = completed
const wrapper = render(); await flushPromises()
expect(wrapper.text()).toContain('操作已完成,页面资料待刷新')
expect(wrapper.text()).not.toContain('原排车请求尚未核对')
await button(wrapper, '刷新加货资料').trigger('click')
expect(wrapper.getComponent({ name: 'DispatchWorkflowDialog' }).props('modelValue')).toBe(true)
expect(recovery.pending.value!.body.idempotencyKey).toBe('known-key')
wrapper.unmount()
})
it('clears a prior add-cargo rejection after the corrected original-dispatch workflow succeeds', async () => {
const wrapper = render(); await flushPromises()
const dialog = wrapper.getComponent({ name: 'DispatchWorkflowDialog' })
dialog.vm.$emit('rejected', { message: '来源版本需重新核对', code: 'A0409' }); await flushPromises()
expect(wrapper.text()).toContain('来源版本需重新核对')
dialog.vm.$emit('saved'); await flushPromises()
expect(wrapper.text()).not.toContain('来源版本需重新核对')
expect(wrapper.emitted('updated')).toHaveLength(2)
wrapper.unmount()
})