'How to mock ref which type is MutableRefObject<HTMLElement>

Let's say we have a function as shown below:

import { MutableRefObject } from 'react';

export const test = (ref: MutableRefObject<HTMLElement>): void => {
    if (ref.current) ref.current.focus();
};

Then I want to write test case for this "test" function:

describe('test', () => {
    it('testing', () => {
        const ref = {
            current: {
                focus: jest.fn()
            }
        };
        test(ref); //show ts type issue
        expect(ref.current.focus).toHaveBeenCalled(); // this works.
    });
});

However, ref in "test" function is showing type issue:

Argument of type '{ current: { focus: jest.Mock<unknown>; }; }' is not assignable to parameter of type 'MutableRefObject<HTMLElement>'.
  Types of property 'current' are incompatible.
    Type '{ focus: Mock<unknown>; }' is missing the following properties from type 'HTMLElement': accessKey, accessKeyLabel, autocapitalize, dir, and 276 more.ts(2345)


Solution 1:[1]

It doesn't make much sense to test this function alone. I would not mock the ref.current, instead, I will test its behavior, not the implementation detail. I will test the test function with a react component, and assert the whether the element is focused or not. Instead of asserting the .focus() method is called or not.

E.g.

import { render, screen } from '@testing-library/react';
import React, { useEffect, useRef } from 'react';
import { MutableRefObject } from 'react';
import '@testing-library/jest-dom/extend-expect';

export const test = (ref: MutableRefObject<HTMLElement | null>): void => {
  if (ref.current) ref.current.focus();
};

describe('test', () => {
  it('testing', () => {
    function TestComp() {
      const ref = useRef<HTMLInputElement>(null);
      useEffect(() => {
        test(ref);
      }, []);
      return <input ref={ref} data-testid="input" />;
    }
    render(<TestComp />);
    const input = screen.getByTestId('input');
    expect(input).toHaveFocus();
  });
});

Test result:

 PASS  stackoverflow/72170421/index.test.tsx (17.4 s)
  test
    ? testing (35 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        21.693 s

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1