10

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

3 Answers 3

18

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)
})
Sign up to request clarification or add additional context in comments.

3 Comments

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 stackoverflow.com/questions/57907756/…, also here stackoverflow.com/questions/60541806/…
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. stackoverflow.com/questions/51536537/…. A lot of this stuff, I don't understand but at least I know what to do, to get my codes working.
Yes, adding parenthesis seemed to fix the issue.
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();
});

Comments

0

Bit late to the party, but for vue-test-utils v1 (for Vue 2) you can do this:

config.stubs['custom-button'] = {
  template: '<button @click="$listeners.click"><slot /></button>',
}

Comments

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.