当窗口事件触发时,React Component实例方法间谍永远不会被调用

时间:2017-08-23 20:38:59

标签: reactjs enzyme jest

我有一个组件触发窗口事件的组件实例方法(调整大小和滚动)。我试图窥探事件处理程序,但间谍永远不会被调用。

这是我的组件:

class PopOverContainer extends PureComponent {
  static propTypes = {
    children: PropTypes.oneOfType([
      PropTypes.arrayOf(PropTypes.node),
      PropTypes.node
    ]),
    transitionState: PropTypes.string,
    animationTiming: PropTypes.object,
    anchorEl: PropTypes.object,
    hAlign: PropTypes.oneOf(['left', 'right'])
  }

  constructor(props) {
    super(props)
    this.state = {
      mounted: false
    }
    this.setRef = this.setRef.bind(this)
    this.forceReposition = this.forceReposition.bind(this)
  }

  componentDidMount() {
    window.addEventListener('resize', this.forceReposition)
    window.addEventListener('scroll', this.forceReposition)
    // Don't normally do this! We need to do this here since our animate in
    // does not work properly if the default styles are not in the DOM before we
    // transition them
    setTimeout(() => this.setState({ mounted: true }), 0)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.forceReposition)
    window.removeEventListener('scroll', this.forceReposition)
  }

  getAnchorPosition() {
    if (!this.state.mounted) return {}
    if (!this.props.anchorEl) return {}
    const { anchorEl, hAlign } = this.props
    const popOverEl = this.popOverEl
    const rect = anchorEl.getBoundingClientRect()

    const calcHOffset = () => {
      if (hAlign === 'right') {
        return rect.left + (anchorEl.offsetWidth - popOverEl.offsetWidth)
      }
      return rect.left
    }

    const pos = {
      top: rect.top + anchorEl.offsetHeight,
      left: calcHOffset()
    }

    return pos
  }

  forceReposition() {
    this.forceUpdate()
  }

  setRef(el) {
    this.popOverEl = el
  }

  render() {
    const {
      transitionState,
      animationTiming,
      children,
      ...styledProps
    } = this.props
    return (
      <StyledPopOver
        innerRef={this.setRef}
        transitionState={transitionState}
        animationTiming={animationTiming}
        style={this.getAnchorPosition()}
        {...styledProps}
      >
        {children}
      </StyledPopOver>
    )
  }
}

这是测试:

it('should force an update on scroll', async () => {
  const wrapper = mount(
    <PopOverContainer anchorEl={anchorEl}>
      <span>Hi</span>
    </PopOverContainer>
  )
  await new Promise(resolve => setTimeout(resolve, 2))
  const instance = wrapper.instance()
  const forceRepositionSpy = jest.spyOn(instance, 'forceReposition')
  wrapper.update()
  window.dispatchEvent(new Event('resize'))
  expect(forceRepositionSpy).toHaveBeenCalled()
})

以下是我得到的测试结果:

expect(jest.fn()).toHaveBeenCalled()

Expected mock function to have been called.

我确实在组件中加入了一些奇怪的东西,因为它有一些动画需要在安装组件后的下一个刻度开始。 (注意setTimeout(() => this.setState({ mounted: true }), 0)

我不知道这与我所看到的有什么关系,但最后,我的spyOn(实例,'forceReposition')永远不会被调用,即使我已经添加了控制台日志并且可以看到事件处理程序this.forceReposition确实在实例中被调用。

0 个答案:

没有答案