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
3 Answers
Reset to default 2Yes, 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();