States undefined in unit testing - reactjs

I'm trying a very simple shallow test for a component:
it('renders without crashing', () => {
shallow(<SampleComponent />);
});
In my sample component, I did a setState :
this.setState({myCurrentState: "InSample"});
Now somewhere in my return, I used that to output an element, say:
return ( <h1> this.state.myCurrentState </h1>)
When I try the above test, I get
TypeError: Cannot read property of undefined.
I know that I can pass in props to shallow, but I can't seem to figure how to do it with states. Is there a better way of doing it? Sorry I'm new to React and unit testing. thanks

Here you go
import React from 'react';
import { render } from 'enzyme';
import SampleComponent from './SampleComponent';
describe('< SampleComponent />', () => {
it('should render', () => {
const wrapper = shallow(<SampleComponent name="Example" />);
expect(wrapper).toHaveLength(1);
});
describe('check props', () => {
const wrapper = shallow(<SampleComponent name="Example" />);
console.log(warpper.instance().props); // you should see name='Example'
});
});
Please check out this link http://airbnb.io/enzyme/docs/api/
You can't call the state like this return ( <h1> this.state.myCurrentState </h1>) you have to put it into { } like
return ( <h1> {this.state.myCurrentState} </h1>)
If you still having a troubles watch this video

Use Something like this:
class SomeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
myCurrentState: null
};
// somewhere in your code in one of the method
this.setState({myCurrentState: "InSample"});
render() {
return (
<h1>{this.state.myCurrentState}</h1>
);
}
}

Related

How to spy on a class property arrow function using Jest

How can I spy on a class property arrow function using Jest? I have the following example test case which fails with the error Expected mock function to have been called.:
import React, {Component} from "react";
import {shallow} from "enzyme";
class App extends Component {
onButtonClick = () => {
// Button click logic.
};
render() {
return <button onClick={this.onButtonClick} />;
}
}
describe("when button is clicked", () => {
it("should call onButtonClick", () => {
const app = shallow(<App />);
const onButtonClickSpy = jest.spyOn(app.instance(), "onButtonClick");
const button = app.find("button");
button.simulate("click");
expect(onButtonClickSpy).toHaveBeenCalled();
});
});
I can make the test pass by changing the button's onClick prop to () => this.onButtonClick() but would prefer not to change my component implementation just for the sake of tests.
Is there any way to make this test pass without changing the component implementation?
According to this enzyme issue and this one, you have two options:
Option 1: Call wrapper.update() after spyOn
In your case, that would be:
describe("when button is clicked", () => {
it("should call onButtonClick", () => {
const app = shallow(<App />);
const onButtonClickSpy = jest.spyOn(app.instance(), "onButtonClick");
// This should do the trick
app.update();
app.instance().forceUpdate();
const button = app.find("button");
button.simulate("click");
expect(onButtonClickSpy).toHaveBeenCalled();
});
});
Option 2: Don't use class property
So, for you, you would have to change your component to:
class App extends Component {
constructor(props) {
super(props);
this.onButtonClick = this.onButtonClick.bind(this);
}
onButtonClick() {
// Button click logic.
};
render() {
return <button onClick={this.onButtonClick} />;
}
}

Passing property dynamically to react component doesn't recognized by karma test

I'm trying to test whether a property that pass to a react component get the correct value, but it doesn't seems to work because (I think) the property get it's value dynamically depends on the parent component state. Here's the code (summarized):
import React from 'react';
import InfiniteScroll from 'react-infinite-scroller';
class myClass extends React.Component {
constructor(props) {
super(props);
this.state = {
....
inputChanged: 0
....
};
...
render() {
let items = [];
... code that retrieve items ...
return (
<InfiniteScroll
pageStart={this.state.inputChanged ? 1 : 0} // page start is changed according to this.state.inputChanged value
loadMore={this.loadMore.bind(this)}
hasMore={this.state.hasMoreItems}
loader={<div className="loader" key={0}>Loading ...</div>}
threshold={200}
>
<div className="container-fluid">
<div className="row">
{items}
</div>
</div>
</InfiniteScroll>
);
}
}
And in my spec file:
import React from 'react';
import {mount} from 'enzyme';
import {expect} from 'chai';
describe('myClass', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(
<myClass/>,
{attachTo: document.createElement('div')}
);
});
it('set correct pageStart', done => {
const InfiniteScroll = wrapper.find('InfiniteScroll');
wrapper.setState({
inputChanged: 1
});
expect(InfiniteScroll.props().pageStart).to.equal(1);
done();
});
}
But no matter what, InfinteScroll.props().pageStart is 0 and the test fails.
As far as I understand, it should changed accounring to wrapper.state().inputChanged, but it doesn't. Any ideas why?
Thanks in advance!
You are holding on to the reference of InfiniteScroll before calling setState. You need to move the code to get the reference of InfiniteScroll after the setState. Here is the updated test.
it('set correct pageStart', done => {
wrapper.setState({
inputChanged: 1
});
const InfiniteScroll = wrapper.find('InfiniteScroll');
expect(InfiniteScroll.props().pageStart).to.equal(1);
done();
});

Shallow test React branch Jest and Enzyme

There are three things I want to figure out. For now I am using shallow render. I use Enzyme and Jest.
I am wondering how I can test the branches in my React component. I
would like to test both sides of the if-else statement (? :). And I
do not want to pull it out in an own function.
How can I check if this.props.myFuncFromProps(value) is been called
when the input changes?
What is the best practice to test mapStateToProps and
mapDispatchToProps?
Here is an example of how my component would look like:
import React from 'react';
import MyChildComponent from 'wherever'; // This component is an input field in this example
export class MyComponent extends React.Component {
render() {
const myFunc(value) {
this.props.myFuncFromProps(value);
}
return (
<div>
{ this.props.isTrue ?
<MyChildComponent
value={this.props.value}
onChange={(value) => myFunc(value)}
/>
: null
}
</div>
);
}
}
To test the different states just render your component with the different attributes and make a snapshot (note, that you have to check the first time the snapshot was created). To test event callback, you have to pass a spy function (jest.fn()) into to component and use simulate to call the event, then test that the spy was called.
describe('MyComponent', () => {
describe('with isTrue is true', () => {
let myComponent
let myFuncFromProps
beforeEach(() => {
myFuncFromProps = jest.fn()
myComponent = shallow(
<MyComponent isTrue myFuncFromProps={myFuncFromProps} />
)
})
it('renders correct', () => {
expect(myComponent).matchSnapshot()
})
it('onchange will call myFuncFromProps', () => {
myComponent
.find('MyChildComponent')
.simulate('onChange', 'someValue')
expect(myFuncFromProps).toHaveBeenCalledWith('someValue')
})
})
it('with isTrue is false it renders correct', () => {
const myComponent = shallow(<MyComponent />)
expect(myComponent).matchSnapshot()
})
})

Test custom method on React component has been called, using Enzyme and Sinon

I want to check that when a button is clicked on my component, it calls the method I have created to handle the click. Here is my component:
import React, { PropTypes, Component } from 'react';
class Search extends Component {
constructor(){
super();
this.state = { inputValue: '' };
}
handleChange = (e) => {
this.setState({ inputValue: e.target.value });
}
handleSubmit = (e) => {
e.preventDefault();
return this.state.inputValue;
}
getValue = () => {
return this.state.inputValue;
}
render(){
return (
<form>
<label htmlFor="search">Search stuff:</label>
<input id="search" type="text" value={this.state.inputValue} onChange={this.handleChange} placeholder="Stuff" />
<button onClick={this.handleSubmit}>Search</button>
</form>
);
}
}
export default Search;
and here is my test
import React from 'react';
import { mount, shallow } from 'enzyme';
import Search from './index';
import sinon from 'sinon';
describe('Search button', () => {
it('calls handleSubmit', () => {
const shallowWrapper = shallow(<Search />);
const stub = sinon.stub(shallowWrapper.instance(), 'handleSubmit');
shallowWrapper.find('button').simulate('click', { preventDefault() {} });
stub.called.should.be.true();
});
});
The call called property comes back false. I have tried loads of variation on the syntax and I think maybe I'm just missing something fundamental. Any help would be greatly appreciated.
I'm relatively new to Sinon as well. I have generally been passing spy()s into component props, and checking those (though you can use stub() in the same way):
let methodSpy = sinon.spy(),
wrapper = shallow(<MyComponent someMethod={methodSpy} />)
wrapper.find('button').simulate('click')
methodSpy.called.should.equal(true)
I point this out because I think it's the most straightforward way to unit test components (testing internal methods can be problematic).
In your example, where you're trying to test internal methods of a component, this wouldn't work. I came across this issue, though, which should help you out. Try:
it('calls handleSubmit', () => {
const shallowWrapper = shallow(<Search />)
let compInstance = shallowWrapper.instance()
let handleSubmitStub = sinon.stub(compInstance, 'handleSubmit');
// Force the component and wrapper to update so that the stub is used
compInstance.forceUpdate()
shallowWrapper.update()
shallowWrapper.find('button').simulate('click', { preventDefault() {} });
handleSubmitStub.called.should.be.true();
});

Testing react component with enzyme and expect fails

I am testing a React component with Enzyme, Mocha, and Expect. The test case is shown below:
import React from 'react';
import expect from 'expect';
import { shallow } from 'enzyme';
import Add from '../src/client/components/add.jsx';
describe('Add', () => {
let add;
let onAdd;
before(() => {
onAdd = expect.createSpy();
add = shallow(<Add onAdd={onAdd} />);
});
it('Add requires onAdd prop', () => {
console.log(add.props());
expect(add.props().onAdd).toExist();
});
});
I am creating a spy using expect and attaching it to the onAdd prop of the Add component. My test checks if the prop exists on the component. For some reason, onAdd is undefined and the test fails. Any help?
The problem is that add isn't wrapping the <Add> component, it wraps what it returns. So, if your component looks like:
class Add extends React.Component {
render() {
return (
<div>
{this.props.foo}
</div>
);
}
}
This statement add.props().onAdd will try to access onAdd prop from <div> not from <Add>, and obviously it will fail.
This assertion:
expect(add.props().onAdd).toExist();
Will succeed, in the component will look like:
class Add extends React.Component {
render() {
return (
<div onAdd={this.props.onAdd}>
{this.props.foo}
</div>
);
}
}
Example shown in enzyme docs, is a little bit confusing.

Resources