import ElementPlus, { ElMessageBox } from 'element-plus' import { createPinia, setActivePinia } from 'pinia' import { flushPromises, mount } from '@vue/test-utils' import { createMemoryHistory, createRouter } from 'vue-router' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { useAuthStore } from '@/core/auth/auth' import { useUnsavedWorkStore } from '@/core/unsaved-work/unsavedWork' import { useWorkspaceTabsStore } from '@/core/workspace-tabs/workspaceTabs' import WorkspaceTabs from './WorkspaceTabs.vue' vi.mock('element-plus', async (importOriginal) => { const actual = await importOriginal() return { ...actual, ElMessage: { error: vi.fn() }, ElMessageBox: { confirm: vi.fn() } } }) async function mountTabs() { const pinia = createPinia() setActivePinia(pinia) const auth = useAuthStore() auth.token = 'token' auth.user = { id: '1', name: '平台管理员', account: 'admin', roles: ['PLATFORM_ADMIN'] } auth.permissions = ['platform:customer:list', 'platform:warehouse:list'] const router = createRouter({ history: createMemoryHistory(), routes: [ { path: '/customers', name: 'customers', component: { template: '

' }, meta: { requiresAuth: true, title: '客户管理' } }, { path: '/warehouses', name: 'warehouses', component: { template: '

' }, meta: { requiresAuth: true, title: '仓库管理' } }, ], }) await router.push('/customers') await router.isReady() const workspace = useWorkspaceTabsStore() workspace.initialize('1') workspace.open({ id: 'warehouses', title: '仓库管理', path: '/warehouses' }) workspace.open({ id: 'customers', title: '客户管理', path: '/customers' }) const wrapper = mount(WorkspaceTabs, { attachTo: document.body, global: { plugins: [pinia, router, ElementPlus] } }) return { wrapper, router, workspace, unsaved: useUnsavedWorkStore() } } describe('WorkspaceTabs', () => { beforeEach(() => { sessionStorage.clear() vi.mocked(ElMessageBox.confirm).mockReset() }) afterEach(() => { document.body.innerHTML = '' }) it('retains its own theme on the teleported management menu', async () => { const { wrapper } = await mountTabs() await wrapper.get('[aria-label="页签管理"]').trigger('click') await flushPromises() const popper = document.body.querySelector('.shell-header-popper') expect(popper?.classList.contains('admin-workbench')).toBe(true) expect(popper?.closest('.workspace-tabs')).toBeNull() wrapper.unmount() }) it('keeps a dirty tab open when discard confirmation is cancelled', async () => { const { wrapper, workspace, unsaved } = await mountTabs() unsaved.upsert({ key: 'customer-form', label: '客户资料', dirty: true, requiredPermission: null, workspaceTabId: 'customers' }) vi.mocked(ElMessageBox.confirm).mockRejectedValueOnce('cancel') await wrapper.get('[aria-label="关闭页签:客户管理"]').trigger('click') await flushPromises() expect(workspace.tabs.map((tab) => tab.id)).toContain('customers') expect(wrapper.find('.workspace-tab.is-dirty').exists()).toBe(true) }) it('closes confirmed dirty work and activates the most recent remaining tab', async () => { const { wrapper, router, workspace, unsaved } = await mountTabs() unsaved.upsert({ key: 'customer-form', label: '客户资料', dirty: true, requiredPermission: null, workspaceTabId: 'customers' }) vi.mocked(ElMessageBox.confirm).mockResolvedValueOnce({} as never) await wrapper.get('[aria-label="关闭页签:客户管理"]').trigger('click') await flushPromises() expect(workspace.tabs.map((tab) => tab.id)).toEqual(['warehouses']) expect(router.currentRoute.value.path).toBe('/warehouses') expect(unsaved.findForWorkspace('customers')).toEqual([]) }) it('uses the mouse wheel to scroll an overflowing tab list horizontally', async () => { const { wrapper } = await mountTabs() const tabList = wrapper.get('.workspace-tab-list') Object.defineProperties(tabList.element, { clientWidth: { configurable: true, value: 320 }, scrollWidth: { configurable: true, value: 720 }, }) await tabList.trigger('wheel', { deltaY: 120 }) expect(tabList.element.scrollLeft).toBe(120) }) })