Search code examples
javascriptvue.jsmocha.jschaivue-test-utils

How to test if a component emits an event in Vue?


I have two components. Child component emits an 'input' event when it's value changed and parent component takes this value with v-model. I'm testing ChildComponent. I need to write a test with Vue-test-utils to verify it works.

ParentComponent.vue:

<template>
 <div>
  <child-component v-model="search"></child-component>
  <other-component></other-component>
  ...
 </div>
</template>

ChildComponent.vue:

<template>
  <input :value="value" @change="notifyChange($event.target.value)"></input>
</template>

<script lang="ts">
  import { Component, Prop, Vue } from 'vue-property-decorator'

  @Component
  export default class ChildComponent extends Vue {

    @Prop({ default: '' }) readonly value!: string

    notifyChange(value: string) {
      this.$emit('input', value)
    }

  }
</script>

child-component.spec.ts:

describe('ChildComponent', () => {
   let wrapper: any
   before(() => {
   wrapper = VueTestUtils.shallowMount(ChildComponent, {})
  })

   it(`Should emit 'input' event when value change`, () => {
    const rootWrapper = VueTestUtils.shallowMount(ParentComponent)
    wrapper.vm.value = 'Value'
    wrapper.findAll('input').at(0).trigger('change')
    assert.isTrue(!!rootWrapper.vm.search)
  })
})

I didn't write the exact same code but the logic is like this. My components work properly. 'child-component.spec.ts' doesn't work. I need to write a test for it.


Solution

  • TESTED. This is a simple way of testing an emit, if someone is looking for this. in your test describe write this.

    describe('Close Button method', () => {
      it('emits return false if button is clicked', (done) => {
        wrapper.find('button').trigger('click')
        wrapper.vm.$nextTick(() => {
          wrapper.vm.closeModal() //closeModal is my method
          expect(wrapper.emitted().input[0]).toEqual([false]) //test if it changes
          done()
        })
      })
    })
    

    my vue comp

    <div v-if="closeButton == true">
          <button
            @click="closeModal()"
          >
          ...
          </button>
    </div>
    

    my props in vue comp

     props: {
        value: {
          type: Boolean,
          default: false
        },
    

    my methods in vue comp

    methods: {
        closeModal() {
          this.$emit('input', !this.value)
        }
      }