import { describe, it, expect, vi, afterEach } from 'vitest'; import { mount, flushPromises, enableAutoUnmount } from '@vue/test-utils'; import { reactive, nextTick } from 'vue'; import ViewUIPlus from 'view-ui-plus'; import ApprovalDrawer from '@/views/flow/admin/def-editor/components/ApprovalDrawer.vue'; import NotifyDrawer from '@/views/flow/admin/def-editor/components/NotifyDrawer.vue'; import { EDITOR_CTX, createApproval, createNotify } from '@/views/flow/admin/def-editor/model'; const { api } = vi.hoisted(() => ({ api: { deptGroups: vi.fn(), deptResolve: vi.fn(), deptOptions: vi.fn() } })); vi.mock('@/api/module/flow', () => ({ flowApi: api })); enableAutoUnmount(afterEach); const ok = (data: unknown) => ({ send: async () => data }); describe('CUSTOM 引用真实抽屉编辑往返', () => { for (const mode of ['approval', 'notify'] as const) { it(`${mode}:无 categoryId 的历史解析仍可反查分类,保存重开再保存不丢引用`, async () => { document.body.innerHTML = ''; const ref = { departmentType: 'CUSTOM', departmentId: 9 }; api.deptGroups.mockImplementation(() => ok([ { departmentType: 'SYSTEM', name: '系统组织' }, { departmentType: 'CUSTOM', categoryId: 4, name: '教研组' }, ])); api.deptResolve.mockImplementation(() => ok([{ ...ref, name: '科学组', memberCount: 2, selectable: true }])); api.deptOptions.mockImplementation(() => ok([{ ...ref, categoryId: 4, name: '科学组', memberCount: 2, selectable: true }])); const node: any = mode === 'approval' ? createApproval('审批') : createNotify('抄送'); const key = mode === 'approval' ? 'assignee' : 'receivers'; node[key] = { type: 'DEPT', deptRefs: [ref] }; const ctx = { model: reactive({ list: [node] }), depts: [], userNames: {}, routers: [], availableVars: [], issueOf: () => [] }; const wrapper = mount(mode === 'approval' ? ApprovalDrawer : NotifyDrawer, { props: { node, modelValue: true }, attachTo: document.body, global: { plugins: [ViewUIPlus], provide: { [EDITOR_CTX as unknown as symbol]: ctx } }, }); await flushPromises(); await nextTick(); expect(document.body.textContent).toContain('科学组'); expect(api.deptOptions).toHaveBeenCalledWith({ type: 'CUSTOM' }); for (let round = 0; round < 2; round++) { if (round) { await wrapper.setProps({ modelValue: false }); await wrapper.setProps({ modelValue: true }); await flushPromises(); } const input = document.querySelector('input.ivu-input') as HTMLInputElement; expect(input).toBeTruthy(); input.value = `修改名称${round}`; input.dispatchEvent(new Event('input', { bubbles: true })); await nextTick(); const confirm = Array.from(document.querySelectorAll('button')).find(b => b.textContent?.trim() === '确定'); expect(confirm).toBeTruthy(); confirm!.click(); await nextTick(); expect(node[key]).toEqual({ type: 'DEPT', deptRefs: [ref] }); expect(node.name).toBe(`修改名称${round}`); } }); } });