import { createRequire } from 'node:module' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils' import type { PlatformWarehouseSummaryResource } from '@/modules/warehouses' import { listWarehouseLogisticsChannels } from '@/modules/ocean-bookings' import { createContainerSimulation } from '../api/platformContainerLoading' import AppDialog from '@/shared/components/AppDialog.vue' import ContainerSimulationCreate from './ContainerSimulationCreate.vue' import DataTable from '@/shared/components/DataTable.vue' import { h } from 'vue' // Node's supported CJS export keeps the real form validator's constructor intact. const ElementPlus = (createRequire(import.meta.url)('element-plus') as typeof import('element-plus')).default vi.mock('@/modules/warehouses', () => ({ listAllPlatformWarehouses: vi.fn() })) vi.mock('@/modules/ocean-bookings', () => ({ listWarehouseLogisticsChannels: vi.fn() })) vi.mock('../api/platformContainerLoading', () => ({ createContainerSimulation: vi.fn() })) const warehouse: PlatformWarehouseSummaryResource = { id: '8', tenantId: 'platform', warehouseCode: 'CN-01', internalCode: null, warehouseName: '测试国内仓', warehouseType: 'DOMESTIC', countryCode: 'CN', timezone: 'Asia/Shanghai', contactName: null, contactPhone: null, contactEmail: null, status: 'ACTIVE', remark: null } enableAutoUnmount(afterEach) beforeEach(() => { vi.clearAllMocks(); vi.mocked(listWarehouseLogisticsChannels).mockResolvedValue([{ channelCode: 'MATSON_CLX_TRUCK', channelName: '美森正班海卡' }]) }) afterEach(() => { document.body.innerHTML = '' }) describe('ContainerSimulationCreate opted-in form', () => { it.each([true, false])('preserves required fields and the fixed request in dense=%s mode', async (dense) => { const host = mount(DataTable, { props: { data: [], columns: [] }, slots: { 'toolbar-actions': () => h(ContainerSimulationCreate, { dense, loadWarehouseOptions: async () => [warehouse] }) }, global: { plugins: [ElementPlus] }, attachTo: document.body, }) const wrapper = host.findComponent(ContainerSimulationCreate) expect(wrapper.get('button').element.closest('.data-table__toolbar-actions')).not.toBeNull() await wrapper.findAll('button').find(button => button.text().includes('新增模拟柜'))!.trigger('click') await flushPromises() const dialog = wrapper.findComponent(AppDialog) const dialogRoot = document.body.querySelector('.simulation-create-dialog')! expect(dialogRoot).not.toBeNull() expect(dialogRoot.closest('.data-table__toolbar')).toBeNull() expect(dialogRoot.querySelector('.el-dialog__footer button')?.closest('.data-table__toolbar')).toBeNull() expect(dialog.props('width')).toBe('min(800px, calc(100vw - 32px))') dialog.vm.$emit('confirm') await flushPromises() expect(createContainerSimulation).not.toHaveBeenCalled() await vi.waitFor(() => expect(dialogRoot.querySelectorAll('.el-form-item__error').length).toBeGreaterThan(0)) const fields = dialog.findAllComponents({ name: 'ElFormItem' }) expect(fields).toHaveLength(3) fields.find(field => field.props('prop') === 'warehouseId')!.findComponent({ name: 'ElSelect' }).vm.$emit('update:modelValue', '8') await flushPromises() expect(listWarehouseLogisticsChannels).toHaveBeenCalledExactlyOnceWith('8') fields.find(field => field.props('prop') === 'channelGroupCode')!.findComponent({ name: 'ElSelect' }).vm.$emit('update:modelValue', 'MATSON_CLX') await flushPromises() dialog.vm.$emit('confirm') await flushPromises() expect(createContainerSimulation).toHaveBeenCalledExactlyOnceWith({ warehouseId: '8', channelGroupCode: 'MATSON_CLX', containerType: '40HQ', capacityCbm: 68, maxWeightKg: 19500 }) expect(wrapper.emitted('created')).toHaveLength(1) expect(dialog.props('modelValue')).toBe(false) await wrapper.get('button').trigger('click') await flushPromises() expect(dialog.props('modelValue')).toBe(true) expect(dialogRoot.closest('.data-table__toolbar')).toBeNull() expect(dialog.findAllComponents({ name: 'ElFormItem' }).find(field => field.props('prop') === 'warehouseId')!.findComponent({ name: 'ElSelect' }).props('modelValue')).toBe('') const cancel = Array.from(dialogRoot.querySelectorAll('.el-dialog__footer button')).find(button => button.textContent?.trim() === '取消')! cancel.click() await flushPromises() expect(dialog.props('modelValue')).toBe(false) expect(host.find('.data-table__toolbar-actions').exists()).toBe(true) expect(createContainerSimulation).toHaveBeenCalledTimes(1) }) })