testing-library / react-hooks-testing-library

🐏 Simple and complete React hooks testing utilities that encourage good testing practices.
https://react-hooks-testing-library.com
MIT License
5.26k stars 233 forks source link

Testing custom hooks that needs the DOM #947

Open kaiofelipejs opened 1 year ago

kaiofelipejs commented 1 year ago

What is your question:

I have a custom hook that checks the document using querySelector to get some information (like width, height, x, y, etc...) about a component.

function search(Component) {
  const name =
    typeof Component === 'string' ? Component : Component?.displayName;

  if (!name) return null;

  const element = global.document?.querySelector(
    `[${NAME_ATTRIBUTE}="${name}"]`
  );

  if (!element) return null;

  const { top, right, bottom, left, width, height, x, y } =
    element.getBoundingClientRect();

  return {
    element,
    top,
    right,
    bottom,
    left,
    width,
    height,
    x,
    y
  };
}

function useComponentSearch(Component) {
  const [data, setData] = useState(null);
  const reload = useCallback(() => setData(search(Component)), [Component]);

  useEffect(() => {
    setData(search(Component));
  }, [Component]);

  return [data, reload];
}

I would like to test this hook using react-hooks, but this hook needs the DOM to work. So I try a test using a wrapper:

 describe('...', () => {
    const displayName = 'Component';
    const Component = () => <div data-component-name={displayName}>test</div>;
    Component.displayName = displayName;

    const Wrapper = ({ children }) => (
      <>
        <Component />
        {children}
      </>
    );

    it('...', async () => {
      const { result, waitForValueToChange } = renderHook(
        () => useDataAttributes(ComponentWithDataAttributes),
        {
          wrapper: Wrapper
        }
      );

      await waitForValueToChange(() => result.current);

      expect(result.current).toEqual([{}, expect.any(Function)]);
    });
});

But when I check the document.body.children.length the value is 0 (no elements). I check the createTestHarness and understood that is not possible to test this way, but I want to confirm this.

I will test with @testing-library/react using a dummy component but is not too good to my case.

Thanks!