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

Vue3: Testing load state fails in async function inside '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 与它应该是的不同(我收到EmptyCollectionv-else 内)。这是我的测试,但它不起作用:

  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 在 ticks 中更新了 html。首先,您的组件使用默认数据安装。然后调用 onMounted 挂钩,您在其中设置 isLoading,它会更新 下一个报价 中的 DOM。您需要等待此 DOM 更改,然后您可以在测试中检查该元素的外观。

那你得等到api通话结束。这可以通过等待 flushPromises 来完成(副作用将包括 DOM 更新的 next tick