Search code examples
javascriptunit-testingvue.jstestingvue-test-utils

Testing vue component that rendered many child component with v-for directive


this is my component called Musics.vue:

<template>
  <div class="flex flex-wrap mb-20 md:mb-32">
    <div
      v-for="(music, index) in musics"
      :key="index"
      class="w-full sm:w-6/12 lg:w-3/12 p-3"
    >
      <MusicCard :music="music" @play="setCurrent($event)" />
    </div>
  </div>
</template>

as you see MusicCard is in the loop. and each MusicCard emit play event to parent component. have can i write test for it? (i tried to use forEach but it failed)

this is my test:

  it("commits a mutation when 'MusicCard' component emits play event", () => {
    const components = wrapper.findAllComponents({ name: "MusicCard" });
    expect(components.exists()).toBe(true);
    
  });

thanks for your helping.


Solution

  • You probably need to decompose your test in several simple tests.

    Assuming that you mount your component with either imported mutations or mocked mutations, you should be able to do something like:

    // import { mutations } from "@/store/MyAppStore.js"
    // or:
    const mutations = {
      myMutation: jest.fn()
    }
    
    const store = new Vuex.Store({ mutations })
    
    const wrapper = mount(Musics, {
      store, localVue
    })
    
    describe("When Musics component is mounted, it:", () => {
    
      it("lists several music cards", () => 
      {
        const components = wrapper.findAllComponents({ name: "MusicCard" });
        expect(components.length).toBeGreaterThan(1);   
      })
    
      it("receive a play event from the 'MusicCard' components", () => 
      {   
        // assert event has been emitted
        expect(wrapper.emitted().myPlayEvent).toBeTruthy()
    
        // assert event count
        expect(wrapper.emitted().myPlayEvent.length).toBe(2)
    
        // assert event payload
        expect(wrapper.emitted().myPlayEvent[1]).toEqual([123])
      })
    
      it("commits a mutation when 'MusicCard' component emits play event", async () => 
      {
        wrapper.vm.$emit('myPlayEvent' /*, payload */)
        
        await wrapper.vm.$nextTick()    
    
        expect(mutations.myMutation).toHaveBeenCalled()
    
        // assert payload
        expect(mutations.myMutation).toHaveBeenCalledWith(payload)
      })
    
    })