Reputation: 624
I'm trying to run some unit test with Chai&Enzyme to my React app.
Enzyme seems to have an issue with props I passed to components. They got undefined in tests (not in app).
main file:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import TaskList from './components/task_list';
import AddingInput from './components/input';
const titleHeader = <h1 className="app__title">Simple to-do list:</h1>;
class App extends Component {
constructor(props) {
super(props);
this.state = {
tasks: [
{id: 0, name: 'Complete task'},
{id: 1, name: 'Add task'},
{id: 2, name: 'Delete task'}
],
id: 3,
};
}
(...)
render () {
return (
<div className="app">
{titleHeader}
<TaskList
tasks={this.state.tasks}
deleteMe={this.deleteMe.bind(this)} />
<AddingInput addTodo={this.addTodo.bind(this)} />
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
Task_list - first component I want to test:
import React from 'react';
import TaskItem from './task_item';
const TaskList = (props) => {
const taskItems = props.tasks.map((task) => {
return (
<TaskItem
key={task.id}
task={task}
deleteMe={props.deleteMe}
/>
);
});
return (
<ol className="ordered-list">
{taskItems}
</ol>
);
};
export default TaskList;
And the second:
import React from 'react';
const TaskItem = React.createClass({
onCompleted: function(e) {
e.target.className += " ordered-list__item--completed"
},
render: function() {
return (
<li><span className="ordered-list__item" onClick={this.onCompleted}>{this.props.task.name}</span>
<span onClick={() => this.props.deleteMe(this.props.task)}
className='btn btn--delete'>Delete</span>
</li>
);
}
});
export default TaskItem;
An here are my tests. Two of them are passed (both component exist) but in other two got undefined on props.tasks
:
import React from 'react';
import { expect, assert } from 'chai';
import { shallow, mount } from 'enzyme';
import TaskList from './src/components/task_list';
import TaskItem from './src/components/task_item';
describe('TaskList', () => {
it('should render TaskItem', () => {
const wrapper = shallow(<TaskList />);
expect(wrapper.containsAllMatchingElements([
<TaskItem />,
])).to.equal(true);
});
it('should exists', () => {
assert.isDefined(TaskList)
})
});
describe('TaskItem', () => {
it('should render one item of unordered list', () => {
const item = mount(<TaskItem />);
expect(item).to.contain('li');
});
it('should exists', () => {
assert.isDefined(TaskList)
})
});
Problems: 1) TaskList should render TaskItem: TypeError: Cannot read property 'map' of undefined 2) TaskItem should render one item of unordered list: TypeError: Cannot read property 'name' of undefined
Upvotes: 1
Views: 429
Reputation: 58372
Your App
component passes a tasks
prop:
<TaskList
tasks={this.state.tasks}
deleteMe={this.deleteMe.bind(this)} />
And TaskList
expects it to be always present. Similarly, TaskItem
expects to always have certain props available (from TaskList
).
If you add the necessary props in your unit tests, it should work. For TaskList
, this might look something like the following (untested):
const tasks = [
{id: 0, name: 'Complete task'},
{id: 1, name: 'Add task'},
{id: 2, name: 'Delete task'}
];
const wrapper = shallow(<TaskList tasks={tasks}/>);
Upvotes: 2