什么是TDD开发
Test-Driven Development 测试驱动开发,简单来说就是先写测试用例代码、再编写产品需求代码, 维基百科
原型
初始化
点击左侧选择框后
需求
显示
-
左侧显示当前传入的颜色
-
右侧显示十种常用的颜色
-
右侧最后一个是透明、点击后清空
点击
-
左侧点击后弹出选择颜色框,选择完后新值将以事件形式发射出去
-
右侧选择完对应的颜色后,新值将以事件形式发射出去,并且左侧框颜色改变成当前选择的
实现思路
左侧我们可以使用 input 设置type为 color 就可以达到我们的要求,具体参考 文档。 右侧只需要定义一些默认颜色、然后进行布局就行。
注意事项
遵循组件设计原则、以属性 value 为传入值、以事件 change 发射出新的要改变的值
有了上面的思路、我们在脑海大体有以下的实现布局
<div><input></div>
<ul class="picked-color-list">
<li class="item-0" or class="transparent-back">
<div></div>
</li></ul>
用例编写
这里使用 @vue/test-utils、vue-jest 作为测试库。
在 tests/unit下新建 ColorPicker.spec.ts, 首先倒入 ColorPicker、并进行实例
import { mount, VueWrapper } from '@vue/test-utils'
import ColorPicker from '@/components/ColorPicker.vue'
const defaultColors = ['#ffffff', '#f5222d', '#fa541c', '#fadb14', '#52c41a', '#1890ff', '#722ed1', '#8c8c8c', '#000000', '']
let wrapper: VueWrapper<any>
describe("ColorPick Component", () => {
beforeAll(() => {
wrapper = mount(ColorPicker, {
props: {
value: '#ffffff'
}
})
})
})
用来检查是否显示正确
it("should render the correct interface", () => {
expect(wrapper.find('input').exists()).toBeTruthy()
const input = wrapper.get('input').element
expect(input.type).toBe('color')
expect(input.value).toBe('#ffffff')
// 测试右侧是否有颜色的列表
expect(wrapper.findAll('.picked-color-list li').length).toBe(defaultColors.length)
// 测试第一个元素的css backgroundColor属性是否相等对应的颜色
const firstItem: HTMLElement = wrapper.get('li:first-child div').element as HTMLElement
expect(fistItem.style.backgroundColor).toBe(defaultColors[0])
// 测试最后一个元素的css 是否有特殊的类名
const lastItem: HTMLElement = wrapper.get('li:last-child div').element as HTMLElement
expect(lastItem.classList.contains('transparent-back')).toBeTruthy()
})
测试对应方法可以参考 conditional-rendering
检测 input 修改后是否发送对应事件和值
it("should send the correct event when change input", async () => {
// 测试 input 修改后是否发送对应的事件和值
const color = '#ffffff'
const input = wrapper.get('input')
await input.setValue(color)
// 检查 props 是否有 change 属性
expect(wrapper.emitted()).toHaveProperty('change')
const events = wrapper.emitted('change') || []
// 检测回调值时候正确
expect(events[0]).toEqual([color])
})
测试对应方法可以参考 events
检测点击右侧列表是否发送对应的值
it('should send the correct event when clicking the color list', async () => {
const firstItem = wrapper.get('li:first-child div')
firstItem.trigger('click')
const events = wrapper.emitted('change') || []
expect(events[0]).toEqual(defaultColors[0])
})
ok、用例编写的差不多了、我们再根据用例去实现我们的代码
代码实现
<template>
<div class="color-picker">
<div class="native-color-container">
<input
type="color"
:value="value"
@input="onChange($event.target.value)"
/>
</div>
<div class="picked-color-list">
<li
v-for="(item, key) in colors"
:key="key"
:class="`item-${key}`"
@click.prevent="onChange(item)"
>
<div
:style="{ backgroundColor: item }"
class="color-item"
v-if="item.startsWith('#')"
></div>
<div v-else class="color-item transparent-back"></div>
</li>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue"
const defaultColors = ['#ffffff', '#f5222d', '#fa541c', '#fadb14', '#52c41a', '#1890ff', '#722ed1', '#8c8c8c', '#000000', '']
export default defineComponent({
props: {
value: {
type: String,
},
colors: {
type: Array as PropType<string[]>,
default: defaultColors,
},
},
emits: ["change"],
setup(props, context) {
const onChange = (v: string) => {
context.emit("change", v)
}
return {
onChange,
}
},
})
</script>
在 package.json 添加 "test:unit": "vue-cli-service test:unit" 并执行
可以看到有两个报错,不要急,根据错误提升发现第一个错误是因为 item 的 background 是用 rbg
显示的,因为我们需要转换下。
使用 rgb-hex 进行下转换、修改下用例
expect('#' + rgbHex(firstItem.style.backgroundColor)).toBe(defaultColors[0])
第二个错误是因为拼写导致错误
expect(events[0]).toEqual([defaultColors[0]])
再次运行用例
所有用例顺利通过,😄 这这是一次简单尝试,但是也得正视、大多数前端人员不重视测试的重要性(包括我自己),在今后开发组件中,应该尽量尝试这种开发模式,保证我们组件的稳定性 💪
广告
最后来波广告
分享我私藏的TS教程,从0到高阶全系列,点击链接,0元获取 链接