Javascript TypeError:无法读取属性';滚动到视图';空-反应。玩笑酶

Javascript TypeError:无法读取属性';滚动到视图';空-反应。玩笑酶,javascript,reactjs,testing,jestjs,enzyme,Javascript,Reactjs,Testing,Jestjs,Enzyme,使用react 16.3.1、jest 16.3.1和酶3.3.0 在我的React类组件中,我创建了一个React引用,用于确保在安装组件时浏览器位于页面顶部 class PageView extends React.Component { constructor(props) { super(props); this.topOfPageRef = React.createRef(); } componentDidMount() { ReactDOM.f

使用react 16.3.1、jest 16.3.1和酶3.3.0

在我的React类组件中,我创建了一个React引用,用于确保在安装组件时浏览器位于页面顶部

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>
    );
  }
}
类页面视图扩展了React.Component{
建造师(道具){
超级(道具);
this.topOfPageRef=React.createRef();
}
componentDidMount(){
ReactDOM.findDOMNode(this.topOfPageRef.current).scrollIntoView();
}
render(){
const{x}=this.props;
返回(
顶部
)}
);
}
}
这一切都可以在浏览器中完美运行,但在我的酶测试中失败

我的测试很简单,它只是尝试渲染组件

  it('should render component correctly', () => {
    const props = {
      ...defaultProps,
    };
    const wrapper = mount(<PageView {...props} />);
    expect(wrapper).toMatchSnapshot();
  });
it('应该正确呈现组件',()=>{
常量道具={
…默认道具,
};
const wrapper=mount();
expect(wrapper.toMatchSnapshot();
});
TypeError:无法读取null的属性“scrollIntoView”


我尝试了shallowmount两种方法,虽然找到的元素不是null,但它似乎是HtmlLevel的react实例,缺少scrollIntoView方法。

您得到的错误是因为ReactDOM.findDOMNode返回null

正如React doc所说:

当组件呈现为null或false时,findDOMNode返回null

在大多数情况下,可以将ref附加到DOM节点,并完全避免使用findDOMNode

您不应该使用React.findDOMNode

componentDidMount() {
   ReactDOM.findDOMNode(this.topOfPageRef.current).scrollIntoView();
}
但是:


希望能有所帮助。

错误消息澄清

在上面的示例代码中使用类似的
mount
会出现以下错误:

TypeError:\u reactDom2.default.findDOMNode(…).scrollIntoView不是函数

使用
shall
会产生上面列出的错误:

TypeError:无法读取null的属性“scrollIntoView”


浅的 问题

shallow
不进行DOM渲染,因此永远不会有可调用
scrollIntoView()
的DOM节点

解决方案

任何执行DOM操作的代码都需要使用
mount
提供的完整DOM呈现进行测试


攀登

问题

jsdom
实现了大部分浏览器环境,但它并没有实现所有功能。这个问题需要特别注意的是,它没有实现
scrollIntoView
,因为
jsdom

因为
jsdom
没有实现
scrollIntoView
,它将在
jsdom
提供的元素上未定义

解决方案

方法是在测试代码中添加以下行:

Element.prototype.scrollIntoView=()=>{}

该行将把
scrollIntoView
的noop实现添加到
jsdom
-提供的
元素中

对于您的测试,您可以更进一步,将
scrollIntoView
设置为
spy
,以确保调用它:

it('应该正确呈现组件',()=>{
常量道具={
…默认道具,
};
Element.prototype.scrollIntoView=jest.fn();//将scrollIntoView设置为间谍
const wrapper=mount();
expect(wrapper.toMatchSnapshot();
expect(Element.prototype.scrollIntoView).toHaveBeenCalled();//传递
});

此外,Antonio认为您不需要使用
ReactDOM.findDOMNode()
,您应该能够直接使用
this.topOfPageRef.current

componentDidMount(){
this.topOfPageRef.current.scrollIntoView();
}
您可以在窗口中进行设置

  it('should call paginator component', () => {
      window.HTMLElement.prototype.scrollIntoView = jest.fn();
      // arrange
      // act
      // assertion
  })
  

我到处都能看到这个修复程序,但您是从中导入元素的吗?“我得到”元素未定义“我正在使用带有chai的酶。@JamesTrickey
Element
引用来自DOM的类。for
Jest
是由
jsdom
提供的类似浏览器的环境,它提供了全局范围内的
元素
类(就像浏览器一样)。感谢您的清理。我用的是酶,但不是开玩笑,所以这就是为什么全球没有酶。最后,将功能提取到“服务”中,并将其传递给组件,以便对其进行模拟。不理想,但停止了错误。干杯,伙计们!
  it('should call paginator component', () => {
      window.HTMLElement.prototype.scrollIntoView = jest.fn();
      // arrange
      // act
      // assertion
  })