Skip to main content

IntersectionObserver

The @archibald/testing package provides a set of functions to work with IntersectionObserver object.

import {
mockIntersectionObserver,
resetIntersectionObserver,
triggerMockIntersection,
unmockIntersectionObserver,
intersectionMockInstance
} from '@archibald/testing';

// Mock global IntersectionObserver instance.
mockIntersectionObserver();

// Reset global IntersectionObserver instance to default one.
unmockIntersectionObserver();

// Reset internal instance, observation maps and spies.
// It preserve mocked global IntersectionObserver instance.
resetIntersectionObserver();

// Change the intersection state of an element
triggerMockIntersection(ELEMENT, true / false);

// Get IntersectionObserver instance of any observed DOM element.
intersectionMockInstance(ELEMENT);

Example

Let's have a look at the following example.

function TestComponent() {
const { setRef, isVisible } = useIsVisible({ multiple: true });

return (
<div ref={setRef} data-testid="area">
{isVisible ? 'Area visible' : 'Area not visible'}
</div>
);
}

export default TestComponent;

In this example useIsVisible hook from @archibald/client package is used to register an intersection observer. The hook is used with the option multiple set to true. This means that the intersection observe can be triggered multiple times.

A test for this component could look like following:

// Other imports

import { act, mockIntersectionObserver, render, triggerMockIntersection, unmockIntersectionObserver } from '@archibald/testing';

const areaVisibleText = 'Area visible';
const areaNotVisibleText = 'Area not visible';

describe('<TestComponent /> component', () => {
beforeAll(() => {
mockIntersectionObserver();
});

afterAll(() => {
unmockIntersectionObserver();
});

it('should render', async () => {
const component = render(<TestComponent />);

const areaEl = await component.findByTestId('area');
expect(areaEl).toHaveTextContent(areaNotVisibleText);

act(() => {
triggerMockIntersection(areaEl, true);
});

expect(areaEl).toHaveTextContent(areaVisibleText);

act(() => {
triggerMockIntersection(areaEl, false);
});

expect(areaEl).toHaveTextContent(areaNotVisibleText);
});
});

In this test following is done:

  1. mockIntersectionObserver function is registered to be called in beforeAll function to register a mocked IntersectionObserver instance before all tests start.
  2. unmockIntersectionObserver function is registered to be called in afterAll function to restore original IntersectionObserver instance after all tests are finished.
  3. In the it-block:
    1. TestComponent component is rendered.
    2. Intersection is enabled using triggerMockIntersection function.
    3. Intersection is disabled using triggerMockIntersection function.