ref from useRef is null from Jest & react-testing-library unit test

Viewed 1994

I have the following component, where I create ref on nav to close the menu on click outside of nav:

import { useState, useEffect, useRef, } from 'react';

const Header = () => {
  const [menuOpen, setMenuOpen] = useState(false);
  const navRef = useRef(null);

  const hideMenu = () => setMenuOpen(false);

  const handleClick = event => {
    if (menuOpen && !navRef.current.contains(event.target)) {
      hideMenu();
    }
  };

  useEffect(() => {
    document.addEventListener('click', handleClick);
    return () => {
      document.removeEventListener('click', handleClick);
    };
  });

  return (
    <header className="header">
      <nav className="header-nav" ref={navRef}>
        ...
      </nav>
    </header>
  );
};

export default Header;

And this is the unit test:

import React from 'react';

import '@testing-library/jest-dom';
import { cleanup, fireEvent } from '@testing-library/react';
import renderer from 'react-test-renderer';

import Header from './Header';
const { act } = renderer;

afterEach(cleanup);

describe('Header', () => {
  test('should open and close mobile menu', () => {
    const headerComponent = renderer.create(<Header />);
    const headerRoot = headerComponent.root;
    const navContainer = headerRoot.findByType('nav');

    act(() => {
      // open menu
      navContainer.children[0].props.onClick(new MouseEvent('click'));
    });
    act(() => {
      // click on document
      fireEvent(document, new MouseEvent('click'));
    });
    headerTree = headerComponent.toJSON();
    expect(headerTree).toMatchSnapshot();
  });
});

The test run results in the following error:

    TypeError: Cannot read property 'contains' of null

      26 |
      27 |   const handleClick = (event) => {
    > 28 |     if (menuOpen && !navRef.current.contains(event.target)) {
         |                                     ^
      29 |       hideMenu();
      30 |     }
      31 |   };

I have tried to mock ref.currrent but it's still null:

jest.spyOn(React, 'useRef').mockReturnValue({
  current: navContainer,
});

Please advice how I can organize the test to be able to test this

P.S. I have found this answer but it doesn't suit me as I don't wanna pass ref as a prop: https://stackoverflow.com/a/59207195/3132457

0 Answers
Related