How to mock a react function component that takes a ref prop?

Viewed 1380

The Problem:

I am trying to use jest and React Testing Library to mock a functional component that is wrapped in React.ForwardRef(), but I keep getting this warning (which is failing my test):

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Here is the component I want to test:

const ParentComponent = () => {
  const childRef = useRef(null);

  return (
    <div data-testid="parent">
      Parent
      {/* want to mock this ChildComponent */}
      <ChildComponent ref={childRef} />
    </div>
  );
};

Here is the component I want to mock:

const ChildComponent = forwardRef((props, ref) => (
  <div ref={ref} {...props}>
    Child
  </div>
));

What I've tried:


jest.mock("../ChildComponent", () => ({
  __esModule: true,
  default: () => <div>Mock Child</div>
}));

result: Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?


jest.mock('../ChildComponent', () => {
  const { forwardRef } = jest.requireActual('react');
  return {
    __esModule: true,
    default: () => forwardRef((props, ref) => <div ref={ref} />),
  };
});

result: Objects are not valid as a React child (found: object with keys {$$typeof, render})

1 Answers

Sweet, I just had this exact same issue and your last attempt where you imported forwardRef within the mock function helped me figure this out. I had luck with this:

jest.mock('../../../client/components/visualizations/Visualizer', () => {
  const { forwardRef } = jest.requireActual('react');
  return {
    __esModule: true,
    default: forwardRef(() => <div></div>),
  };
});

So using your example from above, I believe this should work:

jest.mock('../ChildComponent', () => {
  const { forwardRef } = jest.requireActual('react');
  return {
    __esModule: true,
-   default: () => forwardRef((props, ref) => <div ref={ref} />),
+   default: forwardRef((props, ref) => <div ref={ref} />),
  };
});

Also including my own attempt below with the resulting error message in case it helps someone else find this post in the future:

jest.mock('../ChildComponent', () => ({
  __esModule: true,
  default: React.forwardRef(() => <div></div>),
}));

Resulted in error:

The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: React`
Related