• 开始时间:2020-02-01
  • 目标主要版本:VTU beta-0.3x/1.x
  • 引用 issue:N/A
  • 实现的 PR:N/A

摘要

允许 Vue Test Utils APIs awati 触发的重新渲染,这使得重新渲染后断言改变更容易。

基本范例

  1. const wrapper = mount(Component)
  2. await wrapper.find('.element').trigger('click')
  3. expect(wrapper.emitted('event')).toBeTruthy()

动机

随着 Vue Test Utils beta-29sync 模式的移除,我们现在需要 await 诸如观察者或模版重新渲染,然后再做断言。

这个提案的目的是让开发者更容易使用异步测试,允许你 await 像 trigger 或那些内部使用它的调用。

这个提案假定在测试中使用 async/await

具体设计

一般的想法是,从触发异步变化的行为中返回一个在 NextTick 上 resolving 的 promise。

此时,我们需要手动 await 组件的更新。这导致了额外的模版,并且对初学者来说更难掌握。

  1. const wrapper = mount(Component)
  2. wrapper.find('.element').trigger('click')
  3. // we need to wait for the component to render
  4. await wrapper.vm.$nextTick()
  5. expect(wrapper.emitted('event')).toBeTruthy()

新的 API 看起来像这样:

  1. const wrapper = mount(Component)
  2. await wrapper.find('.element').trigger('click')
  3. expect(wrapper.emitted('event')).toBeTruthy()

使用更复杂的测试例子,好处是显而易见的:

  1. await wrapper.find('.button').trigger('click')
  2. expect(wrapper.emitted('event')).toBeTruthy()
  3. await wrapper.find('.country-option').setValue('US')
  4. expect(wrapper.find('.state').exists()).toBe(true)
  5. await wrapper.find('.radio-option').setChecked()
  6. expect(wrapper.find('.finish').attributes('disabled')).toBeFalsy()

应该返回一个 promise 的方法,在 next tick 时解决:

  • trigger
  • setValue
  • setChecked
  • setData
  • setProps
  • setSelected

上述大多数 helper 在内部依赖于 trigger,所以更新大多数列出的方法很容易。

附加的 helper

目前我们已经看到了 3 种 await 变化的方式:

  1. import flushPromises from 'flush-promises'
  2. await flushPromises()
  3. // or the more preferred
  4. await wrapper.vm.$nextTick()
  5. await Vue.nextTick()

在 Vue 3 中,nextTick 将从 VM 实例中移除,所以用户必须迁移到直接从 Vue 导入它 import { nextTick } from 'vue'

可以在 VTU 的 exports 中添加一个 tick helper。这样一来,用户就可以把所有东西都放在一个地方,并且有一个正式的方法来等待渲染,从不能直接返回一个 promise 的 actions 中。

这样的情况是触发了一个自定义的 Vue 事件:

  1. import { mount, tick } from '@vue/test-utils'
  2. it('test' => {
  3. const wrapper = mount(Component)
  4. wrapper.find('.input').vm.$emit('input', 'Newly added note')
  5. await tick()
  6. expect(wrapper).toMatchSnapshot()
  7. })

或者,我们可以聚焦在一个元素的挂载上,这通常是在 next tick 时进行的:

  1. const wrapper = mount(Component)
  2. // await data to be focused on mounted
  3. await tick()
  4. let input = wrapper.find('input').element
  5. expect(input).toBe(document.activeElement)

缺点

现在每一个 trigger 都会调用 nextTick(),我不确定这是否会损害性能。

用户可能会尝试 await 任何与 DOM 交互的东西,所以写好文档和指南是一个问题。

备选方案

N/A

采纳策略

Vue Test Utils beta-30+

用户必须确保 async/await 在他们的测试环境中是有效的。

用户只需要删除额外的 $nextTickflushPromise 调用,并使用新的 API。

改进关于该主题的文档。

Vue Test Utils prior to beta-30

在移除 sync 之前,没有必要等待渲染。

没有解决的问题

N/A