【问题标题】:What is the proper way to test Vue3 async setup component with suspense?用悬念测试 Vue3 异步设置组件的正确方法是什么?
【发布时间】:2021-04-15 16:38:49
【问题描述】:

毫无疑问,Suspense 功能会带来更简洁的代码库,但尽管它很整洁,但它变得难以测试。具体来说,它还没有很好的记录。

案例:

VUE CLI 生成的常规应用

  • 技术栈:Vuex、路由器、PWA、用于单元测试的笑话

挑战:

我使用了 Suspense 组件,推荐如下:

    <RouterView name="default" v-slot="{ Component, route }">
      <transition :name="route.meta.transition" mode="out-in" :duration="300" :key="route.path">
        <Suspense >
          <template #default>
            <component :is="Component" :key="route.path"/>
          </template>
          <template #fallback>
            <div class="top-0 right-0 h-screen w-screen z-50 flex justify-center items-center">
               <div class="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-yellow-700"></div>
            </div>
          </template>
        </Suspense>
      </transition>
    </RouterView>

我的路线和风景很少:

  • 其中一个用于登录视图
  // here is the gotcha, if ever I removed async from setup the test runs well otherwise it always returns empty vm.
  async setup(){
    const router = useRouter()
    const route = useRoute()
    const form = reactive(new Form({
          username:'',
          password:'',
      }))
}

我的测试套件如下:


  test('Shows login form',  async () => {
      let wrapper = mount(Login,{
        // tried set global.stubs.transition to false
        renderDefaultSlot: true // tried as well to move this attr to beforeEach hook
      })
      expect(wrapper.exists()).toBe(true) // passes
      await nextTick()
      // tried to flushPromises()
      console.log(wrapper.vm) // always empty object {}
      expect(wrapper.findAll('div')).toBeTruthy() // fails accordingly as it can't run helper methods to get the parentElement
    })

有没有VUE老手可以给点提示或者解决方法!

Github 上的所有公开讨论表明,我不是唯一一个偶然发现这个问题的人,但现在这只是一个讨论。

https://github.com/vuejs/vue-test-utils-next/issues/108#issue-611802592

https://github.com/vuejs/vue-test-utils/issues/956

【问题讨论】:

    标签: javascript ecmascript-6 jestjs vuejs3


    【解决方案1】:

    调查后写了一个小助手,引用自上面的 Github 讨论:

    import {defineComponent,h,Suspense } from 'vue'
    import { mount } from '@vue/test-utils'
    import flushPromises from 'flush-promises';
    
    const mountSuspense =  async (component, options) => {
        const wrapper = mount(defineComponent({
          render() {
            return h(Suspense, null, {
              default: h(component),
              fallback: h('div', 'fallback')
            })
          }}), ...options)
    
        await flushPromises()
        return wrapper
      }
    
      describe('App renderes', ()=>{
          test('About page renders',async()=>{
              const wrapper = await mountSuspense(About)
              await console.log(wrapper.text()) // it works
          })
      })
    

    【讨论】:

    • 谢谢,这很有帮助,但是这似乎并不包括在内,例如,我们如何测试后备是否被重新渲染?
    • @Mr.Toxy 该实例现在作为 wrapper.text() 或 wrapper.html() 存在于包装器对象上 - 我建议您在等待 flushPromises 后使用 console.log(wrapper) 并模拟异步回调() 或 nextTick()。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 2020-09-13
    相关资源
    最近更新 更多