Part 4 — You’re here now.
We’ve got a couple more things to do to make our failing e2e test pass; have a .todo-text
element and have it contain the text we submit in our form.
Create the folder structure src/components/todoList/
and then write our first unit test in test.js
that will allow us to create our component:
This should be self explanatory, it’s very similar to how we started building our addTodo
component.
What the component should return in the index.js
:
Line 4
We’ll wrap our component in a <ul>
.
Then let’s test for a todo in the list:
Line 8 — 13
We create our todos
prop, an array containing one todo as an object with id
and text
.
Line 15
We actually pass that todo in as a prop to our component.
Line 22
We expect that our todoList
will contain a .todo-text
element with our todo text.
Now we just have to get our todo to render:
Line 2
import PropTypes
for our validation.
Line 18 — 25
We tell our component that it will receive a prop
called todos
, it will be an array of objects, its id
will be a number and text
will be a string, and everything is required. React prop-types validation.
Line 4
We pass the todos
prop in to our actual component.
Line 5 — 8
We map
over our array, returning an li
whose contents are the todo.text
and it has a key
of todo.id
, the key
is required by React to more efficiently know how to re-render the DOM and if you don’t have it you will get a console warning in dev.
Line 11 — 15
We return our ul
wrapper with all the li
's for each todo in our state.
At this point our TodoList
component knows how to render itself so can be wired in to our main App.
Line 5
import our TodoList
component.
Line 18 — 23
Provide proper validation for it.
Line 8
Bring our todos array from state in to our App as a prop
so that we can pass it down. We’ve made it available as a prop
thanks to line 26
.
Line 12
Add the TodoList
component to our App
and pass todos
from state to it.
We now get a test error because we’ve told the component it requires a todos
array but haven’t passed it in:
So we make that change:
Line 15
Simply pass an empty array to our todos
prop, that’ll stop our App.test
complaining. We don’t want to unit test child components at the parent level.
Now if we view our App in the browser we’ll find that we can actually display those lovely todos we’ve been storing in state. Huzzah!
And now our e2e test should pass:
First we write our e2e test:
Add Line 12 — 21
above to your e2e test.
This test runs through the same procedure as the one before and then clicks the .todo-delete
element and then expects the selector’s state
to equal ‘failure’. If it existed (was not deleted), it would equal ‘success’.
I like to implement functionality by writing the action, the reducer, creating the component, then adding it to the App.
So let’s test for the right action. First let’s create an appropriate constant:
Line 3
Our new DELETE_TODO constant.
Then, in the action
all we need to know to delete a todo will be its unique id
.
Then add the code to make it pass:
And now let’s unit test our reducer functionality:
This should hopefully make a lot of sense by now. We’re giving our reducer
a startingState
which includes a todo, passing it in the action
we just created which should delete that todo from the store, and expecting the returned state to indeed not contain the todo.
We now need to add another case
in our reducer
to handle this:
When the DELETE_TODO action.type
is encountered we return a new state which includes all of the existing ...state
, and we override the todos
array to be only a filtered list where todo.id
s are not the same as the action.id
. Therefore all the todo
s that are not the one we wanted to delete.
That was easy, wasn’t it?
Now let’s test our component can let us delete a todo:
Line 1
Add jest
to the eslint exceptions.
Line 8
Create a mock function for our delete functionality.
Line 10 — 18
Refactor our previous single todos
prop to be an object that holds all the props we need.
Line 20
Let our component
shallow render and unpack all the props
previously specified.
Line 30 — 34
Test that clicking on a .todo-delete
element does indeed call our deleteTodo
function.
And then the code to make our test pass:
Line 36
Validation our deleteTodo
prop.
Line 4
Pass it in to our component.
Line 8 — 14
Add a ‘Delete’ button which will call the deleteTodo
function with the todo.id
as the argument on the onClick
event.
Now we need to hook it up to our UI via the App:
Line 36 — 38
Create the deleteTodo
prop that will dispatch the appropriate action.
Line 24
Validate it.
Line 8
Add it to the props for our component.
Line 12
Add it to the TodoList
component.
And it’s really just that simple. Unit tests and e2e tests should be passing and the functionality should be working in our App in the browser.
If you’re still with me then you’re doing pretty good, and definitely not a newbie! So it’s time for a little challenge. I’m not going to tell you how to do this, why not give it a go yourself?
Think about what you need.
Just above you were able to TDD all the functionality to delete a todo, do the same for undelete. Also think about how, where and when you’re going to store your last deleted todo. With that in place it should click!
It won’t be too difficult to do this, it may take half an hour or a couple of hours but you can do it. Try and TDD it for a solid challenge.
Then check out how I did it:
So our App is sort of working, well the stuff we’ve tested is working. But if you try and use it you may discover some bugs that we’ve not coded for. You could branch off and try and fix them and add more functionality if you wish, but one final challenge I’ll pose you before you do that is to disable the ‘Add Todo’ and ‘Undelete’ buttons when it’s not appropriate to click them.
Have a think about how you could implement this, google around a bit and give it a shot. We both know you can do it!
When you’re done have a look at how I did it. I definitely wouldn’t say there was a right or a wrong way, just different approaches:
As a front ender it pains me to even call this styled but I guess this isn’t a CSS tutorial. If you want to make it pretty then fill your boots. This is just what mine happens to look like:
High production value
This is optional and just for a laugh, but if you do want to deploy your app online easily for free then Heroku offers a quick fix. This will allow you to play around with production builds and your own CI/CD pipelines if you so wish.
First Get set up with Heroku.
Then follow the instructions for the heroku-buildpack for React.
Visit the App online here.
I’ve gone with the simple approach of just listing out how to setup, run and test our App.
Part 4 — You’re here now.
Yup, it really is. Have any feedback? Leave a message below.
I’m outie 9000.