Composition-api: Issues during testing

Created on 12 Dec 2019  路  7Comments  路  Source: vuejs/composition-api

I've noticed some things that do not work with the composition API in testing.

  1. setValue(xxx) does nothing
    resource here

  2. wrapper.vm does not include the component state for reference
    resource here

Component

<template>
  <div class="mt-4 flex px-3 py-2 text-gray-800 rounded-full bg-gray-300">
    <input
      v-model="newTitle"
      @keydown.enter="submit"
      class="mx-2 bg-gray-300"
      aria-label="New Item Title"
    />

    <button @click="submit" class aria-label="Create New Item">
      <PlusSvg classes="h-6 w-6" />
    </button>
  </div>
</template>

<script lang="ts">
import { createComponent, ref } from '@vue/composition-api';
import PlusSvg from '@/components/svg/PlusSvg.vue';

export default createComponent({
  setup(_, { emit }) {
    const newTitle = ref('');

    function submit() {
      if (!newTitle.value.trim()) return;
      emit('submit', newTitle.value.trim());
      newTitle.value = '';
    }

    return { newTitle, submit };
  },

  components: { PlusSvg }
});
</script>

Tests:

import { shallowMount } from '@vue/test-utils';
import NewItem from '@/components/NewItem.vue';

import Vue from 'vue';
import CompositionApi from '@vue/composition-api';
Vue.use(CompositionApi);

describe('NewItem', () => {
  test('is a Vue instance', () => {
    const wrapper = shallowMount(NewItem);
    expect(wrapper.isVueInstance()).toBeTruthy();
  });

  test('initializes with empty input', () => {
    const wrapper = shallowMount(NewItem);
    expect(wrapper.find('input').text()).toBe('');
  });

  test('cannot submit with empty input', () => {
    const wrapper = shallowMount(NewItem);
    wrapper.find('button').trigger('click');
    expect(wrapper.emitted().submit).toBeFalsy();
  });

  test('submit bubbles event with input', async () => {
    const wrapper = shallowMount(NewItem);
    const newTodoTitle = 'Go to the store';
    wrapper.find('input').setValue(newTodoTitle);
    wrapper.find('button').trigger('click');
    await wrapper.vm.$nextTick();
    expect(wrapper.emitted().submit[0]).toBe(newTodoTitle);
  });

  test('input is cleared after submit', async () => {
    const wrapper = shallowMount(NewItem);
    const newTodoTitle = 'Take out the trash';
    expect(wrapper.find('input').is('input')).toBeTruthy();
    wrapper.find('input').setValue(newTodoTitle);
    await wrapper.vm.$nextTick();
    expect(wrapper.find('input').text()).toBe(newTodoTitle);
    wrapper.find('button').trigger('click');
    await wrapper.vm.$nextTick();
    expect(wrapper.find('input').text()).toBe('');
  });
});

Most helpful comment

Hey,
I had similar issue and I found out that I didn't pass local vue to shallowMount.

Instead of creating new Vue instance, try to use createLocalVue from vue test utils.

import { createLocalVue, shallowMount } from '@vue/test-utils'
import CompositionApi from '@vue/composition-api';

import NewItem from '@/components/NewItem.vue';

const localVue = createLocalVue()
localVue.use(CompositionApi)

const wrapper = shallowMount(NewItem , {
  localVue
})
...

All 7 comments

Hey,
I had similar issue and I found out that I didn't pass local vue to shallowMount.

Instead of creating new Vue instance, try to use createLocalVue from vue test utils.

import { createLocalVue, shallowMount } from '@vue/test-utils'
import CompositionApi from '@vue/composition-api';

import NewItem from '@/components/NewItem.vue';

const localVue = createLocalVue()
localVue.use(CompositionApi)

const wrapper = shallowMount(NewItem , {
  localVue
})
...

EDIT: it seems to be fine:) I messed up.

I'm also experienceing an issue with .emitted()

const inputListeners = {
      input: (event) => {
        console.log(event.target.name); // this prints correct value during test
        emit('input', event.target.value, event.target.name, event);
      },
    };
wrapper.emitted().input // this is [ [''] ]

@MartinMalinda a more complete example would be helpful.

@LinusBorg my apologies! On a second try it works well. It seems like I wasn't reemitting an event correctly.

@PrzemyslawPolrolniczak I was having the same issue, but this works for me too. Thank you.

No need to use createLocalVue,

import CompositionApi from '@vue/composition-api';
import Vue from 'vue';

Vue.use(CompositionApi);

const wrapper = mount(YourComponent);

works also.

If you use jest or mocha, you can setup a setupFiles

//jest.config.js
module.exports = {
 setupFiles: [
    "<rootDir>/__tests__/setupTest.js",
  ],
}

// __tests__/setupTest.js
import Vue from 'vue';
import CompositionApi from '@vue/composition-api';

Vue.use(CompositionApi);

// test.spec.js
// tests should work as expected

I'm going to close this issue, if you're still facing issues, please reopen or create a new issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kwanjas3 picture kwanjas3  路  4Comments

SJanJan picture SJanJan  路  3Comments

swuecho picture swuecho  路  4Comments

carlmjohnson picture carlmjohnson  路  5Comments

lixpng picture lixpng  路  6Comments