jwolsborn
jwolsborn

Reputation: 716

Mocking SyntheticEvent handler for onClick

I need to write a test to simulate the click on a chevron for changing pages. The function called when onClick occurs has a synthetic event handler as a parameter and I need some way to mock this event handler (or rewrite the code with the same functionality) . I currently get the error

TypeError: Cannot read property 'preventDefault' of undefined

Edit: Everything is contained in setTimeout because the buttons won't render until several promises have been resolved

Here is the function code

handleClick(e) {
  e.preventDefault();
  if (this.state.currentPage > 0) {
    this.setState({
      currentPage: this.state.currentPage - 1
    });
  }
};

here is the code inside the render function

<Icon
  link
  href="#"
  onClick={this.handleClick}
 >
   chevron_left
 </Icon>

And finally my test code thus far

 test("Chevron left", done=>{
  Enzyme.configure({ adapter: new Adapter() });
  const wrapper = shallow(
      <App/>
  );
  expect(wrapper.exists()).toBe(true);

  setTimeout(()=>{
      wrapper.instance().state.currentPage = 1;
      wrapper.find("Icon").at(0).simulate("click");
      expect(wrapper.instance().state.currentPage).toEqual(0);
      done();
  },0)
});

Upvotes: 3

Views: 2402

Answers (1)

Matt Carlotta
Matt Carlotta

Reputation: 19762

I'm pretty sure you don't need e.preventDefault() in the handleClick method (in this case). You can remove it and be fine.

However, in case you run into this issue where it's required (like form submissions or where you find that the page auto refreshes or you want to prevent a default action event), then just add a mocked preventDefault in the simulated click event:

wrapper.find("Icon").at(0).simulate("click", { preventDefault: () => null });

To ensure proper state changes, change your handleClick method to one of the below (since setState is asynchronous, utilizing its callback ensures values are accurate upon comparison):

Option 1 -- handleClick method:

handleClick() {
  this.setState(prevState => {
     const nextPage =  prevState.currentPage - 1; // subtract 1 from current page

     return nextPage > 0 // if next page is greater than 0
       ? { currentPage: nextPage } // subtract 1
       : { null } // else do nothing

  })
}

Option 2 -- handleClick method:

handleClick() {
  this.setState(prevState => ({
     currentPage: prevState.currentPage > 0 ? prevState.currentPage - 1 : 0 // if current page is greater than 0, subtract 1, else set it 0
  }))
}

Upvotes: 2

Related Questions