0

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:

  1. Mount component with provider having empty array.
  2. Test for "no data"
  3. Trigger state change by updating provider with populated array
  4. Test for "has data"

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?

3
  • Could you post the code of the underlying component as well? There is number of different reasons why it could be failing. Commented Feb 20 at 8:17
  • The paragraph before the code sample includes a link to a stackblitz project. This project contains a fully working example of the issue including "TheList.vue" component. For this example its a very simple component with just the inject and a v-if test. Commented Feb 20 at 20:33
  • Posting a link to an external site is not a valid question. Please include minimal reproducible example in question Commented Feb 25 at 8:08

1 Answer 1

0
  1. You need to create one wrapper per one test

  2. 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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.