Carson Wood
Carson Wood

Reputation: 1314

How to test a Vuex module action is called in Vue component mounted function?

I have a Vue component like this...

<template>
  <div class="mapdiv"></div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { mapViewModule } from "@/store/modules/MapViewModule";

@Component
export default class GeospatialMap extends Vue {
  async mounted(): Promise<void> {
    mapViewModule.initializeMapView(this.$el as HTMLDivElement);
  }
}
</script>

<style scoped>
.mapdiv {
  height: 700px;
  width: 1000px;
}
</style>

...and I am trying to test that the mapViewModule.initalizeMapView function gets called, which is an action in my Vuex module.

I am using Jest and have looked to other answers such as: https://stackoverflow.com/a/66987942/2052752 but have had no luck....

import { shallowMount, createLocalVue } from "@vue/test-utils";
import Vuex from "vuex";
import GeospatialMap from "@/components/Geospatial.vue";

describe("GeospatialMap - ", () => {
  const localVue = createLocalVue();
  localVue.use(Vuex);
  const modules = {
    mapViewModule: {
      state: {},
      actions: {
        initializeMapView: jest.fn()
      },
      namespaced: true
    }
  };
  const store = new Vuex.Store({ modules });

  shallowMount(GeospatialMap, { localVue, store });

  it("when component created, initializes the map view", async () => {
    expect(modules.mapViewModule.actions.initializeMapView).toHaveBeenCalled();
  });
});

Simply put...the jest.fn says its not called in the console..

expect(jest.fn()).toHaveBeenCalled()

    Expected number of calls: >= 1
    Received number of calls:    0

I'm not sure where it is going wrong. Am I not mocking the module action right?

I just want to test that the Vuex action gets called when this component is initialized.

Upvotes: 0

Views: 1840

Answers (1)

Eduardo
Eduardo

Reputation: 1321

Yep, you are not mocking the store right. And I also would like to say, that you are using the store in a little strange way but it is up to you.

I made some changes to component to make the decision of your problem as clear as possible.

<template>
  <div class="mapdiv">
    I am
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import { mapViewModule } from '@/helpers/someModule' // there you put your path to the module

@Component
export default class GeospatialMap extends Vue {
  mounted (): void {
    mapViewModule.initializeMapView(this.$el as HTMLDivElement)
  }
}
</script>

<style scoped>
.mapdiv {
  height: 700px;
  width: 1000px;
}
</style>

When your are calling mapViewModule.initializeMapView in mount hook you are just using simple js-function so I tried to mock that call by creating __mock__ folder in @/helpers/ with someModule.ts file in it with the code below:

// @/helpers/__mock__/someModule.ts
export const mapViewModule = {
  initializeMapView: jest.fn((el: HTMLDivElement) => console.log('I am MOCK!!!', el))
}

Then in spec-file we must tell Jest to use our mock-file instead of real file like that:

import { shallowMount, Wrapper } from '@vue/test-utils'
import GeospatiaMap from '@/components/GeospatiaMap/GeospatiaMap.vue'
import { mapViewModule } from '@/helpers/someModule'

jest.mock('../../helpers/someModule.ts') // there you put your path to module you want to mock
let wrapper: Wrapper<GeospatiaMap & { [key: string]: any }>

describe('GeospatiaMap.vue', () => {
  test('initializeMapView was called', () => {
    wrapper = shallowMount(GeospatiaMap) // wrapper property is useless now but you can use it your future tests
    expect(mapViewModule.initializeMapView).toBeCalled()
  })
})

That's it. Hope that'd help.

Upvotes: 1

Related Questions