admin管理员组

文章数量:1355051

I'm new to React and testing in general so forgive the naivety of the question. I have a React form ponent which onChance on the inputs runs a function handleChange. Tried to test it with Jest but can't make it work.

Here's the Login ponent:

class Login extends React.Component {

  constructor() {
    super();
    this.state = {username: '', password: ''}
    this.disableSubmit = this.disableSubmit.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  render() {

    return(
      <div className="login">
        <form>
          <h3 className="login__title">LOGIN</h3>
          <div className="input-group">
            <input onChange={this.handleChange} value={this.state.username} className="form-control login__input username" type="text" placeholder="user name" name={'username'} autoFocus/>
          </div>
          <div className="input-group">
            <input onChange={this.handleChange} value={this.state.password} className="form-control login__input password" type="password" placeholder="password" name={'password'}/>
          </div>
          <div>
            <button className="btn btn-primary btn-block login__button" type="submit">Login</button>
          </div>
        </form>
      </div>

    )
  }
}

export default Login;

Here's my test:

import React from 'react'
import { shallow, mount } from 'enzyme'
import { shallowToJson } from 'enzyme-to-json'


import {Login} from '../../../src/base/ponents/index'


describe('Given the Login ponent is rendered', () => {

  describe('Snapshots', () => {
    let ponent

    beforeEach(() => {
      ponent = shallow(<Login />)
    })

    it('should be as expected', () => {
      expect(shallowToJson(ponent)).toMatchSnapshot()
    })
  })

})


test('Submitting the form should call handleSubmit', () => {

  const startState = {username: ''};
  const handleChange = jest.fn();
  const login = mount(<Login />);
  const userInput = login.find('.username');

  userInput.simulate('change');

  expect(handleChange).toBeCalled();

})

The snapshot test passes fine, but in this last attempt my function test fails with:

TypeError: Cannot read property 'target' of undefined

Guess I need to pass something to the function? Bit confused!

Thanks in advance for your help.

UPDATE:

changed the test as follows but test fails with: expect(jest.fn()).toBeCalled() Expected mock function to have been called.

test updated:

test('Input should call handleChange on change event', () => {

  const login = mount(<Login />);
  const handleChange = jest.spyOn(login.instance(), 'handleChange');
  const userInput = login.find('.username');
  const event = {target: {name: "username", value: "usertest"}};

  userInput.simulate('change', event);

  expect(handleChange).toBeCalled();

})

I'm new to React and testing in general so forgive the naivety of the question. I have a React form ponent which onChance on the inputs runs a function handleChange. Tried to test it with Jest but can't make it work.

Here's the Login ponent:

class Login extends React.Component {

  constructor() {
    super();
    this.state = {username: '', password: ''}
    this.disableSubmit = this.disableSubmit.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  render() {

    return(
      <div className="login">
        <form>
          <h3 className="login__title">LOGIN</h3>
          <div className="input-group">
            <input onChange={this.handleChange} value={this.state.username} className="form-control login__input username" type="text" placeholder="user name" name={'username'} autoFocus/>
          </div>
          <div className="input-group">
            <input onChange={this.handleChange} value={this.state.password} className="form-control login__input password" type="password" placeholder="password" name={'password'}/>
          </div>
          <div>
            <button className="btn btn-primary btn-block login__button" type="submit">Login</button>
          </div>
        </form>
      </div>

    )
  }
}

export default Login;

Here's my test:

import React from 'react'
import { shallow, mount } from 'enzyme'
import { shallowToJson } from 'enzyme-to-json'


import {Login} from '../../../src/base/ponents/index'


describe('Given the Login ponent is rendered', () => {

  describe('Snapshots', () => {
    let ponent

    beforeEach(() => {
      ponent = shallow(<Login />)
    })

    it('should be as expected', () => {
      expect(shallowToJson(ponent)).toMatchSnapshot()
    })
  })

})


test('Submitting the form should call handleSubmit', () => {

  const startState = {username: ''};
  const handleChange = jest.fn();
  const login = mount(<Login />);
  const userInput = login.find('.username');

  userInput.simulate('change');

  expect(handleChange).toBeCalled();

})

The snapshot test passes fine, but in this last attempt my function test fails with:

TypeError: Cannot read property 'target' of undefined

Guess I need to pass something to the function? Bit confused!

Thanks in advance for your help.

UPDATE:

changed the test as follows but test fails with: expect(jest.fn()).toBeCalled() Expected mock function to have been called.

test updated:

test('Input should call handleChange on change event', () => {

  const login = mount(<Login />);
  const handleChange = jest.spyOn(login.instance(), 'handleChange');
  const userInput = login.find('.username');
  const event = {target: {name: "username", value: "usertest"}};

  userInput.simulate('change', event);

  expect(handleChange).toBeCalled();

})
Share Improve this question edited Sep 18, 2017 at 8:42 Mauro74 asked Sep 15, 2017 at 15:42 Mauro74Mauro74 4,82615 gold badges61 silver badges83 bronze badges 1
  • handleChange isn't currently being mocked. – Oluwafemi Sule Commented Sep 15, 2017 at 15:56
Add a ment  | 

3 Answers 3

Reset to default 2

Yes, you'll need to pass an event object to you simulate function.

  const event = {target: {name: "special", value: "party"}};

  element.simulate('change', event);

EDIT: Oh, and you'll also need to do something like:

jest.spyOn(login.instance(), 'handleChange')

but that's unrelated to your error

Found the solution in here: Enzyme simulate an onChange event

test('Input should call handleChange on change event', () => {

  const event = {target: {name: 'username', value: 'usertest'}};
  const login = mount(<Login />);
  const handleChange = jest.spyOn(login.instance(), 'handleChange');
  login.update(); // <--- Needs this to force re-render
  const userInput = login.find('.username');

  userInput.simulate('change', event);

  expect(handleChange).toBeCalled();

})

It needed this login.update(); in order to work!

Thank everyone for your help!

handleChange isn't currently being mocked. A couple of approaches:

Pass change event handler as prop to Login ponent.

<div className="input-group">
  <input 
    onChange={this.props.handleChange} 
    value={this.state.username}
    className="form-control login__input username" 
    type="text"
    placeholder="user name"
    name={'username'}
    autoFocus
    />
</div>

login.spec.js

...
const handleChange = jest.fn();
const login = mount(<Login handleChange={handleChange}/>);
...

Replace handleChange with the mock function.

...
const handleChange = jest.fn();
const login = mount(<Login />);
login['handleChange'] = handleChange // replace instance
...
expect(handleChange).toBeCalled();

Use jest spyOn to create a mock function that wraps the original function.

...
const handleChange = jest.spyOn(object, 'handleChange') // will call the original method
expect(handleChange).toBeCalled();

Replace handleChange on the Login ponent with a mock function. ... const handleChange = jest.spyOn(object, 'handleChange').mock // will call the original method expect(handleChange).toBeCalled();

本文标签: javascriptTest function with Jest in React JsStack Overflow