I'd like to test that a loading placeholder is displayed, while data from the server is fetching inside onMounted hook. Here is the component I'm testing:
<template>
<section class="container mx-auto p-4">
<div
v-if="collections && Object.keys(collections).length"
class="grid grid-cols-1 tablet:grid-cols-3 gap-4"
data-test="collectionCards"
>
<div
v-for="collection in collections"
:key="collection.cardSetId"
class="relative shadow-lg rounded-sm flex flex-col justify-between"
>
<div class="flex justify-end p-4 border-b border-b-spacer">
<p class="text-spacer uppercase text-sm">4 days ago</p>
</div>
<div class="flex flex-col justify-between h-full text-left">
<div>
<div class="card-cover"></div>
<div class="text-black font-bold relative p-4">
<h3 class="text-2xl" data-test="collectionName">{{ collection.name }}</h3>
<p class="text-sm my-2">
<span data-test="collectionLength">{{ collection.length }}</span> item(s)</p>
</div>
<div class="p-4">
<base-collapse data-test="collectionDescription">{{ collection.description }}</base-collapse>
</div>
</div>
<div class="flex justify-start p-4">
<p class="text-sm">Author: <span class="font-bold">Kanstantsin Lazouski</span></p>
</div>
</div>
</div>
</div>
<div v-else-if="isLoading" data-test="loadingCollections">Loading...</div>
<div v-else class="h-screen flex" data-test="emptyCollectionWrapper">
<EmptyCollection />
</div>
</section>
</template>
/*....*/
onMounted(async () => {
isLoading.value = true;
const collectionList = await getCollectionList(userId.value as string);
try {
collections.value = collectionList;
} catch(err) {
/* TODO: add more appropriate error handling */
console.error(err);
} finally {
isLoading.value = false;
}
})
But everything I tried was not successful. As far as I understand, we should firstly mount component and then call flushPromises in order to make Vue wait until promises inside onMounted will be resolved. So, between calling mount and flushPromises there should be a timespan when isLoading is set to true. The problem is that, when we log 'isLoading' inside the test, it will display true (which is correct), but actual HTML is different from what it is supposed to be (I receive EmptyCollection inside v-else). Here is my test that's not working though:
it('renders "EmptyCollection" if "collectionList" is empty and "Loading..." while data is fetching', async () => {
(getCollectionList as jest.Mock).mockResolvedValueOnce({});
const wrapper = mount(MyCollections, wrapperOptions);
expect(wrapper.find('[data-test="loadingCollections"]').exists()).toBe(true); // received: false
await flushPromises();
expect(wrapper.find('[data-test="collectionCards"]').exists()).toBe(false);
expect(wrapper.find('[data-test="emptyCollectionWrapper"]').exists()).toBe(true);
});
Thanks in advance.
nextTick. I did work!