我最近决定开始为我所参与的项目编写测试,并且我们有一个React组件,我在确定如何正确测试方面遇到了一些麻烦。
该组件被称为FallbackedImage
,它接受字符串或字符串数组并呈现第一个有效图像,正如您可能理解的那样,这是一个异步操作。
我想测试它是否确实如果提供了一个有效的字符串,实际上是渲染图像,但我不能只运行
it("renders img if src is valid string", () => {
const wrapper = mount(<FallbackedImage src={validLink} />)
expect(wrapper.find("img")).to.have.length(1)
})
因为图片尚未呈现,因此wrapper.find("img")
将length
0
。
我已经提出了两个“解决方案”,但它们很黑,而且我不想使用它们:
的setTimeout
这假设图像将在300毫秒内加载。如果图像加载时间较长,则测试将失败;如果花费的时间更少,那我浪费了宝贵的毫秒数。
it("renders img if src is valid string", done => {
const wrapper = mount(<FallbackedImage src={validLink} />)
window.setTimeout(() => {
expect(wrapper.find("img")).to.have.length(1)
done()
}, 300)
})
使用组件的onLoad
道具
这假设onLoad
- 功能按预期工作,这感觉不对,因为这不在此特定测试的范围内。
it("renders img if src is valid string", done => {
const onLoad = () => {
expect(wrapper.find("img")).to.have.length(1)
done()
}
const wrapper = mount(
<FallbackedImage
onLoad={onLoad}
src={validLink} />
)
})
我该如何测试?
我正在使用chai,Enzyme和Mocha,如果有帮助的话。
此外,这是FallbackedImage
- 组件,因此您可以看到我正在使用的内容:
import React, { Component, PropTypes } from "react"
import { noop } from "../../utils"
export default class FallbackedImage extends Component {
constructor(props) {
super(props)
this.componentDidMount = this.tryImage.bind(this)
this.testImg = new window.Image()
this.testImg.onerror = this.onError.bind(this)
this.testImg.onload = this.onLoad.bind(this)
this.photos = [].concat(props.src) // Make array from props.src if it's not
this.state = { index: 0 }
}
static propTypes = {
className: PropTypes.string,
onLoad: PropTypes.func,
src: PropTypes.oneOfType([
PropTypes.array,
PropTypes.string,
]),
}
static defaultProps = {
onLoad: noop,
}
onError() {
const nextIndex = this.state.index + 1
if (nextIndex <= this.photos.length) {
this.setState({ index: nextIndex }, this.tryImage)
}
}
onLoad() {
const { src } = this.testImg
this.setState({ src })
this.props.onLoad(src)
}
tryImage() {
this.testImg.src = this.photos[this.state.index]
}
shouldComponentUpdate(_nextProps, nextState) {
return !!nextState.src
}
render() {
const { src } = this.state
return src
? <img src={src} className={this.props.className} />
: null
}
}