Skip to content

Commit b401adf

Browse files
authored
feat: setQuery and setHash (#47)
1 parent 6d2829d commit b401adf

File tree

5 files changed

+126
-30
lines changed

5 files changed

+126
-30
lines changed

README.md

+15
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,21 @@ it('should display the user details', async () => {
150150
})
151151
```
152152
153+
It can be awaited if you need to wait for Vue to render again:
154+
155+
```js
156+
it('should display the user details', async () => {
157+
const wrapper = mount(UserDetails)
158+
await getRouter().setParams({ userId: 12 })
159+
160+
// test...
161+
})
162+
```
163+
164+
`setQuery` and `setHash` are very similar.
165+
They can be used to set the route query or hash without triggering a navigation,
166+
and can be awaited too.
167+
153168
### Setting the initial location
154169
155170
By default the router mock starts on [`START_LOCATION`](https://next.router.vuejs.org/api/#start-location). In some scenarios this might need to be adjusted by pushing a new location and awaiting it before testing:

__tests__/navigations.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ describe('Navigations', () => {
198198
expect(wrapper.text()).toBe('/bar')
199199
})
200200

201-
it.skip('can wait for an ongoing navigation', async () => {
201+
it('can wait for an ongoing navigation', async () => {
202202
const wrapper = mount(Test)
203203
const router = getRouter()
204204

__tests__/params.spec.ts

-28
This file was deleted.

__tests__/partialLocation.spec.ts

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { mount } from '@vue/test-utils'
2+
import { watch } from 'vue'
3+
import { getRouter } from '../src'
4+
5+
describe('partial location', () => {
6+
describe('setParams', () => {
7+
it('sets current route params', async () => {
8+
const router = getRouter()
9+
router.setParams({ userId: 12 })
10+
const wrapper = mount({
11+
template: `<p>{{ $route.params.userId }}</p>`,
12+
})
13+
const spy = jest.fn()
14+
15+
watch(wrapper.vm.$route, spy)
16+
17+
expect(wrapper.vm.$route.params).toEqual({ userId: '12' })
18+
expect(wrapper.text()).toBe('12')
19+
expect(spy).toHaveBeenCalledTimes(0)
20+
21+
await router.setParams({ userId: 12 })
22+
expect(spy).toHaveBeenCalledTimes(1)
23+
expect(wrapper.text()).toBe('12')
24+
25+
await router.setParams({ userId: 2 })
26+
expect(spy).toHaveBeenCalledTimes(2)
27+
expect(wrapper.text()).toBe('2')
28+
})
29+
})
30+
31+
describe('setQuery', () => {
32+
it('sets current route query', async () => {
33+
const router = getRouter()
34+
router.setQuery({ page: 2 })
35+
const wrapper = mount({
36+
template: `<p>{{ $route.query.page }}</p>`,
37+
})
38+
const spy = jest.fn()
39+
40+
watch(wrapper.vm.$route, spy)
41+
42+
expect(wrapper.vm.$route.query).toEqual({ page: '2' })
43+
expect(wrapper.text()).toBe('2')
44+
expect(spy).toHaveBeenCalledTimes(0)
45+
46+
await router.setQuery({ page: 2 })
47+
expect(spy).toHaveBeenCalledTimes(1)
48+
expect(wrapper.text()).toBe('2')
49+
50+
await router.setQuery({ page: 3 })
51+
expect(spy).toHaveBeenCalledTimes(2)
52+
expect(wrapper.text()).toBe('3')
53+
})
54+
})
55+
56+
describe('setHash', () => {
57+
it('sets current route hash', async () => {
58+
const router = getRouter()
59+
router.setHash('#more')
60+
const wrapper = mount({
61+
template: `<p>{{ $route.hash }}</p>`,
62+
})
63+
const spy = jest.fn()
64+
65+
watch(wrapper.vm.$route, spy)
66+
67+
expect(wrapper.vm.$route.hash).toEqual('#more')
68+
expect(wrapper.text()).toBe('#more')
69+
expect(spy).toHaveBeenCalledTimes(0)
70+
71+
await router.setHash('#more')
72+
expect(spy).toHaveBeenCalledTimes(1)
73+
expect(wrapper.text()).toBe('#more')
74+
75+
await router.setHash('#about')
76+
expect(spy).toHaveBeenCalledTimes(2)
77+
expect(wrapper.text()).toBe('#about')
78+
})
79+
})
80+
})

src/router.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Component, nextTick, Ref, ref } from 'vue'
22
import {
33
createMemoryHistory,
44
createRouter,
5+
LocationQueryRaw,
56
RouteLocationRaw,
67
RouteParamsRaw,
78
Router,
@@ -48,7 +49,23 @@ export interface RouterMock extends Router {
4849
*
4950
* @param params - params to set in the current route
5051
*/
51-
setParams(params: RouteParamsRaw): void
52+
setParams(params: RouteParamsRaw): Promise<void>
53+
54+
/**
55+
* Sets the query of the current route without triggering a navigation. Can
56+
* be awaited to wait for Vue to render again.
57+
*
58+
* @param query - query to set in the current route
59+
*/
60+
setQuery(query: LocationQueryRaw): Promise<void>
61+
62+
/**
63+
* Sets the hash of the current route without triggering a navigation. Can
64+
* be awaited to wait for Vue to render again.
65+
*
66+
* @param hash - hash to set in the current route
67+
*/
68+
setHash(hash: string): Promise<void>
5269
}
5370

5471
export interface RouterMockOptions extends Partial<RouterOptions> {
@@ -188,6 +205,16 @@ export function createRouterMock(options: RouterMockOptions = {}): RouterMock {
188205
return nextTick()
189206
}
190207

208+
function setQuery(query: LocationQueryRaw) {
209+
router.currentRoute.value = router.resolve({ query })
210+
return nextTick()
211+
}
212+
213+
function setHash(hash: string) {
214+
router.currentRoute.value = router.resolve({ hash })
215+
return nextTick()
216+
}
217+
191218
const depth = ref(0)
192219

193220
return {
@@ -196,5 +223,7 @@ export function createRouterMock(options: RouterMockOptions = {}): RouterMock {
196223
setNextGuardReturn,
197224
getPendingNavigation,
198225
setParams,
226+
setQuery,
227+
setHash,
199228
}
200229
}

0 commit comments

Comments
 (0)