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

Posted

技术标签:

【中文标题】如何在 BootstrapVue 元素上使用 Vue Test Utils 触发事件?【英文标题】:How to trigger event with Vue Test Utils on a BootstrapVue element? 【发布时间】:2020-06-17 21:00:18 【问题描述】:

这个问题让我很难受,我不明白如何让 Vue Test UtilsBootstrapVue 一起玩得很好。

一个最小的例子如下所示:

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 中,我们使用BootstrapVueVue.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!");

这里有什么问题?

【问题讨论】:

要让你的 console.log 运行,你可以试试这个:wrapper.vm.play() @lucas 谢谢,但我的目标不是通过显式调用该方法来让console.log 运行。我想测试触发click事件是否会调用该方法。 知道了。但它有效吗?另一种选择是尝试将其更改为 wrapper.find('b-button').trigger('click') @lucas 不,wrapper.find('b-button') 不起作用。 wrapper.find('button') 也不会。使用 BoostrapVue 时,您必须将组件名称传递给 wrapperfind 方法。我不知道如何进一步进行以触发事件。 我对 BootstrapVue 不熟悉,但我有一个想法可能会对您有所帮助。检查他们如何测试存储库上的按钮。希望它能给你一些见解。 github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/… 【参考方案1】:

无法触发事件click 的原因是shallowMountmount 相比的工作方式。

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

安装 浅山

第一个方法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 之类的事件。

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

在使用 BootstrapVue 时,请仔细考虑您需要哪种安装方法。

【讨论】:

而且还适用于任何其他组件库(甚至你自己的子组件),而不仅仅是BootstrapVue @TroyMorehouse 是的,你完全正确。这里我们在 BootstrapVue 上做了一个例子,我相信它是一个流行的库。【参考方案2】:

在执行shallowMount 的同时,您应该可以这样做:

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

【讨论】:

以上是关于如何在 BootstrapVue 元素上使用 Vue Test Utils 触发事件?的主要内容,如果未能解决你的问题,请参考以下文章

Vue Test Util 在 Nuxt.js 中找不到 BootstrapVue html 元素

[BootstrapVue 警告]:弹出框 - 无法在文档中找到目标元素

使用 BootstrapVue 以编程方式编写导航链接的正确方法

BootstrapVue - 数字表单输入在 Firefox 中不起作用

如何在 BootstrapVue 中使用分页

如何将 BootstrapVue 在 Nuxt.js 中使用 Purgecss 所需的所有内容列入白名单