为什么使用 React 测试库测试的 React 组件与 react-intersection-observer 有问题?

Why does a react component, tested with React Testing Library has issue with react-intersection-observer?

我写了一个使用 react 17.0.2 构建的组件,它使用 react-intersection-observer 9.1.0

  import { useInView } from 'react-intersection-observer'

  ...

  const [ref, inView] = useInView({
    threshold: 0.99,
    root: scrollRef.current,
    delay: 250,
    trackVisibility: true,
    onChange: (inView: boolean) => {
      onChildInView(index, inView)
    }
  })

检测视口内外的滑动行为。该组件工作正常。

我使用 @testing-library/react 12.1.4 和 @testing-library/jest-dom 5.16.3 编写了一些单元测试以使组件更安全。

只要我使用以下代码测试上述组件的存在或可见性

  describe('method render', () => {
    test('renders correctly', () => {
      render(
        <MyComponent
          props={...}
          data-testid="component-id"
        >
          <div />
          <div />
        </MyComponent>
      )

      const componentNode = screen.getByTestId('component-id')

      expect(componentNode).toBeInTheDocument()
      expect(componentNode).toBeVisible()
    })
  })

测试库抱怨消息错误。

    ReferenceError: IntersectionObserver is not defined

我试图通过在测试顶部编写的模拟库(如链接)的建议来修复它

  const intersectionObserverMock = () => ({
    observe: () => null
  })

  declare global {
    interface Window {
      IntersectionObserver: typeof IntersectionObserver
    }
  }

  window.IntersectionObserver = jest.fn().mockImplementation(intersectionObserverMock);

但由于

它没有工作
  TypeError: observer.unobserve is not a function

建议?遗漏了什么?

要解决此问题,我建议使用 react-intersection-observer 中的 test-utils.js 中的 mockAllIsIntersecting。此函数模拟 IntersectionObserver。

例如

import { mockAllIsIntersecting } from 'react-intersection-observer/test-utils';   

describe('method render', () => {
    test('renders correctly', () => {
      render(
        <MyComponent
          props={...}
          data-testid="component-id"
        >
          <div />
          <div />
        </MyComponent>
      )

      mockAllIsIntersecting(true)

      const componentNode = screen.getByTestId('component-id')

      expect(componentNode).toBeInTheDocument()
      expect(componentNode).toBeVisible()
    })
  })