0

This is the component code which I am going to test. Here I used one state hook setCheck.

import React, { SyntheticEvent, useEffect, useState } from 'react';
import { Checkbox, Grid, Header } from 'semantic-ui-react';

interface IIdentityItem {
  name: string,
  comment: string,
  checked: boolean,
  handleSetCheckState: any,
  index: number
};


export default ({ name, comment, checked, handleSetCheckState, index }: IIdentityItem) => {

  const [check, setCheck] = useState(true);

  useEffect(() => {
    setCheck(checked);
  }, []);

  const onChange = (e: SyntheticEvent, data: object) => {
    setCheck(!check);
    handleSetCheckState(index, !check);
  };

  return (
    <Grid className='p-16 py-9 bg-white'>
      <Grid.Column width='eleven' textAlign='left'>
        <Header as='p' className='description'>{name}</Header>
        <Header as='p' className='comment'>{comment}</Header>
      </Grid.Column>
      <Grid.Column width='five' verticalAlign='middle'>
        <Checkbox toggle checked={check} onChange={onChange} />
      </Grid.Column>
    </Grid>
  )
}

This is the jest unit test code.

import ChainItem from './ChainItem';
import React from 'react';
import { create, act } from 'react-test-renderer';
import { BrowserRouter } from 'react-router-dom';
import { Checkbox } from 'semantic-ui-react';

const useStateSpy = jest.spyOn(React, "useState");

describe('ChainItem', () => {
  let handleSetCheckState, index;
  beforeEach(() => {
    handleSetCheckState = jest.fn();
    index = 0;
    //useStateSpy.mockReturnValueOnce([true, setCheck]);
  });
  it('should work', () => {
    let tree;
    act(() => {
      tree = create(
        <ChainItem
          handleSetCheckState={handleSetCheckState}
          index={index} />
      );
    });
    expect(tree).toMatchSnapshot();
  });
  it('functions ', () => {
    let setCheck = jest.fn();
    useStateSpy.mockImplementationOnce(function() { return [true, setCheck] });
    let tree;
    act(() => {
      tree = create(
        <ChainItem
          handleSetCheckState={handleSetCheckState}
          checked={true}
          index={index} />
      );
    });
    const items = tree.root.findAllByType(Checkbox);
    act(() => items[0].props.onChange({
      target: {
        value: false
      }
    }));
    expect(setCheck).toHaveBeenCalled();
    expect(handleSetCheckState).toHaveBeenCalledWith(
      index,
      false
    );
  });
  afterAll(() => jest.resetModules());
});

But setCheck is not getting called. What have I done wrong?

Add Unit Test for React components, but still not working with react hook testings.

  • Avoid testing implementation. [Test the behaviour instead](https://kentcdodds.com/blog/testing-implementation-details). – vighnesh153 Nov 02 '22 at 07:58
  • @vighnesh153 do you recommend to use enzyme? – Ivo Sram Nov 02 '22 at 08:13
  • [Enzyme is dead](https://stackoverflow.com/questions/72029189/does-enzyme-support-react-version-18). You should probably checkout react-testing-library. It pairs up well with Jest. – vighnesh153 Nov 02 '22 at 08:23
  • The idea behind testing a behavior would be that you shouldn't check if `setState` is called or not. Instead, you should check if it affects anything in the UI. In the above example, I think you have linked `check` with a checkbox. So, instead of mocking so many things, just grab the checkbox from the screen, perform a click event, and then see if the checkbox is still checked or not. – vighnesh153 Nov 02 '22 at 08:27
  • Here is a quick sample that you can refer: https://stackblitz.com/edit/node-2t4red?file=src%2FCheckbox.tsx,src%2FCheckbox.test.tsx – vighnesh153 Nov 02 '22 at 08:56

0 Answers0