9

I'm using bootstrap as my design framework and have been using bootstrap-vue. Now I would like to implement some tests to go along with my components. I'm writing a very simple test to make sure a modal is opened. What do I use in vue-test-utils to open the bootstrap-vue modal?

I'm using the basics that come with Laravel, bootstrap-vue, vue-test-utils, mocha, and mocha-webpack.

I'm trying to open the modal with wrapper.find('#modal-1').trigger('click'). I've tried using a directive <b-button v-b-modal.modal-1> I've tried using an event <b-button @click="$bvModal.show('modal-1')">. And lastly, I tried a regular button <button @click="showModal = true"> with this on the b-modal <b-modal v-model="showModal">. I've also tried adding a $nextTick in between the trigger and the assertion.

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);
    });
});

I'm expecting the modal to be in the wrapper with expect(wrapper.contains('#modal-1')).toBe(true) and this is where the assertion is failing.

1
  • 3
    Have you found a solution or workaround for this problem? Commented Jun 11, 2019 at 0:24

5 Answers 5

4

Use the attachToDocument: true mount option, as modal needs to be in the document in order to open.

You can see how BootstrapVue tests their modals at https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/modal/modal.spec.js

Sign up to request clarification or add additional context in comments.

2 Comments

attachToDocument is deprecated now in favor of attachTo, which takes an HTMLElment
attachTo: document.body
4

I was looking at the bootstrap-vue test on github as Troy suggested (https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/modal/modal.spec.js)

There you can see that they are using the prop static: true. Adding this to my code solved my problem.

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();
    });
});

I had to select the modal by id because the inner part is getting display: none. When I put a data-qa on the modal it sticks on the outer element which is not hidden itself. Another solution for that would be to select it the following way: const modal = wrapper.find('[data-qa="modal"] .modal');

But I still get the following warning in my console: [BootstrapVue warn]: observeDom: Requires MutationObserver support.

1 Comment

After 2 days wasted on trying multiple solutions static: true solved it for me! (I'm also receiving Requires MutationObserver supportwarning.)
0
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) 
});

1 Comment

a verbal explanation is often helpful
0

I'm using jest to test if a modal appears when a button is clicked adn ended up with related problem. Will leave my answer here for furture readers.

I was trying to do something like:

 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

Leading to this:

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

The thing was that I was using shallowMount:

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

And at some point of MyComponent, it needs to do something like:

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

Therefore this.$ref was comming as undefined.

Using mount instead:

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

allowed me to click that button and find the stub within the wrapper.html().

So make sure to mount your components if you gonna need to access stubs from it.

Comments

-2

In my case this work perfectly,

Here I have a b-modal in template with a id="modal-1" and when the button is clicked bootstrap-vue modal is opened using showModal() method.

Try this:

<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>

1 Comment

Thank you for your suggestion. It does work perfectly in the browser. My problem is not with the modal not working in the browser. I can't seem to get vue-test-utils to open the modal in a test I'm trying to write. I've updated my question with the test I'm trying to run on exactly the code you've shown.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.