diff options
| author | Jules Laplace <jules@okfoc.us> | 2012-09-24 16:22:07 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2012-09-24 16:22:07 -0400 |
| commit | 686106d544ecc3b6ffd4db2b665d3bc879a58d8c (patch) | |
| tree | a5b5e50237cef70e12f0745371896e96f5f6d578 /.bin/_mocha | |
ok
Diffstat (limited to '.bin/_mocha')
| -rwxr-xr-x | .bin/_mocha | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/.bin/_mocha b/.bin/_mocha new file mode 100755 index 0000000..3a7a903 --- /dev/null +++ b/.bin/_mocha @@ -0,0 +1,345 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander') + , exec = require('child_process').exec + , path = require('path') + , resolve = path.resolve + , mocha = require('../') + , utils = mocha.utils + , reporters = mocha.reporters + , interfaces = mocha.interfaces + , Context = mocha.Context + , Runner = mocha.Runner + , Suite = mocha.Suite + , vm = require('vm') + , fs = require('fs') + , join = path.join + , cwd = process.cwd(); + +/** + * Files. + */ + +var files = []; + +/** + * Images. + */ + +var images = { + fail: __dirname + '/../images/error.png' + , pass: __dirname + '/../images/ok.png' +}; + +// options + +program + .version(mocha.version) + .usage('[debug] [options] [files]') + .option('-r, --require <name>', 'require the given module') + .option('-R, --reporter <name>', 'specify the reporter to use', 'dot') + .option('-u, --ui <name>', 'specify user-interface (bdd|tdd|exports)', 'bdd') + .option('-g, --grep <pattern>', 'only run tests matching <pattern>') + .option('-t, --timeout <ms>', 'set test-case timeout in milliseconds [2000]') + .option('-s, --slow <ms>', '"slow" test threshold in milliseconds [75]', parseInt) + .option('-w, --watch', 'watch files for changes') + .option('-c, --colors', 'force enabling of colors') + .option('-C, --no-colors', 'force disabling of colors') + .option('-G, --growl', 'enable growl notification support') + .option('-d, --debug', "enable node's debugger, synonym for node --debug") + .option('-b, --bail', "bail after first test failure") + .option('--debug-brk', "enable node's debugger breaking on the first line") + .option('--globals <names>', 'allow the given comma-delimited global [names]', list, []) + .option('--ignore-leaks', 'ignore global variable leaks') + .option('--interfaces', 'display available interfaces') + .option('--reporters', 'display available reporters') + .option('--compilers <ext>:<module>,...', 'use the given module(s) to compile files', list, []) + +program.name = 'mocha'; + +// --reporters + +program.on('reporters', function(){ + console.log(); + console.log(' dot - dot matrix'); + console.log(' doc - html documentation'); + console.log(' spec - hierarchical spec list'); + console.log(' json - single json object'); + console.log(' progress - progress bar'); + console.log(' list - spec-style listing'); + console.log(' tap - test-anything-protocol'); + console.log(' landing - unicode landing strip'); + console.log(' xunit - xunit reportert'); + console.log(' teamcity - teamcity ci support'); + console.log(' html-cov - HTML test coverage'); + console.log(' json-cov - JSON test coverage'); + console.log(' min - minimal reporter (great with --watch)'); + console.log(' json-stream - newline delimited json events'); + console.log(' markdown - markdown documentation (github flavour)'); + console.log(); + process.exit(); +}); + +// --interfaces + +program.on('interfaces', function(){ + console.log(''); + console.log(' bdd'); + console.log(' tdd'); + console.log(' qunit'); + console.log(' exports'); + console.log(''); + process.exit(); +}); + +// -r, --require + +module.paths.push(cwd, join(cwd, 'node_modules')); + +program.on('require', function(mod){ + var abs = path.existsSync(mod) + || path.existsSync(mod + '.js'); + + if (abs) mod = join(cwd, mod); + require(mod); +}); + +// mocha.opts support + +try { + var opts = fs.readFileSync('test/mocha.opts', 'utf8') + .trim() + .split(/\s+/); + + process.argv = process.argv + .slice(0, 2) + .concat(opts.concat(process.argv.slice(2))); +} catch (err) { + // ignore +} + +// parse args + +program.parse(process.argv); + +// infinite stack traces + +Error.stackTraceLimit = Infinity; // TODO: config + +// reporter + +var suite = new Suite('', new Context) + , Base = require('../lib/reporters/base') + , Reporter = require('../lib/reporters/' + program.reporter) + , ui = interfaces[program.ui](suite); + +// --no-colors + +if (!program.colors) Base.useColors = false; + +// --colors + +if (~process.argv.indexOf('--colors') || + ~process.argv.indexOf('-c')) { + Base.useColors = true; +} + +// --slow <ms> + +if (program.slow) Base.slow = program.slow; + +// --timeout + +if (program.timeout) suite.timeout(program.timeout); + +// --bail + +suite.bail(program.bail); + +// custom compiler support + +var extensions = ['js']; +program.compilers.forEach(function(c) { + var compiler = c.split(':') + , ext = compiler[0] + , mod = compiler[1]; + + if (mod[0] == '.') mod = join(process.cwd(), mod); + require(mod); + extensions.push(ext); +}); + +var re = new RegExp('\\.(' + extensions.join('|') + ')$'); + +// files + +var files = program.args; + +// default files to test/*.{js,coffee} + +if (!files.length) { + files = fs.readdirSync('test').filter(function(path){ + return path.match(re); + }).map(function(path){ + return join('test', path); + }); +} + +// resolve + +files = files.map(function(path){ + return resolve(path); +}); + +// --watch + +if (program.watch) { + console.log(); + hideCursor(); + process.on('SIGINT', function(){ + showCursor(); + console.log('\n'); + process.exit(); + }); + + var frames = [ + ' \033[96m◜ \033[90mwatching\033[0m' + , ' \033[96m◠ \033[90mwatching\033[0m' + , ' \033[96m◝ \033[90mwatching\033[0m' + , ' \033[96m◞ \033[90mwatching\033[0m' + , ' \033[96m◡ \033[90mwatching\033[0m' + , ' \033[96m◟ \033[90mwatching\033[0m' + ]; + + var watchFiles = utils.files(cwd); + + function loadAndRun() { + load(files, function(){ + run(suite, function(){ + play(frames); + }); + }); + } + + function purge() { + watchFiles.forEach(function(file){ + delete require.cache[file]; + }); + } + + loadAndRun(); + + utils.watch(watchFiles, function(){ + purge(); + stop() + suite = suite.clone(); + ui = interfaces[program.ui](suite); + loadAndRun(); + }); + + return; +} + +// load + +load(files, function(){ + run(suite, process.exit); +}); + +// require test files before +// running the root suite + +function load(files, fn) { + var pending = files.length; + files.forEach(function(file){ + delete require.cache[file]; + suite.emit('pre-require', global, file); + suite.emit('require', require(file), file); + suite.emit('post-require', global, file); + --pending || fn(); + }); +} + +// run the given suite + +function run(suite, fn) { + suite.emit('run'); + var runner = new Runner(suite); + var reporter = new Reporter(runner); + runner.globals(program.globals); + if (program.ignoreLeaks) runner.ignoreLeaks = true; + if (program.grep) runner.grep(new RegExp(program.grep)); + if (program.growl) growl(runner, reporter); + runner.run(fn); +} + +// enable growl notifications + +function growl(runner, reporter) { + var notify = require('growl'); + + runner.on('end', function(){ + var stats = reporter.stats; + if (stats.failures) { + var msg = stats.failures + ' of ' + runner.total + ' tests failed'; + notify(msg, { title: 'Failed', image: images.fail }); + } else { + notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { + title: 'Passed' + , image: images.pass + }); + } + }); +} + +/** + * Parse list. + */ + +function list(str) { + return str.split(/ *, */); +} + +/** + * Hide the cursor. + */ + +function hideCursor(){ + process.stdout.write('\033[?25l'); +}; + +/** + * Show the cursor. + */ + +function showCursor(){ + process.stdout.write('\033[?25h'); +}; + +/** + * Stop play()ing. + */ + +function stop() { + process.stdout.write('\033[2K'); + clearInterval(play.timer); +} + +/** + * Play the given array of strings. + */ + +function play(arr, interval) { + var len = arr.length + , interval = interval || 100 + , i = 0; + + play.timer = setInterval(function(){ + var str = arr[i++ % len]; + process.stdout.write('\r' + str); + }, interval); +} |
