如何使用 vue-test-utils 打开 bootstrap-vue 模态?

Posted

技术标签:

【中文标题】如何使用 vue-test-utils 打开 bootstrap-vue 模态?【英文标题】:How do you open a bootstrap-vue modal with vue-test-utils? 【发布时间】:2019-10-07 05:01:14 【问题描述】:

我使用 bootstrap 作为我的设计框架,并且一直在使用 bootstrap-vue。现在我想实现一些测试来配合我的组件。我正在编写一个非常简单的测试来确保打开模式。在 vue-test-utils 中使用什么来打开 bootstrap-vue modal?

我正在使用 Laravel、bootstrap-vue、vue-test-utils、mocha 和 mocha-webpack 附带的基础知识。

我正在尝试使用wrapper.find('#modal-1').trigger('click') 打开模式。我尝试使用指令<b-button v-b-modal.modal-1> 我尝试使用事件<b-button @click="$bvModal.show('modal-1')">。最后,我在 b-modal <b-modal v-model="showModal"> 上尝试了一个常规按钮 <button @click="showModal = true">。我还尝试在触发器和断言之间添加$nextTick

import  createLocalVue, mount  from '@vue/test-utils';
import expect from 'expect';
import BootstrapVue from 'bootstrap-vue';
import MyComponent from '@/components/MyComponent.vue';

const localVue = createLocalVue();

localVue.use(BootstrapVue);

describe ('MyComponent', () => 
    let wrapper;

    beforeEach(() => 
        wrapper = mount(QuotesExceptions, 
            localVue
        );
    );

    it ('opens a modal', () => 
        expect(wrapper.contains('#modal-1')).toBe(false);

        wrapper.find('#btnShow').trigger('click');

        expect(wrapper.contains('#modal-1')).toBe(true);
    );
);

我希望模态框包含在 expect(wrapper.contains('#modal-1')).toBe(true) 的包装器中,这就是断言失败的地方。

【问题讨论】:

您找到解决此问题的解决方案或变通方法了吗? 【参考方案1】:

按照 Troy 的建议,我正在 github 上查看 bootstrap-vue 测试 (https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/modal/modal.spec.js)

在那里你可以看到他们正在使用道具static: true。将此添加到我的代码中解决了我的问题。

component.vue

<b-modal
    v-model="showModal"
    id="myModal"
    data-qa="importModal"
    :static="true"
>
</b-modal>

component.spec.js

it ('opens a modal', (done) => 
    const button = wrapper.find('[data-qa="button"]');
    const modal = wrapper.find('#myModal');
    expect(button.exists()).toBe(true);
    expect(button.is('button')).toBe(true);
    expect(modal.exists()).toBe(true);
    expect(modal.is('div')).toBe(true);

    expect(modal.isVisible()).toBe(false);
    button.trigger('click');

    Vue.nextTick(() => 
      expect(modal.isVisible()).toBe(true);
      done();
    );
);

我必须通过id 选择模态,因为内部部分正在获取display: none。当我在模态框上放置data-qa 时,它会粘在本身不隐藏的外部元素上。另一种解决方案是通过以下方式选择它: const modal = wrapper.find('[data-qa="modal"] .modal');

但我仍然在控制台中收到以下警告: [BootstrapVue warn]: observeDom: Requires MutationObserver support.

【讨论】:

在浪费了 2 天时间尝试多种解决方案之后,static: true 为我解决了这个问题! (我也收到了Requires MutationObserver supportwarning。)【参考方案2】:

使用attachToDocument: true 挂载选项,因为模式需要在文档中才能打开。

您可以在 https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/modal/modal.spec.js 看到 BootstrapVue 如何测试他们的模式

【讨论】:

attachToDocument 现在已弃用,取而代之的是 attachTo,它采用 htmlElment【参考方案3】:
it ('opens a modal', (done) => 
    const button = wrapper.find('[data-qa="button"]');
    expect(!!document.querySelector('myModal')).toBe(false)
    button.trigger('click');
    expect(!!document.querySelector('myModal')).toBe(true) 
);

【讨论】:

口头解释通常很有帮助【参考方案4】:

我正在使用 jest 来测试单击按钮时是否出现模式并最终出现相关问题。将我的答案留给未来的读者。

我试图做类似的事情:

 let openModalBtn = wrapper.find('button[id="openModal"]');
 expect(openModalBtn.exists()).toBe(true); // OK
 expect(openModalBtn.is("button")).toBe(true); // OK
 await deleteBtn.trigger("click"); // BANG

导致:

[Vue warn]: Error in v-on handler (Promise/async): "TypeError: this.$refs.confirmDialogue[0].show is not a function"

问题是我使用的是shallowMount

// not good
describe("some test", () => 
  let wrapper;
  beforeEach(() => 
    wrapper = shallowMount(MyComponent, ...);
  );

MyComponent 的某个时刻,它需要执行以下操作:

...
  methods: 
    openModal() 
      await this.$refs.confirmDialogue[0].show();
      ...
    ,

因此this.$refundefined 的身份出现。

改用mount

// good
describe("some test", () => 
  let wrapper;
  beforeEach(() => 
    wrapper = mount(MyComponent, ...);
  );

允许我单击该按钮并在 wrapper.html() 中找到存根。

因此,如果您需要从中访问 stubs,请确保安装您的组件。

【讨论】:

【参考方案5】:

在我的情况下,这很完美,

这里我在模板中有一个 b-modal,带有 id="modal-1",当单击按钮时,使用 showModal() 方法打开 bootstrap-vue 模式。

试试这个:

<template>

    <b-button v-on:click="showModal()">
    <b-modal id="modal-1"></b-modal>

</template>

<script>
    methods: 
        showModal() 
              this.$root.$emit("bv::show::modal", 'modal-1', "#btnShow");
          ,
    

</script>

【讨论】:

感谢您的建议。它确实在浏览器中完美运行。我的问题不在于模式在浏览器中不起作用。我似乎无法让 vue-test-utils 在我正在尝试编写的测试中打开模式。我已经用我试图在你显示的代码上运行的测试更新了我的问题。

以上是关于如何使用 vue-test-utils 打开 bootstrap-vue 模态?的主要内容,如果未能解决你的问题,请参考以下文章

VueJs 如何删除全局错误处理程序以使用 vue-test-utils 进行测试

vue-test-utils:如何在 mount() 生命周期钩子(使用 vuex)中测试逻辑?

如何使用 vue-test-utils 在单元测试期间触发窗口事件

如何使用 Vue-test-utils 和 Jest 测试 Vuex 突变

如何在单元测试期间使用 vue-test-utils 和 jest 模拟 mixin?

如何使用 vue-test-utils 和 Jest 在 Nuxt 中对使用 vuex-module-decorators 语法定义的 Vuex 模块进行单元测试?