Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test useRef with the "current" prop in jest/enzyme

I hope someone can point me in the right direction to test useRef in the component below.

I have a component structured something like below. I am trying to test the functionality within the otherFunction() but I'm not sure how to mock the current property that comes off the component ref. Has anyone done something like this before?

const Component = (props) => {
    const thisComponent = useRef(null);
    const otherFunction = ({ current, previousSibling  }) => {
        if (previousSibling) return previousSibling.focus();
        if (!previousSibling && current) return current.focus();
    } 
    const handleFocus = () => {
        const {current} = thisComponent;
        otherFunction(current);
    }
     return (
        <div ref={thisComponent} onFocus={handleFocus}>Stuff In here</div>
    );
};
like image 625
Jordan Melendez Avatar asked Jun 24 '19 15:06

Jordan Melendez


Video Answer


1 Answers

Here is my test strategy for your case. I use jest.spyOn method to spy on React.useRef hook. It will let us mock the different return value of ref object for SFC.

index.tsx:

import React, { RefObject } from 'react';
import { useRef } from 'react';

export const Component = props => {
  const thisComponent: RefObject<HTMLDivElement> = useRef(null);
  const otherFunction = ({ current, previousSibling }) => {
    if (previousSibling) return previousSibling.focus();
    if (!previousSibling && current) return current.focus();
  };
  const handleFocus = () => {
    const { current } = thisComponent;
    const previousSibling = current ? current.previousSibling : null;
    otherFunction({ current, previousSibling });
  };
  return (
    <div ref={thisComponent} onFocus={handleFocus}>
      Stuff In here
    </div>
  );
};

index.spec.tsx:

import React from 'react';
import { Component } from './';
import { shallow } from 'enzyme';

describe('Component', () => {
  const focus = jest.fn();
  beforeEach(() => {
    jest.restoreAllMocks();
    jest.resetAllMocks();
  });
  test('should render correctly', () => {
    const wrapper = shallow(<Component></Component>);
    const div = wrapper.find('div');
    expect(div.text()).toBe('Stuff In here');
  });
  test('should handle click event correctly when previousSibling does not exist', () => {
    const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: { focus } });
    const wrapper = shallow(<Component></Component>);
    wrapper.find('div').simulate('focus');
    expect(useRefSpy).toBeCalledTimes(1);
    expect(focus).toBeCalledTimes(1);
  });

  test('should render and handle click event correctly when previousSibling exists', () => {
    const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: { previousSibling: { focus } } });
    const wrapper = shallow(<Component></Component>);
    wrapper.find('div').simulate('focus');
    expect(useRefSpy).toBeCalledTimes(1);
    expect(focus).toBeCalledTimes(1);
  });

  test('should render and handle click event correctly when current does not exist', () => {
    const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: null });
    const wrapper = shallow(<Component></Component>);
    wrapper.find('div').simulate('focus');
    expect(useRefSpy).toBeCalledTimes(1);
    expect(focus).not.toBeCalled();
  });
});

Unit test result with 100% coverage:

 PASS  src/stackoverflow/56739670/index.spec.tsx (6.528s)
  Component
     should render correctly (10ms)
     should handle click event correctly when previousSibling does not exist (3ms)
     should render and handle click event correctly when previousSibling exists (1ms)
     should render and handle click event correctly when current does not exist (2ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        7.689s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/56739670

like image 180
slideshowp2 Avatar answered Sep 21 '22 18:09

slideshowp2