fix: align audit and dispatch workflows and release failed requests

This commit is contained in:
2026-10-22 23:10:09 +08:00
parent 9cdcb9c077
commit 4a3456756f
124 changed files with 1296 additions and 2120 deletions
@@ -38,26 +38,26 @@ it('offers five whole-dispatch slots and only reports saved after binding succee
expect(table.get('tbody tr').text()).toContain('loading.png')
wrapper.unmount()
})
it('keeps the original binding and file after an unknown result and never uploads again', async () => {
it('unlocks after binding failure and accepts a new upload with a fresh key', async () => {
vi.mocked(api.bindLoadingPhoto).mockRejectedValueOnce(new Error('network unknown'))
const wrapper = setup(); await flushPromises(); await upload(wrapper)
expect(wrapper.emitted('saved')).toBeUndefined()
const original = vi.mocked(api.bindLoadingPhoto).mock.calls[0]![2]
await wrapper.findAll('button').find(item => item.text() === '核对原请求并继续保存')!.trigger('click'); await flushPromises()
expect(api.bindLoadingPhoto).toHaveBeenLastCalledWith('PC/1', 'LOADING_SCENE', original)
expect(api.uploadLoadingPhoto).toHaveBeenCalledTimes(1)
await upload(wrapper)
expect(api.bindLoadingPhoto).toHaveBeenLastCalledWith('PC/1', 'LOADING_SCENE', expect.objectContaining({ fileId: original.fileId })); expect(vi.mocked(api.bindLoadingPhoto).mock.calls[1]![2].idempotencyKey).not.toBe(original.idempotencyKey)
expect(api.uploadLoadingPhoto).toHaveBeenCalledTimes(2)
expect(wrapper.emitted('saved')).toHaveLength(1); wrapper.unmount()
})
it('refreshes a definitive version conflict while retaining the uploaded file', async () => {
it('uses the current version when the operator chooses a photo after a conflict', async () => {
vi.mocked(api.bindLoadingPhoto).mockRejectedValueOnce(new ApiResponseError('version conflict', 'A0409'))
const wrapper = setup(); await flushPromises(); await upload(wrapper)
const original = vi.mocked(api.bindLoadingPhoto).mock.calls[0]![2]
vi.mocked(api.getLoadingDocuments).mockResolvedValue(data({ recordVersion: '4' }))
vi.mocked(api.bindLoadingPhoto).mockResolvedValue(data({ stage: 'DELIVERING', complete: true, recordVersion: '5' }))
await wrapper.findAll('button').find(item => item.text() === '刷新并重试保存')!.trigger('click'); await flushPromises()
await upload(wrapper)
expect(api.bindLoadingPhoto).toHaveBeenLastCalledWith('PC/1', 'LOADING_SCENE', expect.objectContaining({ recordVersion: '4', fileId: '101' }))
expect(vi.mocked(api.bindLoadingPhoto).mock.calls[1]![2].idempotencyKey).not.toBe(original.idempotencyKey)
expect(api.uploadLoadingPhoto).toHaveBeenCalledTimes(1); expect(wrapper.emitted('saved')).toHaveLength(1); wrapper.unmount()
expect(api.uploadLoadingPhoto).toHaveBeenCalledTimes(2); expect(wrapper.emitted('saved')).toHaveLength(1); wrapper.unmount()
})
it('shows existing photos without exposing upload for a read-only account', async () => {
can.mockReturnValue(false)