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だよ',
});
});
});