优化
This commit is contained in:
@@ -11,7 +11,7 @@ import { listPlatformTenants } from '@/modules/iam'
|
||||
import AppDialog from '@/shared/components/AppDialog.vue'
|
||||
import type { LocalLooseboardDetail, LocalLooseboardOrder, LocalTransportDetail, LocalTransportOrder, OverseasPurchaseDetail } from '../types'
|
||||
import {
|
||||
createLocalLooseboardOrder, createUsTruckOrder, getLocalLooseboardOrder, getOverseasPurchase, getUsTruckOrder,
|
||||
createOverseasPurchaseFee, uploadOverseasPurchaseFile, createLocalLooseboardOrder, createUsTruckOrder, getLocalLooseboardOrder, getOverseasPurchase, getUsTruckOrder,
|
||||
listLocalLooseboardOrders, listOverseasPurchaseCustomerOptions, listOverseasPurchaseWarehouseOptions,
|
||||
listOverseasPurchases, listUsTruckOrders, reviewOverseasPurchase, updateLocalLooseboardOrder, updateOverseasPurchase, updateUsTruckOrder,
|
||||
} from '../api/platformOverseasBusiness'
|
||||
@@ -64,13 +64,50 @@ describe('overseas business mounted pages', () => {
|
||||
vi.mocked(listPlatformTenants).mockReset().mockResolvedValue({ records: [{ id: '10001', tenantName: '可选客户', status: 'ACTIVE' } as never], page: 1, size: 200, total: 1, pages: 1 })
|
||||
})
|
||||
|
||||
|
||||
it('keeps all procurement facts in dense groups and business references in the heading', async () => {
|
||||
routing.route.params = { purchaseId: 'internal-purchase-route' }; routing.route.query = { customerId: '10001' }
|
||||
const wrapper = mountPage(PurchaseOrderDetailView)
|
||||
await flushPromises()
|
||||
expect(wrapper.get('.density-detail-title').text()).toBe('OP-100')
|
||||
expect(wrapper.get('[aria-label="采购订单概览"]').text()).toContain('洛杉矶采购仓')
|
||||
expect(wrapper.findAll('.density-fields')).toHaveLength(4)
|
||||
expect(wrapper.findAll('.density-fields dt')).toHaveLength(23)
|
||||
expect(wrapper.findAll('.density-fields .wide')).toHaveLength(4)
|
||||
expect(wrapper.text()).not.toContain('internal-purchase-route')
|
||||
await wrapper.get('.density-back').trigger('click')
|
||||
expect(routing.push).toHaveBeenCalledWith({ name: 'overseas-business-purchases' })
|
||||
})
|
||||
|
||||
it('retains the voucher upload and fee dialog workflow with teleported density', async () => {
|
||||
routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }
|
||||
const voucher = { id: 'voucher-1', fileId: 'file-1', fileName: 'voucher.pdf', category: 'VOUCHER' as const, contentType: 'application/pdf', sizeBytes: 3, createdAt: '2026-09-14T10:00:00' }
|
||||
vi.mocked(uploadOverseasPurchaseFile).mockReset().mockResolvedValue(voucher)
|
||||
vi.mocked(createOverseasPurchaseFee).mockReset().mockResolvedValue({ id: 'fee-1', feeNo: 'FEE-1', feeItemCode: 'COURIER', feeItemName: '快递费', amount: '25', currency: 'CNY', voucherFileId: 'file-1', voucherFileName: 'voucher.pdf', remark: null, walletStatus: 'FREEZE_PENDING', walletErrorMessage: null, createdAt: '2026-09-14T10:00:00' })
|
||||
const wrapper = mountPage(PurchaseOrderDetailView)
|
||||
await flushPromises()
|
||||
const input = wrapper.findAll('input[type="file"]')[1]!
|
||||
const file = new File(['pdf'], 'voucher.pdf', { type: 'application/pdf' })
|
||||
Object.defineProperty(input.element, 'files', { value: [file], configurable: true })
|
||||
await input.trigger('change'); await flushPromises()
|
||||
expect(uploadOverseasPurchaseFile).toHaveBeenCalledWith('OP-100', '10001', 'VOUCHER', file)
|
||||
const dialog = wrapper.findAllComponents(AppDialog)[1]!
|
||||
expect(dialog.props('modelValue')).toBe(true)
|
||||
expect(document.querySelector('.admin-density-dialog .density-form')).not.toBeNull()
|
||||
dialog.findComponent({ name: 'ElInputNumber' }).vm.$emit('update:modelValue', 25)
|
||||
await wrapper.vm.$nextTick()
|
||||
dialog.vm.$emit('confirm'); await flushPromises()
|
||||
expect(createOverseasPurchaseFee).toHaveBeenCalledWith('OP-100', '10001', expect.objectContaining({ amount: 25, voucherFileId: 'file-1' }))
|
||||
expect(dialog.props('modelValue')).toBe(false)
|
||||
})
|
||||
|
||||
it('mounts procurement list with customer candidates and real data', async () => { const wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(listOverseasPurchaseCustomerOptions).toHaveBeenCalled(); expect(listOverseasPurchases).toHaveBeenCalledWith({ page: 1, size: 20, customerId: '', orderNo: '', purchaseCategory: '', productName: '' }); expect(wrapper.text()).toContain('OP-100'); expect(wrapper.text()).toContain('待出库'); expect(wrapper.text()).toContain('2026-08-01 10:00') })
|
||||
it('refreshes the cached procurement list after returning from detail or edit', () => { expect(purchaseListSource).toContain('onActivated'); expect(purchaseListSource).toMatch(/onActivated\(\(\) => \{ if \(activatedOnce\) void load\(\)/) })
|
||||
it('refreshes the cached procurement detail after an edit completes', () => { expect(purchaseDetailSource).toContain('onActivated'); expect(purchaseDetailSource).toMatch(/onActivated\(\(\) => \{ if \(activatedOnce\) void load\(\)/) })
|
||||
it('paginates procurement results', async () => { vi.mocked(listOverseasPurchases).mockResolvedValue({ records: [purchase], page: 1, size: 20, total: 40, pages: 2 }); const wrapper = mountPage(PurchaseOrdersView); await flushPromises(); await wrapper.find('button[aria-label="第 2 页"]').trigger('click'); await flushPromises(); expect(listOverseasPurchases).toHaveBeenLastCalledWith(expect.objectContaining({ page: 2 })) })
|
||||
it('renders procurement empty and traceable 403 states', async () => { vi.mocked(listOverseasPurchases).mockResolvedValueOnce({ records: [], page: 1, size: 20, total: 0, pages: 0 }); let wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(wrapper.text()).toContain('暂无符合筛选条件的海外采购订单'); wrapper.unmount(); vi.mocked(listOverseasPurchases).mockRejectedValue(new ApiResponseError('forbidden', 'A0403', 403, null, 'REQ-403')); wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(wrapper.text()).toContain('当前账号无权访问该数据'); expect(wrapper.text()).toContain('REQ-403') })
|
||||
it('mounts procurement detail operation history without exposing internal operator ids', async () => { routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; const wrapper = mountPage(PurchaseOrderDetailView); await flushPromises(); expect(getOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001'); expect(wrapper.text()).toContain('操作流水'); expect(wrapper.text()).toContain('编辑'); expect(wrapper.text()).not.toContain('INTERNAL-OPERATOR-7') })
|
||||
it('reviews a pending procurement from its detail page', async () => { const pending = { ...purchase, status: 'PENDING_REVIEW' as const, inboundQuantity: 0, inventoryQuantity: 0, version: 2 }; routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; vi.mocked(getOverseasPurchase).mockResolvedValue(pending); vi.mocked(reviewOverseasPurchase).mockResolvedValue({ ...pending, status: 'APPROVED', version: 3 }); const wrapper = mountPage(PurchaseOrderDetailView); await flushPromises(); await wrapper.findAll('button').find((button) => button.text().includes('通过'))?.trigger('click'); await wrapper.vm.$nextTick(); const reviewDialog = wrapper.findAllComponents(AppDialog)[0]; expect(reviewDialog.props('modelValue')).toBe(true); reviewDialog.vm.$emit('confirm'); await flushPromises(); expect(reviewOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001', expect.objectContaining({ version: 2, decision: 'APPROVE', idempotencyKey: expect.any(String) })); expect(wrapper.text()).toContain('已通过'); expect(wrapper.find('.header-actions').text()).toBe('返回') })
|
||||
it('reviews a pending procurement from its detail page', async () => { const pending = { ...purchase, status: 'PENDING_REVIEW' as const, inboundQuantity: 0, inventoryQuantity: 0, version: 2 }; routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; vi.mocked(getOverseasPurchase).mockResolvedValue(pending); vi.mocked(reviewOverseasPurchase).mockResolvedValue({ ...pending, status: 'APPROVED', version: 3 }); const wrapper = mountPage(PurchaseOrderDetailView); await flushPromises(); await wrapper.findAll('button').find((button) => button.text().includes('通过'))?.trigger('click'); await wrapper.vm.$nextTick(); const reviewDialog = wrapper.findAllComponents(AppDialog)[0]; expect(reviewDialog.props('modelValue')).toBe(true); reviewDialog.vm.$emit('confirm'); await flushPromises(); expect(reviewOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001', expect.objectContaining({ version: 2, decision: 'APPROVE', idempotencyKey: expect.any(String) })); expect(wrapper.text()).toContain('已通过'); expect(wrapper.find('.header-actions').exists()).toBe(false); expect(wrapper.get('.density-back').text()).toBe('返回列表') })
|
||||
it('submits procurement explicit null clears and keeps a 409 visible without local overwrite', async () => { routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; vi.mocked(updateOverseasPurchase).mockRejectedValue(new ApiResponseError('订单版本冲突,请刷新后重试', 'B0409', 409)); const wrapper = mountPage(PurchaseOrderEditView); await flushPromises(); const productUrl = wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('商品链接'))!.find('input'); const domesticCarrier = wrapper.findAll('.el-form-item').find((item) => item.text().startsWith('国内承运商'))!.find('input'); await productUrl.setValue(''); await domesticCarrier.setValue(''); wrapper.findComponent({ name: 'ElSelect' }).vm.$emit('update:modelValue', null); wrapper.findComponent({ name: 'ElDatePicker' }).vm.$emit('update:modelValue', null); await wrapper.vm.$nextTick(); await wrapper.findAll('button').find((button) => button.text().trim() === '保存')?.trigger('click'); await flushPromises(); expect(updateOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001', expect.objectContaining({ version: 3, productUrl: null, domesticCarrier: null, estimatedArrivalAt: null, purchaseWarehouseId: null })); expect(document.body.textContent).toContain('订单版本冲突,请刷新后重试'); expect((productUrl.element as HTMLInputElement).value).toBe(''); expect((domesticCarrier.element as HTMLInputElement).value).toBe(''); expect(routing.push).not.toHaveBeenCalled() })
|
||||
it('keeps procurement list usable when customer candidates fail', async () => { vi.mocked(listOverseasPurchaseCustomerOptions).mockRejectedValue(new Error('candidate unavailable')); const wrapper = mountPage(PurchaseOrdersView); await flushPromises(); expect(listOverseasPurchases).toHaveBeenCalled(); expect(wrapper.text()).toContain('OP-100'); expect(wrapper.text()).not.toContain('candidate unavailable') })
|
||||
it('loads procurement edit data but blocks unsafe warehouse selection when candidates fail', async () => { routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }; vi.mocked(listOverseasPurchaseWarehouseOptions).mockRejectedValue(new Error('candidate unavailable')); const wrapper = mountPage(PurchaseOrderEditView); await flushPromises(); expect(getOverseasPurchase).toHaveBeenCalledWith('OP-100', '10001'); expect(wrapper.text()).toContain('采购仓候选加载失败'); expect(wrapper.text()).toContain('OP-100') })
|
||||
|
||||
Reference in New Issue
Block a user