如何使用BootstrapVue元素上的Vue Test Utils触发事件?

时间:2020-03-05 09:17:58

标签: javascript vue.js dom bootstrap-vue vue-test-utils

这个问题使我很难受,而且我不明白如何使 Vue Test Utils BootstrapVue 相互配合。

一个最小的示例如下:

MyComponent.vue

<template>
  <div>
    <b-button variant="primary" @click="play">PLAY</b-button>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  methods: {
    play() {
      console.log("Let's play!");
    }
  }
}
</script>

main.js中,我们使用 BootstrapVue Vue.use(BootstrapVue)

这是我试图测试click事件已触发的方式:

import { expect } from 'chai';
import sinon from 'sinon';
import Vue from 'vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import BootstrapVue, { BButton } from 'bootstrap-vue';
import MyComponent from '@/components/MyComponent.vue';

const localVue = createLocalVue();
localVue.use(BootstrapVue);

describe('MyComponent.vue', () => {
  it('should call the method play when button is clicked', () => {
    const playSpy = sinon.spy();
    const wrapper = shallowMount(MyComponent, {
      localVue,
      methods: {
        play: playSpy,
      },
    });
    wrapper.find(BButton).trigger('click');
    expect(playSpy.called).to.equal(true);
  });
});

这给了我

  AssertionError: expected false to equal true
  + expected - actual

  -false
  +true

我检查了How to test for the existance of a bootstrap vue component in unit tests with jest?,但不适用于BButton

运行测试时,我也看不到命令​​行上的任何输出,我希望在该行上执行该操作:

console.log("Let's play!");

这是怎么了?

2 个答案:

答案 0 :(得分:5)

无法触发事件click的原因是与shallowMount相比,mount的工作方式。

我们知道,Vue Test Utils提供了两种安装组件的方法,即渲染模板并生成DOM树:

  • 安装
  • shallowMount

第一个方法mount生成一个完整的DOM树并遍历所有子组件。在大多数情况下,这不是必需的,因此,方法shallowMount是首选的-它在子组件的根目录仅比父组件低一级的地方进行存根。

就我而言,这也是问题的根源。 BootstrapVue 提供了BButton之类的组件,可以在自己的Vue模板中使用它们。这意味着在以下模板中:

<template>
  <div>
    <b-button variant="primary" @click="play">PLAY</b-button>
  </div>
</template>

b按钮是一个子组件,在我们的组件的单元测试中使用shallowMount时会被存根。这就是为什么我们找不到元素按钮的原因:

const wrapper = shallowMount(MyComponent);
wrapper.find('button'); // won't work

我们可以找到以下子组件:

wrapper.find(BButton); // BButton has to be imported from bootstrap-vue

但是如果我们尝试输出渲染的元素:

console.log(wrapper.find(BButton).element);

我们将得到:

HTMLUnknownElement {}

BButton作为子组件尚未完全呈现,并且DOM树中没有button元素。但是,当我们使用mount时,我们会有以下行为:

const wrapper = mount(MyComponent);
console.log(wrapper.find(BButton).element);

我们将得到:

HTMLButtonElement { _prevClass: 'btn btn-primary' }

我们看到mount渲染了子组件。当我们使用mount时,我们可以直接访问button元素:

wrapper.find('button');

现在我们有了button,我们可以在其上触发类似click的事件。

我希望这也会对其他初学者有所帮助。这些示例非常简化,不要忘记使用localVue创建createLocalVue并将其传递给问题中说明的mount方法。

使用 BootstrapVue 时,请仔细考虑所需的安装方法。

答案 1 :(得分:1)

在仍然执行shallowMount的同时,您应该可以执行以下操作:

wrapper.find(BButton).vm.$listeners.click();