No doubt that Suspense feature leads to a cleaner code base, but as tidy as it is, it turns to be hard to test. Specifically it is not well documented yet.
case:
Regular app generated by VUE CLI
- Tech stack: Vuex, Router, PWA, jest for unit testing
Challenge:
I made use of Suspense component as recommended as follows:
JavaScript
x
16
16
1
<RouterView name="default" v-slot="{ Component, route }">
2
<transition :name="route.meta.transition" mode="out-in" :duration="300" :key="route.path">
3
<Suspense >
4
<template #default>
5
<component :is="Component" :key="route.path"/>
6
</template>
7
<template #fallback>
8
<div class="top-0 right-0 h-screen w-screen z-50 flex justify-center items-center">
9
<div class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-yellow-700"></div>
10
</div>
11
</template>
12
</Suspense>
13
</transition>
14
</RouterView>
15
16
I have few routes and views:
- one of them is for Login view
JavaScript
1
10
10
1
// here is the gotcha, if ever I removed async from setup the test runs well otherwise it always returns empty vm.
2
async setup(){
3
const router = useRouter()
4
const route = useRoute()
5
const form = reactive(new Form({
6
username:'',
7
password:'',
8
}))
9
}
10
And my test suite as follows:
JavaScript
1
13
13
1
test('Shows login form', async () => {
2
let wrapper = mount(Login,{
3
// tried set global.stubs.transition to false
4
renderDefaultSlot: true // tried as well to move this attr to beforeEach hook
5
})
6
expect(wrapper.exists()).toBe(true) // passes
7
await nextTick()
8
// tried to flushPromises()
9
console.log(wrapper.vm) // always empty object {}
10
expect(wrapper.findAll('div')).toBeTruthy() // fails accordingly as it can't run helper methods to get the parentElement
11
})
12
13
Does any VUE veteran here can give a hint or workaround!
All open discussions on Github shows that I am not the only one stumbled on this issue, but for now it is just a discussion.
https://github.com/vuejs/vue-test-utils-next/issues/108#issue-611802592
https://github.com/vuejs/vue-test-utils/issues/956
Advertisement
Answer
After investigation wrote a little helper quoted from Github discussion above:
JavaScript
1
24
24
1
import {defineComponent,h,Suspense } from 'vue'
2
import { mount } from '@vue/test-utils'
3
import flushPromises from 'flush-promises';
4
5
const mountSuspense = async (component, options) => {
6
const wrapper = mount(defineComponent({
7
render() {
8
return h(Suspense, null, {
9
default: h(component),
10
fallback: h('div', 'fallback')
11
})
12
}}), options)
13
14
await flushPromises()
15
return wrapper
16
}
17
18
describe('App renderes', ()=>{
19
test('About page renders',async()=>{
20
const wrapper = await mountSuspense(About)
21
await console.log(wrapper.text()) // it works
22
})
23
})
24