8

Been reading up a lot of stackoverflow and github discussions, about vue jest having trouble with button.trigger('click'). I've been struggling over this issue for a few hours today, have to say I'm quite frustrated, and surprised how a simple function such as trigger('click') can cause so much problems.

In short, my code has a b-button, which @click fires off fetchData function, from vuex. This works perfectly well in browser, but in testing mode, the fetchData does not get executed.

Vue Component Code

<template>
  <b-button id="loadButton" variant="outline-primary" @click="fetchData">Load Data</b-button>
</template>

<script>
import { mapActions } from 'vuex';
export default {
    name: "LoadAndSave",
    methods: { ...mapActions(['fetchData']) }
}
</script>

Testing Code

import { shallowMount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import { BootstrapVue } from 'bootstrap-vue'
import LoadAndSave from '../../resources/components/LoadAndSave'

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

describe('LoadAndSave.vue', () => {
  let actions
  let getters
  let store

  beforeEach(() => {
    actions = {
      fetchData: jest.fn()
    }
    store = new Vuex.Store({
      actions
    })
  })
  it('LoadAndSave: onClick executes fetchData', async () => {
    const wrapper = shallowMount(LoadAndSave, { localVue, store })
    const button = wrapper.find("#loadButton")
    await button.trigger('click')
    expect(actions.fetchData).toHaveBeenCalled()
  })
})

Result of testing

expect(jest.fn()).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls:    0

This is not my first day coding, I am no where near an expert in coding either, but just the idea of not being able to get a button click to trigger really sends chills down my spine, not to mention the frustration accompanied.

If anyone could give any suggestion that'd be appreciated, thank you.

Codey

dulerong
  • 231
  • 1
  • 3
  • 8

2 Answers2

14

I have been struggling with this as well, it seems sometimes the test component has a hard time finding the emitting/calls to functions that do not have parentheses.

it('Calls save() when pressing save button', async () => {
  const savebutton = wrapper.find('#saveButton')
  const spy = jest.spyOn(wrapper.vm, 'save')
  savebutton.trigger('click')
  await wrapper.vm.$nextTick()
  expect(spy).toHaveBeenCalled()
  jest.restoreAllMocks()
})

the above test will fail here:

<button class="btn btn-success" id="saveButton" @click="save">Save</button>

but not here:

<button class="btn btn-success" id="saveButton" @click="save()">Spara</button>

You can at-least check if this is your problem, make a reference to the store function in methods and call the function with parentheses on the element.

Another way of asserting the button-click has been fired is by looking at the emitted object.

it('Calls save() when pressing save button', () => {
  const savebutton = wrapper.find('#saveButton')
  savebutton.trigger('click')
  expect(wrapper.emitted('save')).toHaveLength(1)
})
Procrastinator
  • 2,526
  • 30
  • 27
  • 36
  • 1
    Apology for the 20 day long delay after your answer. I just figured out where I was going wrong. Notice that I was using b-button tag instead of the normal button tag? I changed b-button to normal button, and it worked. I actually saw people talking about it here on stackoverflow, url is https://stackoverflow.com/questions/57907756/testing-for-a-function-method-call-on-click-event-inside-a-functional-component, also here https://stackoverflow.com/questions/60541806/how-to-trigger-event-with-vue-test-utils-on-a-bootstrapvue-element – dulerong Aug 25 '20 at 01:54
  • 2
    Also, shallowMount vs. mount, I was using shallowMount in my code, which does not bring in bootstrap BButton. After changing to mount, my code worked and toHaveBeenCalled detected the function has been fired off. https://stackoverflow.com/questions/51536537/running-jest-with-bootstrap-vue. A lot of this stuff, I don't understand but at least I know what to do, to get my codes working. – dulerong Aug 25 '20 at 02:17
  • 2
    Yes, adding parenthesis seemed to fix the issue. – kiwicomb123 May 05 '21 at 19:21
1

I'm returning here to say that I also experienced this issue, and the solution was to use stubs options for the button when using shallowMount and lookup the button using that component. I did not need parenthesis added in the button click.

const wrapper = shallowMount(MyComponent, {
  ...
  stubs: {
    MyButton
  },
  ...
});

test('Click Button', async () => {
  // if async method
  await wrapper.findComponent(MyButton).trigger('click');
  // if sync method - both lines
  wrapper.findComponent(MyButton).trigger('click');
  await wrapper.vm.$nextTick();
  
  expect(wrapper.vm.myMethod).toHaveBeenCalled();
});
Vier
  • 23
  • 5