'Jest testing react component with react-intersection-observer

I'm trying to test a component that has a child component that includes react-intersection-observer but I always get an error

I tried to import the library but it still fails. This the initial test

    beforeEach(() => {
      testContainer = document.createElement("div");
      document.body.appendChild(testContainer);
      subject = memoize(() =>
        mount(<FilterNav {...props} />, { attachTo: testContainer })
      );
    });

    afterEach(() => {
      testContainer.remove();
    });

    context("the main filter is shown initially", () => {
      it("sets focus on the primary filter", () => {
        subject();
        const input = testContainer.querySelector(".main-input");
        expect(document.activeElement).toEqual(input);
      });

I'm getting this error -> Uncaught [ReferenceError: IntersectionObserver is not defined]

Is there a way I can mock IntersectionObserver?

Thanks



Solution 1:[1]

I actually was able to solve this issue with a mock function and include it in the window object

const observe = jest.fn();

window.IntersectionObserver = jest.fn(function() {
  this.observe = observe;
});

Solution 2:[2]

you can do something like this in mock file(i called it intersectionObserverMock.js for exmple):

const intersectionObserverMock = () => ({
     observe: () => null
})
window.IntersectionObserver = jest.fn().mockImplementation(intersectionObserverMock);

and in the test file import the file directly like this:

import '../__mocks__/intersectionObserverMock';

this will solve youre "IntersectionObserver is not defined" issue

Solution 3:[3]

Having same issue with Component that using IntersectionObserver.

Update: we need to import intersection-observer directly on test file.

import 'intersection-observer';

Solution 4:[4]

The only thing that worked for me, create a file src\__mocks__\intersectionObserverMock.js

global.IntersectionObserver = class IntersectionObserver {
  constructor() {}

  observe() {
    return null;
  }

  disconnect() {
    return null;
  };

  unobserve() {
    return null;
  }
};

In your test import file:

import './__mocks__/intersectionObserverMock'

Solution 5:[5]

Create a mock in your setupTests file:

// Mock IntersectionObserver
class IntersectionObserver {
  observe = jest.fn()
  disconnect = jest.fn()
  unobserve = jest.fn()
}

Object.defineProperty(window, 'IntersectionObserver', {
  writable: true,
  configurable: true,
  value: IntersectionObserver,
})

Object.defineProperty(global, 'IntersectionObserver', {
  writable: true,
  configurable: true,
  value: IntersectionObserver,
})

This will sort it not being defined.

Solution 6:[6]

I extended Teebu's solution to trigger a first intersecting element. My test then act as if the intersection would match.

global.IntersectionObserver = class IntersectionObserver {

  constructor(private func, private options) {}

  observe(element: HTMLElement) {
    this.func([{isIntersecting: true, target: element}]);
  }

  disconnect() {
    return null;
  };

  unobserve() {
    return null;
  }
};

Solution 7:[7]

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';

it("sets focus on the primary filter", () => {
    subject();
    mockAllIsIntersecting(true);

    const input = testContainer.querySelector(".main-input");
    expect(document.activeElement).toEqual(input);
  });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rafael Simões
Solution 2
Solution 3
Solution 4 Teebu
Solution 5 Sir.Nathan Stassen
Solution 6 David Dal Busco
Solution 7 Ben Smith