使用16.3.1是16.3.1,酶3.3.0。
在我的React Class组件中,我创建了一个react ref,我用它来确保在安装组件时浏览器位于页面顶部。
class PageView extends React.Component {
constructor(props) {
super(props);
this.topOfPageRef = React.createRef();
}
componentDidMount() {
ReactDOM.findDOMNode(this.topOfPageRef.current).scrollIntoView();
}
render(){
const { x } = this.props;
return (
<React.Fragment>
<div className="main-wrapper" ref={this.topOfPageRef}>
Top
</div>
)}
</React.Fragment>
);
}
}
这一切都在浏览器中完美运行,但在我的酶测试中失败了。
我的测试很简单,它只是尝试渲染组件。
it('should render component correctly', () => {
const props = {
...defaultProps,
};
const wrapper = mount(<PageView {...props} />);
expect(wrapper).toMatchSnapshot();
});
TypeError: Cannot read property 'scrollIntoView' of null
我已经尝试了shallow和mount方法,虽然找到的元素不是null,但它似乎是HTMLDivElement的反应实例,它缺少scrollIntoView方法。
错误消息说明
在上面的示例代码中使用mount
会出现此错误:
TypeError: _reactDom2.default.findDOMNode(...).scrollIntoView is not a function
使用shallow
会出现上面列出的错误:
TypeError: Cannot read property 'scrollIntoView' of null
问题
shallow
不进行DOM渲染,因此永远不会有一个DOM节点可以调用scrollIntoView()
。
解
任何执行DOM操作的代码都需要使用mount
提供的完整DOM渲染进行测试。
"The default environment in Jest is a browser-like environment through jsdom"。
问题
jsdom
实现了大部分浏览器环境,但它没有实现所有功能。特别值得注意的是,自scrollIntoView
jsdom
以来,它没有实施does not do layout and would therefore not be able to provide an accurate implementation。
由于jsdom
没有实现scrollIntoView
,因此在jsdom
提供的元素上将不会定义。
解
recommended approach from this Google dev是将以下行添加到测试代码中:
Element.prototype.scrollIntoView = () => {};
该行将添加scrollIntoView
的noop实现到jsdom
提供的Element
。
对于您的测试,您可以更进一步,并将scrollIntoView
设置为spy
以确保它被调用:
it('should render component correctly', () => {
const props = {
...defaultProps,
};
Element.prototype.scrollIntoView = jest.fn(); // set scrollIntoView to a spy
const wrapper = mount(<PageView {...props} />);
expect(wrapper).toMatchSnapshot();
expect(Element.prototype.scrollIntoView).toHaveBeenCalled(); // PASSES
});
此外,安东尼奥是正确的,你不应该使用ReactDOM.findDOMNode()
,你应该能够直接使用this.topOfPageRef.current
:
componentDidMount() {
this.topOfPageRef.current.scrollIntoView();
}
您得到的错误是因为ReactDOM.findDOMNode返回null。
正如React doc所说:
当组件呈现为null或false时,findDOMNode返回null
也
在大多数情况下,您可以将引用附加到DOM节点,并完全避免使用findDOMNode。
您不应该使用React.findDOMNode
componentDidMount() {
ReactDOM.findDOMNode(this.topOfPageRef.current).scrollIntoView();
}
但:
componentDidMount() {
this.topOfPageRef.current.scrollIntoView();
}
希望它会有所帮助。