Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 9f8de10b072d7dcc8be1c40170250de7e151cfb0 @tj tj committed May 28, 2010
Showing with 404 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +3 −0 .gitmodules
  3. 0 History.md
  4. +27 −0 Makefile
  5. 0 Readme.md
  6. +283 −0 bin/expresso
  7. +1 −0 deps/jscoverage
  8. +26 −0 lib/a.js
  9. +12 −0 lib/b.js
  10. +34 −0 test/a.test.js
  11. +16 −0 test/b.test.js
@@ -0,0 +1,2 @@
+.DS_Store
+lib-cov
@@ -0,0 +1,3 @@
+[submodule "deps/jscoverage"]
+ path = deps/jscoverage
+ url = git://github.com/visionmedia/node-jscoverage.git
No changes.
@@ -0,0 +1,27 @@
+
+BIN = bin/expresso
+PREFIX = /usr/local
+JSCOV = deps/jscoverage/node-jscoverage
+
+test: $(BIN)
+ @./$(BIN) -I lib test/*.test.js
+
+test-cov: $(BIN) $(JSCOV) lib-cov
+ @./$(BIN) -I lib-cov test/*.test.js
+
+lib-cov:
+ @./$(JSCOV) lib lib-cov
+
+install: $(JSCOV) install-expresso
+ install $(JSCOV) $(PREFIX)/bin
+
+install-expresso:
+ install $(BIN) $(PREFIX)/bin
+
+$(JSCOV):
+ @cd deps/jscoverage && ./configure && make && mv jscoverage node-jscoverage
+
+clean:
+ @cd deps/jscoverage && git clean -fd
+
+.PHONY: test test-cov install install-expresso clean
No changes.
@@ -0,0 +1,283 @@
+#!/usr/bin/env node
+
+/*!
+ * Expresso
+ * Copyright(c) TJ Holowaychuk <tj@vision-media.ca>
+ * (MIT Licensed)
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert'),
+ childProcess = require('child_process'),
+ path = require('path'),
+ sys = require('sys'),
+ cwd = process.cwd(),
+ fs = require('fs');
+
+/**
+ * Expresso version.
+ */
+
+var version = '0.0.1';
+
+/**
+ * Usage documentation.
+ */
+
+var usage = [
+ 'usage: expresso [-h|--help] [-v|--version] [-i|-I|--include <path>]',
+ ' [-r|--require <module>] <file ...>'
+].join('\n')
+
+// Parse arguments
+
+var files = [],
+ args = process.argv.slice(2);
+
+while (args.length) {
+ var arg = args.shift();
+ switch (arg) {
+ case '-h':
+ case '--help':
+ sys.puts(usage);
+ process.exit(1);
+ break;
+ case '-v':
+ case '--version':
+ sys.puts(version);
+ process.exit(1);
+ break;
+ case '-i':
+ case '-I':
+ case '--include':
+ if (arg = args.shift()) {
+ require.paths.unshift(arg);
+ } else {
+ throw new Error('--include requires a path');
+ }
+ break;
+ case '-r':
+ case '--require':
+ if (arg = args.shift()) {
+ require(arg);
+ } else {
+ throw new Error('--require requires a path');
+ }
+ break;
+ default:
+ files.push(arg);
+ break;
+ }
+}
+
+// Alias deepEqual as eql for complex equality
+
+assert.eql = assert.deepEqual;
+
+// Report test coverage when available
+
+process.addListener('exit', function(){
+ sys.puts('');
+ if (typeof _$jscoverage === 'object') {
+ reportCoverage(_$jscoverage);
+ }
+});
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param {String} str
+ * @param {Number} width
+ * @return {String}
+ * @api private
+ */
+
+function lpad(str, width) {
+ str = String(str);
+ var n = width - str.length;
+ if (n < 1) return str;
+ while (n--) str = ' ' + str;
+ return str;
+}
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param {String} str
+ * @param {Number} width
+ * @return {String}
+ * @api private
+ */
+
+function rpad(str, width) {
+ str = String(str);
+ var n = width - str.length;
+ if (n < 1) return str;
+ while (n--) str = str + ' ';
+ return str;
+}
+
+/**
+ * Report test coverage.
+ *
+ * @param {Object} cov
+ * @api private
+ */
+
+function reportCoverage(cov) {
+ populateCoverage(cov);
+ sys.puts('\n \x1B[1mTest Coverage\x1B[0m');
+ var sep = ' +--------------------------------+----------+------+------+--------+',
+ lastSep = ' +----------+------+------+--------+';
+ sys.puts(sep);
+ sys.puts(' | filename | coverage | LOC | SLOC | missed |');
+ sys.puts(sep);
+ for (var name in cov) {
+ var file = cov[name];
+ if (file instanceof Array) {
+ sys.print(' | ' + rpad(name, 30));
+ sys.print(' | ' + lpad(file.coverage.toFixed(2), 8));
+ sys.print(' | ' + lpad(file.LOC, 4));
+ sys.print(' | ' + lpad(file.SLOC, 4));
+ sys.print(' | ' + lpad(file.totalMisses, 6));
+ sys.print(' |\n');
+ }
+ }
+ sys.puts(sep);
+ sys.print(' ' + rpad('', 30));
+ sys.print(' | ' + lpad(cov.coverage.toFixed(2), 8));
+ sys.print(' | ' + lpad(cov.LOC, 4));
+ sys.print(' | ' + lpad(cov.SLOC, 4));
+ sys.print(' | ' + lpad(cov.totalMisses, 6));
+ sys.print(' |\n');
+ sys.puts(lastSep);
+}
+
+/**
+ * Populate code coverage data.
+ *
+ * @param {Object} cov
+ * @api private
+ */
+
+function populateCoverage(cov) {
+ cov.LOC =
+ cov.SLOC =
+ cov.totalFiles =
+ cov.totalHits =
+ cov.totalMisses =
+ cov.coverage = 0;
+ for (var name in cov) {
+ var file = cov[name];
+ if (file instanceof Array) {
+ ++cov.totalFiles;
+ cov.totalHits += file.totalHits = coverage(file, true);
+ cov.totalMisses += file.totalMisses = coverage(file, false);
+ file.totalLines = file.totalHits + file.totalMisses;
+ cov.SLOC += file.SLOC = file.totalLines;
+ cov.LOC += file.LOC = file.source.length;
+ file.coverage = (file.totalHits / file.totalLines) * 100;
+ }
+ }
+ cov.coverage = (cov.totalHits / cov.SLOC) * 100;
+};
+
+/**
+ * Total coverage for the given file data.
+ *
+ * @param {Array} data
+ * @return {Type}
+ * @api private
+ */
+
+function coverage(data, val) {
+ var n = 0;
+ for (var i = 0, len = data.length; i < len; ++i) {
+ if (data[i] !== undefined && data[i] == val) ++n;
+ }
+ return n;
+};
+
+/**
+ * Assert that the given array-like object
+ * is empty (length of 0).
+ *
+ * @param {Array} arr
+ * @api public
+ */
+
+assert.empty = function(arr, msg) {
+ assert.equal(arr.length, 0, msg);
+};
+
+/**
+ * Run all test files.
+ *
+ * @param {Array} files
+ * @api public
+ */
+
+function run(files) {
+ if (files.length) {
+ files.forEach(function(file){
+ var title = path.basename(file, '.js')
+ runSuite(title, require(cwd + '/' + file.replace('.js', '')));
+ });
+ }
+}
+
+/**
+ * Run the given tests.
+ *
+ * @param {String} title
+ * @param {Object} tests
+ * @api private
+ */
+
+function runSuite(title, tests) {
+ var title = ' \x1B[1m' + title + '\x1B[0m ',
+ keys = Object.keys(tests),
+ total = keys.length,
+ start = new Date,
+ failures = [],
+ current = 0;
+ (function next(){
+ if (keys.length) {
+ var percent = Math.round(++current / (total + 1) * 100),
+ key = keys.shift(),
+ test = tests[key],
+ async = test.length === 2;
+ sys.print('\x1B[K %' + percent + ' ' + title + ' ' + key + '\r');
+ try {
+ if (async) {
+ var n = test(assert, function(){
+ if (!--n) next();
+ }) || 1;
+ } else {
+ test(assert);
+ next();
+ }
+ } catch (err) {
+ err.test = key;
+ failures.push(err);
+ next();
+ }
+ } else {
+ var duration = ((new Date - start) / 1000).toFixed(3),
+ passes = total - failures.length;
+ sys.print('\x1B[K %100' + title + '\x1B[32m' + passes + '\x1B[0m'
+ + ' \x1B[31m' + failures.length + '\x1B[0m'
+ + ' in ' + duration + ' seconds\n');
+ failures.forEach(function(assertion, i){
+ sys.puts('\n \x1B[1m' + i + ')\x1B[0m ' + assertion.stack);
+ });
+ }
+ })();
+}
+
+// Run test files
+
+run(files);
Submodule jscoverage added at 0d4608
@@ -0,0 +1,26 @@
+
+exports.upper = function(str){
+ if (typeof str === 'string') {
+ return str.toUpperCase();
+ } else {
+ return '';
+ }
+}
+
+exports.lower = function(str){
+ if (typeof str === 'string') {
+ return str.toLowerCase();
+ } else {
+ return '';
+ }
+}
+
+exports.lowerAsync = function(str, fn){
+ process.nextTick(function(){
+ if (typeof str === 'string') {
+ fn(str.toLowerCase());
+ } else {
+ fn('');
+ }
+ })
+}
@@ -0,0 +1,12 @@
+
+exports.selectAsync = function(arr, fn, callback){
+ process.nextTick(function(){
+ var selected = [];
+ for (var i = 0, len = arr.length; i < len; ++i) {
+ if (fn.call(arr, arr[i], i, arr)) {
+ selected.push(arr[i]);
+ }
+ }
+ callback(selected);
+ })
+}
Oops, something went wrong.

0 comments on commit 9f8de10

Please sign in to comment.