您将如何通过Jest和Vue-Test-Utils模拟打字?

时间:2020-01-16 17:28:14

标签: vue.js jestjs vue-test-utils

对于我的测试,我希望它以39的长度(最大长度:40)开头,然后当我按一个键(即:“ a”)时,长度应为40。尝试或查找似乎不允许我触发keypress / keydown / keyup事件。

我的组件:

<q-input
  v-model="name"
  class="my-class"
  maxlength="40"
\>

我的测试:

it('Input should change', async() => {
  let wrapper = mount(Component, { name: 'M'.repeat(39) })
  let name = wrapper.find('.my-class')
  console.log(name.vm.$options.propsData.value) // prints 39 M's as expected
  name.trigger('click') // I try clicking the input. I've also tried triggering 'focus'
  await wrapper.vm.$nextTick() // I've also tried with and without this
  // I've also tried await name.vm.$nextTick()
  name.trigger('keydown', { key: 'a' }) // According to their testing docs, this should press 'a'
  // I've also tried name.trigger('keyup', { key: 'a' })
  // and name.trigger('keypress', { key: 'a' })
  await wrapper.vm.$nextTick()
  console.log(name.vm.$options.propsData.value) // prints 39 M's without the additional 'a'
  expect(name.vm.$options.propsData.value.length).toBe(40)
})

2 个答案:

答案 0 :(得分:0)

我不知道dialog的来源,但是您不应该在wrapper中搜索元素吗?

wrapper.find('.my-class')

我看到的大多数示例都使用mount而不是factory

const wrapper = mount(component)

以下是文档中的示例:

it('Magic character "a" sets quantity to 13', () => {
    const wrapper = mount(QuantityComponent)
    wrapper.trigger('keydown', {
      key: 'a'
    })
    expect(wrapper.vm.quantity).toBe(13)
  })
})

答案 1 :(得分:0)

为什么触发keydown后值没有变化?

简而言之:您无法通过以编程方式调度 input 来更改 texarea/KeyboardEvent 的值。

字符实际上是如何进入 input 的?在 MDN 上,您可以找到 Keyboardevent sequence 的描述(假设未调用 preventDefault):

<块引用>
  • 首先触发 keydown 事件。如果进一步按住该键并且该键产生一个字符键,则该事件会在平台实现相关的时间间隔内继续发出,并且 KeyboardEvent.repeat 只读属性设置为 true。
  • 如果键产生的字符键会导致字符被插入到可能的 <input><textarea> 或 HTMLElement.contentEditable 设置为 true 的元素中,则 beforeinputinput 事件类型按该顺序触发。请注意,如果支持,某些其他实现可能会触发 keypress 事件。按住该键时,这些事件将重复触发。
  • 释放键后会触发 keyup 事件。这样就完成了这个过程。

因此,默认情况下 keydown 会导致 input 事件。但这仅适用于 trusted events

<块引用>

大多数不受信任的事件都不会触发默认操作,但 click 事件除外...所有其他不受信任的事件的行为就像在该事件上调用了 preventDefault() 方法一样。

基本上受信任的事件是由用户发起的,不受信任的事件是由脚本发起的。在大多数浏览器中,每个事件都有一个属性 isTrusted,指示该事件是否可信。

然后如何在 KeyboardEvent 上测试 input

嗯,这取决于您的 KeyboardEvent 处理程序中发生了什么。例如。如果您在某些条件下调用 preventDefault,那么您可以使用间谍检查它是否在测试中被调用。这是一个示例,其中 sinon 作为间谍,chai 作为断言库。

const myEvent = new KeyboardEvent('keydown', { key: 'a' })
sinon.spy(myEvent, 'preventDefault')
await wrapper.find('input').element.dispatchEvent(myEvent)
expect(myEvent.preventDefault.calledOnce).to.equal(true)

但有时您甚至不需要 KeyboardEvent 处理程序。例如。在您的问题中,您写了一个最大长度为 40 个字符的 input。实际上,您可以仅使用 maxlengthinput HTML 属性来防止输入超过 40 个字符。但仅作为学习示例,我们可以在输入处理程序中剪切值(它不仅会在用户输入时控制长度,还会在用户复制粘贴字符串时控制长度):

onInput (event) {
  event.target.value = event.target.value.substr(0, 40)
  ...
}

对此的测试可能如下所示:

 await wrapper.find('input').setValue('M'.repeat(41))
 expect(wrapper.find('input').element.value).to.equal('M'.repeat(40))

所以这里,我们直接改变input的值,而不是通过KeyboardEvent