This commit is contained in:
2026-10-20 23:34:11 +08:00
parent f155976f52
commit 13e4aa56ec
321 changed files with 6756 additions and 2110 deletions
+71 -2
View File
@@ -1,7 +1,10 @@
import { flushPromises, mount } from '@vue/test-utils'
import { defineComponent } from 'vue'
import { defineComponent, markRaw } from 'vue'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { createMemoryHistory, createRouter } from 'vue-router'
import { describe, expect, it } from 'vitest'
import { ElMenu, ElMenuItem, ElSubMenu } from 'element-plus'
import { describe, expect, it, vi } from 'vitest'
import { adminNavigation, filterAdminNavigation, type AdminNavigationNode } from '@/core/navigation/adminNavigation'
import AdminSidebarMenu from './AdminSidebarMenu.vue'
@@ -85,6 +88,72 @@ describe('AdminSidebarMenu', () => {
expect(wrapper.get('nav').attributes('data-collapsed')).toBe('true')
})
it('fits collapsed icons inside the scrolling rail and keeps hover submenus outside it', async () => {
const host = document.createElement('div')
host.className = 'app-shell is-collapsed'
host.innerHTML = '<aside class="app-sidebar"><nav class="side-nav"></nav></aside>'
document.body.append(host)
const style = document.createElement('style')
style.textContent = readFileSync(resolve(process.cwd(), 'src/styles/shell.css'), 'utf8')
document.head.append(style)
const rail = host.querySelector<HTMLElement>('.side-nav')!
const router = routerPlugin()
await router.push('/')
const icon = markRaw(adminNavigation[0].icon)
const items: AdminNavigationNode[] = [
{ key: 'home', title: '首页', icon, path: '/' },
{
key: 'resources', title: '资源管理', icon,
children: [{ key: 'warehouses', title: '仓库管理', icon, path: '/warehouses' }],
},
]
const wrapper = mount(AdminSidebarMenu, {
attachTo: rail,
props: { items, activePath: '/', collapsed: true },
global: { plugins: [router], components: { ElMenu, ElMenuItem, ElSubMenu }, stubs: { transition: false } },
})
try {
await flushPromises()
const menu = wrapper.get('.side-nav-menu.el-menu--collapse')
const group = wrapper.get('.side-nav-menu > .el-sub-menu')
const leafTrigger = wrapper.get('.el-menu-tooltip__trigger')
expect(getComputedStyle(host.querySelector('.app-sidebar')!).width).toBe('76px')
expect(getComputedStyle(rail).overflowX).toBe('hidden')
expect(getComputedStyle(rail).overflowY).toBe('auto')
expect(getComputedStyle(menu.element).width).toBe('100%')
for (const trigger of [leafTrigger, group.get('.el-sub-menu__title')]) {
expect(getComputedStyle(trigger.element).paddingLeft).toBe('0px')
expect(getComputedStyle(trigger.element).paddingRight).toBe('0px')
expect(getComputedStyle(trigger.element).justifyContent).toBe('center')
expect(getComputedStyle(trigger.get('.menu-icon').element).marginRight).toBe('0px')
}
await group.trigger('mouseenter')
await vi.waitFor(() => expect(group.attributes('aria-expanded')).toBe('true'))
const popup = document.body.querySelector('.shell-nav-popper .el-menu--popup')
expect(popup).not.toBeNull()
expect(popup?.closest('.side-nav')).toBeNull()
expect(popup?.textContent).toContain('仓库管理')
const destination = popup!.querySelector<HTMLElement>('.el-menu-item')!
destination.focus()
expect(document.activeElement).toBe(destination)
expect(destination.getAttribute('role')).toBe('menuitem')
destination.click()
await flushPromises()
expect(router.currentRoute.value.path).toBe('/warehouses')
await wrapper.setProps({ collapsed: false })
host.classList.remove('is-collapsed')
expect(getComputedStyle(host.querySelector('.app-sidebar')!).width).toBe('240px')
expect(wrapper.find('.el-menu--collapse').exists()).toBe(false)
} finally {
wrapper.unmount()
style.remove()
host.remove()
}
})
it('renders only entries included in the filtered navigation input', () => {
const items = filterAdminNavigation(adminNavigation, new Set(['platform:permission:list']))
const wrapper = mount(AdminSidebarMenu, {