Reputation: 81
In my react component I have two functions. handleChangeInput(e) is called on 'OnChange' of input field and checkFields() is called from handleChangeInput(e)
constructor(){
super()
this.state={
email: '',
password:'',
validFields: false
}
}
handleChangeInput(e){
const name = e.target.name;
const value = e.target.value;
this.setState({[name]: value},()=>{
this.checkFields();
});
}
checkFields(){
if (this.state.email.length>0 && this.state.password.length>0 ) {
this.setState({validFields: true});
}else {
this.setState({validFields: false});
}
}
And in my index.test.js I have
describe('<Login />', () => {
describe('handleChangeInput', () => {
const component = new Login()
const wrapper = shallow(<Login />);
beforeEach(() => {
component.setState = jest.fn()
})
test('calls setState validFields false when no email/password', () => {
const state = { state : { email: '', password: ''} }
const args = { target : { name: 'name', value: 'value' } }
component.handleChangeInput.call(state, args)
expect(component.setState.mock.calls.length).toBe(1)
expect(wrapper.state().validFields).toEqual(false)
})
test('calls setState validFields true when email/password are ok', () => {
const state = { state : { email: 'email', password: 'password' } }
const args = { target : { name: 'name', value: 'value' } }
component.handleChangeInput.call(state, args)
expect(component.setState.mock.calls.length).toBe(1)
expect(wrapper.state().validFields).toEqual(false)
})
})
});
But my state is not being updated. As a result, 'validFields' is not set to true and my second test is failing. I tried wrapper.update() and wrapper.instance().forceUpdate() but still no success. Any help would be appreciated
Upvotes: 0
Views: 8497
Reputation: 213
I found this answer in one of the git forums. It worked for me.
// somewhere in your test setup code
global.flushPromises = () => {
return new Promise(resolve => setImmediate(resolve))
}
test('something with unreachable promises', () => {
expect.hasAssertions()
const component = mount(<Something />)
// do something to your component here that waits for a promise to return
return flushPromises().then(() => {
component.update() // still may be needed depending on your implementation
expect(component.html()).toMatchSnapshot()
})
})
Upvotes: 0
Reputation: 1217
hope my answer does not come too late, but you are trying to update the state in a wrong way.
First of all, remove these two:
const component = new Login()
beforeEach(() => {
component.setState = jest.fn()
})
And most likely you want to change this:
handleChangeInput(e){
const name = e.target.name;
const value = e.target.value;
this.setState({[name]: value},()=>{
this.checkFields();
});
}
handleChangeInput(e){
const name = e.target.name;
const value = e.target.value;
this.setState(()=>{
return { email: name}
});
this.setState(()=>{
return { password: value }
});
this.checkFields();
}
const component = new Login() does not bring any value to this test and you should not mock the setState if you want that it's actually changed.
Instead you should test the actual component (like you partially already do here)
Change the code like this:
test('calls setState validFields true when email/password are ok', () => {
const args = { target : { email: 'email', password: 'password' } }
wrapper.instance().handleChangeInput(args)
expect(wrapper.state('email')).toEqual('email')
expect(wrapper.state('password')).toEqual('password')
expect(wrapper.state('validFields')).toBeTruthy()
})
Upvotes: 0
Reputation: 2961
I am guessing it might be because you override the setState function with jest.fn()
component.setState = jest.fn()
})
how about removing this?
Upvotes: 1