Evgeni Dikerman
Evgeni Dikerman

Reputation: 516

Vue2: When testing component that contains a functional child component, how to emit event from the child?

I try to unit test a component that contains b-button (bootstrap vue button).

I need to emit a 'click' event to simulate a click on b-button child component, as I use shallowMount so all child components are mocked and I cannot .trigger('click') on it. In addition, I cannot access to the vm of that child as b-button is a functional components that don't have instance, so childWrapper.vm.$emit('click') won't work either.

What is my best option to test my component with shallowMount?

What I tried:

  1. Used mount instead of shallowMount .trigger('click') would do the job
  2. Used shallowMount and pass {stubs: {BButton}} b-button would be mocked with the real implementation and will work as section 1
  3. Tried btnWrapper.trigger('click'), btnWrapper.vm.$emit('click'), btnWrapper.element.click(), none of them worked.
// TemplateComponent.vue
<template>
  <div class="row">
    <div class="col-12 p-2">
      <b-button @click="eatMe">Eat me</b-button>
    </div>
  </div>
</template>

<script>
  import bButton from 'bootstrap-vue/es/components/button/button';

  export default {
    name: "TemplateComponent",
    components: {
      bButton
    },
    methods: {
      eatMe() {
        this.$emit('click')
      }
    }
  }
</script>
// TemplateComponent.test.js
import {shallowMount} from '@vue/test-utils';

import TemplateComponent from './TemplateComponent.vue';

describe('TemplateComponent', () => {
  let wrapper, vm;

  beforeEach(() => {
    wrapper = shallowMount(TemplateComponent);
  });

  it('should trigger the eatMe twice', () => {
    wrapper.setMethods({
      eatMe: jest.fn()
    });
    const btn = wrapper.find('b-button-stub');
    btn.trigger('click'); // won't work
    btn.vm.$emit('click'); // won't work

    expect(vm.eatMe.mock.calls.length).toEqual(2);
  });
});

Upvotes: 3

Views: 1694

Answers (1)

Dre Westcook
Dre Westcook

Reputation: 603

Stub it with a regular button to capture the emit event.

describe('TemplateComponent', () => {
  let wrapper, vm;

  beforeEach(() => {
shallowMount(TemplateComponent, {
  stubs: {
    'b-button': {
      template: `<button @click='$listeners.click'></button>`
    }
  }
});

 it('should trigger the eatMe twice', () => {
    wrapper.setMethods({
      eatMe: jest.fn()
    });
    const btn = wrapper.find('whatever');
    btn.trigger('click'); // will now work. as it's swapped with a generic button, still processing the event.


    expect(vm.eatMe.mock.calls.length).toEqual(2);
  });



Upvotes: 6

Related Questions