import { App, createApp, defineComponent, h, nextTick, reactive } from 'vue' import { afterEach, beforeAll, describe, expect, it } from 'vitest' const ElBreadcrumbStub = defineComponent({ name: 'ElBreadcrumb', props: { separatorClass: { type: String, default: '' } }, setup (props, { slots }) { return () => h('nav', { class: 'el-breadcrumb app-breadcrumb', 'data-separator-class': props.separatorClass }, slots.default?.()) } }) const ElBreadcrumbItemStub = defineComponent({ name: 'ElBreadcrumbItem', props: { to: { type: [String, Object], default: undefined } }, setup (props, { slots }) { return () => h('span', { class: 'el-breadcrumb__item', 'data-to': typeof props.to === 'string' ? props.to : JSON.stringify(props.to) }, [ h('span', { class: 'el-breadcrumb__inner' }, slots.default?.()) ]) } }) let InfoHeader: any let route: Record interface RenderResult { app: App el: HTMLDivElement } const renderedApps: RenderResult[] = [] beforeAll(async () => { route = reactive({ path: '/default', meta: { breadcrumd: [] } }) window.route = route as any window.router = {} as any InfoHeader = (await import('../../../components/infoHeader/index.vue')).default }) const renderHeader = async (options: { separatorClass?: string breadcrumd?: Array> path?: string layoutType?: string } = {}) => { route.path = options.path || '/default' route.meta = { breadcrumd: options.breadcrumd || [] } if (options.layoutType) { window.sessionStorage.setItem('serveConfig', JSON.stringify({ layoutType: options.layoutType })) } else { window.sessionStorage.removeItem('serveConfig') } const el = document.createElement('div') document.body.appendChild(el) const app = createApp({ render () { return h(InfoHeader, { separatorClass: options.separatorClass }) } }) app.component('ElBreadcrumb', ElBreadcrumbStub) app.component('ElBreadcrumbItem', ElBreadcrumbItemStub) app.component('el-breadcrumb', ElBreadcrumbStub) app.component('el-breadcrumb-item', ElBreadcrumbItemStub) app.mount(el) await nextTick() const result = { app, el } renderedApps.push(result) return result } const getRoot = () => document.body afterEach(() => { while (renderedApps.length) { const current = renderedApps.pop()! current.app.unmount() current.el.remove() } window.sessionStorage.clear() document.body.innerHTML = '' route.path = '/default' route.meta = { breadcrumd: [] } }) describe('components/infoHeader', () => { it('根据 route.meta 渲染面包屑内容', async () => { await renderHeader({ separatorClass: 'el-icon-arrow-right', breadcrumd: [ { zhName: '首页', path: '/home' }, { zhName: '详情页', path: '/detail' } ] }) const breadcrumb = getRoot().querySelector('.el-breadcrumb') const items = getRoot().querySelectorAll('.el-breadcrumb__item') expect(breadcrumb).not.toBeNull() expect(items).toHaveLength(2) expect(items[0]?.textContent).toContain('首页') expect(items[1]?.textContent).toContain('详情页') }) it('存在 href 时渲染链接文本,否则渲染普通文本', async () => { await renderHeader({ breadcrumd: [ { zhName: '外部链接', href: 'https://example.com' }, { zhName: '当前页' } ] }) const link = getRoot().querySelector('.el-breadcrumb__inner a') as HTMLAnchorElement | null const items = getRoot().querySelectorAll('.el-breadcrumb__item') expect(link).not.toBeNull() expect(link?.textContent).toBe('外部链接') expect(link?.getAttribute('href')).toBe('https://example.com') expect(items[1]?.querySelector('a')).toBeNull() expect(items[1]?.textContent).toContain('当前页') }) it('layoutType 为 new 或 apex 且只有一个面包屑时隐藏容器', async () => { await renderHeader({ layoutType: 'new', breadcrumd: [ { zhName: '单级页面' } ] }) expect(getRoot().querySelector('.el-breadcrumb')).toBeNull() await renderHeader({ layoutType: 'apex', breadcrumd: [ { zhName: 'apex单级页面' } ] }) expect(getRoot().querySelector('.el-breadcrumb')).toBeNull() }) it('监听 route.path 变化后更新面包屑内容', async () => { await renderHeader({ breadcrumd: [ { zhName: '旧页面' } ] }) let items = getRoot().querySelectorAll('.el-breadcrumb__item') expect(items).toHaveLength(1) expect(items[0]?.textContent).toContain('旧页面') route.meta = { breadcrumd: [ { zhName: '新页面' }, { zhName: '子页面' } ] } route.path = '/updated' await nextTick() items = getRoot().querySelectorAll('.el-breadcrumb__item') expect(items).toHaveLength(2) expect(items[0]?.textContent).toContain('新页面') expect(items[1]?.textContent).toContain('子页面') }) })