3

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?

axel
  • 3,778
  • 4
  • 45
  • 72
  • 1
    Have you tried using `mockAllIsIntersectiong` from the `test-utils.js` https://github.com/thebuilder/react-intersection-observer#testing – Ben Smith May 08 '22 at 15:55
  • 1
    this indeed fixes it, thanks – axel May 09 '22 at 14:26
  • Thats great news. I'll add it as an answer – Ben Smith May 09 '22 at 14:56
  • If you are using nextjs or a framework with SSR, that may be your problem. Intersection observer is a browser API, and wouldn't be available during SSR. https://github.com/vercel/next.js/issues/9805 – Kevin S Nov 16 '22 at 21:03

1 Answers1

4

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()
    })
  })
axel
  • 3,778
  • 4
  • 45
  • 72
Ben Smith
  • 19,589
  • 6
  • 65
  • 93
  • 2
    Hey, it's helped me to fix my problem but I would like to know why ? cause in other tests I got the same use case and I don't need to mock insertion :/ – La pach' Aug 09 '22 at 07:33