Reputation: 365
I'm working on a survey builder in Vue, and survey questions which the user creates are committed to Vuex so they can be retrieved later like so:
computed: {
inputs() {
return this.$store.getters.questions(this.pageNumber);
},
},
pageNumber
is a prop the component receives and inputs()
returns an array of questions. This all seems to work in terms of rendering the correct questions on screen but I'm having trouble with Jest tests.
In order to test I was hoping I could mock the store with getters like my attempt below (omitting some parts):
const localVue = createLocalVue();
localVue.use(Vuex);
beforeEach(() => {
state = {
survey: {
pages: [
// pages objects
],
},
};
getters = {
questions: () => [
{ type: 'Radio', config: { label: 'Test label', options: [{ label: 'Test option label' }] }, validation: [] },
],
};
store = new Vuex.Store({
state,
getters,
});
});
But this results in the error:
TypeError: this.$store.getters.questions is not a function
However, removing that arrow function from getters.questions gives me:
[vuex] getters should be function but "getters.questions" is [{"type":"Radio","config":{"label":"Test label","options":[{"label":"Test option label"}]},"validation":[]}].
So I think I could be completely misunderstanding. Could someone point me in the right direction?
Upvotes: 7
Views: 17246
Reputation: 878
In my case, I created a new module but I forgot to register it in the index.js
file.
New file in src/store/modules: entities.js
Then in the index.js
file:
import entities from "./modules/entities";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
...
entities,
},
});
Upvotes: 0
Reputation: 21
Write the questions method in getters like this:
getters = {
questions: (state) => (page_number)=>{ [
{ type: 'Radio', config: { label: 'Test
label',
options: [{ label: 'Test option label' }]
},
validation: [] },
],
}
};
Upvotes: 0
Reputation: 7810
Under vue-test-utils and Jest you could easily mock a getter (especially deep nested module getter) if you replace your mocked store with the following:
store: new Vuex.Store({
getters: {
'top-level-module/nested-module-level-1/more-nested-module/dataItem': function () {
return 'any fake data you want'
}
}
}),
This soulution meakes you free from writing deep nested store objects mocks if you just want to test a component on a mocked getter (say you obtain value from the nested store module in your component's computed). Just return the fake (!) object of your preference from the mock getter.
Note you do not need to mock store state if you do not test it.
As well do not test the getter's returned object in this test. Extract it to the separate dedicated test.
You would not even need Vuex. Just use vue-test-utils mocks as follows:
mocks: {
$store: {
getters: {
'top-level-module/nested-module-level-1/more-nested-module/dataItem': (function () {
return 'any fake data you want'
})()
}
}
},
Note that vs Approach #1 you have to make your mock getter to be an IIFE to get the value from mock as the mock does not invoke getter as Vuex does.
Upvotes: 0
Reputation: 29112
The getters of a store are just like computed properties on components, they are defined using functions but accessed as properties, without the parentheses.
Given this line:
return this.$store.getters.questions(this.pageNumber);
it would appear that your questions
getter is returning a function that accepts a pageNumber
. That isn't what you're currently defining in your test getter, you're just returning an array.
So either the invocation needs to change to use square brackets:
return this.$store.getters.questions[this.pageNumber];
or the getter needs to return a function:
getters = {
questions: () => () => [
{ type: 'Radio', config: { label: 'Test label', options: [{ label: 'Test option label' }] }, validation: [] }
]
};
If it helps to clarify, this is equivalent to:
getters = {
questions: function () {
return function () {
const questions = [
{ type: 'Radio', config: { label: 'Test label', options: [{ label: 'Test option label' }] }, validation: [] }
];
return questions;
};
}
};
Note that I'm completely ignoring the passed pageNumber
as I assume your test getter is hard-coded to return the correct array of questions.
You may wish to consult with the non-test version of this getter as I expect you'll see it returns an extra level of function.
Upvotes: 20