import ElementPlus from 'element-plus' import { createPinia, setActivePinia } from 'pinia' import { flushPromises, mount } from '@vue/test-utils' import { beforeEach, describe, expect, it, vi } from 'vitest' import { useAuthStore } from '@/core/auth/auth' import UnifiedOrderWorkflowPanel from './UnifiedOrderWorkflowPanel.vue' import { getEvidence, getOutboundDispatch, getPreload, smartSplit, } from '../api' vi.mock('../api', async (importOriginal) => { const original = await importOriginal() return { ...original, getEvidence: vi.fn(), getOutboundDispatch: vi.fn(), getPreload: vi.fn(), smartSplit: vi.fn(), } }) function preload(cargoReference: string, version = 3) { return { id: '2086085512165634050', inboundId: '2086085512165634051', tenantId: '2086085512165634052', status: 'PENDING', version, items: [{ containerCode: 'CAB-01', cargoReference, packageCount: 2, volumeCbm: 1.25, remark: null }], remark: null, createdAt: null, updatedAt: null, } } function mountPanel(permissions: string[], mainStatus: 'WAIT_SPLIT' | 'LOADING' | 'LOADED' = 'WAIT_SPLIT') { const pinia = createPinia() setActivePinia(pinia) useAuthStore().permissions = permissions return mount(UnifiedOrderWorkflowPanel, { props: { tenantId: '2086085512165634052', inboundId: '2086085512165634051', orderId: '2086085512165634053', mainStatus, inboundVersion: 4, }, global: { plugins: [pinia, ElementPlus] }, }) } describe('UnifiedOrderWorkflowPanel preload editor', () => { beforeEach(() => { vi.mocked(getOutboundDispatch).mockReset().mockResolvedValue(null as never) vi.mocked(getEvidence).mockReset().mockResolvedValue({ inboundId: '2086085512165634051', evidences: [] }) vi.mocked(getPreload).mockReset().mockResolvedValue(preload('REF-OLD')) vi.mocked(smartSplit).mockReset() }) it('renders the formal preload table and keeps the operation column first', async () => { const wrapper = mountPanel(['firstleg:inbound:preload-view', 'firstleg:inbound:split']) await flushPromises() expect(getPreload).toHaveBeenCalledWith('2086085512165634052', '2086085512165634051') expect(wrapper.text()).toContain('入库预装清单') expect(wrapper.text()).toContain('REF-OLD') const headers = wrapper.findAll('.el-table__header-wrapper th').map((node) => node.text()) expect(headers[0]).toContain('操作') expect(wrapper.find('button[aria-label="编辑第 1 条预装明细"]').exists()).toBe(true) }) it('does not query or expose editing controls without permission', async () => { const wrapper = mountPanel([]) await flushPromises() expect(getPreload).not.toHaveBeenCalled() expect(wrapper.text()).toContain('当前账号无预装清单查询权限') expect(wrapper.find('button[aria-label="编辑第 1 条预装明细"]').exists()).toBe(false) }) it('blocks an empty list before calling the real endpoint', async () => { vi.mocked(getPreload).mockResolvedValue({ ...preload('REF-OLD'), items: [] }) const wrapper = mountPanel(['firstleg:inbound:preload-view', 'firstleg:inbound:split']) await flushPromises() const save = wrapper.findAll('button').find((button) => button.text().includes('保存分柜清单')) expect(save).toBeTruthy() await save!.trigger('click') expect(smartSplit).not.toHaveBeenCalled() expect(wrapper.text()).toContain('请至少添加一条预装明细') }) it('refreshes the version but preserves submitted rows after a conflict', async () => { vi.mocked(getPreload) .mockResolvedValueOnce(preload('REF-OLD', 3)) .mockResolvedValueOnce(preload('REF-SERVER', 4)) vi.mocked(smartSplit).mockRejectedValue(new Error('数据已被其他人修改,请刷新后重试')) const wrapper = mountPanel(['firstleg:inbound:preload-view', 'firstleg:inbound:split']) await flushPromises() const save = wrapper.findAll('button').find((button) => button.text().includes('保存分柜清单')) await save!.trigger('click') await flushPromises() expect(getPreload).toHaveBeenCalledTimes(2) expect(wrapper.text()).toContain('系统已刷新最新数据,请核对后重新提交') expect(wrapper.text()).toContain('REF-OLD') expect(wrapper.text()).not.toContain('REF-SERVER') }) it('keeps completed loading evidence visible and renders every active photo', async () => { vi.mocked(getEvidence).mockResolvedValue({ inboundId: '2086085512165634051', evidences: [ { id: '1', inboundId: '2086085512165634051', tenantId: '2086085512165634052', evidenceType: 'PHOTO_STEP_1', fileId: '11', fileName: 'empty-1.jpg', sealNo: null, remark: null, version: 0, status: 'ACTIVE', createdAt: null, updatedAt: null }, { id: '2', inboundId: '2086085512165634051', tenantId: '2086085512165634052', evidenceType: 'PHOTO_STEP_1', fileId: '12', fileName: 'empty-2.jpg', sealNo: null, remark: null, version: 0, status: 'ACTIVE', createdAt: null, updatedAt: null }, ], }) const wrapper = mountPanel(['platform:firstleg:inbound:loading:view'], 'LOADED') await flushPromises() expect(getEvidence).toHaveBeenCalledWith('2086085512165634052', '2086085512165634051') expect(wrapper.text()).toContain('empty-1.jpg') expect(wrapper.text()).toContain('empty-2.jpg') expect(wrapper.text()).toContain('2 张') expect(wrapper.text()).not.toContain('完成装柜') expect(wrapper.findAll('button').some((button) => button.text() === '作废')).toBe(false) }) })