vue-test-utils: Unable to detect method call when using @click attribute on child component

Vue-test-utils is unable to detect method call when using @click attribute on child component, but is able to detect it when using the @click attribute on a native HTML-element, e.g. a button. Let me demonstrate:

This works:

// Test.vue
<template>
    <form @submit.prevent>
        <button name="button" type="button" @click="click">Test</button>
    </form>
</template>

<script>
import { defineComponent } from 'vue'

export default defineComponent({
    name: 'Test',
    setup() {
        const click = () => {
            console.log('Click')
        }

        return { click }
    }
})
</script>

// Test.spec.js
import { mount } from '@vue/test-utils'
import Test from './src/components/Test.vue'

describe('Test.vue', () => {
    const wrapper = mount(Test)

    if ('detects that method was called', () => {
        const spy = spyOn(wrapper.vm, 'click')
        wrapper.find('button').trigger('click')
        expect(wrapper.vm.click).toHaveBeenCalled() // SUCCESS. Called once
    })
})

This does NOT work:

// Test.vue
<template>
    <form @submit.prevent>
        <ButtonItem @click="click" />
    </form>
</template>

<script>
import { defineComponent } from 'vue'
import ButtonItem from './src/components/ButtonItem.vue'

export default defineComponent({
    name: 'Test',
    components: { ButtonItem },
    setup() {
        const click = () => {
            console.log('Click')
        }

        return { click }
    }
})
</script>

// ButtonItem.vue
<template>
    <button type="button">Click</button>
</template>

<script>
import { defineComponent } from 'vue'

export default defineComponent({
    name: 'ButtonItem',
})
</script>

// Test.spec.js
import { mount } from '@vue/test-utils'
import Test from './src/components/Test.vue'
import ButtonItem from './src/components/ButtonItem.vue'

describe('Test.vue', () => {
    const wrapper = mount(Test)

    if ('detects that method was called', () => {
        const spy = spyOn(wrapper.vm, 'click')
        wrapper.findComponent(ButtonItem).trigger('click')
        expect(wrapper.vm.click).toHaveBeenCalled() // FAIL. Called 0 times
    })
})

This issue stumbles me. I am not sure what I do wrong. I would be grateful if someone could describe the fault and show me the solution. Thanks!


I haven't run your code to test it yet, but why won't you use a more straightforward solution?

Look out for when the component emits click.

describe('Test.vue', () => {
    const wrapper = mount(Test)

    it('when clicked on ButtonItem it should be called one time', () => {
        const button = wrapper.findComponent(ButtonItem)
        button.trigger('click')
        expect(wrapper.emitted().click).toBeTruthy()
        expect(wrapper.emitted().click.length).toBe(1)
    })
})