Skip to content

Commit

Permalink
complete rewrite of bin/vows
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudhead committed Jun 5, 2010
1 parent af04a10 commit 88b5ade
Showing 1 changed file with 168 additions and 87 deletions.
255 changes: 168 additions & 87 deletions bin/vows
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,104 @@
var path = require('path'),
sys = require('sys'),
fs = require('fs'),
events = require('events'),
spawn = require('child_process').spawn;
events = require('events');

var inspect = require('eyes').inspector({ stream: null });

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

var console = require('vows/reporters/dot-matrix');
var console = require('vows/console');
var _reporter = require('vows/reporters/dot-matrix'), reporter = {
name: _reporter.name,
};

var options = {
reporter: reporter,
brief: false,
matcher: /.*/
};

var suites = [];

// Get rid of process runner
// ('node' in most cases)
var arg, args = [], argv = process.argv.slice(2);

var options = [];
//
// Parse command-line parameters
//
while (arg = argv.shift()) {
if (arg === __filename) { continue }

var argv = process.argv.slice(1).filter(function (a) {
if (a !== __filename) {
if (a[0] === '-') { options.push(a) }
return true;
if (arg[0] !== '-') {
args.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;
} else {
switch (arg) {
case 'json':
_reporter = require('vows/reporters/json');
break;
case 'spec':
_reporter = require('vows/reporters/spec');
break;
case 'verbose':
case 'v':
options.verbose = true;
break;
}
}
}
});
}

if (args.length === 0) {
options.reporter = reporter = require('vows/reporters/watch');
}

var vows = require('vows').config(options);
var stylize = require('vows/console').stylize;

if (argv.length > 0) {
argv.forEach(function (arg) {
runTest(arg, function (result) {
console.report(result);
msg('bin', 'argv', args);
msg('bin', 'options', { reporter: options.reporter.name, matcher: options.matcher });

if (args.length > 0) {
reporter.report = function (data) {
switch (data[0]) {
case 'subject':
_reporter.report(data);
break;
case 'vow':
case 'context':
_reporter.report(data);
break;
case 'end':
(options.verbose || _reporter.name === 'json') && _reporter.report(data);
break;
case 'finish':
options.verbose ? _reporter.print('\n') : _reporter.print(' ');
}
};
suites = args.map(function (a) {
a = path.join(process.cwd(), a.replace(/\.js$/, ''));
msg('runner', "loading", a);
return require(a).vows;
});
runSuites(suites, function (results) {
!options.verbose && _reporter.print('\n');
msg('runner', 'finish');
_reporter.report(['finish', results], {
write: function (str) {
sys.print(str.replace(/^\n\n/, '\n'));
}
});
});
} else {
msg('watcher', 'watching files in', process.cwd() + '/');
//
// Watch mode
//
Expand All @@ -34,16 +109,12 @@ if (argv.length > 0) {
'. ', '.. ', '... ', ' ...',
' ..', ' .', ' .', ' ..',
'... ', '.. ', '. '
], wheel = [
'-', '\\', '|', '/'
];
var current = 0,
runningTests = 0,
currentFile,
gracePeriod = 0,
status,
lastRun,
var status,
current = 0,
testFolder,
running = 0,
lastRun,
colors = ['32m', '33m', '31m'],
timer = setInterval(tick, 100),
root = fs.readdirSync('.');
Expand All @@ -56,40 +127,38 @@ if (argv.length > 0) {
throw new(Error)("Couldn't find test folder");
}

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

cursorHide();

// Run every 100ms
function tick() {
if (running) { return }

cursorSave();
eraseLine();
lastRun && esc(colors[status.errored ? 2 : (status.broken ? 1 : 0)]);
print(clock[current]);

if (runningTests > 0 || gracePeriod) {
gracePeriod--;
print(wheel[current]);
esc('39m');
print(' detected change in ' + currentFile + '...');
if (current == wheel.length - 1) { current = -1 }
} else {
print(clock[current]);
print(' ');
status && print(console.report(['finish', status], null));
if (lastRun) {
esc('90m');
print( ' (' + lastRun.valueOf() + ')');
}
if (current == clock.length - 1) { current = -1 }
}
if (current == clock.length - 1) { current = -1 }

current++;
current ++;
esc('39m');
cursorRestore();
}

//
// Utility functions
//
function print(str) { process.stdout.write(str) }
function print(str) { sys.print(str) }
function esc(str) { print("\033[" + str) }
function eraseLine() { esc("2K") }
function cursorSave() { esc("s") }
Expand All @@ -104,24 +173,35 @@ if (argv.length > 0) {
//
function changed(file) {
status = { honored: 0, broken: 0, errored: 0 };
gracePeriod = 10;
current = 0;

currentFile = file + '.js';

file = /-(test|spec)$/.test(file) ? path.join(testFolder, file + '.js')
: path.join(testFolder, file + '-' + testFolder + '.js');

paths(testFolder).forEach(function (p) {
runningTests ++;
runTest(p).addListener('finish', function (obj) {
runningTests --;
delete obj.time;
status.honored += obj.honored;
status.broken += obj.broken;
status.errored += obj.errored;
lastRun = new(Date);
});

msg('watcher', 'detected change in', file + '.js');

file = (/-(test|spec)$/.test(file) ? path.join(testFolder, file)
: path.join(testFolder, file + '-' + testFolder)) + '.js';

try {
fs.statSync(file);
} catch (e) {
msg('watcher', 'no equivalence found, running all tests.');
file = null;
}

var suites = (/-(test|spec)\.js$/.test(file) ? [file] : paths(testFolder)).map(function (p) {
return path.join(process.cwd(), p.replace(/\.js$/, ''));
}).map(function (p) {
delete(require.main.moduleCache[p]);
return p;
});

msg('watcher', 'loading', suites);
running ++;

runSuites(suites.map(function (s) { return require(s).vows }), function (results) {
delete(results.time);
print(console.result(results).join('') + '\n\n');
lastRun = new(Date);
status = results;
running --;
});
}
//
Expand Down Expand Up @@ -167,38 +247,39 @@ if (argv.length > 0) {
}
});
});

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

function runTest(file, callback) {
var test = spawn('node', options.concat([file, '--json'])), obj;
var promise = new(events.EventEmitter);

test.stdout.addListener('data', function (data) {
data.toString('utf8').trim().split('\n').forEach(function (chunk) {
try {
obj = JSON.parse(chunk);
promise.emit(obj[0], obj[1]);
if (callback) { callback(obj) }
} catch (e) {
sys.puts(e, chunk);
}
});
});

test.stderr.addListener('data', function (data) {
sys.debug(data.stack);
});
test.addListener('exit', function (code) {});
return promise;
function runSuites(suites, callback) {
var results = {
honored: 0,
broken: 0,
errored: 0,
total: 0,
time: 0
};
(function run(suites, callback) {
var suite = suites.shift();
if (suite) {
msg('runner', "running", suite.subject);
suite.run(function (result) {
Object.keys(result).forEach(function (k) {
results[k] += result[k];
});
run(suites, callback);
});
} else {
callback(results);
}
})(suites, callback);
}

function msg(cmd, subject, str) {
if (options.verbose) {
sys.puts( stylize('vows ', 'green')
+ stylize(cmd, 'bold')
+ ' ' + subject + ' '
+ (str ? (str[0] === '/' ? str : inspect(str)) : '')
);
}
}

0 comments on commit 88b5ade

Please sign in to comment.