'use strict'; const vueRouter = require('vue-router'); const testUtils = require('@vue/test-utils'); const vue = require('vue'); function createReactiveRouteLocation(route) { return vue.reactive( Object.keys(route.value).reduce( (newRoute, key) => { newRoute[key] = vue.computed(() => route.value[key]); return newRoute; }, {} ) ); } function getJestGlobal() { return typeof jest !== "undefined" && jest; } function getSinonGlobal() { return typeof sinon !== "undefined" && sinon; } function getVitestGlobal() { return typeof vi !== "undefined" && vi; } function createSpy(fn, spyFactory) { if (spyFactory) { const spy = spyFactory.create(fn); return [spy, () => spyFactory.reset(spy)]; } const sinon = getSinonGlobal(); if (sinon) { const spy = sinon.spy(fn); return [spy, () => spy.resetHistory()]; } const jest = getVitestGlobal() || getJestGlobal(); if (jest) { const spy = jest.fn(fn); return [spy, () => spy.mockClear()]; } console.error( `Couldn't detect a global spy (tried jest and sinon). Make sure to provide a "spy.create" option when creating the router mock.` ); throw new Error( "No Spy Available. See https://github.com/posva/vue-router-mock#testing-libraries" ); } const EmptyView = vue.defineComponent({ name: "RouterMockEmptyView", render: () => null }); function createRouterMock(options = {}) { const router = vueRouter.createRouter({ history: vueRouter.createMemoryHistory(), routes: [ { path: "/:pathMatch(.*)*", component: EmptyView } ], ...options }); router.onError(() => { }); let { runPerRouteGuards, removePerRouteGuards, runInComponentGuards, useRealNavigation, noUndeclaredRoutes, spy } = options; const initialLocation = options.initialLocation || vueRouter.START_LOCATION; const { push, addRoute, replace, beforeEach, beforeResolve, onError } = router; const [addRouteMock, addRouteMockClear] = createSpy( (parentRecordName, record) => { record = record || parentRecordName; if (!runPerRouteGuards || removePerRouteGuards) { delete record.beforeEnter; } return addRoute(parentRecordName, record); }, spy ); const [pushMock, pushMockClear] = createSpy((to) => { return consumeNextReturn(to); }, spy); const [replaceMock, replaceMockClear] = createSpy((to) => { return consumeNextReturn(to, { replace: true }); }, spy); router.push = pushMock; router.replace = replaceMock; router.addRoute = addRouteMock; let guardRemovers = []; router.beforeEach = (...args) => { const removeGuard = beforeEach(...args); guardRemovers.push(removeGuard); return removeGuard; }; router.beforeResolve = (...args) => { const removeGuard = beforeResolve(...args); guardRemovers.push(removeGuard); return removeGuard; }; let onErrorRemovers = []; router.onError = (...args) => { const removeOnError = onError(...args); onErrorRemovers.push(removeOnError); return removeOnError; }; function reset() { pushMockClear(); replaceMockClear(); addRouteMockClear(); guardRemovers.forEach((remove) => remove()); guardRemovers = []; onErrorRemovers.forEach((remove) => remove()); onErrorRemovers = []; nextReturn = void 0; router.currentRoute.value = initialLocation === vueRouter.START_LOCATION ? vueRouter.START_LOCATION : router.resolve(initialLocation); } let nextReturn = void 0; function setNextGuardReturn(returnValue) { nextReturn = returnValue; } function consumeNextReturn(to, options2 = {}) { if (nextReturn != null || runInComponentGuards || useRealNavigation) { const removeGuard = router.beforeEach(() => { const value = nextReturn; removeGuard(); nextReturn = void 0; return value; }); const record = router.currentRoute.value.matched[depth.value]; if (record && !runInComponentGuards) { record.leaveGuards.clear(); record.updateGuards.clear(); Object.values(record.components || {}).forEach((component) => { delete component.beforeRouteUpdate; delete component.beforeRouteLeave; }); } pendingNavigation = (options2.replace ? replace : push)(to); pendingNavigation.catch(() => { }).finally(() => { pendingNavigation = void 0; }); return pendingNavigation; } try { router.currentRoute.value = router.resolve(to); } catch (error) { if (noUndeclaredRoutes) { throw error; } } return Promise.resolve(); } let pendingNavigation; function getPendingNavigation() { return pendingNavigation || Promise.resolve(); } function setParams(params) { router.currentRoute.value = router.resolve({ params }); return vue.nextTick(); } function setQuery(query) { router.currentRoute.value = router.resolve({ query }); return vue.nextTick(); } function setHash(hash) { router.currentRoute.value = router.resolve({ hash }); return vue.nextTick(); } const depth = vue.ref(0); reset(); return { ...router, push: pushMock, replace: replaceMock, addRoute: addRouteMock, depth, setNextGuardReturn, getPendingNavigation, setParams, setQuery, setHash, reset }; } function injectRouterMock(router) { router = router || createRouterMock(); const provides = createProvide(router); const route = provides[vueRouter.routeLocationKey]; Object.assign(testUtils.config.global.provide, provides); testUtils.config.global.mocks.$router = router; testUtils.config.global.mocks.$route = route; testUtils.config.global.components.RouterView = vueRouter.RouterView; testUtils.config.global.components.RouterLink = vueRouter.RouterLink; testUtils.config.global.stubs.RouterLink = true; testUtils.config.global.stubs.RouterView = true; return { router, route }; } function createProvide(router) { const route = createReactiveRouteLocation(router.currentRoute); const matchedRouteRef = vue.computed( () => router.currentRoute.value.matched[router.depth.value] ); return { [vueRouter.routerKey]: router, [vueRouter.routeLocationKey]: route, [vueRouter.routerViewLocationKey]: router.currentRoute, [vueRouter.matchedRouteKey]: matchedRouteRef }; } function plugin(wrapper) { const router = getRouter(); router.currentRoute.value.matched.forEach((record) => { for (const name in record.components) { record.instances[name] = wrapper.vm; } }); wrapper.router = router; return wrapper; } function getRouter() { return testUtils.config.global.provide[vueRouter.routerKey]; } exports.EmptyView = EmptyView; exports.VueRouterMock = plugin; exports.createProvide = createProvide; exports.createRouterMock = createRouterMock; exports.getRouter = getRouter; exports.injectRouterMock = injectRouterMock;