我写了一个React组件Button
:
import PropTypes from 'prop-types'
import Radium from 'radium'
import React from 'react'
import { Icon } from 'components'
import { COLOURS, GLOBAL_STYLES, ICONS, MEASUREMENTS } from 'app-constants'
@Radium
export default class Button extends React.Component {
static propTypes = {
children: PropTypes.string,
dark: PropTypes.bool,
icon: PropTypes.oneOf(Object.values(ICONS)).isRequired,
style: PropTypes.object,
}
render() {
const { children, dark, icon, style } = this.props
let mergedStyles = Object.assign({}, styles.base, style)
if (!children)
mergedStyles.icon.left = 0
if (dark)
mergedStyles = Object.assign(mergedStyles, styles.dark)
return (
<button
className="btn btn-secondary"
style={mergedStyles}
tabIndex={-1}>
<Icon name={icon} style={mergedStyles.icon} />
{children &&
<span style={mergedStyles.text}>{children}</span>
}
</button>
)
}
}
export const styles = {
base: {
backgroundColor: COLOURS.WHITE,
border: `1px solid ${COLOURS.BORDER_LIGHT}`,
borderRadius: GLOBAL_STYLES.BORDER_RADIUS,
cursor: 'pointer',
padding: GLOBAL_STYLES.BUTTON_PADDING,
':focus': {
outline: 'none',
},
':hover': {
boxShadow: GLOBAL_STYLES.BOX_SHADOW,
},
icon: {
fontSize: GLOBAL_STYLES.ICON_SIZE_TINY,
left: '-3px',
verticalAlign: 'middle',
},
text: {
fontSize: GLOBAL_STYLES.FONT_SIZE_TINY,
fontWeight: GLOBAL_STYLES.FONT_2_WEIGHT_MEDIUM,
marginLeft: `${MEASUREMENTS.BUTTON_PADDING.HORIZONTAL}px`,
verticalAlign: 'middle',
},
},
dark: {
backgroundColor: COLOURS.PRIMARY_3,
border: `1px solid ${COLOURS.PRIMARY_2}`,
color: COLOURS.WHITE,
':hover': {
boxShadow: GLOBAL_STYLES.BOX_SHADOW_DARK,
},
},
}
我还使用Jest和Enzyme编写了Button
的测试,当dark
道具设置为dark
时,它会验证是否应用了true
个样式:
import { ICONS } from 'app-constants'
import Button, { styles } from 'components/Button'
describe("<Button>", () => {
let props
let mountedComponent
const getComponent = () => {
if (!mountedComponent)
mountedComponent = shallow(
<Button {...props} />
)
return mountedComponent
}
beforeEach(() => {
mountedComponent = undefined
props = {
children: undefined,
dark: undefined,
icon: ICONS.VIBE,
style: undefined,
}
})
describe("when `dark` is `true`", () => {
beforeEach(() => {
props.dark = true
})
it("applies the component's `dark` styles", () => {
const componentStyles = getComponent().props().style
expect(componentStyles).toEqual(expect.objectContaining(styles.dark))
})
})
})
正如您所看到的,我通过检查styles.dark
的属性是否在呈现的Button
的{{1}}属性中来执行此操作。如果是,则表示样式已成功应用。
问题是style
和styles.dark
不匹配:
componentStyles
console.log(styles.dark)
ObjectContaining{
":hover": {
"boxShadow": "0px 0px 0px 2px rgba(0,0,0,0.2)"
},
"backgroundColor": [Object],
"border": "1px solid rgb(47, 52, 63)",
"color": [Object]
}
console.log(componentStyles)
我在这里注意到一些问题:
{
"backgroundColor": "rgb(31, 34, 40)",
"border": "1px solid rgb(47, 52, 63)",
"borderRadius": "4px",
"color": "rgb(255, 255, 255)",
"cursor": "pointer",
"padding": "3px 5px 3px 5px"
}
有来自styles.dark
库的多个Color()
[Object]
个。他们没有将color
值作为字符串输出,但rgb()
中的属性相同,从而导致不匹配。componentStyles
删除了Radium的交互式样式,例如componentStyles
和:focus
(我假设Radium在由Enzyme的:hover
函数触发的渲染过程中执行此操作)。这会导致与shallow()
不匹配,而styles.dark
没有剥离这些属性。因此,我不确定如何测试。我想不出任何替代解决方案来验证styles.dark
已被应用。我认为在测试期间对styles.dark
执行以下操作将是一个解决方案:
Color()
[Object]
进行处理,以便将rgb()
值作为字符串输出。:focus
和:hover
)这样做会导致styles.dark
等于componentStyles
的值,从而通过测试。我只是不确定该怎么做。
答案 0 :(得分:0)
describe("<Button>", () => {
let props
let mountedComponent
let defaultComponent
const getComponent = () => {
if (!mountedComponent)
mountedComponent = shallow(
<Button {...props} />
)
return mountedComponent
}
beforeEach(() => {
props = {
children: undefined,
dark: undefined,
icon: ICONS.VIBE,
style: undefined,
}
defaultComponent = getComponent()
mountedComponent = undefined
})
describe("when `dark` is `true`", () => {
beforeEach(() => {
props.dark = true
})
it("applies the component's `dark` styles", () => {
const darkStyles = getComponent().props().style
expect(defaultComponent.props().style).not.toEqual(darkStyles)
})
})
})
而不是断言渲染的组件style
道具包含styles.dark
(这是脆弱的),它只是在{{1}时检查样式是否完全改变了} prop设置为dark
。