Skip to content

Commit c40a583

Browse files
committed
add tests for 6, 7 & 8 for #48 (shift up a gear! time to get this done!!)
1 parent e367ce8 commit c40a583

File tree

4 files changed

+291
-4
lines changed

4 files changed

+291
-4
lines changed

edit-todo.md

+194
Original file line numberDiff line numberDiff line change
@@ -844,3 +844,197 @@ document.addEventListener('keyup', function handler (e) {
844844

845845
when you re-run the tests, they will pass:
846846
![cancel-editing-on-esc-keypress-test-passing](https://user-images.githubusercontent.com/194400/45189286-15e05d80-b230-11e8-938c-4df80e49fda9.png)
847+
848+
### 6. Counter
849+
850+
```
851+
✓ should display the current number of todo items
852+
```
853+
854+
#### 6. Counter _Test_
855+
856+
Append following test code to your `test/todo-app.test.js` file:
857+
858+
```js
859+
test.only('6. Counter > should display the current number of todo items',
860+
function (t) {
861+
elmish.empty(document.getElementById(id));
862+
const model = {
863+
todos: [
864+
{ id: 0, title: "Make something people want.", done: false },
865+
{ id: 1, title: "Bootstrap for as long as you can", done: false },
866+
{ id: 2, title: "Let's solve our own problem", done: false }
867+
],
868+
hash: '#/'
869+
};
870+
// render the view and append it to the DOM inside the `test-app` node:
871+
elmish.mount(model, app.update, app.view, id, app.subscriptions);
872+
// count:
873+
const count = parseInt(document.getElementById('count').textContent, 10);
874+
t.equal(count, model.todos.length, "displays todo item count: " + count);
875+
876+
elmish.empty(document.getElementById(id)); // clear DOM ready for next test
877+
localStorage.removeItem('todos-elmish_' + id);
878+
t.end();
879+
});
880+
```
881+
882+
Thankfully, the counter was already implemented above
883+
so this test **_already_ passes**:
884+
885+
![counter-test-passing](https://user-images.githubusercontent.com/194400/45190621-ca7d7d80-b236-11e8-92b3-5a4fbda6f12a.png)
886+
887+
Just keep on [_movin_'](https://youtu.be/uvRBUw_Ls2o)
888+
889+
890+
### 7. Clear Completed Button
891+
892+
When items are complete we should be able to `delete` them in bulk.
893+
894+
```
895+
✓ should display the number of completed items
896+
✓ should remove completed items when clicked
897+
✓ should be hidden when there are no items that are completed
898+
```
899+
900+
#### 7. Clear Completed Button _Test_
901+
902+
Append following test code to your `test/todo-app.test.js` file:
903+
904+
```js
905+
test.only('7. Clear Completed > should display the number of completed items',
906+
function (t) {
907+
elmish.empty(document.getElementById(id));
908+
const model = {
909+
todos: [
910+
{ id: 0, title: "Make something people want.", done: false },
911+
{ id: 1, title: "Bootstrap for as long as you can", done: true },
912+
{ id: 2, title: "Let's solve our own problem", done: true }
913+
],
914+
hash: '#/'
915+
};
916+
// render the view and append it to the DOM inside the `test-app` node:
917+
elmish.mount(model, app.update, app.view, id, app.subscriptions);
918+
// count todo items in DOM:
919+
t.equal(document.querySelectorAll('.view').length, 3,
920+
"at the start, there are 3 todo items in the DOM.");
921+
922+
// count completed items
923+
const completed_count =
924+
parseInt(document.getElementById('completed-count').textContent, 10);
925+
const done_count = model.todos.filter(function(i) {return i.done }).length;
926+
t.equal(completed_count, done_count,
927+
"displays completed items count: " + completed_count);
928+
929+
// clear completed items:
930+
const button = document.querySelectorAll('.clear-completed')[0];
931+
button.click();
932+
933+
// confirm that there is now only ONE todo list item in the DOM:
934+
t.equal(document.querySelectorAll('.view').length, 1,
935+
"after clearing completed items, there is only 1 todo item in the DOM.");
936+
937+
// no clear completed button in the DOM when there are no "done" todo items:
938+
t.equal(document.querySelectorAll('clear-completed').length, 0,
939+
'no clear-completed button when there are no done items.')
940+
941+
elmish.empty(document.getElementById(id)); // clear DOM ready for next test
942+
localStorage.removeItem('todos-elmish_' + id);
943+
t.end();
944+
});
945+
```
946+
947+
#### 7. Clear Completed Button _Implementation_
948+
949+
First we need to update the `button` section in the `render_footer` function
950+
to include the `done` count:
951+
952+
_Before:_
953+
954+
```js
955+
button(["class=clear-completed", "style=display:" + display_clear],
956+
[
957+
text("Clear completed")
958+
]
959+
)
960+
```
961+
962+
_After:_
963+
964+
```js
965+
button(["class=clear-completed", "style=display:" + display_clear,
966+
signal('CLEAR_COMPLETED')
967+
],
968+
[
969+
text("Clear completed ["),
970+
span(["id=completed-count"], [
971+
text(done)
972+
]),
973+
text("]")
974+
]
975+
)
976+
```
977+
978+
_Seconde_ we need to add a `'CLEAR_COMPLETED'` `case` to the `update` function:
979+
980+
```js
981+
case 'CLEAR_COMPLETED':
982+
new_model.todos = new_model.todos.filter(function (item) {
983+
return !item.done; // only return items which are item.done = false
984+
});
985+
break;
986+
```
987+
988+
The tests should pass:
989+
990+
![clear-completed-button-tests-passing](https://user-images.githubusercontent.com/194400/45191359-a58b0980-b23a-11e8-91bf-dcb016d6f4bb.png)
991+
992+
<br />
993+
994+
### 8. Persistence > Save Todo List items to `localStorage`
995+
996+
```
997+
✓ should persist its data
998+
```
999+
1000+
#### 8. Persistence _Test_
1001+
1002+
We have already covered saving the `model`
1003+
to `localStorage` in _detail_ (_above_),
1004+
we are adding a "proxy" test for completeness:
1005+
1006+
```js
1007+
test.only('8. Persistence > should persist its data', function (t) {
1008+
elmish.empty(document.getElementById(id));
1009+
const model = {
1010+
todos: [
1011+
{ id: 0, title: "Make something people want.", done: false }
1012+
],
1013+
hash: '#/'
1014+
};
1015+
// render the view and append it to the DOM inside the `test-app` node:
1016+
elmish.mount(model, app.update, app.view, id, app.subscriptions);
1017+
// confirm that the model is saved to localStorage
1018+
console.log('localStorage', localStorage.getItem('todos-elmish_' + id));
1019+
t.equal(localStorage.getItem('todos-elmish_' + id),
1020+
JSON.stringify(model), "data is persisted to localStorage");
1021+
1022+
elmish.empty(document.getElementById(id)); // clear DOM ready for next test
1023+
localStorage.removeItem('todos-elmish_' + id);
1024+
t.end();
1025+
});
1026+
```
1027+
1028+
Again, this test should _already_ pass:
1029+
1030+
![persistence-test-passing](https://user-images.githubusercontent.com/194400/45190477-0a903080-b236-11e8-991c-bab61efb3d22.png)
1031+
1032+
### 9. Routing
1033+
1034+
The following assertions:
1035+
```
1036+
✓ should allow me to display active items
1037+
✓ should allow me to display completed items
1038+
✓ should allow me to display all items
1039+
✓ should highlight the currently applied filter
1040+
```

examples/todo-list/todo-app.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ function update(action, model, data) {
101101
new_model.clicked = false;
102102
new_model.editing = false;
103103
break;
104+
case 'CLEAR_COMPLETED':
105+
new_model.todos = new_model.todos.filter(function (item) {
106+
return !item.done; // only return items which are item.done = false
107+
});
108+
break;
104109
default: // if action unrecognised or undefined,
105110
return model; // return model unmodified
106111
} // see: https://softwareengineering.stackexchange.com/a/201786/211301
@@ -234,9 +239,15 @@ function render_footer (model, signal) {
234239
])
235240
]), // </ul>
236241
button(["class=clear-completed", "style=display:" + display_clear,
237-
// signal('CLEAR_COMPLETED')
242+
signal('CLEAR_COMPLETED')
238243
],
239-
[text("Clear completed")]
244+
[
245+
text("Clear completed ["),
246+
span(["id=completed-count"], [
247+
text(done)
248+
]),
249+
text("]")
250+
]
240251
)
241252
])
242253
)

test/todo-app.test.js

+83-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,6 @@ test('5.2.2 Slow clicks do not count as double-click > no edit!', function (t) {
473473
}, 301)
474474
});
475475

476-
477476
test('5.3 [ENTER] Key in edit mode triggers SAVE action', function (t) {
478477
elmish.empty(document.getElementById(id));
479478
localStorage.removeItem('todos-elmish_' + id);
@@ -548,3 +547,86 @@ test('5.5 CANCEL should cancel edits on escape', function (t) {
548547
model.todos[1].title, 'todo id 1 has title: ' + model.todos[1].title);
549548
t.end();
550549
});
550+
551+
test('6. Counter > should display the current number of todo items',
552+
function (t) {
553+
elmish.empty(document.getElementById(id));
554+
const model = {
555+
todos: [
556+
{ id: 0, title: "Make something people want.", done: false },
557+
{ id: 1, title: "Bootstrap for as long as you can", done: false },
558+
{ id: 2, title: "Let's solve our own problem", done: false }
559+
],
560+
hash: '#/'
561+
};
562+
// render the view and append it to the DOM inside the `test-app` node:
563+
elmish.mount(model, app.update, app.view, id, app.subscriptions);
564+
// count:
565+
const count = parseInt(document.getElementById('count').textContent, 10);
566+
t.equal(count, model.todos.length, "displays todo item count: " + count);
567+
568+
elmish.empty(document.getElementById(id)); // clear DOM ready for next test
569+
localStorage.removeItem('todos-elmish_' + id);
570+
t.end();
571+
});
572+
573+
test.only('7. Clear Completed > should display the number of completed items',
574+
function (t) {
575+
elmish.empty(document.getElementById(id));
576+
const model = {
577+
todos: [
578+
{ id: 0, title: "Make something people want.", done: false },
579+
{ id: 1, title: "Bootstrap for as long as you can", done: true },
580+
{ id: 2, title: "Let's solve our own problem", done: true }
581+
],
582+
hash: '#/'
583+
};
584+
// render the view and append it to the DOM inside the `test-app` node:
585+
elmish.mount(model, app.update, app.view, id, app.subscriptions);
586+
// count todo items in DOM:
587+
t.equal(document.querySelectorAll('.view').length, 3,
588+
"at the start, there are 3 todo items in the DOM.");
589+
590+
// count completed items
591+
const completed_count =
592+
parseInt(document.getElementById('completed-count').textContent, 10);
593+
const done_count = model.todos.filter(function(i) {return i.done }).length;
594+
t.equal(completed_count, done_count,
595+
"displays completed items count: " + completed_count);
596+
597+
// clear completed items:
598+
const button = document.querySelectorAll('.clear-completed')[0];
599+
button.click();
600+
601+
// confirm that there is now only ONE todo list item in the DOM:
602+
t.equal(document.querySelectorAll('.view').length, 1,
603+
"after clearing completed items, there is only 1 todo item in the DOM.");
604+
605+
// no clear completed button in the DOM when there are no "done" todo items:
606+
t.equal(document.querySelectorAll('clear-completed').length, 0,
607+
'no clear-completed button when there are no done items.')
608+
609+
elmish.empty(document.getElementById(id)); // clear DOM ready for next test
610+
localStorage.removeItem('todos-elmish_' + id);
611+
t.end();
612+
});
613+
614+
test('8. Persistence > should persist its data', function (t) {
615+
elmish.empty(document.getElementById(id));
616+
const model = {
617+
todos: [
618+
{ id: 0, title: "Make something people want.", done: false }
619+
],
620+
hash: '#/'
621+
};
622+
// render the view and append it to the DOM inside the `test-app` node:
623+
elmish.mount(model, app.update, app.view, id, app.subscriptions);
624+
// confirm that the model is saved to localStorage
625+
console.log('localStorage', localStorage.getItem('todos-elmish_' + id));
626+
t.equal(localStorage.getItem('todos-elmish_' + id),
627+
JSON.stringify(model), "data is persisted to localStorage");
628+
629+
elmish.empty(document.getElementById(id)); // clear DOM ready for next test
630+
localStorage.removeItem('todos-elmish_' + id);
631+
t.end();
632+
});

todo-list.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1325,7 +1325,7 @@ _however_ we still cannot _interact_ with the app.
13251325
_Next_ we're going to move to "wiring-up" the _functionality_
13261326
to construct the UX.
13271327

1328-
## _Fun_ctionality - The _Fun_ Part!
1328+
## Functionality - The _Fun_ Part!
13291329

13301330
With all the "foundation" well defined and tested,
13311331
we can _confidently_ move on to building out the _features_

0 commit comments

Comments
 (0)