Jest: Received number of calls: 0

Viewed 7665

I'm writing Jest for the components to make sure that handleLogin will be executed when the button is clicked. Not sure why I keep getting error that jest.fn() is not executed once. I have removed most of unnecessary code here

class Login extends React.Component{
constructor(props){
    super(props);
    this.state = { }
    this.handleLogin = this.handleLogin.bind(this);
}

handleLogin(e){
    e.preventDefault();
    const { email, password, invalidEmail, invalidPassword } = this.state;
    if(!invalidEmail && !invalidPassword){
        userAPI.login({email, password}).then(data=>{
            window.localStorage.setItem('email',data.email);
            window.localStorage.setItem('password',data.password);
        }).catch(error=>{
            this.setState({
                incorrectCredential: true  // login failed due to wrong credential
            })
        })
    }else{
        this.setState({
            invalidCredential: true   // login failed due to wrong format
        })
    }  // login failed 
}
render(){
    return(
        <header>
            <div className="login" data-test="login">
               <button className="login_content_main_join" type="submit" onClick={this.handleLogin} data-test="submit">Log in</button>

                </div>
            </header>
        )
}
export default Login;

Here is my testing part

    it('Login/click to trigger this.handleLogin()', ()=>{
  const wrapper = shallow(<Login />);
  const instance = wrapper.instance();
  jest.spyOn(instance, 'handleLogin');
  findTestWrapper(wrapper, 'submit').simulate('click', {
    preventDefault: ()=> {}
  });
  expect(instance.handleLogin).toHaveBeenCalled();
})

I have verified that handleLogin() can be executed with simulated 'click',by adding console.log("run") to it but I keep getting error as below.

expect(jest.fn()).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls:    0

  26 |     preventDefault: ()=> {}
  27 |   });
> 28 |   expect(instance.handleLogin).toHaveBeenCalled();
     |                                ^
  29 | })
2 Answers

Just figured out the solution myself LOL. wrapper.instance() needs to be re-rendered after listening to it.

it('Login/click to trigger this.handleLogin()', ()=>{
  const wrapper = shallow(<Login />);
  jest.spyOn(wrapper.instance(), 'handleLogin');
  wrapper.instance().forceUpdate(); // add this line
  findTestWrapper(wrapper, 'submit').simulate('click', {
    preventDefault: ()=> {}
  });
  expect(wrapper.instance().handleLogin).toHaveBeenCalled();
})

Consider spying on the Component prototype and use build-in .find method on the wrapper

it("Login/click to trigger this.handleLogin()", () => {
  const wrapper = shallow(<Login />);

  const spy = jest.spyOn(Login.prototype, "handleLogin");  // spying on the Component prototype

  wrapper.find('button.login_content_main_join').simulate('click'); // use .find method on wrapper

  expect(spy).toHaveBeenCalled();
});
Related