javascripttypescriptjestjsvuejs3vuex4

jest mock vuex useStore() with vue 3 composition api


I'm trying to unit test a component where you click a button which should then call store.dispatch('favoritesState/deleteFavorite').

This action then calls an api and does it's thing. I don't want to test the implementation of the vuex store, just that the vuex action is called when you click the button in the component.

The Component looks like this

<template>
    <ion-item :id="favorite.key">
        <ion-thumbnail class="clickable-item remove-favorite-item" @click="removeFavorite()" slot="end" id="favorite-star-thumbnail">           
        </ion-thumbnail>
    </ion-item>
</template>

import {useStore} from "@/store";
export default defineComponent({
     setup(props) {
        const store = useStore();
    
        function removeFavorite() {
            store.dispatch("favoritesState/deleteFavorite", props.item.id);
        }

        return {
            removeFavorite,
        }
     }
});

The jest test

import {store} from "@/store";

test(`${index}) Test remove favorite for : ${mockItemObj.kind}`, async () => {

    const wrapper = mount(FavoriteItem, {
        propsData: {
            favorite: mockItemObj
        },
        global: {
            plugins: [store]
        }
    });
    const spyDispatch = jest.spyOn(store, 'dispatch').mockImplementation();

    await wrapper.find('.remove-favorite-item').trigger('click');
    expect(spyDispatch).toHaveBeenCalledTimes(1);
});

I have tried different solutions with the same outcome. Whenever the "trigger('click')" is run it throws this error:

Cannot read properties of undefined (reading 'dispatch') TypeError: Cannot read properties of undefined (reading 'dispatch')

The project is written in vue3 with typescript using composition API and vuex4


Solution

  • I found a solution to my problem. This is the solution I ended up with.

    favorite.spec.ts

    import {key} from '@/store';
    
    let storeMock: any;
    
    beforeEach(async () => {
        storeMock = createStore({});
    });
    
    test(`Should remove favorite`, async () => {
    
            const wrapper = mount(Component, {
                propsData: {
                    item: mockItemObj
                },
                global: {
                    plugins: [[storeMock, key]],
                }
            });
            const spyDispatch = jest.spyOn(storeMock, 'dispatch').mockImplementation();
    
            await wrapper.find('.remove-favorite-item').trigger('click');
            expect(spyDispatch).toHaveBeenCalledTimes(1);
            expect(spyDispatch).toHaveBeenCalledWith("favoritesState/deleteFavorite", favoriteId);
        });
    

    This is the Component method:

      setup(props) {
        const store = useStore();
       
        function removeFavorite() {
            store.dispatch("favoritesState/deleteFavorite", favoriteId);
        }
    
        return {
            removeFavorite
        }
      }