VTL for Vue 3: The routes option does not work correctly
See original GitHub issueDescribe the bug When using the routes option of the render function, it throws up some warnings that have to do with the _history property and the asynchronic handling that vue router 4 has. This causes you to not be able to use the routes option correctly.
To Reproduce
import { render, screen } from '@testing-library/vue'
import '@testing-library/jest-dom'
import { defineComponent } from 'vue'
import { RouteRecordRaw } from 'vue-router'
test('Component with route', () => {
const ComponentA = defineComponent({
name: 'ComponentA',
props: {
to: {
type: Object,
required: true
}
},
template: `<router-link :to="to" role="button">Learn More</router-link>`
})
const ComponentB = defineComponent({
name: 'ComponentB'
})
const routeRecordRaw: RouteRecordRaw = {
path: '/',
name: 'componentB',
component: ComponentB
}
const to = { name: routeRecordRaw.name }
render(ComponentA, {
props: { to },
routes: [routeRecordRaw]
})
const button = screen.getByRole('button')
expect(button).toBeInTheDocument()
expect(button?.getAttribute('href')).toBe(routeRecordRaw.path)
})
This throws the following warning
console.warn node_modules/vue-router/dist/vue-router.cjs.js:75
[Vue Router warn]: Unexpected error when starting the router: TypeError: Cannot read property '_history' of null
The warning is known. This is explained in the vue-test-utils v2 documentation https://vue-test-utils.vuejs.org/v2/guide/vue-router.html#with-a-real-router
So to solve it apply what is indicated in documentation
import { render, screen } from '@testing-library/vue'
import '@testing-library/jest-dom'
import { defineComponent } from 'vue'
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
test('Component with route', async () => {
const ComponentA = defineComponent({
name: 'ComponentA',
props: {
to: {
type: Object,
required: true
}
},
template: `<router-link :to="to" role="button">Learn More</router-link>`
})
const ComponentB = defineComponent({
name: 'ComponentB'
})
const routeRecordRaw: RouteRecordRaw = {
path: '/',
name: 'componentB',
component: ComponentB
}
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes: [routeRecordRaw]
})
router.push('/')
await router.isReady()
const to = { name: routeRecordRaw.name }
render(ComponentA, {
props: { to },
global: {
plugins: [router]
}
})
const button = screen.getByRole('button')
expect(button).toBeInTheDocument()
expect(button?.getAttribute('href')).toBe(routeRecordRaw.path)
})
Expected behavior Be able to correctly use the routes option provided by the render function
Related information:
@testing-library/vue
version: ^6.3.1Vue
version: ^3.0.0node
version: 14.4.0npm
version: 6.14.9
Issue Analytics
- State:
- Created 3 years ago
- Comments:25 (16 by maintainers)
Top Results From Across the Web
Routing in Vue3: Navigating the Options - CODE Magazine
This is where Vue Routing comes in. It allows you to build the kinds of apps you need to create. Let's see how...
Read more >Lazily added routes are not accessible by url - Stack Overflow
When component introduces new route for its router-view it is working while going trough the app, but once you refresh or try to...
Read more >FAQ | Testing Library
Short answer: yes, it is. If you use Vue Testing Library (VTL) there's no need to install @vue/test-utils. Longer answer: VTL is built...
Read more >Migrating from Vue 2 - Vue Router
This is no longer possible and there are two options: Using the name of the route without the param: redirect: { name: 'events'...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I have definitely seen the
_history
error before. It was related to awaiting the router to be read, but you’ve already done that.I wonder if this is a bug here? I feel like it might be either in Test Utils or something else. I wonder if we can reproduce it without Testing Library (VTU + Jest). I wonder if you need to have a top level component (like
<app>
) with a<router-view />
for this to work as expected.Going back to this. As I see it, we’re down to two options:
Make
render
async whenroutes
is present, and then callrouter.isReady()
internally. API change: you’d need toawait render(Comp, { routes })
, but not when routes is not there. We could warn users somehow (plus, TS types would help, too).Remove vuex/router integration for Vue 3, and leave it to users. This would make users responsible for setting up router (and store) and call
router.isReady()
, which is an implementation detail (even though it is on the Arrange section of tests, which is OK, I guess), and would keeprender
sync. This solution makes VTL more aligned to other Testing Lib flavors.To be fair, setting up your own router/vuex isn’t that bad now with VTU 2 since there’s no need to set up a local vue instance. On the other hand, “hiding” the need to mke router ready feels… right for users.