Vue3:在'onMounted'内部异步函数中测试负载状态失败



我想测试加载占位符是否显示,而来自服务器的数据正在onMounted钩子内抓取。下面是我要测试的组件:

<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;
}
})

但是我做的每件事都不成功。据我所知,我们应该先挂载组件,然后调用flushPromises,以便让Vue等待,直到onMounted内部的承诺将被解决。因此,在调用mountflushPromises之间,isLoading设置为true时应该有一个时间间隔。问题是,当我们在测试中记录'isLoading'时,它将显示true(这是正确的),但实际的HTML与它应该是不同的(我在v-else中收到EmptyCollection)。这是我的测试,但不工作:

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);
});

提前感谢。

const wrapper = mount(MyCollections, wrapperOptions);
await wrapper.vm.$nextTick();
expect(wrapper.find('[data-test="loadingCollections"]').exists()).toBe(true);
await flushPromises();
expect(wrapper.find('[data-test="loadingCollections"]').exists()).toBe(false);

你好!您需要等待,直到vue更新了html。然后你需要等到所有的承诺都完成了,然后你可以再次检查。原因是Vue以tick为单位更新html。首先,您的组件使用默认数据挂载。然后调用onMounted钩子,在其中设置isLoading,它更新下一个tick中的DOM。. 您需要等待DOM更改,然后才能在测试中检查该元素的外观。

那么你必须等到api调用结束。这可以通过等待flushPromises来完成(它的副作用将包括下一个tick)

最新更新