Files
workspace/code/fms/fms-vue/tests/views/layout-page-transition.spec.js
T
2026-09-21 23:13:14 +08:00

77 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 回归:路由过渡的页面外壳(.fms-page-holder,由 getPageWrapper 的渲染函数创建)。
*
* 路由页面是异步组件(懒加载 chunk),加载中的渲染是注释节点(非元素根)——
* <Transition> 无法动画化非元素根:既报 warning(Component inside <Transition>
* renders non-element root node that cannot be animated),out-in 下 enter 也会失败、
* 页面内容一直不显示。页面外壳是恒定元素,兜住该场景。
*
* 本用例用「先渲染 null 再渲染元素」的桩模拟异步组件加载过程,断言:
* 1. 全程不出现 non-element root 警告;
* 2. 异步就绪后内容正常显示(过渡没有吞掉页面)。
*/
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { flushPromises, mount } from '@vue/test-utils'
vi.mock('@/views/dashboard/index.vue', async () => {
const { h, onMounted, ref } = await import('vue')
return {
default: {
name: 'Dashboard',
setup() {
const ready = ref(false)
onMounted(() => {
setTimeout(() => {
ready.value = true
}, 30)
})
// 加载中渲染 null(Vue 渲染为注释节点),模拟异步组件解析前的状态
return () => (ready.value ? h('div', { 'data-page': 'Dashboard' }, 'DB') : null)
},
},
}
})
vi.mock('@/views/detail/DetailPage.vue', () => ({
default: { name: 'DetailPageStub', props: ['id'], template: '<div />' },
}))
vi.mock('@/services/api', () => ({
loadDataApi: vi.fn(() => Promise.resolve({ data: [], code: 0, success: true })),
describeApi: vi.fn(() => Promise.resolve({ data: [], code: 0, success: true })),
saveObjectApi: vi.fn(() => Promise.resolve({ code: 0, success: true })),
nextIdApi: vi.fn(() => Promise.resolve({ data: 1, code: 0, success: true })),
}))
import App from '@/App.vue'
import router from '@/router'
import { createTestPinia } from '../helpers/app.js'
import { useAuthStore } from '@/stores/auth'
beforeEach(async () => {
localStorage.clear()
sessionStorage.clear()
createTestPinia()
useAuthStore().setSession({ token: 't', user: { id: 1, account: 'g3soft', name: 'U' } }, 'ORG')
await router.push('/dashboard')
await router.isReady()
})
describe('路由过渡 · 页面外壳', () => {
it('异步页面加载中不产生 non-element root 警告,完成后内容正常显示', async () => {
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
const wrapper = mount(App, { global: { plugins: [router] }, attachTo: document.body })
await flushPromises()
// 等待桩组件异步就绪(模拟 chunk 下载完成)
await new Promise((resolve) => setTimeout(resolve, 60))
await flushPromises()
const warnings = warnSpy.mock.calls.map((args) => String(args[0])).join('\n')
expect(warnings).not.toContain('non-element root node')
// 内容最终可见(过渡未吞掉页面)
expect(wrapper.find('[data-page="Dashboard"]').exists()).toBe(true)
warnSpy.mockRestore()
wrapper.unmount()
})
})