Reputation: 39034
I have a very basic test, however it throws the error below when I try to mount a component const wrapper = mount(HomeHeader)
. I've pasted my vite config, test, component and packages.
This error happened without updating my vite config, but I went ahead and updated the config with test: { globals: true, }
so I don't have to import test
and expect
.
Full error
stderr | src/components/home/__tests__/HomeHeader.test.js > HomeHeader renders properly
[Vue warn]: injection "Symbol([vue-router]: router)" not found.
at <RouterLink to="/" >
at <HomeHeader ref="VTU_COMPONENT" >
at <VTUROOT>
[Vue warn]: injection "Symbol([vue-router]: route location)" not found.
at <RouterLink to="/" >
at <HomeHeader ref="VTU_COMPONENT" >
at <VTUROOT>
[Vue warn]: Unhandled error during execution of setup function
at <RouterLink to="/" >
at <HomeHeader ref="VTU_COMPONENT" >
at <VTUROOT>
FAIL src/components/home/__tests__/HomeHeader.spec.js > HomeHeader > renders properly
TypeError: Cannot read properties of undefined (reading 'resolve')
❯ ReactiveEffect.fn node_modules/vue-router/dist/vue-router.cjs.js:2068:45
2066| const router = vue.inject(routerKey);
2067| const currentRoute = vue.inject(routeLocationKey);
2068| const route = vue.computed(() => router.resolve(vue.unref(props.to)));
| ^
Vitest UI
Vite Config
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
test: {
globals: true,
},
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})
My test
import { mount } from '@vue/test-utils'
import HomeHeader from '../HomeHeader.vue'
describe('HomeHeader', () => {
it('renders properly', () => {
// This breaks
const wrapper = mount(HomeHeader)
expect(wrapper.text()).toContain('MOONHOLDINGS.XYZ')
})
})
The component being tested
<script setup>
import { RouterLink } from 'vue-router'
import {
MOON_XYZ,
LOGIN,
LOGIN_PATH,
GET_STARTED,
SIGN_UP_PATH,
} from '../../constants'
import PrimaryBtn from '@/components/partials/PrimaryBtn.vue'
</script>
<template>
<main>
<header>
<h1>
<RouterLink to="/">
{{ MOON_XYZ }}
</RouterLink>
</h1>
<nav>
<RouterLink :to="LOGIN_PATH">{{ LOGIN }}</RouterLink>
<PrimaryBtn :copy="GET_STARTED" :url="SIGN_UP_PATH" />
</nav>
</header>
</main>
</template>
<style lang="scss" scoped>
h1 {
margin: 1em;
font-size: 1.375rem;
color: #fff;
}
a {
color: #fff;
text-decoration: none;
}
nav {
position: absolute;
right: 2em;
a {
display: inline-block;
padding: 0 1rem;
font-size: 2em;
text-decoration: none;
color: #fff;
transition: 0.4s;
.router-link-exact-active {
color: #fff;
}
.router-link-exact-active:hover {
background-color: transparent;
}
&:hover {
text-decoration: underline;
}
&:first-of-type {
border: 0;
}
}
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
}
</style>
Script command "coverage": "vitest run --coverage",
My dependencies
"dependencies": {
"animate.css": "^4.1.1",
"axios": "^0.27.2",
"pinia": "^2.0.14",
"vue": "^3.2.36",
"vue-router": "^4.0.15"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.1.0",
"@vitejs/plugin-vue": "^2.3.3",
"@vitejs/plugin-vue-jsx": "^1.3.10",
"@vitest/ui": "^0.20.3",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/test-utils": "^2.0.2",
"c8": "^7.11.3",
"eslint": "^8.5.0",
"eslint-plugin-vue": "^9.0.0",
"happy-dom": "^6.0.4",
"jsdom": "^19.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"ramda": "^0.28.0",
"sass": "^1.53.0",
"start-server-and-test": "^1.14.0",
"vite": "^2.9.9",
"vitest": "^0.20.3",
"vue-tsc": "^0.35.2"
}
Anyone else run into this before while using Vitest?
Upvotes: 8
Views: 25276
Reputation: 581
Vue Router is automatically mocked and because of that, no methods can be called from it. That's the reason why you are getting errors on calling resolve()
.
Correct test should look like this:
import { vi } from 'vitest';
import { mount } from '@vue/test-utils'
import HomeHeader from '../HomeHeader.vue'
// you need to mock router
vi.mock('vue-router', () => ({
resolve: vi.fn(),
}));
describe('HomeHeader', () => {
it('renders properly', () => {
const wrapper = mount(HomeHeader)
expect(wrapper.text()).toContain('MOONHOLDINGS.XYZ')
})
})
Upvotes: 6