-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vue Router test utils #152
Comments
About the waiting for navigation. The full code should also account for errors with onErrors function waitNavigation(router: Router, allowRejection = false) {
return new Promise<NavigationFailure | undefined>(
(resolve, reject) => {
let removeError = () => {}
if (!allowRejection) {
removeError = router.onError(err => {
removeError()
removeAfterEach()
reject(err)
})
}
let removeAfterEach = router.afterEach((_to, _from, failure) => {
removeError()
removeAfterEach()
resolve(failure)
})
}
)
} I think it would be even better if the test utils could provide an extended version of the router with its own extended RouterLink that would add a Symbol to I think it's also worth noting what scenarios would require the user to use the whole router when writing tests with VTU. I've almost always mocked the |
Yep, I normally mock out the router (and the |
My 2 cents: I don't think we should offer special methods on the wrapper for the router (or even encourage to have tests like these). As @posva mentioned, most tests should use a mock version, and our APIs/docs should hint that way. If you want to navigate between components, isn't it more an e2e tests than a unit test? I wouldn't mind a |
A fake router with spies and stubs that are still able to change a location is what I was thinking about. Similar to https://github.com/posva/vuex-mock-store |
I think we can build I agree we should provide a mock router that does all the good stuff you would expect without any of the caveats. We could do something like vuex-mock-store. |
I thought about this a bit more - just getting the ball rolling. I think we could do something like this:
Example: import { mockRouter } from '@vue/test-utils'
const Foo = {
template: `<router-link :to="link">{{ post }}</router-link> <router-view />`,
setup() {
const title = useRoute().params.title
return {
link: `/posts/${title}`,
post: `Go to post about {{ title }}`
}
}
const router = mockRouter({
initialPath: '/posts'
})
const wrapper = mount(Foo, {
global: {
plugins: [router]
}
})
expect(router.history).toEqual(['/posts'])
expect(wrapper.html()).toContain('Go to post about mocking-params')
await wrapper.find('a').trigger('click')
expect(router.history).toEqual(['/posts', '/posts/mocking-params]) Just came up with this in 5-10 mins, I'm sure I'm missing tons of things - want to make sure we are on the same page, design wise, before we right too much code. |
|
Having a way to mock the current route out of the box would also be nice. I currently do something like this: // fake router params
mockRouter.currentRoute.value.params = {
userId: '12'
}; |
I will try to work on this soon. @posva I wonder if we will need to export the |
Yeah, we might need to expose them as internal utilities |
I played around with this a bit and noticed some complexity. I modified my vue-router build to export the setup() {
const router = useRouter()
} So I decided to mock 🤔 Building a mock router doesn't seem too difficult but I the hooks may present some complexity. |
The doc should mention to wait for |
Just in case anyone stumbles upon this issue: https://github.com/posva/vue-router-mock is an alternative to mock routing interactions in Vue 3 |
Going to close this one now since we have a solution for a mock router - let's open issues and PRs there if it has any missing features. |
In writing some small apps and the VTU docs, I encounted some caveats when testing components using Vue Router. This is mainly because the navigation is now all async (which I think it is a great design decision, it fits into Vue's async update model perfectly).
When I first tried writing some tests using Vue Router, I didn't realize I had to do
await router.isReady
, or the initial navigation may not be completed before the component renders.Also, I triggered a click on a
<router-link>
I got an error. It turns out that you need to wait for the navigation to complete (makes sense with the new async navigation model).Here is a full snippet demonstrating what is currently required when using VueRouter in a jsdom environment (sans VTU).
The user must
await isReady
, and alsoawait resolve
using theafterEach
callback to ensure the navigation triggered when clicking on the<a>
tag (from<router-link>
) before continuing their tests. Kind of like how you need to doawait nextTick
for Vue to update the DOM.We should bundle some goodies to make testing Vue Router a more smooth experience. @posva suggested
await routerMock.pendingNavigation()
. I think we need both good utils for testing with the actual VueRouter, and a mocked VueRouter.This is the kind of thing you would previously write in VTU 1.x with Vue 2.x and Vue Router 3.x:
I see a few options, but I think the best and most simple is some additional methods on
wrapper
. Here are some ideas I had:I like the latter the best. Tight integration with Vue Router, and I think it's really readable.
Any ideas or feedback would be great 👍
The text was updated successfully, but these errors were encountered: