0

I'm trying to write a test for when my button is clicked, that the handleClick function will be called but I keep receiving false in the assertion from my test. Here's the React component:

function Profile() {

    const [name, setName] = useState({
        firstName: '',
        lastName: ''
    });
    const [names, setNames] = useState([]);

    const handleClick = (e) => {
        e.preventDefault();
        names.push(name);
    }

    return ( 
       <form >
        <input 
          type = "text"
          value = {name.firstName}
          onChange = {
            e => setName({
                ...name,
                firstName: e.target.value
            })
        }/> 
        <input 
          type = "text"
          value = {name.lastName}
          onChange = {
            e => setName({
                ...name,
                lastName: e.target.value
            })
        }/> 
        <button onClick = {handleClick} > Add Name < /button> </form>
    )
}
export default Profile

And here's the test:

it('test 1 - call handleClick spy', () => {
  const handleClick = sinon.spy();
  let wrapper = shallow(<Profile handleClick={handleClick}/>);  
  wrapper.find('button').simulate('click',{preventDefault:()=>{}});
  expect(handleClick.calledOnce).toBe(true); 
  }); 

1 Answer 1

3

The click event does not trigger the mocked handleClick method you pass in, but rather the handleClick method defined inside the component. This is why the mocked handleClick method is not called.

To determine if the handleClick method inside the component is being called, you can use indirect methods such as preventDefault to determine if the preventDefault function is being called.

E.g.

index.jsx:

import React, { useState } from 'react';

function Profile() {
  const [name, setName] = useState({
    firstName: '',
    lastName: '',
  });
  const [names, setNames] = useState([]);

  const handleClick = (e) => {
    e.preventDefault();
    names.push(name);
  };

  return (
    <form>
      <input
        type="text"
        value={name.firstName}
        onChange={(e) =>
          setName({
            ...name,
            firstName: e.target.value,
          })
        }
      />
      <input
        type="text"
        value={name.lastName}
        onChange={(e) =>
          setName({
            ...name,
            lastName: e.target.value,
          })
        }
      />
      <button onClick={handleClick}> Add Name </button>{' '}
    </form>
  );
}
export default Profile;

index.test.jsx:

import React from 'react';
import Profile from '.';
import { shallow } from 'enzyme';

describe('62202833', () => {
  it('should pass', () => {
    const wrapper = shallow(<Profile></Profile>);
    const mEvent = { preventDefault: jest.fn() };
    wrapper.find('button').simulate('click', mEvent);
    expect(mEvent.preventDefault).toBeCalledTimes(1);
  });
});

unit test result:

 PASS  stackoverflow/62202833/index.test.jsx (13.273s)
  62202833
    ✓ should pass (12ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   85.71 |      100 |      50 |      80 |                   
 index.jsx |   85.71 |      100 |      50 |      80 | 21-31             
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        15.05s
Sign up to request clarification or add additional context in comments.

3 Comments

This solution worked great and thank you. How would I have tested if I didn't have the preventDefault event?
Functional Components do not have an instance in React 16+ so you cannot get the method to test directly. One possible test strategy could be simulating a change on the two input boxes which would update the name property in state and then simulating the click event. You can then assert for the value of state.names for your wrapper.
This solution isn't working for me. I have asked a separate question stackoverflow.com/questions/66674051/… @slideshowp2 any help ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.