2026-03-12 15:49:37 +04:00

163 lines
4.1 KiB
JavaScript

import { vi } from 'vitest'
/**
* Create a mock Vue Router instance
* @param {object} options - Router options
* @returns {object} Mock router
*/
export function createMockRouter(options = {}) {
const {
currentRoute = { path: '/', name: 'home', params: {}, query: {}, meta: {} },
routes = []
} = options
const router = {
currentRoute: {
value: currentRoute
},
options: {
routes
},
push: vi.fn(() => Promise.resolve()),
replace: vi.fn(() => Promise.resolve()),
go: vi.fn(),
back: vi.fn(),
forward: vi.fn(),
beforeEach: vi.fn((guard) => {
router._beforeEachGuards.push(guard)
return () => {
const index = router._beforeEachGuards.indexOf(guard)
if (index > -1) router._beforeEachGuards.splice(index, 1)
}
}),
afterEach: vi.fn((hook) => {
router._afterEachHooks.push(hook)
return () => {
const index = router._afterEachHooks.indexOf(hook)
if (index > -1) router._afterEachHooks.splice(index, 1)
}
}),
beforeResolve: vi.fn(),
hasRoute: vi.fn((name) => routes.some(r => r.name === name)),
getRoutes: vi.fn(() => routes),
resolve: vi.fn((to) => ({
path: typeof to === 'string' ? to : to.path || '/',
name: typeof to === 'object' ? to.name : undefined,
params: typeof to === 'object' ? to.params || {} : {},
query: typeof to === 'object' ? to.query || {} : {},
meta: {},
matched: [],
redirectedFrom: undefined,
href: typeof to === 'string' ? to : to.path || '/'
})),
addRoute: vi.fn(),
removeRoute: vi.fn(),
isReady: vi.fn(() => Promise.resolve()),
install: vi.fn(),
// Internal tracking
_beforeEachGuards: [],
_afterEachHooks: []
}
return router
}
/**
* Create a mock route object
* @param {object} options - Route options
* @returns {object} Mock route
*/
export function createMockRoute(options = {}) {
const {
path = '/',
name = 'default',
params = {},
query = {},
meta = {},
hash = '',
fullPath = null,
matched = [],
redirectedFrom = undefined
} = options
return {
path,
name,
params,
query,
meta,
hash,
fullPath: fullPath || path + (Object.keys(query).length ? '?' + new URLSearchParams(query).toString() : '') + hash,
matched,
redirectedFrom
}
}
/**
* Simulate navigation with guards
* @param {object} router - Mock router instance
* @param {object} to - Target route
* @param {object} from - Source route
* @returns {Promise} Navigation result
*/
export async function simulateNavigation(router, to, from = { path: '/' }) {
const toRoute = typeof to === 'string' ? { path: to } : to
const fromRoute = typeof from === 'string' ? { path: from } : from
let nextCalled = false
let nextArg = undefined
const next = vi.fn((arg) => {
nextCalled = true
nextArg = arg
})
// Run through beforeEach guards
for (const guard of router._beforeEachGuards) {
await guard(toRoute, fromRoute, next)
if (nextCalled) {
if (nextArg === false) {
return { success: false, redirect: null }
}
if (nextArg && typeof nextArg === 'object') {
return { success: false, redirect: nextArg }
}
if (typeof nextArg === 'string') {
return { success: false, redirect: { path: nextArg } }
}
}
nextCalled = false
nextArg = undefined
}
// Update current route
router.currentRoute.value = { ...router.currentRoute.value, ...toRoute }
// Run afterEach hooks
for (const hook of router._afterEachHooks) {
hook(toRoute, fromRoute)
}
return { success: true, redirect: null }
}
/**
* Create a mock useRoute composable return value
* @param {object} options - Route options
* @returns {object} Mock useRoute return
*/
export function createMockUseRoute(options = {}) {
return createMockRoute(options)
}
/**
* Create a mock useRouter composable return value
* @param {object} options - Router options
* @returns {object} Mock useRouter return
*/
export function createMockUseRouter(options = {}) {
return createMockRouter(options)
}