30 lines
2.9 KiB
TypeScript
30 lines
2.9 KiB
TypeScript
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
|
|
import { shallowMount, flushPromises, type VueWrapper } from '@vue/test-utils'
|
|
import Cell from './TripOperationsFinanceCell.vue'
|
|
import * as api from '../api/tripOperationsFinance'
|
|
const access = vi.hoisted(() => ({ read: true }))
|
|
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => access.read }) }))
|
|
vi.mock('../api/tripOperationsFinance', () => ({ getTripOperationsFinance: vi.fn() }))
|
|
const wrappers: VueWrapper[] = []
|
|
function mount() { const w = shallowMount(Cell, { props: { tripNo: 'TR-A' }, global: { stubs: { ElButton: { template: '<button><slot/></button>' }, ElPopover: { template: '<div><slot/><slot name="reference"/></div>' }, ApiErrorMeta: true } } }); wrappers.push(w); return w }
|
|
const result: api.TripFinanceResult = { tripNo: 'TR-A', dispatchNos: ['DS-A'], receiptsVisible: true, attributionStatus: 'ATTRIBUTED', attributionReason: 'frozen', finance: { status: 'AVAILABLE', totals: [{ currency: 'CNY', receivableAmount: 20, receivedAmount: null }], sources: [], documents: [{ billNo: 'BILL-A', currency: 'CNY', receivedAmount: null, allocationStatus: 'PENDING_ALLOCATION', reason: '混合来源' }], reason: 'authority' } }
|
|
beforeEach(() => { vi.resetAllMocks(); access.read = true; vi.mocked(api.getTripOperationsFinance).mockResolvedValue(structuredClone(result)) })
|
|
afterEach(() => wrappers.splice(0).forEach(w => w.unmount()))
|
|
it('loads only on explicit click and displays pending without inventing zero', async () => {
|
|
const w = mount(); await flushPromises(); expect(api.getTripOperationsFinance).not.toHaveBeenCalled()
|
|
await w.find('button').trigger('click'); await flushPromises()
|
|
expect(api.getTripOperationsFinance).toHaveBeenCalledExactlyOnceWith('TR-A')
|
|
expect(w.text()).toContain('应收 20.00 / 实收 待分配'); expect(w.text()).toContain('BILL-A'); expect(w.text()).not.toContain('实收 0.00')
|
|
})
|
|
it('does not fetch without existing financial permission', async () => { access.read = false; const w = mount(); await flushPromises(); expect(w.text()).toContain('无应收读取权限'); expect(api.getTripOperationsFinance).not.toHaveBeenCalled() })
|
|
it('ignores a response arriving after switching trip', async () => {
|
|
let resolve!: (v: api.TripFinanceResult) => void
|
|
vi.mocked(api.getTripOperationsFinance).mockImplementation(() => new Promise(r => { resolve = r }))
|
|
const w = mount(); await w.find('button').trigger('click'); await w.setProps({ tripNo: 'TR-B' }); resolve(result); await flushPromises()
|
|
expect(w.text()).not.toContain('20.00'); expect(w.text()).toContain('查看应收/实收')
|
|
})
|
|
it('separates no receipt permission from unallocated values', async () => {
|
|
vi.mocked(api.getTripOperationsFinance).mockResolvedValue({ ...result, receiptsVisible: false, finance: { ...result.finance, documents: [] } })
|
|
const w = mount(); await w.find('button').trigger('click'); await flushPromises(); expect(w.text()).toContain('实收 无读取权限')
|
|
})
|