先定义一些typescript类型
import React, { FC, ButtonHTMLAttributes, AnchorHTMLAttributes } from 'react'
export type ButtonSize = 'lg' | 'sm'
export type ButtonType = 'primary' | 'default' | 'danger' | 'link'
interface BaseButtonProps {
className?: string;
disabled?: boolean;
size?: ButtonSize;
btnType?: ButtonType;
children: React.ReactNode;
href?: string;
}
type NativeButtonProps = BaseButtonProps & ButtonHTMLAttributes<HTMLElement>
type AnchorButtonProps = BaseButtonProps & AnchorHTMLAttributes<HTMLElement>
export type ButtonProps = Partial<NativeButtonProps & AnchorButtonProps>
使用reacthook来写按钮逻辑代码
export const Button: FC<ButtonProps> = (props) => {
const {
btnType,
className,
disabled,
size,
children,
href,
...restProps
} = props
const classes = classNames('btn', className, {
[`btn-${btnType}`]: btnType,
[`btn-${size}`]: size,
'disabled': (btnType === 'link') && disabled
})
if (btnType === 'link' && href ) {
return (
<a
className={classes}
href={href}
{...restProps}
>
{children}
</a>
)
} else {
return (
<button
className={classes}
disabled={disabled}
{...restProps}
>
{children}
</button>
)
}
}
Button.defaultProps = {
disabled: false,
btnType: 'default'
}
export default Button;
为什么要有测试
使用react自带的jest库来测试我们的react组件。 比如我们要测试我们的button组件好不好用的时候呢,我只能手动不断的去创建不同类型的button,给他们注入不同的属性,然后用肉眼观测符不符合我的预期,是一种非常低效的做法,人终究会犯错误的,我还要看一下新增加的功能是不是会对原来的功能会不会产生影响。
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import Button, { ButtonProps } from './button'
const defaultProps = {
onClick: jest.fn()
}
const testProps: ButtonProps = {
btnType: 'primary',
size: 'lg',
className: 'klass'
}
const disabledProps: ButtonProps = {
disabled: true,
onClick: jest.fn(),
}
describe('测试按钮组件', () => {
it('应该正确渲染默认按钮类型', () => {
const wrapper = render(<Button {...defaultProps}>Nice</Button>)
const element = wrapper.getByText('Nice') as HTMLButtonElement
expect(element).toBeInTheDocument()
expect(element.tagName).toEqual('BUTTON')
expect(element).toHaveClass('btn btn-default')
expect(element.disabled).toBeFalsy()
fireEvent.click(element)
expect(defaultProps.onClick).toHaveBeenCalled()
})
it('应该正确渲染特定props的按钮样式', () => {
const wrapper = render(<Button {...testProps}>Nice</Button>)
const element = wrapper.getByText('Nice')
expect(element).toBeInTheDocument()
expect(element).toHaveClass('btn-primary btn-lg klass')
})
it('应该渲染link 当 按钮类型 btnType 等于 link 和 href 是 provided 的时候', () => {
const wrapper = render(<Button btnType='link' href="http://dummyurl">Link</Button>)
const element = wrapper.getByText('Link')
expect(element).toBeInTheDocument()
expect(element.tagName).toEqual('A')
expect(element).toHaveClass('btn btn-link')
})
it('应该渲染 disabled 按钮当 disabled is true', () => {
const wrapper = render(<Button {...disabledProps}>Nice</Button>)
const element = wrapper.getByText('Nice') as HTMLButtonElement
expect(element).toBeInTheDocument()
expect(element.disabled).toBeTruthy()
fireEvent.click(element)
expect(disabledProps.onClick).not.toHaveBeenCalled()
})
})
|