I've been working in a test where I need the data from Vuex. However, I'm having some problems, I need to change that data in each test in order to test the functionality of the component. Here is my component:
<template>
<div id="cb-items-displayer" @click="textClick">
<span>(</span>
<p>{{ text }}</p>
<span>)</span>
</div>
</template>
<script lang="ts" setup>
import { capitalize } from '@/utils/capitalize'
import { ItemsDisplayer } from '@/models/ItemsDisplayer'
import { computed, PropType } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
const props = defineProps({
type: {
type: String,
default: '',
},
menuType: {
type: String,
default: '',
},
items: {
type: Array as PropType<ItemsDisplayer[]>,
default: () => [],
}
})
const emit = defineEmits<{
(event: 'textClicked'): void
}>()
const text = computed(() => {
const param = props.menuType === 'radio' ? 'One' : 'Many'
console.log( "TYPEEE ", props.type, " ", param )
const itemsIds = store.getters['filters/get' capitalize(props.type) param]
console.log("ITEMSSS", JSON.stringify(itemsIds))
return getTextToShow(itemsIds)
})
const getTextToShow = (itemsIds: string) => {
//TODO - improve it
if (itemsIds === 'all') {
return 'all'
} else if (itemsIds.length === 0) {
return '-'
} else if (itemsIds.length === 1) {
return getName(itemsIds[0], props.items)
} else {
return itemsIds.length
}
}
const textClick = () => {
emit('textClicked')
}
const getName = (id: string, items: ItemsDisplayer[]) => {
const found: ItemsDisplayer = items.find((x) => x.id! === id) as ItemsDisplayer
console.log("GETNAME ", found.name)
return found?.name
}
</script>
And this is the test:
import { render, screen, click, waitFor } from '@tests/app-test-utils'
import ItemsDisplayer from './ItemsDisplayer.vue'
import { capitalize } from '@/utils/capitalize'
let mockStoreCommit: jest.Mock
jest.mock('vuex', () => ({
...jest.requireActual('vuex'),
useStore: () => ({
getters: {
[`filters/get${capitalize('categories')}Many`]: [],
},
commit: mockStoreCommit,
}),
}))
describe('ItemsDisplayer', () => {
beforeEach(() => {
mockStoreCommit = jest.fn()
render(
ItemsDisplayer,
{},
{
props: {
type: 'categories',
menuType: 'checkbox',
items: [
{
box_templates:"",
id:"1",
name:"Culture"
},
{
box_templates:"",
id:"2",
name:"Economy"
},
{
box_templates:"",
id:"3",
name:"Education"
}
]},
}
)
})
it('renders the component', async() => {
await screen.getByText('-')
})
it('renders the component with one item', async() => {
//DON'T WORK HERE THERE SHOULD BE A CHANGE OF DATA IN THE MOCKED STORE IN ORDER TO WORK
await screen.getByText('Culture')
})
})
My problem is that I need to change the value of [filters/get${capitalize('categories')}Many
] to ["1"] in the second test.
I tried several things in order to change the mocked data but they don't work. How can I change the mocked store data in each test?
Thanks!
CodePudding user response:
You can achieve this by lazy loading your vue component:
- Add
jest.resetModules();
in thebeforeEach
to reset all of the imported modules before each test so they can be re-evaluated and re-mocked:
beforeEach(() => {
jest.resetModules();
- In each unit test, you will first need to import the vue component using the
require
syntax as follows:
const ItemsDisplayer = require('./ItemsDisplayer.vue').default;
- Then add the mock directly after the import with the
[`filters/get${capitalize('categories')}Many`]
value being set to whatever you want it to be:
jest.mock('vuex', () => ({
...jest.requireActual('vuex'),
useStore: () => ({
getters: {
[`filters/get${capitalize('categories')}Many`]: ["1"],
},
commit: mockStoreCommit,
}),
}));
- I have noticed that you do your rendering in the
beforeEach
. Unfortunately because you import and mock your modules during the test, the rendering will need to be done after these have taken place - hence you will need to either move that logic into your unit test or extract it into another function which can be called from within the unit test.
Each unit test should look something like this:
it('renders the component', async() => {
const ItemsDisplayer = require('./ItemsDisplayer.vue').default;
jest.mock('vuex', () => ({
...jest.requireActual('vuex'),
useStore: () => ({
getters: {
[`filters/get${capitalize('categories')}Many`]: ["1"],
},
commit: mockStoreCommit,
}),
}));
// beforeEach logic here or a call to a function that contains it
await screen.getByText('-')
})