View a List of Todos
Story: As a user, I want to see all of todos in my todos list
To complete this story, we will need to create the TodoItem and MainSection components. Since this story does not involve making any changes to state, we will not have to write any more actions or reducers at this time.
TodoItem component
Should render correctly
It should be an li
Write the test.
// tests/todomvc/components/TodoItem.spec.js
'use strict';
import React from 'react'
import {expect} from 'chai'
import {shallow} from 'enzyme'
import TodoItem from '../../../src/todomvc/components/TodoItem'
function setup() {
const component = shallow(
<TodoItem/>
);
return {
component: component
}
}
describe('TodoItem component', () => {
describe('Should render correctly', () => {
it('Should be an li', () => {
const {component} = setup();
expect(component.type()).to.equal('li')
})
})
});
Run the test and watch it fail.
module.js:487
throw err;
^
Error: Cannot find module '../../../src/todomvc/components/TodoItem'
Write the code to make the test pass.
// src/todomvc/components/TodoItem.js
'use strict';
import React, {Component} from 'react'
export default class TodoItem extends Component {
render() {
return (
<li/>
)
}
}
Run the test and watch it pass.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
TodoApp component
Should render correctly
✓ Should be a TodoApp
TodoItem component
Should render correctly
✓ Should be an li
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
15 passing (61ms)
Commit changes.
$ git add .
$ git commit -m 'be an li'
It should have a label
Write the test.
diff --git a/tests/todomvc/components/TodoItem.spec.js b/tests/todomvc/components/TodoItem.spec.js
index e285de1..772bb61 100644
--- a/tests/todomvc/components/TodoItem.spec.js
+++ b/tests/todomvc/components/TodoItem.spec.js
@@ -1,18 +1,24 @@
'use strict';
import React from 'react'
+import {Map} from 'immutable'
+import uuid from 'uuid'
import {expect} from 'chai'
import {shallow} from 'enzyme'
import TodoItem from '../../../src/todomvc/components/TodoItem'
function setup() {
+ const props = {
+ todo: Map({id: uuid.v4(), description: 'Use Redux', completed: false})
+ };
const component = shallow(
- <TodoItem/>
+ <TodoItem {...props} />
);
return {
- component: component
+ component: component,
+ props: props
}
}
@@ -22,6 +28,14 @@ describe('TodoItem component', () => {
const {component} = setup();
expect(component.type()).to.equal('li')
+ });
+
+ it('Should have a label', () => {
+ const {component, props} = setup();
+ const label = component.children('label');
+
+ expect(label).to.have.length(1);
+ expect(label.children().text()).to.equal(props.todo.get('description'))
})
})
});
(END)
Run the test and watch it fail.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
TodoApp component
Should render correctly
✓ Should be a TodoApp
TodoItem component
Should render correctly
✓ Should be an li
1) Should have a label
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
15 passing (67ms)
1 failing
1) TodoItem component Should render correctly Should have a label:
AssertionError: expected { Object (root, unrendered, ...) } to have a length of 1 but got 0
+ expected - actual
-0
+1
at Context.<anonymous> (tests/todomvc/components/TodoItem.spec.js:37:29)
Write the code to make the test pass.
diff --git a/src/todomvc/components/TodoItem.js b/src/todomvc/components/TodoItem.js
index 8c64c9d..6afa1eb 100644
--- a/src/todomvc/components/TodoItem.js
+++ b/src/todomvc/components/TodoItem.js
@@ -1,11 +1,22 @@
'use strict';
import React, {Component} from 'react'
+import PropTypes from 'prop-types'
export default class TodoItem extends Component {
+ static propTypes = {
+ todo: PropTypes.object.isRequired
+ };
+
render() {
+ const {todo} = this.props;
+
return (
- <li/>
+ <li>
+ <label>
+ { todo.get('description') }
+ </label>
+ </li>
)
}
}
(END)
Run the test and watch it pass.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
TodoApp component
Should render correctly
✓ Should be a TodoApp
TodoItem component
Should render correctly
✓ Should be an li
✓ Should have a label
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
16 passing (68ms)
Commit changes.
$ git add .
$ git commit -m 'have a label'
MainSection component
Should render correctly
It should be a MainSection component
Write the test.
// tests/todomvc/components/MainSection.spec.js
'use strict';
import React from 'react'
import {expect} from 'chai'
import {shallow} from 'enzyme'
import MainSection from '../../../src/todomvc/components/MainSection'
function setup() {
const component = shallow(
<MainSection/>
);
return {
component: component
}
}
describe('MainSection component', () => {
describe('Should render correctly', () => {
it('Should be a MainSection component', () => {
const {component} = setup();
expect(component.type()).to.equal('section')
})
})
});
Run the test and watch it fail.
module.js:487
throw err;
^
Error: Cannot find module '../../../src/todomvc/components/MainSection'
Write the code to make the test pass.
// src/todomvc/components/MainSection.js
'use strict';
import React, {Component} from 'react'
export default class MainSection extends Component {
render() {
return (
<section/>
)
}
}
Run the test and watch it pass.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
MainSection component
Should render correctly
✓ Should be a MainSection component
TodoApp component
Should render correctly
✓ Should be a TodoApp
TodoItem component
Should render correctly
✓ Should be an li
✓ Should have a label
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
17 passing (70ms)
Commit changes.
$ git add .
$ git commit -m 'be a MainSection'
It should include a list of todos
Write the test.
diff --git a/tests/todomvc/components/MainSection.spec.js b/tests/todomvc/components/MainSection.spec.js
index fc31f15..9e0dedd 100644
--- a/tests/todomvc/components/MainSection.spec.js
+++ b/tests/todomvc/components/MainSection.spec.js
@@ -1,18 +1,29 @@
'use strict';
import React from 'react'
+import {List, Map} from 'immutable'
+import uuid from 'uuid'
import {expect} from 'chai'
import {shallow} from 'enzyme'
import MainSection from '../../../src/todomvc/components/MainSection'
+import TodoItem from '../../../src/todomvc/components/TodoItem'
function setup() {
+ const props = {
+ todos: List([
+ Map({id: uuid.v4(), description: 'Use Redux', completed: false}),
+ Map({id: uuid.v4(), description: 'Run the tests', completed: false})
+ ])
+ };
+
const component = shallow(
- <MainSection/>
+ <MainSection {...props} />
);
return {
- component: component
+ component: component,
+ props: props
}
}
@@ -22,6 +33,19 @@ describe('MainSection component', () => {
const {component} = setup();
expect(component.type()).to.equal('section')
+ });
+
+ it('Should include a list of todos', () => {
+ const {component, props} = setup();
+ const ul = component.children('ul');
+ const items = ul.children();
+
+ expect(ul).to.have.length(1);
+ expect(items).to.have.length(props.todos.size);
+ items.forEach((item, i) => {
+ expect(item.type()).to.equal(TodoItem);
+ expect(item.props().todo).to.equal(props.todos.get(i))
+ })
})
})
});
(END)
Run the test and watch it fail.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
MainSection component
Should render correctly
✓ Should be a MainSection component
1) Should include a list of todos
TodoApp component
Should render correctly
✓ Should be a TodoApp
TodoItem component
Should render correctly
✓ Should be an li
✓ Should have a label
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
17 passing (76ms)
1 failing
1) MainSection component Should render correctly Should include a list of todos:
AssertionError: expected { Object (root, unrendered, ...) } to have a length of 1 but got 0
+ expected - actual
-0
+1
at Context.<anonymous> (tests/todomvc/components/MainSection.spec.js:43:26)
Write the code to make the test pass.
diff --git a/src/todomvc/components/MainSection.js b/src/todomvc/components/MainSection.js
index 997a7fa..72bd1e9 100644
--- a/src/todomvc/components/MainSection.js
+++ b/src/todomvc/components/MainSection.js
@@ -1,11 +1,24 @@
'use strict';
import React, {Component} from 'react'
+import PropTypes from 'prop-types'
+
+import TodoItem from './TodoItem'
export default class MainSection extends Component {
+ static propTypes = {
+ todos: PropTypes.object.isRequired
+ };
+
render() {
+ const props = this.props;
+
return (
- <section/>
+ <section>
+ <ul>
+ {props.todos.map(todo => <TodoItem key={todo.get('id')} todo={todo}/>)}
+ </ul>
+ </section>
)
}
}
(END)
Run the test and watch it pass.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
MainSection component
Should render correctly
✓ Should be a MainSection component
✓ Should include a list of todos
TodoApp component
Should render correctly
✓ Should be a TodoApp
TodoItem component
Should render correctly
✓ Should be an li
✓ Should have a label
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
18 passing (73ms)
Commit changes.
$ git add .
$ git commit -m 'include a list of todos'
TodoApp Component
It should render correctly
It should have a MainSection
Write the test.
diff --git a/tests/todomvc/components/TodoApp.spec.js b/tests/todomvc/components/TodoApp.spec.js
index 67f18ac..4632b7f 100644
--- a/tests/todomvc/components/TodoApp.spec.js
+++ b/tests/todomvc/components/TodoApp.spec.js
@@ -32,7 +32,19 @@ describe('TodoApp component', () => {
it('Should be a TodoApp', () => {
const {component} = setup();
- expect(component.name()).to.equal('Header')
+ expect(component.name()).to.equal('div')
+ });
+
+ it('Should have a header', () => {
+ const {component} = setup();
+
+ expect(component.children('Header')).to.have.length(1)
+ });
+
+ it('Should have a main section', () => {
+ const {component} = setup();
+
+ expect(component.children('MainSection')).to.have.length(1)
})
})
});
(END)
Run the test and watch it fail.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
MainSection component
Should render correctly
✓ Should be a MainSection component
✓ Should include a list of todos
TodoApp component
Should render correctly
1) Should be a TodoApp
2) Should have a header
3) Should have a main section
TodoItem component
Should render correctly
✓ Should be an li
✓ Should have a label
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
17 passing (77ms)
3 failing
1) TodoApp component Should render correctly Should be a TodoApp:
AssertionError: expected 'Header' to equal 'div'
+ expected - actual
-Header
+div
at Context.<anonymous> (tests/todomvc/components/TodoApp.spec.js:35:35)
2) TodoApp component Should render correctly Should have a header:
AssertionError: expected { Object (root, unrendered, ...) } to have a length of 1 but got 0
+ expected - actual
-0
+1
at Context.<anonymous> (tests/todomvc/components/TodoApp.spec.js:41:52)
3) TodoApp component Should render correctly Should have a main section:
AssertionError: expected { Object (root, unrendered, ...) } to have a length of 1 but got 0
+ expected - actual
-0
+1
at Context.<anonymous> (tests/todomvc/components/TodoApp.spec.js:47:57)
Write the code to make the test pass.
diff --git a/src/todomvc/components/TodoApp.js b/src/todomvc/components/TodoApp.js
index faf089a..1507dbb 100644
--- a/src/todomvc/components/TodoApp.js
+++ b/src/todomvc/components/TodoApp.js
@@ -1,18 +1,28 @@
'use strict';
import React, {Component} from 'react'
+import PropTypes from 'prop-types'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import Header from '../components/Header'
+import MainSection from '../components/MainSection'
import * as actions from '../actions'
class TodoApp extends Component {
+ static propTypes = {
+ todos: PropTypes.object.isRequired,
+ actions: PropTypes.object.isRequired
+ };
+
render() {
- const props = this.props;
+ const {todos, actions} = this.props;
return (
- <Header actions={props.actions}/>
+ <div>
+ <Header actions={actions}/>
+ <MainSection todos={todos} actions={actions}/>
+ </div>
)
}
}
(END)
Run the test and watch it pass.
TodoMVC actions
✓ Should create an action to add a todo
Header component
Should render correctly
✓ Should be a Header
✓ Should have a title
✓ Should have a TodoTextInput field
Should behave correctly
✓ Should call addTodo() if length of text is greater than 0
MainSection component
Should render correctly
✓ Should be a MainSection component
✓ Should include a list of todos
TodoApp component
Should render correctly
✓ Should be a TodoApp
✓ Should have a header
✓ Should have a main section
TodoItem component
Should render correctly
✓ Should be an li
✓ Should have a label
TodoTextInput component
✓ Should not call onSave() on blur if isNew
Should render correctly
✓ Should be a TodoTextInput component
Should behave correctly
✓ Should update value on change
✓ Should call onSave() on return key press
✓ Should reset state on return key press if isNew
✓ Should call onSave() on blur if not isNew
TodoMVC reducer
✓ Should handle initial state
✓ Should handle ADD todo
20 passing (78ms)
Commit changes.
$ git add .
$ git commit -m 'have a MainSection'
Run It!
Now let's see what this looks like.
Open http://localhost:4000 in your web browser.
Type "Hello" into the text input box and see what happens. Then enter "World" You can see the todos appear in your list, as well as watch state update with each action in the Redux Dev Tools window on the right, like this:
Last updated
Was this helpful?