React 单元测试,enzyme/mocha 测试(或模拟?)html 图片api
React unit testing, enzyme/mocha testing (or mocking?) html image api
我为我的项目创建了一个组件来帮助加载一些图像。该组件对我来说非常有用,但是在尝试进行单元测试时,我 运行 在使用 html 图片 api:
时遇到了一些困难
首先,我的组件使用 new Image();
语法加载一些图像,这里是组件
import React from 'react';
require('./progressive-image.scss');
export default class ProgressiveImage extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
const small = this.refs['small-img'];
const large = this.refs['large-img'];
const img = new Image();
img.src = this.props.smallImg;
img.onload = function() {
small.classList.add('loaded');
};
const imgLarge = new Image();
imgLarge.src = this.props.largeImg;
imgLarge.onload = function() {
imgLarge.classList.add('loaded');
};
large.appendChild(imgLarge);
}
componentDidUpdate() {
const small = this.refs['small-img'];
const large = this.refs['large-img'];
const sameImg = large.childNodes[2].src === this.props.largeImg;
// if loading same img, do nothing
if (!sameImg) {
// remove loaded
small.classList.remove('loaded');
const img = new Image();
img.src = this.props.smallImg;
img.onload = function() {
small.classList.add('loaded');
};
// remove old img
large.childNodes[2].remove();
const imgLarge = new Image();
imgLarge.src = this.props.largeImg;
imgLarge.onload = function() {
imgLarge.classList.add('loaded');
};
large.appendChild(imgLarge);
}
}
render() {
const imgStyle = { 'paddingBottom': this.props.heightRatio };
return (
<div className="progressive-placeholder" ref="large-img">
<img className="img-small" ref="small-img" />
<div style={imgStyle} ></div>
</div>
);
}
}
ProgressiveImage.displayName = 'ProgressiveImage';
ProgressiveImage.propTypes = {
bgColor: React.PropTypes.string,
heightRatio: React.PropTypes.string.isRequired,
largeImg: React.PropTypes.string.isRequired,
smallImg: React.PropTypes.string.isRequired,
};
使用酶 mount
完全渲染,我正在做这样的事情来对 componentDidMount 进行单元测试(并希望将来对 componentdidupdate)。
it('should load images on mount', () => {
const instance = mount(
<FollainProgressiveImage
bgColor={bgColor}
heightRatio={heightRatio}
largeImg={largeImg}
smallImg={smallImg}
/>
);
});
但是测试跑步者对我大喊Image is not defined
。所以我尝试了
it('should load images on mount', () => {
global.Image = spy();
const instance = mount(
<FollainProgressiveImage
bgColor={bgColor}
heightRatio={heightRatio}
largeImg={largeImg}
smallImg={smallImg}
/>
);
});
那个间谍是 sinon.spy
,但是这给了我 First argument to Node.prototype.appendChild must be a Node
的错误,但我可以在覆盖率报告中看到 componentDidMount 被击中了。
我不确定如何最好地测试这个,我应该完全模拟这个对象,还是有更好的方法来做到这一点?
仅供参考 - 我的测试环境设置如下:
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = document.defaultView;
global.navigator = {userAgent: 'node.js'};
也许这需要改变?
真的卡在这里,寻找有关如何测试此代码的任何输入。谢谢!!
Image()
构造函数是浏览器的一部分,因此不在 Node.js 中。在浏览器中调用 new Image()
相当于调用 new window.Image()
。使用 jsdom
,您已设置 global.window
来模拟浏览器的 window
。这意味着您现在可以访问 window.Image
。如果你想让它在没有 window
前缀的情况下可用,你可以将它设为全局,无需手动制作间谍或模拟。只需将其添加到您的测试设置中:
global.Image = window.Image;
按照 global-jsdom 的安装和 Mocha 说明为我解决了这个问题。
我为我的项目创建了一个组件来帮助加载一些图像。该组件对我来说非常有用,但是在尝试进行单元测试时,我 运行 在使用 html 图片 api:
时遇到了一些困难首先,我的组件使用 new Image();
语法加载一些图像,这里是组件
import React from 'react';
require('./progressive-image.scss');
export default class ProgressiveImage extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
const small = this.refs['small-img'];
const large = this.refs['large-img'];
const img = new Image();
img.src = this.props.smallImg;
img.onload = function() {
small.classList.add('loaded');
};
const imgLarge = new Image();
imgLarge.src = this.props.largeImg;
imgLarge.onload = function() {
imgLarge.classList.add('loaded');
};
large.appendChild(imgLarge);
}
componentDidUpdate() {
const small = this.refs['small-img'];
const large = this.refs['large-img'];
const sameImg = large.childNodes[2].src === this.props.largeImg;
// if loading same img, do nothing
if (!sameImg) {
// remove loaded
small.classList.remove('loaded');
const img = new Image();
img.src = this.props.smallImg;
img.onload = function() {
small.classList.add('loaded');
};
// remove old img
large.childNodes[2].remove();
const imgLarge = new Image();
imgLarge.src = this.props.largeImg;
imgLarge.onload = function() {
imgLarge.classList.add('loaded');
};
large.appendChild(imgLarge);
}
}
render() {
const imgStyle = { 'paddingBottom': this.props.heightRatio };
return (
<div className="progressive-placeholder" ref="large-img">
<img className="img-small" ref="small-img" />
<div style={imgStyle} ></div>
</div>
);
}
}
ProgressiveImage.displayName = 'ProgressiveImage';
ProgressiveImage.propTypes = {
bgColor: React.PropTypes.string,
heightRatio: React.PropTypes.string.isRequired,
largeImg: React.PropTypes.string.isRequired,
smallImg: React.PropTypes.string.isRequired,
};
使用酶 mount
完全渲染,我正在做这样的事情来对 componentDidMount 进行单元测试(并希望将来对 componentdidupdate)。
it('should load images on mount', () => {
const instance = mount(
<FollainProgressiveImage
bgColor={bgColor}
heightRatio={heightRatio}
largeImg={largeImg}
smallImg={smallImg}
/>
);
});
但是测试跑步者对我大喊Image is not defined
。所以我尝试了
it('should load images on mount', () => {
global.Image = spy();
const instance = mount(
<FollainProgressiveImage
bgColor={bgColor}
heightRatio={heightRatio}
largeImg={largeImg}
smallImg={smallImg}
/>
);
});
那个间谍是 sinon.spy
,但是这给了我 First argument to Node.prototype.appendChild must be a Node
的错误,但我可以在覆盖率报告中看到 componentDidMount 被击中了。
我不确定如何最好地测试这个,我应该完全模拟这个对象,还是有更好的方法来做到这一点?
仅供参考 - 我的测试环境设置如下:
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = document.defaultView;
global.navigator = {userAgent: 'node.js'};
也许这需要改变?
真的卡在这里,寻找有关如何测试此代码的任何输入。谢谢!!
Image()
构造函数是浏览器的一部分,因此不在 Node.js 中。在浏览器中调用 new Image()
相当于调用 new window.Image()
。使用 jsdom
,您已设置 global.window
来模拟浏览器的 window
。这意味着您现在可以访问 window.Image
。如果你想让它在没有 window
前缀的情况下可用,你可以将它设为全局,无需手动制作间谍或模拟。只需将其添加到您的测试设置中:
global.Image = window.Image;
按照 global-jsdom 的安装和 Mocha 说明为我解决了这个问题。