I wrote a component built with react 17.0.2 that uses 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)
    }
  })

to detect sliding behaviours inside or outside the viewport. And the component works fine.

I wrote some unit tests to make the component safer, using @testing-library/react 12.1.4 and @testing-library/jest-dom 5.16.3.

As soon as I test just the existence or visibility of the above component with the following code

  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()
    })
  })

the testing library complains with the message error.

    ReferenceError: IntersectionObserver is not defined

I tried to fix it with this suggestion of mocking the library (as linked here) written at the top of the test

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

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

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

but it did not work due to

  TypeError: observer.unobserve is not a function

Suggestions? Missing something?

1

There are 1 answers

1
Ben Smith On BEST ANSWER

To fix this issue I'd recommend using mockAllIsIntersecting from test-utils.js in react-intersection-observer. This function mocks the IntersectionObserver.

e.g.

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()
    })
  })