I need to access the state of the inner component, to make it active for click event, my problem is Enzyme does not allow this when using mount
, this can only be achieved by shallow
rendering of enzyme as mentioned over here, also as mentioned I have tried to use dive to fetch the Form component and again from Form to get Button component which I need to reach, the problem is that my test case keeps on failing as Form component length is zero.
enzyme: 3.1.0
enzyme-adapter-react-15: 1.0.1"
I am pretty new to Enzyme, Any help will be appreciated, Thanks
contactus.test.js :
test('It should simulate submit action ', ()=>{
let contactUs = shallow(<ContactUs />);
sinon.spy(ContactUs.prototype, 'submitMessage');// Verify this method call
let form = contactUs.find(Form)
expect(form.length).toBe(1);//Failing over here
let button = form.dive().find(Button);
expect(button.length).toBe(1);
button.setState({disabled : false});//Need to achieve this
expect(button).toBeDefined();
expect(button.length).toBe(1);
expect(button.props().label).toBe('SEND MESSAGE');
button.find('a').get(0).simulate('click');
expect(ContactUs.prototype.submitMessage).toHaveProperty('callCount',
1);
});
contactus.js :
import React, {Component,PropTypes} from 'react';
import Form from './form';
import {sendSubscriptionMessage} from '../../network';
import Button from '../Fields/Button';
export default class ContactUs extends Component {
constructor(props) {
super(props);
this.state = {
contactData: {}
}
}
onChangeHandler(event) {
let value = event.target.value;
this.state.contactData[event.target.name] = value;
}
submitMessage(event) {
event.preventDefault();
sendSubscriptionMessage(this.state.contactData);
}
render() {
return (<div className = "row pattern-black contact logo-container" id = "contact">
<div className = "container" >
<h2 className = "sectionTitle f-damion c-white mTop100" >
Get in Touch!
<Form onChangeHandler = {
this.onChangeHandler.bind(this)
} >
<Button onClick = {
this.submitMessage.bind(this)
}
className = "gradientButton pink inverse mTop50"
label = "SEND MESSAGE" / >
</Form> </div>
</div>
);
}
}
setState(state) => Self. A method to invoke setState() on the root component instance similar to how you might in the definition of the component, and re-renders. This method is useful for testing your component in hard to achieve states, however should be used sparingly.
The setState() Method State can be updated in response to event handlers, server responses, or prop changes. This is done using the setState() method. The setState() method enqueues all of the updates made to the component state and instructs React to re-render the component and its children with the updated state.
Yes, it's optional as we could store a string in the state and render the component conditionally but in some cases, it is simpler to just store the component in the state.
Here is how you can access them: import {shallow} from 'enzyme'; describe('SomeComponent component', () => { it('Shallow rendering', () => { const wrapper = shallow(<SomeComponent someProp={1}/>); const componentInstance = wrapper. instance(); //Accessing react lifecyle methods componentInstance.
First of all I think you should not test the Button and the Form functionalities here. In this file you should test only the ContactForm
component.
For the first fail, this should work:
find('Form')
(the Form
should have quotes)
Same for the button:
find('Button');
In this way you don't even have to import the Form
and the Button
components in your test file at all;
Then, you don't have to set any state for that button. You test the button functionality in the Button.test.js
file.
All you have to do here is to call its method like this:
button.nodes[0].props.onClick();
Overall, this is how your test should look like ( note that I didn't test it, I've been using Jest for testing my components, but the logic should be the same ):
test('It should simulate submit action ', ()=>{
const wrapper = shallow(<ContactUs />);
const spy = sinon.spy(ContactUs.prototype, 'submitMessage'); // Save the spy into a new variable
const form = wrapper.find('Form') // I don't know if is the same, but in jest is enough to pass the component name as a string, so you don't have to import it in your test file anymore.
expect(form).to.have.length(1);
const button = wrapper.find('Button'); // from what I see in your code, the Button is part of the ContactUs component, not of the Form.
expect(button).to.have.length(1);
/* These lines should not be part of this test file. Create a test file only for the Button component.
button.setState({disabled : false});
expect(button).toBeDefined();
expect(button.length).toBe(1);
expect(button.props().label).toBe('SEND MESSAGE');
*/
button.nodes[0].props.onClick(); // Here you call its method directly, cause we don't care about its internal functionality; we want to check if the "submitMessage" method has been called.
assert(spy.called); // Here I'm not very sure... I'm a Jest fan and i would have done it like this "expect(spy).toHaveBeenCalled();"
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With