优化
This commit is contained in:
+59
@@ -0,0 +1,59 @@
|
||||
import { defineComponent, h } from 'vue'
|
||||
import { flushPromises, mount } from '@vue/test-utils'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { ApiResponseError } from '@/shared/api/http'
|
||||
import OutsourcedBusinessOperationsEditor from './OutsourcedBusinessOperationsEditor.vue'
|
||||
import { outsourcedBusinessFixture } from './OutsourcedBusinessFixtures'
|
||||
|
||||
const calls = vi.hoisted(() => ({ save: vi.fn(), detail: vi.fn(), command: vi.fn(), canEdit: true }))
|
||||
vi.mock('../api/outsourcedBusiness', () => ({ saveOutsourcedBusinessOperations: calls.save, getOutsourcedBusiness: calls.detail, getOutsourcedBusinessCommand: calls.command }))
|
||||
vi.mock('@/core/auth/auth', () => ({ useAuthStore: () => ({ user: { id: 'actor' } }) }))
|
||||
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => calls.canEdit }) }))
|
||||
vi.mock('@/core/unsaved-work/useUnsavedWorkRegistration', () => ({ useUnsavedWorkRegistration: () => ({ captureBaseline: vi.fn() }) }))
|
||||
vi.mock('element-plus', () => ({ ElMessage: { success: vi.fn() }, ElMessageBox: { confirm: vi.fn() } }))
|
||||
const Frame = defineComponent({ props: ['modelValue','busy','saveDisabled','pending'], emits: ['save','update:modelValue'], setup(props,{ slots,emit }) { return () => h('div', [...Object.values(slots).map(slot => slot?.()), h('button',{ 'data-save':'',disabled: props.busy || props.saveDisabled,onClick: () => emit('save') },'save')]) } })
|
||||
const Control = defineComponent({ props: ['modelValue'], emits: ['update:modelValue'], template: '<input :value="modelValue" @input="$emit(\'update:modelValue\', $event.target.value)" />' })
|
||||
const Field = defineComponent({ props: ['label'], template: '<label>{{label}}<slot /></label>' })
|
||||
const global = { stubs: { OutsourcedBusinessOperationsDialog: Frame, ElForm: { template:'<div><slot /></div>' }, ElFormItem: Field, ElInput: Control, ElSelect: Control, ElOption: true, ElDatePicker: Control, LoadErrorState: { props:['message'],template:'<div>{{message}}</div>' }, ApiErrorMeta: true } }
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks(); sessionStorage.clear(); calls.canEdit = true
|
||||
const current = outsourcedBusinessFixture(); current.row.recordVersion = '1'
|
||||
calls.save.mockResolvedValue(current); calls.detail.mockResolvedValue(current)
|
||||
calls.command.mockRejectedValue(new ApiResponseError('not found','A0404',404))
|
||||
})
|
||||
|
||||
describe('outsourced operations registration', () => {
|
||||
it('sends explicit zero and destination arrival with auxiliary zero, without fuel or mileage fields', async () => {
|
||||
const wrapper = mount(OutsourcedBusinessOperationsEditor,{ global,props:{modelValue:true,detail:outsourcedBusinessFixture()} }); await flushPromises()
|
||||
const currency = wrapper.findAll('label').find(field => field.text() === '币种')!.find('input')
|
||||
const amount = wrapper.findAll('label').find(field => field.text() === '整车承运金额')!.find('input')
|
||||
await currency.setValue('USD'); await amount.setValue('0.00')
|
||||
await wrapper.findAll('input').at(-1)!.setValue('2026-10-20T12:00:00+08:00')
|
||||
await wrapper.find('[data-save]').trigger('click'); await flushPromises()
|
||||
const body = calls.save.mock.calls[0]![1]
|
||||
expect(body).toEqual({ recordVersion:'0',idempotencyKey:expect.any(String),operations:{money:{currency:'USD',amount:'0.00'},arrivals:[{destinationKey:'destination-1',actualArrivedAt:'2026-10-20T12:00:00+08:00'}]},reason:null })
|
||||
expect(calls.save).toHaveBeenCalledTimes(1); expect(wrapper.emitted('saved')).toHaveLength(1)
|
||||
expect(wrapper.text()).not.toContain('油耗'); expect(wrapper.text()).not.toContain('里程'); wrapper.unmount()
|
||||
})
|
||||
it('clears money as null and retains exactly the original request after an unknown save', async () => {
|
||||
const detail = outsourcedBusinessFixture(); detail.row.operations.money = {currency:'CNY',amount:'123.45'}
|
||||
calls.save.mockRejectedValueOnce(new TypeError('network interrupted'))
|
||||
const wrapper = mount(OutsourcedBusinessOperationsEditor,{global,props:{modelValue:true,detail}}); await flushPromises()
|
||||
await wrapper.findAll('label').find(field => field.text() === '币种')!.find('input').setValue('')
|
||||
await wrapper.findAll('label').find(field => field.text() === '整车承运金额')!.find('input').setValue('')
|
||||
await wrapper.find('[data-save]').trigger('click'); await flushPromises()
|
||||
const original = JSON.parse(JSON.stringify(calls.save.mock.calls[0]![1]))
|
||||
expect(original.operations.money).toBeNull(); expect(wrapper.emitted('saved')).toBeUndefined()
|
||||
await wrapper.find('[data-save]').trigger('click'); await flushPromises()
|
||||
expect(calls.command).toHaveBeenCalledExactlyOnceWith('DS-OUT-1',original.idempotencyKey)
|
||||
expect(calls.save).toHaveBeenNthCalledWith(2,'DS-OUT-1',original); expect(wrapper.emitted('saved')).toHaveLength(1); wrapper.unmount()
|
||||
})
|
||||
it('does not write for an unchanged form or a user without edit permission', async () => {
|
||||
const first = mount(OutsourcedBusinessOperationsEditor,{global,props:{modelValue:true,detail:outsourcedBusinessFixture()}}); await flushPromises()
|
||||
await first.find('[data-save]').trigger('click'); await flushPromises(); expect(calls.save).not.toHaveBeenCalled(); first.unmount()
|
||||
calls.canEdit = false
|
||||
const readonly = mount(OutsourcedBusinessOperationsEditor,{global,props:{modelValue:true,detail:outsourcedBusinessFixture()}}); await flushPromises()
|
||||
expect(readonly.find('[data-save]').attributes('disabled')).toBeDefined(); expect(calls.save).not.toHaveBeenCalled(); readonly.unmount()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user