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