Skip to content

Commit

Permalink
bin/vows, autotesting utility
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudhead committed May 2, 2010
1 parent 051bb40 commit 1a64009
Showing 1 changed file with 180 additions and 0 deletions.
180 changes: 180 additions & 0 deletions bin/vows
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#!/usr/bin/env node

var path = require('path'),
sys = require('sys'),
fs = require('fs'),
exec = require('child_process').exec,
Script = process.binding('evals').Script;

require.paths.unshift(path.join(__dirname, '..', 'lib'));

var argv = [], options = {
matcher: /.*/,
brief: false
};

//
// Parse command-line parameters
//
for (var i = 0, arg; i < process.argv.length; i++) {
arg = process.argv[i];

if (arg === __filename) { continue }

if (arg[0] !== '-') {
argv.push(arg);
} else {
arg = arg.match(/^--?(.*)/)[1];

if (arg[0] === 'R') {
options.matcher = new(RegExp)(arg.slice(1));
} else if (arg in options) {
options[arg] = true;
}
}
}

// Get rid of process runner
// ('node' in most cases)
argv = argv.slice(1);

var vows = require('vows').config(options);

if (argv.length > 0) {
argv.forEach(function (arg) {
runTest(arg);
});
} else {
//
// Watch mode
//
vows.options.brief = true;

(function () {
var clock = [
'. ', '.. ', '... ', ' ...',
' ..', ' .', ' .', ' ..',
'... ', '.. ', '. '
];
var current = 0,
status = 0,
runningTests = false,
statusText = '',
colors = ['\033[32m', '\033[33m', '\033[91m'],
timer = setInterval(tick, 100);

cursorHide();

// Run every 100ms
function tick() {
cursorSave();
eraseLine();
print(colors[status]);
print(clock[current]);

if (runningTests) {
print(' \033[39mrunning tests...');
} else {
print(' ' + statusText);
}

print('\033[39m');
cursorRestore();
current = (current == clock.length - 1) ? 0 : current + 1;
}

//
// Utility functions
//
function print(str) { process.stdout.write(str) }
function eraseLine() { print("\033[2K") }
function cursorSave() { print("\033[s") }
function cursorRestore() { print("\033[u") }
function cursorHide() { print("\033[?25l") }
function cursorShow() { print("\033[?25h") }
function cleanup() { cursorShow(), print('\n') }

//
// Called when a file has been modified.
// Run the matching tests and change the status.
//
function changed(file) {
runningTests = true;
runTest("test/" + file + "-test.js").addListener('end', function (h, b, e) {
runningTests = false;
statusText = h + " honored, " +
b + " broken, " +
e + " errored";

if (b || e) {
eraseLine();
status = e ? 2 : 1;
} else {
status = 0;
}
});
}
//
// Recursively traverse a hierarchy, returning
// a list of all relevant .js files.
//
function paths(dir) {
var paths = [];

try { fs.statSync(dir) }
catch (e) { return [] }

(function traverse(dir, stack) {
stack.push(dir);
fs.readdirSync(stack.join('/')).forEach(function (file) {
var path = stack.concat([file]).join('/'),
stat = fs.statSync(path);

if (file[0] == '.' || file === 'vendor') {
return;
} else if (stat.isFile() && /\.js$/.test(file)) {
paths.push(path);
} else if (stat.isDirectory()) {
traverse(file, stack);
}
});
stack.pop();
})(dir || '.', []);

return paths;
}

//
// Watch all relevant files in lib/ and src/,
// and call `changed()` on change.
//
paths('lib').concat(paths('src')).forEach(function (p) {
fs.watchFile(p, function (current, previous) {
if (new(Date)(current.mtime).valueOf() ===
new(Date)(previous.mtime).valueOf()) { return }
else {
changed(path.basename(p, '.js'));
}
});
});

process.addListener('exit', cleanup);
process.addListener('SIGINT', function () {
cleanup();
process.exit();
});
process.addListener('SIGQUIT', function () {
changed();
});
})();
}

function runTest(file) {
var code = (function (require, __filename, __dirname) {
/* content */
}).toString().replace('/* content */', fs.readFileSync(file));

return Script.runInThisContext('(' + code + ')', file)
.call(global, require, file, path.dirname(file));
}

0 comments on commit 1a64009

Please sign in to comment.