reader: adds modules + boilerplate for tests, and coverage
* Adds tape.
* Adds a simple component test that can run in browser or node.
* Adds helpers for setting up components and testing updates/input/render.
* Adds disc to help inspect the size impact of modules on public/bundle.js.
* Adds a coverage tool.
Closes #2
Change-Id: I3429b1848cd2c9b0ba3f6fb533e31e692b90446d
diff --git a/.gitignore b/.gitignore
index 018dc7e..d86576c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@
node_modules
npm-debug.log
public/bundle.*
+coverage
+disc.html
diff --git a/.jshintignore b/.jshintignore
index 312a3a0..0d4db1c 100644
--- a/.jshintignore
+++ b/.jshintignore
@@ -1,2 +1,3 @@
node_modules
public/*.js
+coverage
diff --git a/.jshintrc b/.jshintrc
index 5d863c8..44fcb6d 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -25,6 +25,8 @@
"globals": {
"PDFJS": false,
- "window": true
+ "window": true,
+ "event": true,
+ "document": true
}
}
diff --git a/Makefile b/Makefile
index a0f2f90..ba5fb96 100644
--- a/Makefile
+++ b/Makefile
@@ -36,8 +36,15 @@
@jshint .
.PHONY:
-test: lint all
- @true
+test: lint node_modules
+ tape test/index.js
+
+coverage: $(js_files) node_modules
+ @istanbul cover --report html --print detail ./test/index.js
+ @touch coverage
+
+disk.html: browser/index.js $(js_files) node_modules
+ browserify --full-paths $< | discify > $@
.PHONY:
start: all
diff --git a/browser/components/vanadium/index.js b/browser/components/peers/index.js
similarity index 92%
rename from browser/components/vanadium/index.js
rename to browser/components/peers/index.js
index ba72ea1..8d632a0 100644
--- a/browser/components/vanadium/index.js
+++ b/browser/components/peers/index.js
@@ -7,6 +7,6 @@
// Wraps Vanadium functionality in a mercury style component so that state can
// be easily modified, observed, and rendered into the UI as appropriate.
module.exports = {
- state: require('./state'),
+ create: require('./state'),
render: require('./render')
};
diff --git a/browser/components/vanadium/render.js b/browser/components/peers/render.js
similarity index 66%
rename from browser/components/vanadium/render.js
rename to browser/components/peers/render.js
index c07d7c5..7e21473 100644
--- a/browser/components/vanadium/render.js
+++ b/browser/components/peers/render.js
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+var hg = require('mercury');
var h = require('mercury').h;
var format = require('format');
+var uuid = require('uuid');
module.exports = render;
@@ -13,7 +15,14 @@
h('li', format('status: %s', state.status)),
h('li', format('error: %s', state.error ? state.error.message : 'none')),
h('ul.peers', Object.keys(state.peers).map(function(key) {
- return h('li', format('peer: %s', key));
- }))
+ return h('li.peer', {
+ 'data-id': key
+ }, format('peer: %s', key));
+ })),
+ h('li', [
+ h('a.add-peer', {
+ 'ev-click': hg.send(channels.add, { id: uuid.v4() })
+ }, 'Add peer')
+ ])
]);
}
diff --git a/browser/components/peers/state.js b/browser/components/peers/state.js
new file mode 100644
index 0000000..a0e6807
--- /dev/null
+++ b/browser/components/peers/state.js
@@ -0,0 +1,30 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var debug = require('debug')('reader:vanadium:state');
+var hg = require('mercury');
+var uuid = require('uuid');
+
+module.exports = create;
+
+// Create state for the Vanadium component
+function create(options) {
+ debug('initialize state');
+
+ var state = hg.state({
+ error: hg.value(null),
+ id: hg.value(uuid.v4()),
+ status: hg.value('new'),
+ peers: hg.varhash({}),
+ channels: {
+ add: add
+ }
+ });
+
+ return state;
+}
+
+function add(state, data) {
+ state.peers.put(data.id, data);
+}
diff --git a/browser/components/vanadium/state.js b/browser/components/vanadium/state.js
deleted file mode 100644
index b0ba929..0000000
--- a/browser/components/vanadium/state.js
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 The Vanadium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-var vanadium = require('../../vanadium');
-var debug = require('debug')('reader:vanadium:state');
-var hg = require('mercury');
-var uuid = require('uuid');
-
-module.exports = create;
-
-// Create state for the Vanadium component
-function create(options) {
- debug('initialize state');
-
- var state = hg.state({
- error: hg.value(null),
- id: hg.value(null),
- status: hg.value(''),
- peers: hg.varhash({}),
- channels: {
- }
- });
-
- var config = {
- app: 'reader-example',
- id: uuid.v4()
- };
-
- vanadium(config)
- .on('error', function(err) {
- state.error.set(err);
- })
- .on('status', function(status) {
- state.status.set(status);
- })
- .on('name', function(name) {
- state.id.set(name);
- })
- .on('connect', function(name, service) {
- debug('connect :D %s %o', name, service);
- // NOTE: objects in the varhash might be better off as components depending
- // on how they need to be interacted with...
- state.peers.put(name, service);
- });
-
- return state;
-}
diff --git a/browser/index.js b/browser/index.js
index 0cc120a..9d3172c 100644
--- a/browser/index.js
+++ b/browser/index.js
@@ -11,7 +11,7 @@
var filePicker = require('./components/file-picker');
var pageControls = require('./components/page-control');
var pdf = require('./components/pdf');
-var vanadium = require('./components/vanadium');
+var peers = require('./components/peers');
domready(function ondomready() {
debug('domready');
@@ -20,12 +20,12 @@
var state = hg.state({
pdf: pdf.state(),
pageControls: pageControls.state(),
- vanadium: vanadium.state()
+ peers: peers.create()
});
// TODO(jasoncampbell): add an error component for aggregating, logging, and
// displaying errors in the UI.
- state.vanadium.error(function(err) {
+ state.peers.error(function(err) {
throw err;
});
@@ -45,6 +45,10 @@
}
});
+ // TODO(jasoncampbell): Add/couple Vanadium functionality to the state here
+ // instead of inside the peers component so that async paths which are hard to
+ // test/stub can be isolated to the application initialization.
+
hg.app(document.body, state, render);
});
@@ -52,7 +56,7 @@
if (state.pdf.pdf === null) {
return h('div', [
hg.partial(filePicker.render, state.pdf, state.pdf.channels),
- hg.partial(vanadium.render, state.vanadium, state.vanadium.channels)
+ hg.partial(peers.render, state.peers, state.peers.channels)
]);
} else {
return h('div', [
@@ -61,7 +65,7 @@
state.pageControls,
state.pageControls.channels),
hg.partial(pdf.render, state.pdf, state.pdf.channels),
- hg.partial(vanadium.render, state.vanadium, state.vanadium.channels)
+ hg.partial(peers.render, state.peers, state.peers.channels)
]);
}
}
diff --git a/browser/vanadium/index.js b/browser/vanadium/index.js
index 751edef..919580b 100644
--- a/browser/vanadium/index.js
+++ b/browser/vanadium/index.js
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+var window = require('global/window');
var debug = require('debug')('reader:vanadium-wrapper');
var vanadium = require('vanadium');
var inherits = require('inherits');
@@ -71,7 +72,9 @@
wrapper.emit('runtime', runtime);
wrapper.emit('status', 'initialized');
- window.addEventListener('beforeunload', beforeunload);
+ if (window.addEventListener) {
+ window.addEventListener('beforeunload', beforeunload);
+ }
var server = runtime.newServer();
var name = wrapper.name();
diff --git a/package.json b/package.json
index 47941e8..cf615b0 100644
--- a/package.json
+++ b/package.json
@@ -13,9 +13,12 @@
"license": "BSD",
"devDependencies": {
"browserify": "^10.2.4",
+ "disc": "^1.3.2",
+ "istanbul": "^0.3.17",
"jshint": "^2.8.0",
- "proxyquire": "^1.5.0",
+ "raf": "^3.0.0",
"st": "^0.5.4",
+ "synthetic-dom-events": "git://github.com/Raynos/synthetic-dom-events",
"tape": "^4.0.0"
},
"dependencies": {
diff --git a/test/components/dispatch.js b/test/components/dispatch.js
new file mode 100644
index 0000000..bf2f668
--- /dev/null
+++ b/test/components/dispatch.js
@@ -0,0 +1,21 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var event = require('synthetic-dom-events');
+var query = require('./query');
+
+module.exports = dispatch;
+
+function dispatch(type, selector) {
+ var nodes = query(selector);
+
+ if (! (nodes instanceof Array)) {
+ nodes = [ nodes ];
+ }
+
+ var length = nodes.length;
+ for (var i = 0; i < length; i++) {
+ nodes[i].dispatchEvent(event(type));
+ }
+}
diff --git a/test/components/query.js b/test/components/query.js
new file mode 100644
index 0000000..b028998
--- /dev/null
+++ b/test/components/query.js
@@ -0,0 +1,41 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var document = require('global/document');
+var separators = [ '.', '#' ];
+
+module.exports = query;
+
+function query(selector) {
+ if (typeof selector !== 'string') {
+ throw new Error('selector must be a string');
+ }
+
+ // TODO(jasoncampbell): guard against selectors that go more than one depth.
+
+ var separator;
+ var length = separators.length;
+ for (var i = 0; i < length; i++) {
+ if (selector.indexOf(separators[i]) > -1) {
+ separator = separators[i];
+ break;
+ }
+ }
+
+ var results;
+ switch (separator) {
+ case '.':
+ var className = selector.replace(separator, '');
+ results = document.getElementsByClassName(className);
+ break;
+ case '#':
+ var id = selector.replace(separator, '');
+ results = document.getElementById(id);
+ break;
+ default:
+ results = document.getElementsByTagName(selector);
+ }
+
+ return results;
+}
diff --git a/test/components/setup.js b/test/components/setup.js
new file mode 100644
index 0000000..570c31c
--- /dev/null
+++ b/test/components/setup.js
@@ -0,0 +1,35 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var document = require('global/document');
+var hg = require('mercury');
+
+module.exports = setup;
+
+// Wraps up functioanility for embedding a component in the document and setting
+// up some test cleanup to run after t.end() is called.
+//
+// SEE: http://git.io/vmR3O
+function setup(component, callback) {
+ var div = document.createElement('div');
+ document.body.appendChild(div);
+
+ var state = component.create();
+ var initial = state();
+ var remove = hg.app(div, state, render);
+
+ return function fn(t) {
+ t.once('end', function() {
+ state.set(initial);
+ document.body.removeChild(div);
+ remove();
+ });
+
+ callback(t, state);
+ };
+
+ function render(state) {
+ return hg.partial(component.render, state, state.channels);
+ }
+}
diff --git a/test/components/test-peers.js b/test/components/test-peers.js
new file mode 100644
index 0000000..ea743a0
--- /dev/null
+++ b/test/components/test-peers.js
@@ -0,0 +1,37 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var test = require('tape');
+var component = require('../../browser/components/peers');
+var raf = require('raf');
+var query = require('./query');
+var setup = require('./setup');
+var dispatch = require('./dispatch');
+
+test('components/peers - state', function(t) {
+ var state = component.create();
+
+ t.ok(state.id(), 'state should have id');
+ t.equal(state.status(), 'new');
+ t.same(state.peers(), {});
+ t.end();
+});
+
+test('components/peers - fake test', setup(component, function(t, state){
+ t.same(state.peers(), {});
+
+ dispatch('click', '.add-peer');
+
+ t.notSame(state.peers(), {});
+
+ raf(function() {
+ var nodes = query('.peer');
+ var element = nodes[0];
+
+ t.equal(nodes.length, 1);
+ t.ok(element['data-id'], 'should have data-id attribute');
+ t.equal(element.childNodes[0].data, 'peer: ' + element['data-id']);
+ t.end();
+ });
+}));
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..20ac3fe
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,5 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+require('./components/test-peers');