Reputation: 33
I have a vue component written in Typescript where i import a vuex store that was written with vuex-module-decorators. My code works well but when i try to write a unit test using vue-test-utils and jest i'm not able to inject my store.
Here is my vue component :
mycomponent.vue
<template>
<v-autocomplete
v-model="job
:items="jobs"
outlined
dense
@change="editJob"
/>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { jobsWantedStore } from '../../utils/store-accessor'
@Component
export default class SelectJob extends Vue {
async editJob() {
try {
await jobsWantedStore.EDIT_JOB(this.job)
} catch (error) {
this.error = error
}
}
}
}
</script>
The store :
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Module, VuexModule, Action, Mutation, getModule } from 'vuex-module-decorators'
import { PrioritisedJob } from '~/models'
import JobsWantedService from '~/services/jobs-wanted-service'
@Module({
name: 'jobsWanted',
stateFactory: true,
namespaced: true,
})
export default class JobsWanted extends VuexModule {
jobsWanted: Array<PrioritisedJob> = []
// Getters
public get JobsWanted(): Array<PrioritisedJob> {
return this.jobsWanted
}
// Mutations
@Mutation
setJobs(jobsWanted: Array<PrioritisedJob>): any {
this.jobsWanted = jobsWanted
}
@Mutation
setJob(jobWanted: PrioritisedJob): any {
this.jobsWanted = this.jobsWanted.map((job) => {
if (jobWanted.id === job.id) {
return jobWanted
}
return { ...job }
})
}
@Action({ rawError: true })
public async EDIT_JOB(newJob: PrioritisedJob): Promise<any> {
try {
const job = await JobsWantedService.editJob(newJob)
this.setJob(job)
} catch (error) {
throw error.response
}
}
}
Store accessor :
/* eslint-disable import/no-mutable-exports */
import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import jobsWanted from '../store/jobsWanted'
let jobsWantedStore: jobsWanted
function initialiseStores(store: Store<any>): void {
jobsWantedStore = getModule(jobsWanted, store)
}
export { initialiseStores, jobsWantedStore }
Here is my test file :
job.spec.js
import { shallowMount, createLocalVue } from '@vue/test-utils'
import mycomponent from '@/components/mycomponent.vue'
import Vuetify from 'vuetify'
import Vuex from 'vuex'
const localVue = createLocalVue()
const vuetify = new Vuetify()
localVue.use(Vuex)
describe('SelectJob', () => {
let wrapper
let store
let actions
let model
beforeEach(() => {
actions = {
EDIT_JOB: jest.fn(),
}
store = new Vuex.Store({
modules: {
jobsWanted: {
namespaced: true,
actions,
},
},
})
wrapper = shallowMount(SelectJob, {
propsData,
localVue,
vuetify,
store,
})
})
it('should edit a job', () => {
wrapper.vm.editJob()
try {
expect(actions.EDIT_JOB).toHaveBeenCalled()
} catch (e) {
expect(e).toMatch('error')
}
})
})
It tells me that it received 0 number of calls, and it's because jobsWantedStore
is undefined
when i run my tests. Anyone knows how to inject a store properly using vuex-module-decorators ?
Upvotes: 1
Views: 1744
Reputation: 33
Turns out I forgot to inject localVue
when I declare my wrapper!
So it should be:
wrapper = shallowMount(SelectJob, {
propsData,
localVue,
vuetify,
store,
})
Upvotes: 1
Reputation: 36
I ran into the same issue. Just to clarify: component, store module and store accessor described in the question look similar to what I had. Probably we both used examples from vuex-module-decorators GitHub.
I won't include the code from the whole testing spec, because it will be the same as from Elsa, so here's only missing part. The thing that helped me was calling initialiseStores in beforeEach hook, like this:
import { initialiseStores } from '~/store';
describe('MyComponent test', () => {
...
beforeEach(() => {
initialiseStores(store) // pass your mock store
})
...
}
Upvotes: 1