Skip to content

Commit 28ab679

Browse files
committed
add instructions for empty function in todo-list.md for #44
1 parent eeec661 commit 28ab679

File tree

3 files changed

+122
-40
lines changed

3 files changed

+122
-40
lines changed

Diff for: examples/todo-list/elmish.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* `empty` the contents of a given DOM element "node" (before re-rendering).
77
* This is the *fastest* way according to: stackoverflow.com/a/3955238/1148249
88
* @param {Object} node the exact DOM node you want to empty
9-
* @return {Boolean} returns true once the DOM node is empty.
109
* @example
1110
* // returns true (once the 'app' node is emptied)
1211
* const node = document.getElementById('app');
@@ -16,7 +15,6 @@ function empty(node) {
1615
while (node.lastChild) {
1716
node.removeChild(node.lastChild);
1817
}
19-
return true;
2018
}
2119

2220
/**
@@ -25,7 +23,6 @@ function empty(node) {
2523
* @param {Function} update how the application state is updated ("controller")
2624
* @param {Function} view function that renders HTML/DOM elements with model.
2725
* @param {String} root_element_id root DOM element in which the app is mounted
28-
* @return {Boolean} returns true once app has been mounted.
2926
*/
3027
function mount(model, update, view, root_element_id) {
3128
var root = document.getElementById(root_element_id); // root DOM element
@@ -37,14 +34,19 @@ function mount(model, update, view, root_element_id) {
3734
};
3835
};
3936
view(signal, model, root); // render initial model (once)
40-
return true;
4137
}
4238

39+
/**
40+
* init initialises the document (Global) variable for DOM operations.
41+
* @param {Object} doc window.document in browser and JSDOM.document in tests.
42+
* @return {Object} document returns whatever is passed in.
43+
*/
4344
function init(doc){
44-
document = doc; // this is used for instantiating JSDOM. ignore!
45+
document = doc; // this is used for instantiating JSDOM for testing.
46+
return document;
4547
}
4648

47-
/* The code block below ONLY Applies to tests run using Node.js */
49+
/* module.exports is needed to run the functions using Node.js for testing! */
4850
/* istanbul ignore next */
4951
if (typeof module !== 'undefined' && module.exports) {
5052
module.exports = {

Diff for: test/elmish.test.js

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
const test = require('tape'); // https://github.com/dwyl/learn-tape
2-
const fs = require('fs');
3-
const path = require('path');
4-
const elmish = require(path.resolve(__dirname,
5-
'../examples/todo-list/elmish.js'))
1+
const test = require('tape'); // https://github.com/dwyl/learn-tape
2+
const fs = require('fs'); // read html files (see below)
3+
const path = require('path'); // so we can open files cross-platform
4+
const elmish = require('../examples/todo-list/elmish.js');
65
const html = fs.readFileSync(path.resolve(__dirname,
76
'../examples/todo-list/index.html'));
8-
require('jsdom-global')(html); // https://github.com/rstacruz/jsdom-global
9-
elmish.init(document); // pass the JSDOM into counter.js
10-
const id = 'test-app';
7+
require('jsdom-global')(html); // https://github.com/rstacruz/jsdom-global
8+
elmish.init(document); // pass JSDOM into elmish for DOM functions
9+
const id = 'test-app'; // all tests use separate root element
1110

1211
test('empty("root") removes DOM elements from container', function (t) {
1312
// setup the test div:
@@ -23,15 +22,14 @@ test('empty("root") removes DOM elements from container', function (t) {
2322
t.equal(actual, text, "Contents of mydiv is: " + actual + ' == ' + text);
2423
t.equal(root.childElementCount, 1, "Root element " + id + " has 1 child el");
2524
// empty the root DOM node:
26-
elmish.empty(root);
25+
elmish.empty(root); // exercise the `empty` function!
2726
t.equal(root.childElementCount, 0, "After empty(root) has 0 child elements!")
2827
t.end();
2928
});
3029

3130
// use view and update from counter-reset example
3231
// to confirm that our elmish.mount function is generic!
33-
const { view, update} = require(path.resolve(__dirname,
34-
'../examples/counter-reset/counter.js'));
32+
const { view, update } = require('../examples/counter-reset/counter.js');
3533

3634
test('elmish.mount app expect state to be Zero', function (t) {
3735
const root = document.getElementById(id);

Diff for: todo-list.md

+105-23
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,115 @@ please see:
7777
and
7878
[front-end-with-tape.md](https://github.com/dwyl/learn-tape/blob/master/front-end-with-tape.md)
7979

80+
It's "OK" to ask: "_Where do I **start** (my **TDD** quest)?_" <br />
81+
The answer is: create **two** new files:
82+
`examples/todo-list/elmish.js` and `test/elmish.test.js`
8083

84+
We will create a couple of tests and their corresponding functions _next_!
8185

86+
## Elm(_ish_)
87+
88+
Our **first step** is to _abstract_ and _generalise_
89+
the Elm Architecture (`mount`) and HTML ("DOM") functions
90+
we used in the "counter" example.
91+
92+
Recall that there are **3 parts** to "TEA": `model`, `update` and `view`. <br />
93+
These correspond to the `M`odel, `C`ontroller and `V`iew of "**MVC**".
94+
The _reason_ Elm refers to the "Controller" as "Update" is because
95+
this name _more accurately_ reflects what the function _does_:
96+
it updates the _state_ of the application.
8297

83-
### _Analyse_
98+
Our `update` and `view` functions form
99+
the "business logic" of our Todo List App,
100+
so we cannot abstract these. <br />
101+
The `update` function is a simple `switch` statement
102+
that "decides" how to to _update_ the app's `model`
103+
each `case` is functionality that is _specific_ to the Todo List App. <br />
104+
The `view` function _invokes_ several "helper" functions
105+
which create HTML elements e.g: `div` & `<button>`;
106+
these _can_ (_will_) be generalised (_below_).
107+
108+
Let's kick-off with a couple of "_familiar_" _generic_ functions:
109+
`empty` and `mount`.
110+
111+
112+
#### `empty` the DOM
113+
114+
Given that we _know_ we are going to use the `empty`
115+
function we used previously in our `counter`,
116+
`counter-reset` and `multiple-counters` examples (_in the "basic" TEA tutorial_)
117+
we can write a _test_ for the `empty` function quite easily.
118+
119+
In the `test/elmish.test.js` file, type the following code:
120+
```js
121+
const test = require('tape'); // https://github.com/dwyl/learn-tape
122+
const fs = require('fs'); // read html files (see below)
123+
const path = require('path'); // so we can open files cross-platform
124+
const elmish = require('../examples/todo-list/elmish.js');
125+
const html = fs.readFileSync(path.resolve(__dirname,
126+
'../examples/todo-list/index.html'));
127+
require('jsdom-global')(html); // https://github.com/rstacruz/jsdom-global
128+
elmish.init(document); // pass JSDOM into elmish for DOM functions
129+
const id = 'test-app'; // all tests use separate root element
130+
131+
test('empty("root") removes DOM elements from container', function (t) {
132+
// setup the test div:
133+
const text = 'Hello World!'
134+
const root = document.getElementById(id);
135+
const div = document.createElement('div');
136+
div.id = 'mydiv';
137+
const txt = document.createTextNode(text);
138+
div.appendChild(txt);
139+
root.appendChild(div);
140+
// check text of the div:
141+
const actual = document.getElementById('mydiv').textContent;
142+
t.equal(actual, text, "Contents of mydiv is: " + actual + ' == ' + text);
143+
t.equal(root.childElementCount, 1, "Root element " + id + " has 1 child el");
144+
// empty the root DOM node:
145+
elmish.empty(root); // exercise the `empty` function!
146+
t.equal(root.childElementCount, 0, "After empty(root) has 0 child elements!")
147+
t.end();
148+
});
149+
```
150+
151+
> _**Note**: if any line in this file is **unfamiliar** to you,
152+
please **first** go back over the previous example(s),
153+
**then** do bit of "googling" for any words or functions you don't recognise
154+
e.g: `childElementCount`,
155+
and if you are **still** "**stuck**"_,
156+
[***please open an
157+
issue***!](https://github.com/dwyl/learn-elm-architecture-in-javascript/issues)
158+
_It's **essential** that you **understand** each **character**
159+
in the code **before** continuing to **avoid** "**confusion**" later._
160+
161+
Now that we have the **test** for our `empty` function written,
162+
we can add the `empty` function to `examples/todo-list/elmish.js`:
163+
```js
164+
/**
165+
* `empty` the contents of a given DOM element "node" (before re-rendering).
166+
* This is the *fastest* way according to: stackoverflow.com/a/3955238/1148249
167+
* @param {Object} node the exact DOM node you want to empty
168+
* @example
169+
* // returns true (once the 'app' node is emptied)
170+
* const node = document.getElementById('app');
171+
* empty(node);
172+
*/
173+
function empty(node) {
174+
while (node.lastChild) {
175+
node.removeChild(node.lastChild);
176+
}
177+
}
178+
```
179+
180+
If the comment syntax above the function definition is _unfamiliar_,
181+
please see:
182+
[https://github.com/dwyl/**learn-jsdoc**](https://github.com/dwyl/learn-jsdoc)
84183

85-
Our _first_ step is to _analyse_ the required functionality of a Todo List.
184+
185+
### _Analyse_ the TodoMVC App to "Gather Requirements"
186+
187+
Once we have a
188+
Our _next_ step is to _analyse_ the required functionality of a Todo List.
86189

87190
### Todo List _Basic_ Functionality
88191

@@ -156,27 +259,6 @@ _so don't expect to **understand** it all the first time without study._
156259
_Don't worry, we will walk through building each feature in detail._
157260

158261

159-
## Elm(_ish_)
160-
161-
Our **first step** is to _abstract_ and _generalise_
162-
the Elm Architecture (`mount`) and HTML ("DOM") functions
163-
we used in the "counter" example.
164-
165-
Recall that there are **3 parts** to "TEA": `model`, `update` and `view`. <br />
166-
These correspond to the `M`odel, `C`ontroller and `V`iew of "**MVC**".
167-
The _reason_ Elm refers to the "Controller" as "Update" is because
168-
this name _more accurately_ reflects what the function _does_:
169-
it updates the _state_ of the application.
170-
171-
Our `update` and `view` functions form
172-
the "business logic" of our Todo List App,
173-
so we cannot abstract these. <br />
174-
The `update` function is a simple `switch` statement
175-
that "decides" how to to _update_ the app's `model`
176-
each `case` is functionality that is _specific_ to the Todo List App. <br />
177-
The `view` function _invokes_ several "helper" functions
178-
which create HTML elements e.g: `div` & `<button>`; these _can_ be generalised.
179-
180262

181263
### HTML Elements (Functions)
182264

0 commit comments

Comments
 (0)