Search code examples
reactjsjestjsenzyme

How to write jest test case for moveover and mouseleave for functional component in react?


I'm newbie for jest test cases, i wanted to write jest test case for a react component which have mouseover and mouseleave event. i'm not sure how to write the test case for those events. I've gone through one stackoverflow answer, it is very similar to my requirement How to simulate mouse over event on a div using enzyme for testing a react application? As per the stackoverflow answer it is written for class component but i need it for functional component.

Here is the code:

import React, {useState} from "react";

export const SearchMenu = () => <input />;

const Toggle = () => {
  const[dropdownShown, setDropdownShown] = useState(false);

    return (
      <div
        className="search-type"
        onMouseOver={() => setDropdownShown(true)}
        onMouseLeave={() => setDropdownShown(false)}
      >
        <h1>Hover over me to hide/unhide the input</h1>
        {dropdownShown && <SearchMenu />}
      </div>
    );
}

export default Toggle;

the test case:

import React from "react";
import { shallow } from "enzyme";
import Toggle from "./Toggle";
import Enzyme from "enzyme";
import { SearchMenu } from "./Toggle";

describe("Toggle Component", () => {
  it("check state", () => {
    const wrapper = shallow(<Toggle />);
    expect(wrapper.find(<SearchMenu />).exists).toBeTruthy();

    // Testing Initial State
    expect(wrapper.state("dropdownShown")).toBe(true);
    wrapper.simulate("mouseleave");

    // Testing state after mouseleave
    expect(wrapper.state("dropdownShown")).toBe(false);

    // Testing state after mouseover
    wrapper.simulate("mouseover");
    expect(wrapper.state("dropdownShown")).toBe(true);
  });
});

Here i'm getting error ShallowWrapper::state() can only be called on class component

Can anyone help me how to write this test case in functional component? Thanks! in advance.


Solution

  • The error message is clear.

    Functional components don’t have state, or an instance.

    useState isn’t the same as component state - React manages that; it’s not directly tied to the instance.

    So you can test what will be rendered when triggering the mouse event.

    E.g.

    Toggle.test.tsx:

    import React from 'react';
    import { shallow } from 'enzyme';
    import Toggle, { SearchMenu } from './Toggle';
    
    describe('Toggle Component', () => {
      it('check state', () => {
        const wrapper = shallow(<Toggle />);
    
        // Testing Initial State
        expect(wrapper.find(SearchMenu).exists()).toBeFalse();
    
        // Testing state after mouseover
        wrapper.simulate('mouseover');
        expect(wrapper.find(SearchMenu).exists()).toBeTrue();
    
        // Testing state after mouseleave
        wrapper.simulate('mouseleave');
        expect(wrapper.find(SearchMenu).exists()).toBeFalse();
      });
    });
    

    Test result:

     PASS  stackoverflow/75952818/Toggle.test.tsx (10.562 s)
      Toggle Component
        ✓ check state (29 ms)
    
    ------------|---------|----------|---------|---------|-------------------
    File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ------------|---------|----------|---------|---------|-------------------
    All files   |      90 |      100 |      75 |     100 |                   
     Toggle.tsx |      90 |      100 |      75 |     100 |                   
    ------------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        11.354 s
    Ran all test suites related to changed files.