IconSwitch组件的开发与测试
IconSwitch组件
使用了ant-design-vue中的a-tooltip和a-button组件。
<template>
<div class="icon-switch">
<a-tooltip :placement="placement" :title="title">
<a-button :type="type" :shape="shape" @click="onChange">
<slot></slot>
</a-button>
</a-tooltip>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
export default defineComponent({
name: 'IconSwitch',
props: {
value: {
type: Boolean,
default: false
},
placement: {
type: String,
default: 'top'
},
title: {
type: String,
default: 'title'
},
shape: {
type: String,
default: 'circle'
}
},
emits: ['change'],
setup(props, context) {
const type = computed(() => {
return props.value ? 'primary' : '';
});
const onChange = () => {
context.emit('change', !props.value);
};
return {
type,
onChange
};
}
});
</script>
单元测试
import { mount, VueWrapper } from '@vue/test-utils';
import IconSwitch from '@/components/IconSwitch.vue';
const mockComponent = {
template: '<div><slot>B</slot></div>'
};
let wrapper: VueWrapper<any>;
const title = '我是鼠标悬浮提示';
describe('IconSwitch.vue', () => {
beforeAll(() => {
wrapper = mount(IconSwitch, {
props: {
value: true,
title
},
global: {
components: {
'a-button': mockComponent,
'a-tooltip': mockComponent
}
}
}
);
});
it('测试title', () => {
const tooltip = wrapper.findAll('.icon-switch>div')[0];
// 判断传入的title
expect(tooltip.attributes('title')).toBe(title);
});
it('测试title位置', async () => {
const tooltip = wrapper.findAll('.icon-switch>div')[0];
expect(tooltip.attributes('placement')).toBe('top');
await wrapper.setProps({
placement: 'topLeft'
});
// 判断传入的placement是否正确
expect(tooltip.attributes('placement')).toBe('topLeft');
});
it('测试value值', async () => {
// 判断传入的value值
expect(wrapper.props('value')).toBeTruthy();
});
it('测试value值 - 2', async () => {
await wrapper.setProps({
value: false
});
// 判断传入的value值
expect(wrapper.props('value')).toBeFalsy();
});
it('测试点击事件', async () => {
const item = wrapper.get('div[type=primary]');
// 触发点击事件
await item.trigger('click');
const events = wrapper.emitted('change');
// 传入属性为 value === true,取反则为false
expect(events[0]).toEqual([false]);
});
afterEach(() => {
// 测试value值 - 2 会更改props,如果不还原会导致测试点击事件失败
wrapper.setProps({
value: true
});
});
});
集成到编辑器
步骤一
由于使用了图标,需要安装@ant-design/icons-vue,命令如下
cnpm install --save @ant-design/icons-vue
步骤二
在PropsTable组件中引入要使用的IconSwitch和字体组件
import IconSwitch from '@/components/IconSwitch.vue';
import BoldOutlined from '@ant-design/icons-vue/BoldOutlined';
import ItalicOutlined from '@ant-design/icons-vue/ItalicOutlined';
import UnderlineOutlined from '@ant-design/icons-vue/UnderlineOutlined';
步骤三
组件外层循环增加一个新的类名,命名规则为“组件名-item”,如icon-switch-item
步骤四
增加如下css样式
.icon-switch-item {
display: inline-block;
margin-right: 10px;
}
步骤五
设置第一个icon-switch距离左边的位置
onMounted(() => {
const firstElement = document.getElementsByClassName('icon-switch-item')[0] as HTMLElement;
firstElement.style.paddingLeft = '28%';
});
步骤六
编写css属性与组件的映射关系
fontWeight: {
component: 'icon-switch',
subComponent: 'BoldOutlined',
text: '',
extraProps: {
title: '常规/加粗'
},
initalTransform(value: string) {
return value === 'bold';
},
afterTransform(value: boolean) {
return value ? 'bold' : 'normal';
},
options: [{value: '', text: ''}]
},
fontStyle: {
component: 'icon-switch',
subComponent: 'ItalicOutlined',
text: '',
extraProps: {
title: '常规/斜体'
},
initalTransform(value: string) {
return value === 'italic';
},
afterTransform(value: boolean) {
return value ? 'italic' : 'normal';
},
options: [{value: '', text: ''}]
},
textDecoration: {
component: 'icon-switch',
subComponent: 'UnderlineOutlined',
text: '',
extraProps: {
title: '常规/下划线'
},
initalTransform(value: string) {
return value === 'underline';
},
afterTransform(value: boolean) {
return value ? 'underline' : 'none';
},
options: [{value: '', text: ''}]
}
效果图