LoginSignup
97
81

More than 5 years have passed since last update.

Vue.jsでよく使うテストコード(jest/test-utils)

Last updated at Posted at 2019-05-06

Vue/Vuexのテストコードをまとめてみました。
「jest」と「@vue/test-utils」を使用しています。

環境

  • vue: ^2.6.10
  • vuex: ^3.1.0
  • jest: ^24.7.1
  • @vue/test-utils: ^1.0.0-beta.29

clickメソッドが実行されるかどうか

test.vue

button(
  @click="clickButton"
)

methods: {
  clickButton() {
    console.log('click button');
  },
},
test
describe('v-on', () => {
  test('clickでclickButtonメソッドが実行されること', () => {
    const wrapper = shallowMount(test);
    const stub = jest.fn();
    wrapper.setMethods({
      clickButton: stub,
    });
    wrapper.trigger('click');
    expect(stub).toHaveBeenCalled();
  });
});

slotにコンテンツが挿入できてること

test.vue
div
  slot
test
describe('slot', () => {
  test('slotにコンテンツが挿入できること', () => {
    const wrapper = shallowMount(test, {
      slots: {
        default: '<div data-test="slotContent">slot content</div>',
      },
    });
    const slotContent = wrapper.find('[data-test="slotContent"]');
    expect(slotContent.exists()).toBe(true);
    expect(slotContent.text()).toBe('slot content');
  });
});

propsが受け取れること

test.vue
props: {
  hoge: {
    type: String,
    default: '',
    required: true,
  },
},
test
describe('props', () => {
  test('propsを受け取れること', () => {
    const wrapper = shallowMount(test);
    wrapper.setProps({
      hoge: 'hogeだよ',
    });
    expect(wrapper.vm.$props.hoge).toBe('hogeだよ');
  });
});

propsの型が合っているかどうか

test.vue
props: {
  hoge: {
    type: String,
    default: '',
    required: true,
  },
},
test.vue
describe('props', () => {
  test('型が期待しているとおりか', () => {
    const requiredProps = {
      hoge: 'hogeだよ',
    };
    const wrapper = shallowMount(test, {
      propsData: requiredProps,
    });
    expect(typeof wrapper.vm.$props.hoge).toBe('string');
  });
});

propsがrequired:trueになっているかどうか

test.vue
props: {
  hoge: {
    type: String,
    default: '',
    required: true,
  },
},
test
describe('props', () => {
  test('requiredがtrueになっていること', () => {
    const requiredProps = {
      hoge: 'hogeだよ',
    };
    const wrapper = shallowMount(test, {
      propsData: requiredProps,
    });
    expect(wrapper.vm.$options.props.hoge.required).toBe(true);
  });
});

emitされること

test.vue
input(
  type="text"
  @input="inputText"
)

methods: {
  inputText(e) {
    this.$emit('input-text', e);
  },
},
test
describe('inputText', () => {
    test('emitされること', () => {
      const wrapper = shallowMount(test);
      wrapper.vm.inputText({ target: { value: 'valueだよ' } });
      expect(wrapper.emitted('input-text')).not.toBeUndefined();
    });
  });
});

emitで値が渡されること

test.vue
input(
  type="text"
  @input="inputText"
)

methods: {
  inputText(e) {
    this.$emit('input-text', e);
  },
},
test
describe('inputText', () => {
  test('emitで値が渡されること', () => {
    const wrapper = shallowMount(test);
    wrapper.vm.inputText({ target: { value: 'valueだよ' } });
    expect(wrapper.emitted('input-text')[0][0].target.value).toBe('valueだよ');
  });
});

stateの値をpropsに渡せているかどうか(mapState使用)

Sample.vue
<template lang="pug">
  te-sample(
    :label01="label01"
  )
</template>

<script>
import { mapState } from 'vuex';
import TeSample from '@/components/templates/TeSample';

export default {
  components: {
    TeSample,
  },
  computed: {
    ...mapState({
      label01(state) {
        return state.label01;
      },
    }),
  },
};
</script>
test
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Sample from '@/components/pages/Sample';
import TeSample from '@/components/templates/TeSample';

const localVue = createLocalVue();
localVue.use(Vuex);

const store = new Vuex.Store({
  state: {
    label01: 'valueだよ',
  },
});

describe('Sample test', () => {
  let wrapper;
  beforeEach(() => {
    wrapper = shallowMount(Sample, {
      store,
      localVue,
    });
  });
  describe('mount', () => {
    test('TeSampleにstateの値をpropsで渡せているかどうか', () => {
      expect(wrapper.find(TeSample).props().label01).toBe('valueだよ');
    });
  });
});

dispatchした値が渡されるかどうか

test.vue
<template lang="pug">
  div
    slot(
      :inputText="inputText"
    )
</template>

<script>
export default {
  props: {
    actionType: {
      type: String,
      default: '',
      required: true,
    },
  },
  methods: {
    inputText(e) {
      return this.$store.dispatch(this.actionType, {
        value: e.target.value,
      });
    },
  },
};
</script>
test
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import test from '@/components/test';

const localVue = createLocalVue();
localVue.use(Vuex);

describe('test', () => {
  let wrapper;
  const mockStore = {
    dispatch: jest.fn(),
  };
  beforeEach(() => {
    wrapper = shallowMount(test, {
      mocks: {
        $store: mockStore,
      },
      localVue,
    });
  });
  describe('mount', () => {
    test('dispatchで値が渡されること', () => {
      wrapper.setProps({
        actionType: 'actionだよ',
      });
      wrapper.vm.inputText({ target: { value: 'valueだよ' } });
      expect(mockStore.dispatch).toHaveBeenCalledWith(
        'actionだよ', {
          value: 'valueだよ',
        },
      );
    });
  });
});

actionでcommitの値を渡せているかどうか

actions.js
export const SAMPLE_ACTION = 'SAMPLE_ACTION';

const actions = {
  action01(context, payload) {
    context.commit(SAMPLE_ACTION, payload);
  },
};

export default actions;
test
import actions, { SAMPLE_ACTION } from '@/store/actions';

describe('actions test', () => {
  test('action01のcommitでデータを渡せるかどうか', () => {
    const commit = jest.fn();
    const { action01 } = actions;
    const payload = {
      value: 'valueだよ',
    };
    action01({ commit }, payload);

    expect(commit).toHaveBeenCalledWith(SAMPLE_ACTION, payload);
  });
});

mutationでStateの値が更新できてるかどうか

mutations.js
import { SAMPLE_ACTION } from './actions';

const mutations = {
  [SAMPLE_ACTION](state, inputData) {
    const data = state;
    const { value, name } = inputData;
    data[name] = value;
  },
};

export default mutations;
test
import mutations from '@/store/mutations';

describe('SAMPLE_ACTION test', () => {
  test('SAMPLE_ACTIONのactionでstateを更新する', () => {
    const inputData = {
      name: 'label01',
      value: 'valueだよ',
    };
    const state = {
      label01: '',
    };

    mutations.SAMPLE_ACTION(state, inputData);

    expect(state).toEqual({
      label01: 'valueだよ',
    });
  });
});
97
81
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
97
81