I build a custom hook and I want to build test from it and I can't figure out where to start I would like you help to explain to me few things:
1.how I catch mousedown on the test 2. how I use the useRef and assigin it to current value It will be very helpful if you could help me and show me a code because I am sit sometimes on it
below this is the custom hook and the code I implemented the custom hook in thanks in advance 😁
import { useEffect } from 'react';
function useOnClickOutside(ref, callback) {
useEffect(
() => {
const listener = (event) => {
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target)) {
return;
}
callback(event);
};
document.addEventListener('mousedown', listener);
document.addEventListener('touchstart', listener);
return () => {
document.removeEventListener('mousedown', listener);
document.removeEventListener('touchstart', listener);
};
},
[ref, callback],
);
}
export default useOnClickOutside;
and this is the component that use it:
import React, { useRef, useEffect } from 'react';
import ReactDOM from 'react-dom';
import styles from './OverlayDialog.module.css';
import useOnClickOutside from '../../CustomeHooks/useOnClickOutside/useOnClickOutside';
const OverlayDialog = (props) => {
const wrapperRef = useRef(null);
useEffect(() => {
window.addEventListener("mousedown", handleClickOutside);
return () => {
window.removeEventListener("mousedown", handleClickOutside);
};
});
const handleClickOutside = event => {
const { current: wrap } = wrapperRef;
if (wrap && !wrap.contains(event.target)) {
props.onClose(false);
}
};
useOnClickOutside( wrapperRef,()=>props.onClose(false))
return ReactDOM.createPortal(
<div className={styles.Dialog}>
<div className={styles.InnerDialog} tabIndex={1}>
<div className={styles.DialogCard} tabIndex={-1}>
<div className={props.className ? props.className : styles.DialogContent} ref={wrapperRef}>
{props.children}
</div>
</div>
</div>
</div>,
document.getElementById('OverlayDialog')
)
}
export default OverlayDialog;
I found good blog post for your case. There's information how to test onClickOutside https://webman.pro/blog/how-to-detect-and-test-click-outside-in-react/ I looked on your component and was curios how it actually works) So if you add live example of your code I'll can give you more help)
update I added test id for content in your component) component:
import React, { useRef } from "react";
import ReactDOM from "react-dom";
import styles from "./OverlayDialog.module.css";
import useOnClickOutside from "./useOnClickOutside";
const OverlayDialog = (props) => {
const wrapperRef = useRef(null);
useOnClickOutside(wrapperRef, () => props.onClose());
return ReactDOM.createPortal(
<div className={styles.Dialog}>
<div className={styles.InnerDialog} tabIndex={1}>
<div className={styles.DialogCard} tabIndex={-1}>
<div
className={props.className ? props.className : styles.DialogContent}
ref={wrapperRef}
data-testid="content"
>
{props.children}
</div>
</div>
</div>
</div>,
document.getElementById("OverlayDialog")
);
};
export default OverlayDialog;
test:
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import OverlayDialog from "./OverlayDialog";
test('renders learn react link', () => {
const onClose = jest.fn();
const modalRoot = document.createElement('div');
modalRoot.setAttribute('id', 'OverlayDialog');
const body = document.querySelector('body');
body.appendChild(modalRoot);
render(
<OverlayDialog onClose={onClose}>
content
</OverlayDialog>
);
/*checking that if we click on content nothing happens*/
expect(screen.queryByTestId('content')).toBeInTheDocument();
fireEvent(screen.queryByTestId('content'), new MouseEvent('mousedown', {
bubbles: true,
cancelable: true,
}));
expect(onClose).not.toBeCalled();
/*checking that if we click outside we'll fire onClose*/
fireEvent(body, new MouseEvent('mousedown', {
bubbles: true,
cancelable: true,
}));
expect(onClose).toBeCalled();
});