Files

71 lines
2.8 KiB
JavaScript
Raw Permalink 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.
/**
* 测试 harness:为「页面/功能」组件测试提供统一装配。
*
* 设计原则:
* - 所有请求都收敛在 @/services/api,测试时只需 vi.mock('@/services/api') 即可确定性驱动状态。
* - pinia 带 persist 插件(与生产一致),避免 stores 在测试里行为漂移。
* - 用 memory history 路由,避免真实 History API 副作用。
* - 子组件默认 shallowMount 打桩,页面测试只关注「页面自身逻辑」:把子组件事件 emit 出来即可。
*
* 用法见 tests/views/*.spec.js
*/
import { shallowMount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import { createRouter, createMemoryHistory } from 'vue-router'
/**
* 创建一个带 persist 插件的全新 pinia,并设为 active(便于测试里直接 useXStore())。
*
* 注意:pinia 4 的 `pinia.use()` 在实例未安装到 app 前只把插件放入 toBeInstalled 队列,
* 必须经过 `install(app)` 才会真正注册。页面测试经 @vue/test-utils 的 plugins 挂载会自动 install,
* 但"纯 store 层测试"(setActivePinia + useXStore)不会,导致 persist 插件静默失效、
* store 上缺少 $hydrate/$persist。这里用一个假 app 触发 install,保证两类测试行为一致。
*/
export function createTestPinia() {
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
pinia.install({ provide() {}, config: { globalProperties: {} } })
setActivePinia(pinia)
return pinia
}
/** 创建一个 memory history 路由,并可预先定位到某个 location(含 query) */
export function createTestRouter(initialLocation = '/') {
const router = createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/:pathMatch(.*)*', name: 'catch-all', component: { template: '<div />' } },
],
})
router.push(initialLocation)
return router
}
/**
* 挂载一个页面/功能组件。
* @param {object} Component 组件定义(通常 import 自 @/views/...)
* @param {object} [options]
* @param {string} [options.location] 初始路由 location,如 '/login?redirect=/dashboard'
* @param {object} [options.stubs] 额外子组件打桩(覆盖 shallowMount 默认打桩)
* @param {object} [options.global] 透传给 @vue/test-utils 的 global 选项
* @param {object} [options.mountOptions] 透传其余 mount 选项
* @returns {Promise<{ wrapper, router, pinia }>}
*/
export async function mountPage(Component, options = {}) {
const pinia = createTestPinia()
const router = createTestRouter(options.location || '/')
await router.isReady()
const wrapper = shallowMount(Component, {
global: {
plugins: [pinia, router],
stubs: options.stubs || {},
...options.global,
},
...options.mountOptions,
})
return { wrapper, router, pinia }
}