如何用 enzyme, chai 测试 HOC
How to test HOC with enzyme, chai
我有一个 HOC 函数,它接收一个 React 组件和 returns 用两个新方法属性(handleBack
和 moveitOnTop
)对组件做出反应,如下所示:
import React, { Component } from "react";
import classNames from "classnames";
export default WrappedComponent => {
return class extends Component {
constructor(props) {
super(props);
this.moveitOnTop = this.moveitOnTop.bind(this);
this.handleBack = this.handleBack.bind(this);
this.state = {
isSearchActive: false
};
}
moveitOnTop(flag) {
this.setState({ isSearchActive: flag });
window.scrollTo(0, -100);
}
handleBack() {
this.setState({ isSearchActive: false });
if (document.body.classList.contains("lock-position")) {
document.body.classList.remove("lock-position");
}
}
render() {
const props = {
...this.props,
isSearchActive: this.state.isSearchActive,
moveitOnTop: this.moveitOnTop,
goBack: this.handleBack
};
const classes = classNames({ "c-ftsOnTop": this.state.isSearchActive });
return (
<div className={classes}>
<WrappedComponent {...props} />
</div>
);
}
};
};
组件:
//import fireAnalytics
import { fireAnalytics } from "@modules/js-utils/lib";
class MyComponent extender Component{
constructor(){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
// calling analytics function by passing vals
fireAnalytics({
event: "GAEvent",
category: "",
action: `Clicked on the ${e.target.id} input`,
label: "Click"
});
// I CALL THE HOC PROPERTY
this.props.moveitOnTop(true);
// I CALL THE HOC PROPERTY
this.props.handleBack();
}
render(){
return(
<div className="emailBlock">
<input type="text" onClick={handleClick} />
<Button className="submit">Submit</Button>
</div>
)
}
}
// export HOC component
export default hoc(MyComponent);
// export just MyComponent
export {MyComponent};
我想测试 HOC:
- 我需要检查 class
.c-ftsOnTop
是否存在
- 我需要检查调用
this.props.handleBack
& `this.props.moveitOnTop' 的 onClick
函数
- 我需要检查 class名称
emailBlock
是否存在。
我试过但失败的测试:
import { mount, shallow } from 'enzyme';
import sinon from 'sinon';
import React from 'react';
import { expect } from 'chai';
import hoc from '....';
import {MyComponent} from '...';
import MyComponent from '....';
it('renders component', () => {
const props = {}
const HocComponent = hoc(MyComponent);
const wrapper = mount(
<HocComponent {...props} />
);
console.log('wrapper:', wrapper);
expect(wrapper.find('.c-ftsOnTop')).to.have.lengthOf(1);
expect(wrapper.hasClass('c-fts-input-container')).toEqual(true);
})
错误
AssertionError: expected {} to have a length of 1 but got 0
console.log: wrapper: ReactWrapper {}
任何人都可以帮助我如何渲染 HOC 吗?
这是一个工作测试:
import { mount } from 'enzyme';
import React from 'react';
import WrappedMyComponent from './MyComponent';
it('renders component', () => {
const props = {}
const moveitOnTopSpy = jest.spyOn(WrappedMyComponent.prototype, 'moveitOnTop');
const handleBackSpy = jest.spyOn(WrappedMyComponent.prototype, 'handleBack');
const wrapper = mount(
<WrappedMyComponent {...props} />
);
// 1. I need to check that class .c-ftsOnTop exists
wrapper.setState({ isSearchActive: true }); // <= set isSearchActive to true so .c-ftsOnTop is added
expect(wrapper.find('.c-ftsOnTop')).toHaveLength(1); // Success!
// 2. I need to check onClick function that calls this.props.handleBack & `this.props.moveitOnTop'
window.scrollTo = jest.fn(); // mock window.scrollTo
wrapper.find('input').props().onClick();
expect(moveitOnTopSpy).toHaveBeenCalled(); // Success!
expect(window.scrollTo).toHaveBeenCalledWith(0, -100); // Success!
expect(handleBackSpy).toHaveBeenCalled(); // Success!
// 3. I need to check if className emailBlock exists
expect(wrapper.find('.emailBlock')).toHaveLength(1); // Success!
})
详情
.c-ftsOnTop
仅在 isSearchActive
为 true
时添加,因此只需设置组件的状态即可添加 class。
如果您在 moveitOnTop
和 handleBack
的原型方法上创建间谍,那么当 hoc
通过将它们绑定到 this
构造函数,实例方法将绑定到你的间谍。
window.scrollTo
在 jsdom
中默认将错误记录到控制台,因此您可以模拟它以避免该错误消息并验证它是否使用预期参数调用。
注意上面的测试需要在MyComponent
中修复以下错别字:
extender
应该是 extends
constructor
应该采用 props
参数
onClick
应该绑定到 this.handleClick
而不是 handleClick
handleClick
应该调用 this.props.goBack()
而不是 this.props.handleBack()
(我猜 MyComponent
只是作为实际组件的示例放在一起)
我有一个 HOC 函数,它接收一个 React 组件和 returns 用两个新方法属性(handleBack
和 moveitOnTop
)对组件做出反应,如下所示:
import React, { Component } from "react";
import classNames from "classnames";
export default WrappedComponent => {
return class extends Component {
constructor(props) {
super(props);
this.moveitOnTop = this.moveitOnTop.bind(this);
this.handleBack = this.handleBack.bind(this);
this.state = {
isSearchActive: false
};
}
moveitOnTop(flag) {
this.setState({ isSearchActive: flag });
window.scrollTo(0, -100);
}
handleBack() {
this.setState({ isSearchActive: false });
if (document.body.classList.contains("lock-position")) {
document.body.classList.remove("lock-position");
}
}
render() {
const props = {
...this.props,
isSearchActive: this.state.isSearchActive,
moveitOnTop: this.moveitOnTop,
goBack: this.handleBack
};
const classes = classNames({ "c-ftsOnTop": this.state.isSearchActive });
return (
<div className={classes}>
<WrappedComponent {...props} />
</div>
);
}
};
};
组件:
//import fireAnalytics
import { fireAnalytics } from "@modules/js-utils/lib";
class MyComponent extender Component{
constructor(){
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
// calling analytics function by passing vals
fireAnalytics({
event: "GAEvent",
category: "",
action: `Clicked on the ${e.target.id} input`,
label: "Click"
});
// I CALL THE HOC PROPERTY
this.props.moveitOnTop(true);
// I CALL THE HOC PROPERTY
this.props.handleBack();
}
render(){
return(
<div className="emailBlock">
<input type="text" onClick={handleClick} />
<Button className="submit">Submit</Button>
</div>
)
}
}
// export HOC component
export default hoc(MyComponent);
// export just MyComponent
export {MyComponent};
我想测试 HOC:
- 我需要检查 class
.c-ftsOnTop
是否存在 - 我需要检查调用
this.props.handleBack
& `this.props.moveitOnTop' 的 - 我需要检查 class名称
emailBlock
是否存在。
onClick
函数
我试过但失败的测试:
import { mount, shallow } from 'enzyme';
import sinon from 'sinon';
import React from 'react';
import { expect } from 'chai';
import hoc from '....';
import {MyComponent} from '...';
import MyComponent from '....';
it('renders component', () => {
const props = {}
const HocComponent = hoc(MyComponent);
const wrapper = mount(
<HocComponent {...props} />
);
console.log('wrapper:', wrapper);
expect(wrapper.find('.c-ftsOnTop')).to.have.lengthOf(1);
expect(wrapper.hasClass('c-fts-input-container')).toEqual(true);
})
错误
AssertionError: expected {} to have a length of 1 but got 0
console.log: wrapper: ReactWrapper {}
任何人都可以帮助我如何渲染 HOC 吗?
这是一个工作测试:
import { mount } from 'enzyme';
import React from 'react';
import WrappedMyComponent from './MyComponent';
it('renders component', () => {
const props = {}
const moveitOnTopSpy = jest.spyOn(WrappedMyComponent.prototype, 'moveitOnTop');
const handleBackSpy = jest.spyOn(WrappedMyComponent.prototype, 'handleBack');
const wrapper = mount(
<WrappedMyComponent {...props} />
);
// 1. I need to check that class .c-ftsOnTop exists
wrapper.setState({ isSearchActive: true }); // <= set isSearchActive to true so .c-ftsOnTop is added
expect(wrapper.find('.c-ftsOnTop')).toHaveLength(1); // Success!
// 2. I need to check onClick function that calls this.props.handleBack & `this.props.moveitOnTop'
window.scrollTo = jest.fn(); // mock window.scrollTo
wrapper.find('input').props().onClick();
expect(moveitOnTopSpy).toHaveBeenCalled(); // Success!
expect(window.scrollTo).toHaveBeenCalledWith(0, -100); // Success!
expect(handleBackSpy).toHaveBeenCalled(); // Success!
// 3. I need to check if className emailBlock exists
expect(wrapper.find('.emailBlock')).toHaveLength(1); // Success!
})
详情
.c-ftsOnTop
仅在 isSearchActive
为 true
时添加,因此只需设置组件的状态即可添加 class。
如果您在 moveitOnTop
和 handleBack
的原型方法上创建间谍,那么当 hoc
通过将它们绑定到 this
构造函数,实例方法将绑定到你的间谍。
window.scrollTo
在 jsdom
中默认将错误记录到控制台,因此您可以模拟它以避免该错误消息并验证它是否使用预期参数调用。
注意上面的测试需要在MyComponent
中修复以下错别字:
extender
应该是extends
constructor
应该采用props
参数onClick
应该绑定到this.handleClick
而不是handleClick
handleClick
应该调用this.props.goBack()
而不是this.props.handleBack()
(我猜 MyComponent
只是作为实际组件的示例放在一起)