Files
admin-web/src/modules/overseas-warehouse/components/DispatchVehicleMaintenanceFees.test.ts
T

48 lines
3.7 KiB
TypeScript

import { flushPromises, mount } from '@vue/test-utils'
import ElementPlus from 'element-plus'
import { beforeEach, expect, it, vi } from 'vitest'
import { getDeliveryOrder, type DeliveryOrderDetail } from '../api/deliveryOrders'
import type { DeliveryReference } from '../dispatchContracts'
import DispatchVehicleMaintenanceFees from './DispatchVehicleMaintenanceFees.vue'
const can = vi.hoisted(() => vi.fn(() => true))
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can }) }))
vi.mock('../api/deliveryOrders', () => ({ getDeliveryOrder: vi.fn() }))
const reference: DeliveryReference = { groupKey: 'group-a', customerId: 'C1', customerName: '客户甲', outboundNo: 'OUT-1', deliveryNo: 'DL-1', status: 'CREATED', packageCount: 2, palletCount: 1, destination: { key: 'WAREHOUSE:ONT8', type: 'FBA', warehouseId: null, warehouseCode: 'ONT8', warehouseName: null, address: null, postalCode: null, contactName: null, contactPhone: null } }
function result(): DeliveryOrderDetail {
return { order: { id: '11', version: 0, allowedActions: [], customerId: 'C1', deliveryNo: 'DL-1', outboundNo: 'OUT-1', dispatchNo: 'PC/1', status: 'CREATED', palletCount: 1, packageCount: 2, signedPackages: null, createdAt: '2026-10-21T10:00:00Z' }, skus: [], operations: [], fees: [{ id: '21', feeDirection: 'RECEIVABLE', feeType: 'DELIVERY_FEE', currency: 'USD', amount: 28, voidStatus: 'CONFIRMED' }] }
}
function render(deliveries = [reference]) { return mount(DispatchVehicleMaintenanceFees, { props: { dispatchNo: 'PC/1', deliveries }, global: { plugins: [ElementPlus] } }) }
beforeEach(() => { vi.resetAllMocks(); can.mockReturnValue(true); vi.mocked(getDeliveryOrder).mockResolvedValue(result()) })
it('reads official fees once per customer and delivery and preserves their currency and status', async () => {
const wrapper = render([reference, reference]); await flushPromises()
expect(getDeliveryOrder).toHaveBeenCalledExactlyOnceWith('DL-1', 'C1')
expect(wrapper.text()).toContain('派送费用'); expect(wrapper.text()).toContain('USD'); expect(wrapper.text()).toContain('28'); expect(wrapper.text()).toContain('已作废')
expect(wrapper.find('input').exists()).toBe(false); wrapper.unmount()
})
it('does not request or invent fees before a formal delivery exists', async () => {
const wrapper = render([]); await flushPromises()
expect(getDeliveryOrder).not.toHaveBeenCalled(); expect(wrapper.text()).toContain('尚未生成派送单费用'); wrapper.unmount()
})
it('preserves the existing delivery-list read permission', async () => {
can.mockReturnValue(false)
const wrapper = render(); await flushPromises()
expect(getDeliveryOrder).not.toHaveBeenCalled(); expect(wrapper.text()).toContain('暂无派送单费用查看权限'); wrapper.unmount()
})
it('rejects a fee response belonging to another dispatch and keeps failures separate from empty records', async () => {
const wrong = result(); wrong.order.dispatchNo = 'PC/OTHER'
vi.mocked(getDeliveryOrder).mockResolvedValueOnce(wrong)
const wrapper = render(); await flushPromises()
expect(wrapper.text()).toContain('费用读取失败'); expect(wrapper.text()).not.toContain('暂无正式费用记录'); expect(wrapper.text()).not.toContain('USD')
wrapper.unmount()
})
it('ignores a late response from the previous dispatch', async () => {
let resolve!: (value: DeliveryOrderDetail) => void
vi.mocked(getDeliveryOrder).mockImplementationOnce(() => new Promise(done => { resolve = done }))
const wrapper = render(); await flushPromises()
await wrapper.setProps({ dispatchNo: 'PC/2', deliveries: [] })
resolve(result()); await flushPromises()
expect(wrapper.text()).toContain('尚未生成派送单费用'); expect(wrapper.text()).not.toContain('USD'); wrapper.unmount()
})