何时测试组件?
一般业务组件是不写测试的, 只有在写组件库(如: element-plus) 的时候才会写单元测试,
原因是因为业务组件可能会经常的改动, 写测试没有多大意义, 还不如直接手动测试
但是 UI 组件库中的组件一般是不会随便改动功能的
如何测试组件?
如何将组件挂载到内存中?
如何模拟用户操作事件?
测试例子
ts
import XButton from './index.vue';
import { mount } from '@vue/test-utils';
describe('XButton', () => {
it('render', () => {
const wrapper = mount(XButton);
expect(wrapper.classes()).toContain('xbtn');
expect(wrapper.classes()).toContain('default');
expect(wrapper.text()).toContain('button');
});
it('should be set text when set props text field', () => {
const text = 'clickMe';
const wrapper = mount(XButton, { props: { text } });
expect(wrapper.text()).toContain(text);
});
it('should be add color className when set props color field', () => {
const wrapper = mount(XButton, {
props: {
color: 'info',
},
});
expect(wrapper.classes()).toContain('info');
});
it('should be trigger click event', () => {
const onClick = vi.fn();
const wrapper = mount(XButton, {
props: {
onClick,
},
});
wrapper.find('button').trigger('click');
expect(onClick).toBeCalled();
});
it('should be not trigger click event when disabled is true', () => {
const onClick = vi.fn();
const wrapper = mount(XButton, {
props: {
onClick,
disabled: true,
},
});
wrapper.find('button').trigger('click');
expect(onClick).not.toBeCalled();
});
});
vue
<template>
<button :class="classes" :disabled="props.disabled" @click="handleClick">
{{ props.text }}
</button>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { buttonProps, buttonEmits, COMPONENT_NAME, useButton } from './button';
defineOptions({
name: COMPONENT_NAME,
});
const props = defineProps(buttonProps);
const emits = defineEmits(buttonEmits);
const classes = computed(() => {
let classNames = ['xbtn'];
if (props.color === 'default') {
classNames.push('default');
} else {
classNames.push(props.color);
}
return classNames;
});
/* @ts-ignore */
const { handleClick } = useButton(props, emits);
</script>
<style lang="scss" scoped>
.xbtn {
margin: 0;
border: none;
padding: 10px 20px;
display: inline-flex;
color: #f8f8f8;
&.default {
background: #c8c9cc;
color: #909399;
}
&.primary {
background-color: #409eff;
}
&.info {
background-color: #b1b3b8;
}
&.dadnger {
background-color: #f56c6c;
}
&.success {
background-color: #67c23a;
}
&.warning {
background-color: #e6a23c;
}
}
</style>
ts
import { ExtractPropTypes, SetupContext } from 'vue';
export const COMPONENT_NAME = 'XButton';
const buttonColors = ['default', 'primary', 'success', 'info', 'danger', 'warning'];
export const buttonProps = {
text: {
type: String,
default: 'button',
},
color: {
type: String,
values: buttonColors,
default: 'default',
},
disabled: Boolean,
} as const;
export const buttonEmits = {
click: (e: MouseEvent) => e instanceof MouseEvent,
};
export function useButton(props: ButtonPropsType, emit: SetupContext<ButtonEmitsType>['emit']) {
function handleClick(e: MouseEvent) {
if (props.disabled) {
return;
}
emit('click', e);
}
return {
handleClick,
};
}
// types
export type ButtonPropsType = ExtractPropTypes<typeof buttonProps>;
export type ButtonEmitsType = ExtractPropTypes<typeof buttonProps>;