71 lines
2.8 KiB
JavaScript
71 lines
2.8 KiB
JavaScript
/**
|
||
* 测试 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 }
|
||
}
|