469 lines
26 KiB
TypeScript
469 lines
26 KiB
TypeScript
import { flushPromises, shallowMount } from '@vue/test-utils'
|
||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||
import { getPlatformUnifiedOrderStatusCounts, listPlatformUnifiedOrders, updatePlatformUnifiedOrderPlanning } from '@/modules/unified-orders/api/unifiedOrders'
|
||
import { createPlatformExportTask } from '@/modules/downloads'
|
||
import { showExportTaskCreatedDialog } from '@/shared/components/exportTaskCreatedDialog'
|
||
import { ApiResponseError } from '@/shared/api/http'
|
||
import { ElMessage } from 'element-plus'
|
||
import UnifiedOrdersView from './UnifiedOrdersView.vue'
|
||
|
||
vi.mock('vue-router', () => ({
|
||
useRoute: () => ({ params: {}, query: {} }),
|
||
useRouter: () => ({ push: vi.fn() }),
|
||
}))
|
||
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: () => true }) }))
|
||
vi.mock('@/modules/iam', async importOriginal => ({
|
||
...await importOriginal<typeof import('@/modules/iam')>(), listPlatformTenants: vi.fn().mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 }) }))
|
||
vi.mock('@/modules/warehouses', () => ({ listAllPlatformWarehouses: vi.fn().mockResolvedValue([]) }))
|
||
vi.mock('@/modules/inbounds', async () => {
|
||
const { defineComponent } = await import('vue')
|
||
return {
|
||
downloadWeightImage: vi.fn(), getInboundMeasurement: vi.fn(),
|
||
InboundTaskList: defineComponent({
|
||
name: 'InboundTaskList', props: ['mode', 'title', 'taskLoader'],
|
||
methods: { reload() { return this.taskLoader({ page: 1, size: 20 }) } },
|
||
mounted() { void this.reload() },
|
||
template: '<section><slot name="filters" :loading="false" /><slot name="status-tabs" /></section>',
|
||
}),
|
||
}
|
||
})
|
||
vi.mock('@/modules/downloads', () => ({ createPlatformExportTask: vi.fn() }))
|
||
vi.mock('@/shared/components/exportTaskCreatedDialog', () => ({ showExportTaskCreatedDialog: vi.fn() }))
|
||
vi.mock('@/modules/unified-orders/workflows', () => ({ UnifiedOrderWorkflowPanel: { template: '<div />' } }))
|
||
vi.mock('@/modules/unified-orders/api/coLoadGroups', () => ({
|
||
cancelPlatformCoLoadGroup: vi.fn(),
|
||
createPlatformCoLoadGroup: vi.fn(),
|
||
getPlatformCoLoadGroupByInboundCode: vi.fn(),
|
||
}))
|
||
vi.mock('@/modules/unified-orders/api/unifiedOrders', () => ({
|
||
updatePlatformUnifiedOrderRemarks: vi.fn(),
|
||
approvePlatformUnifiedOrder: vi.fn(),
|
||
getPlatformUnifiedOrder: vi.fn(),
|
||
listPlatformUnifiedOrderFeeDetails: vi.fn(),
|
||
getPlatformUnifiedOrderStatusCounts: vi.fn().mockResolvedValue({ counts: {} }), listPlatformUnifiedOrders: vi.fn(),
|
||
updatePlatformUnifiedOrderPlanning: vi.fn(),
|
||
unifiedOrderStatusOptions: [
|
||
{ value: 'PENDING_REVIEW', label: '待审核' },
|
||
{ value: 'WAIT_MEASURE', label: '待测量数据' },
|
||
{ value: 'WAIT_SPLIT', label: '待装柜' },
|
||
{ value: 'LOADING', label: '装柜中' },
|
||
{ value: 'LOADED', label: '装柜完成' },
|
||
{ value: 'DELIVERING', label: '派送中' },
|
||
{ value: 'SIGNED', label: '派送完成' },
|
||
],
|
||
}))
|
||
|
||
function emptyPage() {
|
||
return { records: [], page: 1, size: 20, total: 0, pages: 0 }
|
||
}
|
||
|
||
function mountView() {
|
||
return shallowMount(UnifiedOrdersView, {
|
||
global: {
|
||
directives: { loading: () => undefined },
|
||
stubs: {
|
||
AdminPage: { template: '<main><slot /></main>' },
|
||
InboundTaskList: false,
|
||
ListPageLayout: { template: '<section><slot name="toolbar" /><slot name="state" /><slot /></section>' },
|
||
QueryToolbar: { name: 'QueryToolbar', props: ['modelValue', 'fields', 'maxVisible'], emits: ['update:modelValue', 'search', 'reset'], template: '<div data-testid="query-toolbar"><slot name="actions" /></div>' },
|
||
DataTable: { name: 'DataTable', props: ['page', 'pageSize', 'data'], emits: ['update:page', 'update:pageSize', 'selection-change'], template: '<div data-testid="data-table"><slot name="toolbar-start" /><slot name="toolbar-actions" /><slot name="filters" /><slot name="notices" /><div v-for="row in data" :key="row.orderId" class="test-row"><slot name="estimatedVolume" :row="row" /><slot name="expectedArrival" :row="row" /></div></div>' },
|
||
'el-button': { template: '<button><slot /></button>' },
|
||
'el-input-number': { name: 'ElInputNumber', props: ['modelValue', 'disabled'], emits: ['update:modelValue', 'change'], template: '<input class="number-input" :value="modelValue" :disabled="disabled" @change="$emit(\'change\')" />' },
|
||
'el-date-picker': { name: 'ElDatePicker', props: ['modelValue', 'disabled'], emits: ['update:modelValue', 'change'], template: '<input class="date-input" :value="modelValue" :disabled="disabled" @change="$emit(\'change\')" />' },
|
||
ApiErrorMeta: { props: ['details'], template: '<code class="api-meta">{{ details.code }} {{ details.requestId }} {{ details.traceId }}</code>' },
|
||
},
|
||
},
|
||
})
|
||
}
|
||
|
||
describe('UnifiedOrdersView list request coordination', () => {
|
||
beforeEach(() => {
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockReset().mockResolvedValue({ counts: {} })
|
||
vi.mocked(listPlatformUnifiedOrders).mockReset().mockResolvedValue(emptyPage())
|
||
vi.mocked(updatePlatformUnifiedOrderPlanning).mockReset()
|
||
vi.mocked(createPlatformExportTask).mockReset().mockResolvedValue({ taskName: '国内仓订单', taskNo: 'EXP-1' } as never)
|
||
vi.mocked(showExportTaskCreatedDialog).mockReset().mockResolvedValue(false)
|
||
})
|
||
|
||
it('shares applied filters, advanced fields and reset across measurement review and other tabs', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const model = { receivingWarehouseId: '9007199254740993', destinationWarehouseId: '200', inboundCode: ' IN-9 ', tenantId: '300', channelName: '海派', containerNo: 'CONT-1', cabinetNo: 'CAB-1', loaded: 'false', fullContainer: 'true', expectedArrivalDate: '2026-10-20', sailingDate: '2026-11-01', feeReviewStatus: 'APPROVED', measurementReviewStatus: 'PENDING', fbaCode: 'SKU-1', createdRange: ['2026-10-01', '2026-10-20'] }
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
toolbar.vm.$emit('update:modelValue', { ...toolbar.props('modelValue'), ...model })
|
||
await flushPromises()
|
||
toolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
const ordinaryQuery = vi.mocked(listPlatformUnifiedOrders).mock.lastCall![0]
|
||
await wrapper.findAll('[role="tab"]').find(tab => tab.text().startsWith('测量数据审核'))!.trigger('click')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith({ ...ordinaryQuery, mainStatus: 'MEASUREMENT_REVIEW' })
|
||
const reviewToolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
expect(reviewToolbar.props('modelValue')).toMatchObject(model)
|
||
expect(reviewToolbar.attributes('preference-key')).toBe('unified-orders-query-v2')
|
||
expect(reviewToolbar.props('maxVisible')).toBe(3)
|
||
expect(reviewToolbar.props('fields').map((field: { key: string }) => field.key)).toEqual(expect.arrayContaining(['createdRange', 'tenantId', 'inboundCode']))
|
||
reviewToolbar.vm.$emit('reset')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ mainStatus: 'MEASUREMENT_REVIEW', receivingWarehouseId: undefined, inboundCode: undefined, channelName: undefined, tenantId: undefined }))
|
||
reviewToolbar.vm.$emit('update:modelValue', { ...reviewToolbar.props('modelValue'), inboundCode: 'IN-REVIEW' })
|
||
await flushPromises()
|
||
reviewToolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ mainStatus: 'MEASUREMENT_REVIEW', inboundCode: 'IN-REVIEW' }))
|
||
await wrapper.findAll('[role="tab"]').find(tab => tab.text().startsWith('待审核'))!.trigger('click')
|
||
await flushPromises()
|
||
expect(wrapper.getComponent({ name: 'QueryToolbar' }).props('modelValue')).toMatchObject({ inboundCode: 'IN-REVIEW' })
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ mainStatus: 'PENDING_REVIEW', inboundCode: 'IN-REVIEW' }))
|
||
})
|
||
|
||
it.each(['全部', '测量数据审核'])('limits fields after saved ordering without changing filters or querying when %s is expanded and collapsed', async (tabLabel) => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
if (tabLabel !== '全部') {
|
||
await wrapper.findAll('[role="tab"]').find(tab => tab.text().startsWith(tabLabel))!.trigger('click')
|
||
await flushPromises()
|
||
}
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
const fieldKeys = toolbar.props('fields').map((field: { key: string }) => field.key)
|
||
expect(fieldKeys).toHaveLength(15)
|
||
expect(fieldKeys).toEqual(expect.arrayContaining(['createdRange', 'tenantId', 'inboundCode']))
|
||
expect(toolbar.props('maxVisible')).toBe(3)
|
||
const model = { ...toolbar.props('modelValue'), tenantId: 'customer-1', inboundCode: 'IN-KEEP', createdRange: ['2026-10-01', '2026-10-28'] }
|
||
toolbar.vm.$emit('update:modelValue', model)
|
||
await flushPromises()
|
||
const requestCount = vi.mocked(listPlatformUnifiedOrders).mock.calls.length
|
||
await wrapper.get('[aria-controls="unified-orders-advanced-filters"]').trigger('click')
|
||
expect(toolbar.props('maxVisible')).toBeUndefined()
|
||
await wrapper.get('[aria-controls="unified-orders-advanced-filters"]').trigger('click')
|
||
expect(toolbar.props('maxVisible')).toBe(3)
|
||
expect(toolbar.props('fields').map((field: { key: string }) => field.key)).toEqual(fieldKeys)
|
||
expect(toolbar.props('modelValue')).toEqual(model)
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(requestCount)
|
||
wrapper.unmount()
|
||
})
|
||
|
||
it('shows only supported counts, keeps all text-only and never scopes counts by status or pagination', async () => {
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockResolvedValue({ counts: { PENDING_REVIEW: 12, WAIT_MEASURE: 0, SIGNED: 3 } })
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const tabs = wrapper.findAll('[role="tab"]')
|
||
expect(tabs[0]!.text()).toBe('全部')
|
||
expect(tabs[1]!.text()).toBe('待审核(12)')
|
||
expect(tabs[2]!.text()).toBe('待测量数据(0)')
|
||
expect(tabs[3]!.text()).toBe('测量数据审核')
|
||
expect(tabs.at(-1)!.text()).toBe('派送完成(3)')
|
||
expect(tabs.map((tab) => tab.text())).not.toContain('派送完成')
|
||
expect(tabs.map((tab) => tab.text())).not.toContain('已完成')
|
||
await tabs[1]!.trigger('click')
|
||
wrapper.getComponent({ name: 'DataTable' }).vm.$emit('update:page', 2)
|
||
await flushPromises()
|
||
expect(getPlatformUnifiedOrderStatusCounts).toHaveBeenCalledTimes(1)
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
toolbar.vm.$emit('update:modelValue', { ...toolbar.props('modelValue'), inboundCode: ' IN-9 ', loaded: 'false' })
|
||
toolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
expect(getPlatformUnifiedOrderStatusCounts).toHaveBeenCalledTimes(2)
|
||
const params = vi.mocked(getPlatformUnifiedOrderStatusCounts).mock.lastCall![0]
|
||
expect(params).toMatchObject({ inboundCode: 'IN-9', loaded: false })
|
||
expect(params).not.toHaveProperty('mainStatus')
|
||
expect(params).not.toHaveProperty('page')
|
||
expect(params).not.toHaveProperty('size')
|
||
toolbar.vm.$emit('reset')
|
||
await flushPromises()
|
||
expect(getPlatformUnifiedOrderStatusCounts).toHaveBeenCalledTimes(3)
|
||
})
|
||
|
||
it('ignores older count responses and hides stale counts during loading and failures with retry', async () => {
|
||
let resolveOld!: (value: { counts: { PENDING_REVIEW: number } }) => void
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockImplementationOnce(() => new Promise((resolve) => { resolveOld = resolve }))
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
expect(wrapper.get('[role="tablist"]').attributes('aria-busy')).toBe('true')
|
||
expect(wrapper.find('.order-status-count').exists()).toBe(false)
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockResolvedValueOnce({ counts: { PENDING_REVIEW: 7 } })
|
||
wrapper.getComponent({ name: 'QueryToolbar' }).vm.$emit('search')
|
||
await flushPromises()
|
||
resolveOld({ counts: { PENDING_REVIEW: 99 } })
|
||
await flushPromises()
|
||
expect(wrapper.findAll('[role="tab"]')[1]!.text()).toBe('待审核(7)')
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockRejectedValueOnce(new Error('统计不可用'))
|
||
wrapper.getComponent({ name: 'QueryToolbar' }).vm.$emit('search')
|
||
await flushPromises()
|
||
expect(wrapper.find('.order-status-count').exists()).toBe(false)
|
||
expect(wrapper.findComponent({ name: 'DataTable' }).exists()).toBe(true)
|
||
expect(wrapper.find('.order-status-feedback').text()).toContain('重试数量')
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockResolvedValueOnce({ counts: { PENDING_REVIEW: 8, MEASUREMENT_REVIEW: 3 } })
|
||
await wrapper.findAll('button').find((button) => button.text() === '重试数量')!.trigger('click')
|
||
await flushPromises()
|
||
expect(wrapper.findAll('[role="tab"]')[1]!.text()).toBe('待审核(8)')
|
||
expect(wrapper.findAll('[role="tab"]')[3]!.text()).toBe('测量数据审核(3)')
|
||
})
|
||
|
||
it('keeps every count and the toolbar state stable when switching between ordinary and review tabs', async () => {
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockResolvedValueOnce({ counts: { PENDING_REVIEW: 12, WAIT_MEASURE: 0, MEASUREMENT_REVIEW: 4, SIGNED: 3 } })
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const labels = wrapper.findAll('[role="tab"]').map(tab => tab.text())
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockImplementation(() => new Promise(() => {}))
|
||
for (const label of ['待审核(12)', '测量数据审核(4)', '待测量数据(0)', '全部']) {
|
||
await wrapper.findAll('[role="tab"]').find(tab => tab.text() === label)!.trigger('click')
|
||
await flushPromises()
|
||
expect(wrapper.findAll('[role="tab"]').map(tab => tab.text())).toEqual(labels)
|
||
expect(wrapper.get('[aria-selected="true"]').text()).toBe(label)
|
||
expect(wrapper.get('[role="tablist"]').attributes('aria-busy')).toBe('false')
|
||
expect(wrapper.find('.order-status-feedback').exists()).toBe(false)
|
||
expect(getPlatformUnifiedOrderStatusCounts).toHaveBeenCalledTimes(1)
|
||
}
|
||
})
|
||
|
||
it.each(['全部', '测量数据审核'])('keeps the %s tab bar mounted without a loading text row during query', async (label) => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
if (label !== '全部') {
|
||
await wrapper.findAll('[role="tab"]').find(tab => tab.text() === label)!.trigger('click')
|
||
await flushPromises()
|
||
}
|
||
const tabList = wrapper.get('[role="tablist"]').element
|
||
let resolveCounts!: (value: { counts: {} }) => void
|
||
vi.mocked(getPlatformUnifiedOrderStatusCounts).mockImplementationOnce(() => new Promise(resolve => { resolveCounts = resolve }))
|
||
wrapper.getComponent({ name: 'QueryToolbar' }).vm.$emit('search')
|
||
await flushPromises()
|
||
expect(wrapper.get('[role="tablist"]').element).toBe(tabList)
|
||
expect(wrapper.get('[role="tablist"]').attributes('aria-busy')).toBe('true')
|
||
expect(wrapper.find('.order-status-feedback').exists()).toBe(false)
|
||
resolveCounts({ counts: {} })
|
||
await flushPromises()
|
||
expect(wrapper.get('[role="tablist"]').element).toBe(tabList)
|
||
expect(wrapper.get('[role="tablist"]').attributes('aria-busy')).toBe('false')
|
||
wrapper.unmount()
|
||
})
|
||
|
||
it.each(['success', 'failure'] as const)('ignores an older tab request %s after the current tab has loaded', async (outcome) => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
let resolveOlder!: (value: Awaited<ReturnType<typeof listPlatformUnifiedOrders>>) => void
|
||
let rejectOlder!: (reason: Error) => void
|
||
vi.mocked(listPlatformUnifiedOrders).mockImplementationOnce(() => new Promise((resolve, reject) => { resolveOlder = resolve; rejectOlder = reject }))
|
||
await wrapper.findAll('[role="tab"]').find(tab => tab.text() === '待审核')!.trigger('click')
|
||
const latest = { ...emptyPage(), records: [{ orderId: 'new-order', tenantId: '8', orderVersion: 1, inboundCode: 'IN-NEW', internalOrderStatus: 'SUBMITTED', mainStatus: 'WAIT_MEASURE', expectedArrivalAt: null, estimatedVolumeCbm: null }], total: 1, pages: 1 } as Awaited<ReturnType<typeof listPlatformUnifiedOrders>>
|
||
vi.mocked(listPlatformUnifiedOrders).mockResolvedValueOnce(latest)
|
||
await wrapper.findAll('[role="tab"]').find(tab => tab.text() === '待测量数据')!.trigger('click')
|
||
await flushPromises()
|
||
expect(wrapper.getComponent({ name: 'DataTable' }).props('data')).toEqual(latest.records)
|
||
if (outcome === 'success') resolveOlder(emptyPage())
|
||
else rejectOlder(new Error('旧页签请求失败'))
|
||
await flushPromises()
|
||
expect(wrapper.get('[aria-selected="true"]').text()).toBe('待测量数据')
|
||
expect(wrapper.getComponent({ name: 'DataTable' }).props('data')).toEqual(latest.records)
|
||
expect(wrapper.findComponent({ name: 'LoadErrorState' }).exists()).toBe(false)
|
||
})
|
||
|
||
it('loads once initially and once for query, reset, status tab and pagination', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(1)
|
||
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
toolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(2)
|
||
|
||
toolbar.vm.$emit('reset')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(3)
|
||
|
||
await wrapper.findAll('.status-tab')[1]!.trigger('click')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(4)
|
||
|
||
wrapper.getComponent({ name: 'DataTable' }).vm.$emit('update:page', 2)
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(5)
|
||
})
|
||
|
||
it('opens the existing measurement review list beside measurement and returns to order queries', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const labels = wrapper.findAll('[role="tab"]').map((tab) => tab.text())
|
||
expect(labels.indexOf('测量数据审核')).toBe(labels.indexOf('待测量数据') + 1)
|
||
|
||
await wrapper.findAll('[role="tab"]').find((tab) => tab.text() === '测量数据审核')!.trigger('click')
|
||
await flushPromises()
|
||
expect(wrapper.getComponent({ name: 'InboundTaskList' }).props()).toMatchObject({ mode: 'review', title: '订单列表' })
|
||
expect(wrapper.getComponent({ name: 'InboundTaskList' }).classes()).toContain('is-embedded')
|
||
expect(wrapper.get('main').classes()).not.toContain('is-embedded')
|
||
expect(wrapper.get('[aria-selected="true"]').text()).toBe('测量数据审核')
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(2)
|
||
|
||
await wrapper.findAll('[role="tab"]').find((tab) => tab.text() === '待测量数据')!.trigger('click')
|
||
await flushPromises()
|
||
expect(wrapper.findComponent({ name: 'InboundTaskList' }).exists()).toBe(false)
|
||
expect(wrapper.find('.is-embedded').exists()).toBe(false)
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ mainStatus: 'WAIT_MEASURE' }))
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(3)
|
||
})
|
||
|
||
it('does not apply draft filters to pagination until query is submitted', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
const draft = { ...toolbar.props('modelValue'), inboundCode: ' DRAFT-CODE ' }
|
||
toolbar.vm.$emit('update:modelValue', draft)
|
||
await wrapper.vm.$nextTick()
|
||
|
||
wrapper.getComponent({ name: 'DataTable' }).vm.$emit('update:page', 2)
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ page: 2, inboundCode: undefined }))
|
||
|
||
toolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(3)
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ page: 1, inboundCode: 'DRAFT-CODE' }))
|
||
})
|
||
|
||
it('resets a later page and changes page size with one request per interaction', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const table = wrapper.getComponent({ name: 'DataTable' })
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
|
||
table.vm.$emit('update:page', 3)
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(2)
|
||
|
||
toolbar.vm.$emit('reset')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(3)
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ page: 1 }))
|
||
|
||
table.vm.$emit('update:pageSize', 50)
|
||
table.vm.$emit('update:page', 1)
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(4)
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ page: 1, size: 50 }))
|
||
})
|
||
|
||
it('does not turn a cleared full-container filter into false', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
const selected = { ...toolbar.props('modelValue'), fullContainer: 'true' }
|
||
toolbar.vm.$emit('update:modelValue', selected)
|
||
toolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ fullContainer: true }))
|
||
|
||
toolbar.vm.$emit('update:modelValue', { ...selected, fullContainer: undefined })
|
||
toolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ fullContainer: undefined }))
|
||
})
|
||
|
||
it('exports the selected business order numbers without loading other pages', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
wrapper.getComponent({ name: 'DataTable' }).vm.$emit('selection-change', [
|
||
{ orderId: '1', orderNo: 'ORDER-1', tenantId: '8' },
|
||
{ orderId: '2', orderNo: 'ORDER-2', tenantId: '8' },
|
||
])
|
||
await wrapper.vm.$nextTick()
|
||
|
||
await wrapper.findAll('button').find((button) => button.text().includes('导出'))!.trigger('click')
|
||
await flushPromises()
|
||
|
||
expect(createPlatformExportTask).toHaveBeenCalledWith({
|
||
exportType: 'DOMESTIC_WAREHOUSE_ORDER_LIST', format: 'XLSX', taskName: '国内仓订单-已选2票',
|
||
parameters: { selectedOrderNos: ['ORDER-1', 'ORDER-2'] },
|
||
})
|
||
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(1)
|
||
})
|
||
|
||
it('exports every result matching the applied filters instead of the current page', async () => {
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const toolbar = wrapper.getComponent({ name: 'QueryToolbar' })
|
||
toolbar.vm.$emit('update:modelValue', {
|
||
...toolbar.props('modelValue'), inboundCode: ' IN-8 ', loaded: 'false', createdRange: ['2026-08-01', '2026-08-31'],
|
||
})
|
||
toolbar.vm.$emit('search')
|
||
await flushPromises()
|
||
|
||
await wrapper.findAll('button').find((button) => button.text() === '导出')!.trigger('click')
|
||
await flushPromises()
|
||
|
||
expect(createPlatformExportTask).toHaveBeenCalledWith(expect.objectContaining({
|
||
exportType: 'DOMESTIC_WAREHOUSE_ORDER_LIST', taskName: '国内仓订单-当前筛选',
|
||
parameters: expect.objectContaining({
|
||
inboundCode: 'IN-8', loaded: false,
|
||
createdFrom: '2026-08-01T00:00:00', createdTo: '2026-08-31T23:59:59',
|
||
}),
|
||
}))
|
||
expect(createPlatformExportTask).not.toHaveBeenCalledWith(expect.objectContaining({
|
||
parameters: expect.objectContaining({ page: expect.anything(), size: expect.anything() }),
|
||
}))
|
||
})
|
||
|
||
it('edits arrival and estimated volume and reports compact failure evidence through a message', async () => {
|
||
const errorMessage = vi.spyOn(ElMessage, 'error').mockImplementation(() => undefined as never)
|
||
vi.mocked(listPlatformUnifiedOrders).mockResolvedValue({
|
||
records: [{
|
||
orderId: '2089223263733518337', orderVersion: 7, tenantId: '2089176869176389634',
|
||
internalOrderStatus: 'SUBMITTED',
|
||
inboundCode: 'NYEXX2609030001', expectedArrivalAt: '2026-09-10T08:30:00', estimatedVolumeCbm: 0.25,
|
||
}], page: 1, size: 20, total: 1, pages: 1,
|
||
} as never)
|
||
vi.mocked(updatePlatformUnifiedOrderPlanning)
|
||
.mockResolvedValueOnce({ version: 8 } as never)
|
||
.mockRejectedValueOnce(new ApiResponseError('订单版本已变化', 'A0409', 200, undefined, 'req-planning', 'trace-planning'))
|
||
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
const volume = wrapper.getComponent({ name: 'ElInputNumber' })
|
||
volume.vm.$emit('update:modelValue', 0.5)
|
||
volume.vm.$emit('change', 0.5)
|
||
await flushPromises()
|
||
|
||
expect(updatePlatformUnifiedOrderPlanning).toHaveBeenNthCalledWith(1,
|
||
'2089176869176389634', '2089223263733518337', {
|
||
expectedVersion: 7, expectedArrivalAt: '2026-09-10T08:30:00', estimatedVolumeCbm: 0.5,
|
||
})
|
||
|
||
const arrival = wrapper.getComponent({ name: 'ElDatePicker' })
|
||
arrival.vm.$emit('update:modelValue', '2026-09-12T16:00:00')
|
||
arrival.vm.$emit('change', '2026-09-12T16:00:00')
|
||
await flushPromises()
|
||
|
||
expect(updatePlatformUnifiedOrderPlanning).toHaveBeenNthCalledWith(2,
|
||
'2089176869176389634', '2089223263733518337', {
|
||
expectedVersion: 8, expectedArrivalAt: '2026-09-12T16:00:00', estimatedVolumeCbm: 0.5,
|
||
})
|
||
expect(wrapper.getComponent({ name: 'ElDatePicker' }).props('modelValue')).toBe('2026-09-12T16:00:00')
|
||
expect(wrapper.text()).not.toContain('订单版本已变化')
|
||
expect(wrapper.find('.planning-error').exists()).toBe(false)
|
||
expect(errorMessage).toHaveBeenCalledWith(expect.objectContaining({
|
||
message: '订单版本已变化(错误码 A0409;Request ID req-planning;Trace ID trace-planning)',
|
||
showClose: true,
|
||
}))
|
||
})
|
||
|
||
it('shows planning values without editors after the order enters irreversible fulfillment', async () => {
|
||
vi.mocked(listPlatformUnifiedOrders).mockResolvedValue({
|
||
records: [{
|
||
orderId: '2099751993783402497', orderVersion: 7, tenantId: '2097708157074210818',
|
||
internalOrderStatus: 'PROCESSING', mainStatus: 'LOADED', inboundCode: 'AT0E9B5BF2839C6944CFA3',
|
||
expectedArrivalAt: '2026-10-15T00:00:00', estimatedVolumeCbm: 220,
|
||
}], page: 1, size: 20, total: 1, pages: 1,
|
||
} as never)
|
||
|
||
const wrapper = mountView()
|
||
await flushPromises()
|
||
|
||
expect(wrapper.findComponent({ name: 'ElInputNumber' }).exists()).toBe(false)
|
||
expect(wrapper.findComponent({ name: 'ElDatePicker' }).exists()).toBe(false)
|
||
expect(wrapper.text()).toContain('220')
|
||
expect(wrapper.text()).toContain('2026-10-15 00:00')
|
||
expect(updatePlatformUnifiedOrderPlanning).not.toHaveBeenCalled()
|
||
})
|
||
})
|