Skip to content

Commit

Permalink
update tests to new directory structure. still passing. #5
Browse files Browse the repository at this point in the history
  • Loading branch information
nelsonic committed Nov 1, 2018
1 parent c1e6156 commit 606f300
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 13 deletions.
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
"jsdom-global": "^3.0.2",
"live-server": "^1.2.0",
"pre-commit": "^1.2.2",
"qunit-tap": "^1.5.1",
"qunitjs": "^2.3.2",
"tap-spec": "^5.0.0",
"tape": "^4.9.1"
},
Expand Down
54 changes: 54 additions & 0 deletions test/counter-reset-keyboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// this file is borrowed from:
// https://github.com/dwyl/learn-elm-architecture-in-javascript/blob/master/examples/counter-reset-keyboard/counter.js
// it is included here purely for testing the "elmish" functions.

/* if require is available, it means we are in Node.js Land i.e. testing!
in the broweser, the "elmish" DOM functions are loaded in a <script> tag */
/* istanbul ignore next */
if (typeof require !== 'undefined' && this.window !== this) {
var { button, div, empty, mount, text } = require('../lib/elmish.js');
}

function update (action, model) { // Update function takes the current state
switch(action) { // and an action (String) runs a switch
case 'inc': return model + 1; // add 1 to the model
case 'dec': return model - 1; // subtract 1 from model
case 'reset': return 0; // reset state to 0 (Zero) git.io/v9KJk
default: return model; // if no action, return curent state.
} // (default action always returns current)
}

function view (model, signal) {
return div([], [
button(["class=inc", "id=inc", signal('inc')], [text('+')]), // increment
div(["class=count", "id=count"], [text(model.toString())]), // count
button(["class=dec", "id=dec", signal('dec')], [text('-')]), // decrement
button(["class=reset", "id=reset", signal('reset')], [text('Reset')])
]);
}

function subscriptions (signal) {
var UP_KEY = 38; // increment the counter when [↑] (up) key is pressed
var DOWN_KEY = 40; // decrement the counter when [↓] (down) key is pressed

document.addEventListener('keyup', function handler (e) {
switch (e.keyCode) {
case UP_KEY:
signal('inc')(); // invoke the signal > callback function directly
break;
case DOWN_KEY:
signal('dec')();
break;
}
});
}

/* The code block below ONLY Applies to tests run using Node.js */
/* istanbul ignore else */
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
subscriptions: subscriptions,
view: view,
update: update,
}
}
92 changes: 92 additions & 0 deletions test/counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// this file is borrowed from:
// https://github.com/dwyl/learn-elm-architecture-in-javascript/blob/master/examples/counter-reset/counter.js
// it is included here purely for testing the "elmish" functions.

// Define the Component's Actions:
var Inc = 'inc'; // increment the counter
var Dec = 'dec'; // decrement the counter
var Res = 'reset'; // reset counter: git.io/v9KJk

function update (action, model) { // Update function takes the current state
switch(action) { // and an action (String) runs a switch
case Inc: return model + 1; // add 1 to the model
case Dec: return model - 1; // subtract 1 from model
case Res: return 0; // reset state to 0 (Zero) git.io/v9KJk
default: return model; // if no action, return curent state.
} // (default action always returns current)
}

function view(model, signal) {
return container([ // Store DOM nodes in an array
button('+', signal, Inc), // then iterate to append them
div('count', model), // create div with stat as text
button('-', signal, Dec), // decrement counter
button('Reset', signal, Res) // reset counter
]); // forEach is ES5 so IE9+
} // yes, for loop is "faster" than forEach, but readability trumps "perf" here!

// Mount Function receives all MUV and mounts the app in the "root" DOM Element
function mount(model, update, view, root_element_id) {
var root = document.getElementById(root_element_id); // root DOM element
function signal(action) { // signal function takes action
return function callback() { // and returns callback
model = update(action, model); // update model according to action
empty(root);
root.appendChild(view(model, signal)); // subsequent re-rendering
};
};
root.appendChild(view(model, signal)); // render initial model (once)
}

// The following are "Helper" Functions which each "Do ONLY One Thing" and are
// used in the "View" function to render the Model (State) to the Browser DOM:

// empty the contents of a given DOM element "node" (before re-rendering)
function empty(node) {
while (node.firstChild) {
node.removeChild(node.firstChild);
}
} // Inspired by: stackoverflow.com/a/3955238/1148249

function button(text, signal, action) {
var button = document.createElement('button');
var text = document.createTextNode(text); // human-readable button text
button.appendChild(text); // text goes *inside* not attrib
button.className = action; // use action as CSS class
button.id = action;
// console.log(signal, ' action:', action)
button.onclick = signal(action); // onclick tells how to process
return button; // return the DOM node(s)
} // how to create a button in JavaScript: stackoverflow.com/a/8650996/1148249

function div(divid, text) {
var div = document.createElement('div');
div.id = divid;
div.className = divid;
if(text !== undefined) { // if text is passed in render it in a "Text Node"
var txt = document.createTextNode(text);
div.appendChild(txt);
}
return div;
}

// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section
function container(elements) {
var con = document.createElement('section');
con.className = 'counter';
elements.forEach(function(el) { con.appendChild(el) });
return con;
}

/* The code block below ONLY Applies to tests run using Node.js */
/* istanbul ignore else */
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
view: view,
mount: mount,
update: update,
div: div,
button: button,
empty: empty,
}
}
12 changes: 5 additions & 7 deletions test/elmish.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
const test = require('tape'); // https://github.com/dwyl/learn-tape
const fs = require('fs'); // read html files (see below)
const path = require('path'); // so we can open files cross-platform
const elmish = require('../examples/todo-list/elmish.js');
const html = fs.readFileSync(path.resolve(__dirname,
'../examples/todo-list/index.html'));
const elmish = require('../lib/elmish.js');
const html = fs.readFileSync(path.resolve(__dirname, '../index.html'));
require('jsdom-global')(html); // https://github.com/rstacruz/jsdom-global
const id = 'test-app'; // all tests use separate root element

Expand Down Expand Up @@ -31,7 +30,7 @@ test('elmish.empty("root") removes DOM elements from container', function (t) {
test('elmish.mount app expect state to be Zero', function (t) {
// use view and update from counter-reset example
// to confirm that our elmish.mount function is generic!
const { view, update } = require('../examples/counter-reset/counter.js');
const { view, update } = require('./counter.js');

const root = document.getElementById(id);
elmish.mount(7, update, view, id);
Expand Down Expand Up @@ -387,7 +386,7 @@ localStorage.removeItem('todos-elmish_' + id);
// // Test mount's localStorage using view and update from counter-reset example
// // to confirm that our elmish.mount localStorage works and is "generic".
test('elmish.mount sets model in localStorage', function (t) {
const { view, update } = require('../examples/counter-reset/counter.js');
const { view, update } = require('./counter.js');
const root = document.getElementById(id);

elmish.mount(7, update, view, id);
Expand Down Expand Up @@ -453,8 +452,7 @@ test('elmish.add_attributes onclick=signal(action) events!', function (t) {


test('subscriptions test using counter-reset-keyaboard ⌨️', function (t) {
const { view, update, subscriptions } =
require('../examples/counter-reset-keyboard/counter.js');
const { view, update, subscriptions } = require('./counter-reset-keyboard.js')
const root = document.getElementById(id);

// mount the counter-reset-keyboard example app WITH subscriptions:
Expand Down
7 changes: 3 additions & 4 deletions test/todo-app.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
const test = require('tape'); // https://github.com/dwyl/learn-tape
const fs = require('fs'); // to read html files (see below)
const path = require('path'); // so we can open files cross-platform
const html = fs.readFileSync(path.resolve(__dirname,
'../examples/todo-list/index.html')); // sample HTML file to initialise JSDOM.
const html = fs.readFileSync(path.resolve(__dirname, '../index.html'));
require('jsdom-global')(html); // https://github.com/rstacruz/jsdom-global
const app = require('../examples/todo-list/todo-app.js'); // functions to test
const app = require('../lib/todo-app.js'); // functions to test
const id = 'test-app'; // all tests use 'test-app' as root element
const elmish = require('../examples/todo-list/elmish.js'); // import "empty" etc
const elmish = require('../lib/elmish.js'); // import "elmish" core functions

test('`model` (Object) has desired keys', function (t) {
const keys = Object.keys(app.model);
Expand Down

0 comments on commit 606f300

Please sign in to comment.