import { flushPromises, shallowMount } from '@vue/test-utils'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { 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', () => ({ 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', () => ({
downloadWeightImage: vi.fn(), getInboundMeasurement: vi.fn(),
InboundTaskList: { name: 'InboundTaskList', props: ['mode', 'title'], template: '
{{ details.code }} {{ details.requestId }} {{ details.traceId }}' },
},
},
})
}
describe('UnifiedOrdersView list request coordination', () => {
beforeEach(() => {
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('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.get('[aria-selected="true"]').text()).toBe('测量数据审核')
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(1)
await wrapper.findAll('[role="tab"]').find((tab) => tab.text() === '待测量数据')!.trigger('click')
await flushPromises()
expect(wrapper.findComponent({ name: 'InboundTaskList' }).exists()).toBe(false)
expect(listPlatformUnifiedOrders).toHaveBeenLastCalledWith(expect.objectContaining({ mainStatus: 'WAIT_MEASURE' }))
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(2)
})
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()
})
})