feat(admin): streamline appointments and fleet intake
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { flushPromises, mount } from '@vue/test-utils'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import AppointmentCargoPanel from './AppointmentCargoPanel.vue'
|
||||
import { listPlanningCargo } from './planningApi'
|
||||
|
||||
vi.mock('./planningApi', () => ({ listPlanningCargo: vi.fn(), resolvePlanningSource: vi.fn() }))
|
||||
vi.mock('vue-router', () => ({ useRouter: () => ({ push: vi.fn() }) }))
|
||||
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => true }) }))
|
||||
const empty = { records: [], page: 1, size: 20, total: 0, pages: 0 }
|
||||
function render() {
|
||||
return mount(AppointmentCargoPanel, { global: { stubs: {
|
||||
DataTable: { name: 'DataTable', props: ['data', 'total', 'resultsVisible'], emits: ['update:page'], template: '<div><slot name="filters"/><slot name="notices"/><button data-next @click="$emit(\'update:page\',2)">下一页</button></div>' },
|
||||
QueryToolbar: { name: 'QueryToolbar', emits: ['search'], template: '<button data-search @click="$emit(\'search\')">查询</button>' },
|
||||
LoadErrorState: true, ApiErrorMeta: true, RowActions: true,
|
||||
} } })
|
||||
}
|
||||
describe('appointment planning cargo query', () => {
|
||||
beforeEach(() => { vi.resetAllMocks(); vi.mocked(listPlanningCargo).mockResolvedValue(empty) })
|
||||
it('uses one server-page request per entry, page change and reset', async () => {
|
||||
const wrapper = render(); await flushPromises()
|
||||
expect(listPlanningCargo).toHaveBeenCalledTimes(1)
|
||||
await wrapper.get('[data-next]').trigger('click'); await flushPromises()
|
||||
expect(listPlanningCargo).toHaveBeenLastCalledWith({ page: 2, size: 20, keyword: undefined }, expect.any(AbortSignal))
|
||||
await wrapper.get('[data-search]').trigger('click'); await flushPromises()
|
||||
expect(listPlanningCargo).toHaveBeenCalledTimes(3)
|
||||
expect(listPlanningCargo).toHaveBeenLastCalledWith({ page: 1, size: 20, keyword: undefined }, expect.any(AbortSignal))
|
||||
})
|
||||
it('shows a source failure instead of an authoritative empty list', async () => {
|
||||
vi.mocked(listPlanningCargo).mockRejectedValueOnce(new Error('目录不可用'))
|
||||
const wrapper = render(); await flushPromises()
|
||||
expect(wrapper.findComponent({ name: 'LoadErrorState' }).exists()).toBe(true)
|
||||
expect(wrapper.findComponent({ name: 'DataTable' }).props('resultsVisible')).toBe(false)
|
||||
})
|
||||
it('discards a late previous page and uses the new server total', async () => {
|
||||
let resolveOld!: (value: typeof empty) => void
|
||||
vi.mocked(listPlanningCargo).mockImplementationOnce(() => new Promise(resolve => { resolveOld = resolve }))
|
||||
const wrapper = render()
|
||||
vi.mocked(listPlanningCargo).mockResolvedValueOnce({ ...empty, page: 2, total: 21, pages: 2 })
|
||||
await wrapper.get('[data-next]').trigger('click'); await flushPromises()
|
||||
resolveOld({ ...empty, total: 100, pages: 5 }); await flushPromises()
|
||||
expect(wrapper.findComponent({ name: 'DataTable' }).props('total')).toBe(21)
|
||||
expect(vi.mocked(listPlanningCargo).mock.calls[0]![1]!.aborted).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user