Search code examples
javascriptreactjsunit-testingreact-test-renderer

React / Unit Test (Jest) click method with preventDefault


So I got a little issue I am stumped with...

I have a Link component which will either go to a specific route via a to prop, if a certain condition is met. If that condition is not met, that link, when clicked, will do something else (launch a custom modal, in my case).

I have a class method which is bound to an onClick handler on my Link component

// Card.jsx

import Link from 'components/Link';

...

static props = {
  condition: PropTypes.bool
};

constructor(props) {
  this.state = {
    showModal: false
  };
}

...

goToUrlOrLaunchModal() {
  return (
    <Link
      to="www.google.com"
      onClick={this.handleClick}
    />
  );
}


... 


handleClick(e) {
  const { condition } = this.props;

  if (!condition) {
    e.preventDefault();

    this.setState({
      showModal: true
    });
  }
}

My issue is with unit testing. I have a unit test for clicking the link when condition is false

// Card.test.js

...

import renderer from 'react-test-renderer';

...

const event = {
  preventDefault: jest.fn()
};

const component = renderer.create(<Card>).getInstance();

instance.handleClick(event);
expect(event.preventDefault).toHaveBeenCalled();
expect(instance.state.showModal).toBe(true);

Where I am getting lost is testing the other side - when condition is true, I do not need to call preventDefault or perform any logic after that. I do not need anything in handleClick to fire. The only logic in handleClick is for when condition is false.

The logic to go to the route when clicking the Link component is fine, it's just the unit test for when condition is true.

I need to test that preventDefault has not been called, and that instance.state.showModal is to be true, but I am stumped. Here is what I keep thinking it has to be, but cannot get past it...

const event = {
  preventDefault: jest.fn()
};

expect(instance.handleManageClick).not.toHaveBeenCalled();
expect(event.preventDefault).not.toHaveBeenCalled();
expect(instance.state.showModal).toBe(false);

If anyone has some guidance, would be very much appreciated! Thank you!


Solution

  • I got to the answer, thanks to the help of Andrew who commented on the initial post.

    Here is what I did:

    // Card.test.js
    
    const event = {
      preventDefault: jest.fn()
    };
    
    const component = renderer.create(<Card>).getInstance();
    
    const spy = jest.spyOn(instance, 'handleManageClick');
    
    expect(spy).not.toHaveBeenCalled();
    expect(event.preventDefault).not.toHaveBeenCalled();
    expect(instance.state.showModal).toBe(false);
    

    Thanks for your help!