Delete a Todo

Story: As a user, I want to delete a todo from my todos list.

TodoMVC actions

It should create an action to delete a todo

Write a test.

diff --git a/tests/todomvc/actions.spec.js b/tests/todomvc/actions.spec.js
index 694dd04..fd31f8f 100644
--- a/tests/todomvc/actions.spec.js
+++ b/tests/todomvc/actions.spec.js
@@ -21,5 +21,13 @@ describe('TodoMVC actions', () => {
     };

     expect(todomvc.actions.editTodo('my_id', description)).to.deep.equal(expectedAction)
+  });
+
+  it('Should create an action to delete a todo', () => {
+    const expectedAction = {
+      type: todomvc.types.DELETE, id: 'my_id'
+    };
+
+    expect(todomvc.actions.deleteTodo('my_id')).to.deep.equal(expectedAction)
   })
 });
(END)

Run the test and watch it fail.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    1) Should create an action to delete 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
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave

  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
    ✓ Should handle EDIT todo


  25 passing (88ms)
  1 failing

  1) TodoMVC actions Should create an action to delete a todo:
     TypeError: _todomvc2.default.actions.deleteTodo is not a function
      at Context.<anonymous> (tests/todomvc/actions.spec.js:31:28)

Write the code to make the test pass. This time we will define the DELETE action type and use it in the same code change.

diff --git a/src/todomvc/ActionTypes.js b/src/todomvc/ActionTypes.js
index 28b3b32..60f8aa8 100644
--- a/src/todomvc/ActionTypes.js
+++ b/src/todomvc/ActionTypes.js
@@ -2,3 +2,4 @@

 export const ADD = 'todomvc/ADD';
 export const EDIT = 'todomvc/EDIT';
+export const DELETE = 'todomvc/DELETE';
(END)
diff --git a/src/todomvc/actions.js b/src/todomvc/actions.js
index dc30850..0f1e307 100644
--- a/src/todomvc/actions.js
+++ b/src/todomvc/actions.js
@@ -9,3 +9,7 @@ export function addTodo(text) {
 export function editTodo(id, text) {
   return {type: types.EDIT, id: id, description: text}
 }
+
+export function deleteTodo(id) {
+  return {type: types.DELETE, id: id}
+}
(END)

Run the test and watch it pass.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave

  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
    ✓ Should handle EDIT todo


  26 passing (94ms)

Commit changes.

$ git add .
$ git commit -m 'created an action to delete a todo'

TodoMVC reducer

It should handle DELETE todo

Write the test.

diff --git a/tests/todomvc/reducer.spec.js b/tests/todomvc/reducer.spec.js
index 0c4fb5e..dd79807 100644
--- a/tests/todomvc/reducer.spec.js
+++ b/tests/todomvc/reducer.spec.js
@@ -41,5 +41,18 @@ describe('TodoMVC reducer', () => {
     expect(new_state.get(1).get('id')).to.equal(state.get(1).get('id'));
     expect(new_state.get(1).get('description')).to.equal('My updated todo');
     expect(new_state.get(1).get('completed')).to.equal(state.get(1).get('completed'))
+  });
+
+  it('Should handle DELETE todo', () => {
+    const state = List([
+      Map({id: uuid.v4(), description: 'My todo', completed: false}),
+      Map({id: uuid.v4(), description: 'My soon to be deleted todo', completed: false})
+    ]);
+    const new_state = todomvc.reducer(state, {
+      type: todomvc.types.DELETE, id: state.get(1).get('id')
+    });
+
+    expect(new_state.size).to.equal(1);
+    expect(new_state.get(0)).to.equal(state.get(0))
   })
 });
(END)

Run the test and watch it fail.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave

  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
    ✓ Should handle EDIT todo
    1) Should handle DELETE todo


  26 passing (90ms)
  1 failing

  1) TodoMVC reducer Should handle DELETE todo:

      AssertionError: expected 2 to equal 1
      + expected - actual

      -2
      +1

      at Context.<anonymous> (tests/todomvc/reducer.spec.js:55:31)

Write the code to make the test pass.

diff --git a/src/todomvc/reducer.js b/src/todomvc/reducer.js
index b79948a..5f9a53c 100644
--- a/src/todomvc/reducer.js
+++ b/src/todomvc/reducer.js
@@ -11,6 +11,8 @@ export default function reducer(state = List([]), action) {
       return (state.push(Map({id: uuid.v4(), description: action.description, completed: false})));
     case types.EDIT:
       return (state.map(todo => todo.get('id') === action.id ? todo.set('description', action.description) : todo));
+    case types.DELETE:
+      return state.filter(todo => todo.get('id') !== action.id);
     default:
       // just return the same state
       return (state)
(END)

Run the test and watch it pass.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  27 passing (83ms)

Commit changes.

$ git add .
$ git commit -m 'handle DELETE todo'

TodoItem component

It Should render correctly

It should have a delete button

Write the test.

diff --git a/tests/todomvc/components/TodoItem.spec.js b/tests/todomvc/components/TodoItem.spec.js
index 50c527e..8c2611f 100644
--- a/tests/todomvc/components/TodoItem.spec.js
+++ b/tests/todomvc/components/TodoItem.spec.js
@@ -38,6 +38,14 @@ describe('TodoItem component', () => {

       expect(label).to.have.length(1);
       expect(label.children().text()).to.equal(props.todo.get('description'))
+    });
+
+    it('Should have a delete button', () => {
+      const {component} = setup();
+      const button = component.children('button');
+
+      expect(button).to.have.length(1);
+      expect(button.children().text()).to.equal('delete todo')
     })
   });

(END)

Run the test and watch it fail.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
      1) Should have a delete button
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  27 passing (86ms)
  1 failing

  1) TodoItem component Should render correctly Should have a delete button:

      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:47:30)

Write the code to make the test pass.

diff --git a/src/todomvc/components/TodoItem.js b/src/todomvc/components/TodoItem.js
index ef548fa..de2de69 100644
--- a/src/todomvc/components/TodoItem.js
+++ b/src/todomvc/components/TodoItem.js
@@ -34,6 +34,7 @@ export default class TodoItem extends Component {
         <label onDoubleClick={this.handleDoubleClick.bind(this)}>
           {todo.get('description')}
         </label>
+        <button>delete todo</button>
       </li>
     )
   }
@@ -44,6 +45,7 @@ export default class TodoItem extends Component {
     return (
       <li>
         <TodoTextInput text={todo.get('description')} onSave={(text) => this.handleSave(todo.get('id'), text)}/>
+        <button>delete todo</button>
       </li>
     )
   }
(END)

Run the test and watch it pass.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
      ✓ Should have a delete button
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  28 passing (97ms)

Commit changes.

$ git add .
$ git commit -m 'have a delete button'

It Should behave correctly

Should call deleteTodo() when the delete button is clicked

Write the test

diff --git a/tests/todomvc/components/TodoItem.spec.js b/tests/todomvc/components/TodoItem.spec.js
index 8c2611f..21c704d 100644
--- a/tests/todomvc/components/TodoItem.spec.js
+++ b/tests/todomvc/components/TodoItem.spec.js
@@ -12,7 +12,8 @@ import TodoItem from '../../../src/todomvc/components/TodoItem'
 function setup() {
   const props = {
     todo: Map({id: uuid.v4(), description: 'Use Redux', completed: false}),
-    editTodo: sinon.spy()
+    editTodo: sinon.spy(),
+    deleteTodo: sinon.spy()
   };
   const component = shallow(
     <TodoItem {...props} />
@@ -76,6 +77,14 @@ describe('TodoItem component', () => {
       component.find('TodoTextInput').props().onSave('Use Redux'); // update
       component.update(); // force component to re-render
       expect(component.children('label')).to.have.length(1) // switched back to label
+    });
+
+    it('Should call deleteTodo() when the delete button is clicked', () => {
+      const {component, props} = setup();
+      const button = component.find('button');
+
+      button.simulate('click');
+      expect(props.deleteTodo.called).to.be.true
     })
   })
 });
(END)

Run the test and watch it fail

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
      ✓ Should have a delete button
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave
      1) Should call deleteTodo() when the delete button is clicked

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  28 passing (90ms)
  1 failing

  1) TodoItem component Should behave correctly Should call deleteTodo() when the delete button is clicked:

      AssertionError: expected false to be true
      + expected - actual

      -false
      +true

      at Context.<anonymous> (tests/todomvc/components/TodoItem.spec.js:87:7)

Write the code to make the test pass.

diff --git a/src/todomvc/components/TodoItem.js b/src/todomvc/components/TodoItem.js
index de2de69..f125dc5 100644
--- a/src/todomvc/components/TodoItem.js
+++ b/src/todomvc/components/TodoItem.js
@@ -7,7 +7,8 @@ import TodoTextInput from './TodoTextInput'
 export default class TodoItem extends Component {
   static propTypes = {
     todo: PropTypes.object.isRequired,
-    editTodo: PropTypes.func.isRequired
+    editTodo: PropTypes.func.isRequired,
+    deleteTodo: PropTypes.func.isRequired
   };

   constructor(props, context) {
@@ -27,25 +28,25 @@ export default class TodoItem extends Component {
   }

   renderTodoListItem() {
-    const {todo} = this.props;
+    const {todo, deleteTodo} = this.props;

     return (
       <li>
         <label onDoubleClick={this.handleDoubleClick.bind(this)}>
           {todo.get('description')}
         </label>
-        <button>delete todo</button>
+        <button onClick={ () => deleteTodo(todo.get('id')) }>delete todo</button>
       </li>
     )
   }

   renderTodoTextInput() {
-    const {todo} = this.props;
+    const {todo, deleteTodo} = this.props;

     return (
       <li>
         <TodoTextInput text={todo.get('description')} onSave={(text) => this.handleSave(todo.get('id'), text)}/>
-        <button>delete todo</button>
+        <button onClick={ () => deleteTodo(todo.get('id')) }>delete todo</button>
       </li>
     )
   }
(END)

Run the test and watch it pass.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
Warning: Failed prop type: The prop `deleteTodo` is marked as required in `TodoItem`, but its value is `undefined`.
    in TodoItem
      ✓ 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
      ✓ Should have a delete button
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave
      ✓ Should call deleteTodo() when the delete button is clicked

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  29 passing (98ms)

Let's now fix the required prop warning regression in the same way we did it for editTodo action.

diff --git a/tests/todomvc/components/MainSection.spec.js b/tests/todomvc/components/MainSection.spec.js
index ff09a7b..badf84c 100644
--- a/tests/todomvc/components/MainSection.spec.js
+++ b/tests/todomvc/components/MainSection.spec.js
@@ -17,7 +17,8 @@ function setup() {
       Map({id: uuid.v4(), description: 'Run the tests', completed: false})
     ]),
     actions: {
-      editTodo: sinon.spy ()
+      editTodo: sinon.spy(),
+      deleteTodo: sinon.spy()
     }
   };

(END)

Run the test and watch it pass, this time without the warning.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
      ✓ Should have a delete button
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave
      ✓ Should call deleteTodo() when the delete button is clicked

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  29 passing (98ms)

Commit changes.

$ git add .
$ git commit -m 'call deleteTodo() when the delete button is clicked'

Should call deleteTodo() when TodoTextInput onSave is called with no text

Write the test

diff --git a/tests/todomvc/components/TodoItem.spec.js b/tests/todomvc/components/TodoItem.spec.js
index 21c704d..9792ed2 100644
--- a/tests/todomvc/components/TodoItem.spec.js
+++ b/tests/todomvc/components/TodoItem.spec.js
@@ -85,6 +85,14 @@ describe('TodoItem component', () => {

       button.simulate('click');
       expect(props.deleteTodo.called).to.be.true
+    });
+
+    it('Should call deleteTodo() when TodoTextInput onSave is called with no text', () => {
+      const {component, props} = setup();
+
+      component.children('label').simulate('doubleclick'); // switch to edit mode
+      component.find('TodoTextInput').props().onSave('');
+      expect(props.deleteTodo.called).to.be.true
     })
   })
 });
(END)

Run the test and watch it fail

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
      ✓ Should have a delete button
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave
      ✓ Should call deleteTodo() when the delete button is clicked
      1) Should call deleteTodo() when TodoTextInput onSave is called with no text

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  29 passing (99ms)
  1 failing

  1) TodoItem component Should behave correctly Should call deleteTodo() when TodoTextInput onSave is called with no text:

      AssertionError: expected false to be true
      + expected - actual

      -false
      +true

      at Context.<anonymous> (tests/todomvc/components/TodoItem.spec.js:95:7)

Write the code to make the test pass.

diff --git a/src/todomvc/components/TodoItem.js b/src/todomvc/components/TodoItem.js
index eb68ddd..a3d8959 100644
--- a/src/todomvc/components/TodoItem.js
+++ b/src/todomvc/components/TodoItem.js
@@ -23,7 +23,7 @@ export default class TodoItem extends Component {
   }

   handleSave(id, text) {
-    this.props.editTodo(id, text);
+    text === '' ? this.props.deleteTodo(id) : this.props.editTodo(id, text);
     this.setState({editing: false})
   }

(END)

Run the test and watch it pass, this time without the warning.

  TodoMVC actions
    ✓ Should create an action to add a todo
    ✓ Should create an action to edit a todo
    ✓ Should create an action to delete 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
      ✓ Should have a delete button
    Should behave correctly
      ✓ Should switch to edit mode when label onDoubleClick is fired
      ✓ Should call editTodo() when TodoTextInput onSave is called
      ✓ Should leave edit mode after TodoTextInput onSave
      ✓ Should call deleteTodo() when the delete button is clicked
      ✓ Should call deleteTodo() when TodoTextInput onSave is called with no text

  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
    ✓ Should handle EDIT todo
    ✓ Should handle DELETE todo


  30 passing (98ms)

Commit changes.

$ git add .
$ git commit -m 'call deleteTodo() when TodoTextInput onSave is called with no text'

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 a new delete button appear. Then enter "World". Now click on the "delete todo" button next to the "World" todo.

Now doubleclick on "Hello", delete all of the text, hit "enter" button and see that todo being deleted too.

Last updated

Was this helpful?