I have a vue3 component which simply renders a list using an array of objects provided to it. If the array is empty it shows a "no data" message.
The component gets its data via a dependency provider.
Using vitest and test-utils I am trying to write a test which ensures the "no data" message is rendered if the provided array is empty and renders the data if the array is populated. I am trying to do this within the same test suite where the steps are:
This is the test (a working example is available on stackblitz):
import { ref } from 'vue';
import { shallowMount } from '@vue/test-utils';
import { describe, expect, it } from 'vitest';
import TheList from '../components/TheList.vue';
import { ListKey, type ListProvideType } from '../components/symbols';
const listData = ref<string[]>([]);
const listProvide: ListProvideType = {
data: listData,
};
const mountOptions = {
global: {
provide: {
[ListKey as symbol]: listProvide,
},
},
};
describe('List', () => {
const wrapper = shallowMount(TheList, mountOptions);
it('no data message rendered', () => {
expect(wrapper.text()).toContain('No Data');
});
// listData.value = ['item 1'];
it('has data messae rendered', () => {
listData.value = ['item 1'];
expect(wrapper.text()).toContain('Has Data');
});
});
The above test works for "no data" but the second test fails as the listData update does not effect the mounted component (or effects after the test?). If I perform the listData update outside the "it" statement then the first test fails as there is now data.
One work around has been to mount the component twice, once with no data and the second time with data. But this seems wrong.
So my question is - how do I test for "no data" then "has data" via dependency provider?
You need to create one wrapper per one test
You need to add https://test-utils.vuejs.org/api/#enableautounmount hook to unmount wrappers after tests
This precaution simply avoids many mistakes in tests.
Your second test should be like
it('has data messae rendered', async () => {
// Updating provider here has no effect on subsequent test.
const listProvide: ListProvideType = {
data: ref<string[]>(['item 1']),
};
const mountOptions = {
global: {
provide: {
[ListKey as symbol]: listProvide,
},
},
};
const wrapper = shallowMount(TheList, mountOptions);
expect(wrapper.text()).toContain('Has Data');
});
The problem is that provide/inject isn't reactive by default