Files
admin-web/src/modules/unified-orders/pages/UnifiedOrdersView.coLoad.test.ts
T

104 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { flushPromises, shallowMount } from '@vue/test-utils'
import { ElMessageBox } from 'element-plus'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ApiResponseError } from '@/shared/api/http'
import { listPlatformUnifiedOrders } from '@/modules/unified-orders/api/unifiedOrders'
import { batchQueryPlatformCoLoadGroups, cancelPlatformCoLoadGroup, createPlatformCoLoadGroup } from '@/modules/unified-orders/api/coLoadGroups'
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() }))
vi.mock('@/modules/unified-orders/workflows', () => ({ UnifiedOrderWorkflowPanel: { template: '<div />' } }))
vi.mock('@/modules/unified-orders/api/unifiedOrders', () => ({
addPlatformUnifiedOrderNote: vi.fn(), approvePlatformUnifiedOrder: vi.fn(), batchApprovePlatformUnifiedOrders: vi.fn(),
getPlatformUnifiedOrder: vi.fn(), listPlatformUnifiedOrderFeeDetails: vi.fn(), listPlatformUnifiedOrders: vi.fn(),
unifiedOrderStatusOptions: [{ value: 'WAIT_SPLIT', label: '待分柜' }],
}))
vi.mock('@/modules/unified-orders/api/coLoadGroups', () => ({
batchQueryPlatformCoLoadGroups: vi.fn(), cancelPlatformCoLoadGroup: vi.fn(), createPlatformCoLoadGroup: vi.fn(),
}))
const rows = ['5001', '5002'].map((orderId, index) => ({
orderId, tenantId: `600${index}`, orderNo: `ORD-${index + 1}`, mainStatus: 'WAIT_SPLIT' as const, nextAction: null,
relation: null, internalOrderStatus: 'WAIT_SPLIT', customerId: `600${index}`, customerName: `客户${index + 1}`,
channelName: 'NY-EXX', receivingWarehouseId: '8', receivingWarehouseName: '义乌仓', destinationWarehouseId: '9', destinationWarehouseName: 'ONT8',
inboundId: `700${index}`, inboundVersion: 1, inboundCode: `IN-${index + 1}`, expectedShipDate: null, totalPackageCount: 5,
locationCodes: null, actualGrossWeightKg: 10, actualVolumeCbm: 1, measurement: null, preload: null, loading: null, delivery: null, transport: null,
createdAt: null, updatedAt: null, expectedArrivalAt: null, feeReviewStatus: null, requestedPickupAt: null, totalPalletCount: null,
chargeableVolumeCbm: null, volumetricWeightKg: null, totalNetWeightKg: null, measurementCompletedAt: null, inboundCompletedAt: null,
expressCompany: null, expressTrackingNo: null, skuNos: null, totalQuantity: null, shipmentId: null, referenceId: null,
}))
const group = {
groupId: '9001', groupNo: 'CLG-9001', status: 'ACTIVE' as const, warehouseId: '8', channelCode: 'NY-EXX', lockedPlanId: null, version: 0, fullPackageCount: 10,
members: rows.map((row) => ({ tenantId: String(row.tenantId), orderId: String(row.orderId), inboundId: String(row.inboundId), fullPackageCount: 5 })),
createdAt: '2026-08-29T10:00:00', updatedAt: '2026-08-29T10:00:00',
}
function mountView() {
return shallowMount(UnifiedOrdersView, {
global: { directives: { loading: () => undefined }, stubs: {
AdminPage: { template: '<main><slot /></main>' },
ListPageLayout: { template: '<section><slot name="toolbar" /><slot name="state" /><slot /></section>' },
QueryToolbar: { template: '<div />' },
DataTable: { name: 'DataTable', props: ['data'], emits: ['selection-change'], template: '<section><slot name="toolbar-actions" /><button data-testid="select" @click="$emit(\'selection-change\', data)">勾选两票</button><template v-if="data?.length"><slot name="actions" :row="data[0]" /><slot name="orderNo" :row="data[0]" /></template></section>' },
AppDialog: { name: 'AppDialog', props: ['modelValue', 'confirmText'], emits: ['confirm', 'update:modelValue'], template: '<section v-if="modelValue"><slot /><button data-testid="dialog-confirm" @click="$emit(\'confirm\')">{{ confirmText }}</button></section>' },
ApiErrorMeta: { props: ['details'], template: '<div>{{ details.code }} {{ details.requestId }} {{ details.traceId }}</div>' },
CopyButton: { props: ['value', 'label'], template: '<button :data-copy="value">复制 ID</button>' },
'el-button': { template: '<button @click="$emit(\'click\')"><slot /></button>' },
'el-tag': { template: '<span><slot /></span>' },
'el-alert': { props: ['title'], template: '<div>{{ title }}</div>' },
} },
})
}
describe('UnifiedOrdersView co-load group behavior', () => {
beforeEach(() => {
vi.clearAllMocks()
vi.mocked(listPlatformUnifiedOrders).mockResolvedValue({ records: rows, page: 1, size: 20, total: 2, pages: 1 })
vi.mocked(batchQueryPlatformCoLoadGroups).mockResolvedValue([])
})
it('keeps both selected orders and backend tracing evidence when create validation fails', async () => {
vi.mocked(createPlatformCoLoadGroup).mockRejectedValue(new ApiResponseError('成员路线不一致', 'A0409', 409, undefined, 'request-coload', 'trace-coload'))
const wrapper = mountView()
await flushPromises()
await wrapper.get('[data-testid="select"]').trigger('click')
await wrapper.findAll('button').find((button) => button.text().includes('设为同柜不可拆组'))!.trigger('click')
await wrapper.get('[data-testid="dialog-confirm"]').trigger('click')
await flushPromises()
expect(createPlatformCoLoadGroup).toHaveBeenCalledWith(['5001', '5002'])
expect(wrapper.text()).toContain('设为同柜不可拆组(2)')
expect(wrapper.text()).toContain('成员路线不一致')
expect(wrapper.text()).toContain('A0409 request-coload trace-coload')
expect(listPlatformUnifiedOrders).toHaveBeenCalledTimes(1)
})
it('shows group number and member count and cancels only the whole ACTIVE group', async () => {
const multiInboundGroup = {
...group,
fullPackageCount: 13,
members: [group.members[0], { ...group.members[0], inboundId: '7003', fullPackageCount: 3 }, group.members[1]],
}
vi.mocked(batchQueryPlatformCoLoadGroups).mockResolvedValue(rows.map((row) => ({ orderId: row.orderId, group: multiInboundGroup })))
vi.mocked(cancelPlatformCoLoadGroup).mockResolvedValue({ ...multiInboundGroup, status: 'CANCELLED', version: 1 })
vi.spyOn(ElMessageBox, 'prompt').mockResolvedValue({ value: '计划调整', action: 'confirm' } as never)
const wrapper = mountView()
await flushPromises()
expect(wrapper.text()).toContain('CLG-9001')
expect(wrapper.text()).toContain('CLG-9001 · 2 票 · 未锁定')
await wrapper.get('[aria-label="查看同柜组 CLG-9001 详情"]').trigger('click')
expect(wrapper.text()).toContain('2 票 · 3 个入仓片段 · 未锁定')
expect(wrapper.text()).toContain('13 箱')
expect(wrapper.text()).toContain('7003')
expect(wrapper.findAll('[data-copy="7003"]')).toHaveLength(1)
expect(wrapper.findAll('[data-copy="5001"]')).toHaveLength(2)
await wrapper.findAll('button').find((button) => button.text().includes('取消同柜组'))!.trigger('click')
await flushPromises()
expect(cancelPlatformCoLoadGroup).toHaveBeenCalledWith('9001', 0, '计划调整')
expect(ElMessageBox.prompt).toHaveBeenCalledWith(expect.stringContaining('不支持单独移除成员'), '取消同柜不可拆组', expect.any(Object))
})
})