#!/usr/bin/env node var nodeunit = require('nodeunit'), fs = require('fs'), path = require('path'), AssertionError = require('assert').AssertionError; require('console.log'); var optimist = require('optimist') .usage('Run the jsdom test suite') .alias('s', 'suites') .string('s') .describe('s', 'suites that you want to run. ie: -s level1/core,1/html,html') .alias('f', 'fail-fast') .describe('f', 'stop on the first failed test') .alias('h', 'help') .describe('h', 'show the help') .alias('t', 'tests') .describe('t', 'choose the test cases to run. ie: -t jquery') .alias('d', 'debug') .describe('d', 'run in node\'s interactive debugger mode') .alias('v', 'verbose') .describe('v', 'show all tests that are being run'); var argv = optimist.argv; if (argv.help) { optimist.showHelp(); process.exit(); } var totalTests = 0; var failedTests = 0; var passedTests = 0; var modules = {}; var currentModule = ""; var moduleIndex = 0; var start = new Date().getTime(); var fileFilter = []; var testFilter = []; Error.stackTraceLimit = 100; if (argv.suites) { fileFilter = argv.suites.replace(/\s/g, '').split(','); } if (argv.tests) { testFilter = argv.tests.replace(/\s/g, '').split(','); } var assert = require('nodeunit/lib/assert'); require('nodeunit/lib/assert').equal = function equal(actual, expected, message) { if (actual != expected) { if (actual && actual.nodeType) { actual = actual.toString(); } if (expected && expected.nodeType) { expected = expected.toString(); } assert.fail(actual, expected, message, '==', assert.equal); } }; assert.domSame = function(actual, expected, message) { if(expected != actual) { assert.equal(expected.nodeType, actual.nodeType); assert.equal(expected.nodeValue, actual.nodeValue); } }; var files = [ "level1/core.js", "level1/html.js", "level1/svg.js", "level2/core.js", "level2/html.js", "level2/style.js", "level2/extra.js", //"level3/core.js", //"level3/ls.js", "level3/xpath.js", "window/index.js", "window/script.js", "window/frame.js", "sizzle/index.js", "jsdom/index.js", "jsonp/jsonp.js" ]; if (fileFilter.length > 0) { files = files.filter(function(val) { var ok = false; fileFilter.forEach(function(v) { if (val.indexOf(v) > -1) { ok = true; } }); return ok; }); } var modules = {}; var modulesToRun = {}; files.map(function (p) { var required = require(path.join(__dirname, p)); var module = required.tests || required; var filteredModule = {}; if (testFilter.length) { var moduleKeys = Object.keys(module); testFilter.forEach(function(filter) { filter = filter.toLowerCase(); moduleKeys.forEach(function(moduleKey) { if (moduleKey.toLowerCase().indexOf(filter) > -1) { filteredModule[moduleKey] = module[moduleKey]; } }); }); module = filteredModule; } if (module && Object.keys(module).length > 0) { modulesToRun[p] = module; } }); nodeunit.runModules(modulesToRun, { moduleStart: function (name) { currentModule = name.replace('.js', ''); console.log("running", name, currentModule); modules[currentModule] = { total : 0, fail : 0, pass : 0 }; moduleIndex++; }, moduleDone: function (name, assertions) { if (argv['verbose']) { console.log(' '); } }, testStart: function (test) { modules[currentModule].total++; if (argv['verbose']) { process.stdout.write(' ' + test[0] + ' ...'); } }, testDone: function (test, assertions) { if (argv['verbose']) { console.log(' done'); } totalTests++; if (!assertions.failures()) { passedTests++; modules[currentModule].pass++; } else { failedTests++; modules[currentModule].fail++; console.log('✖ ' + currentModule + '/' + test); assertions.forEach(function (a) { if (a.failed()) { if (a.error instanceof AssertionError) { a = nodeunit.utils.betterErrors(a); if (a.message) { console.log( 'Assertion Message: ' + assertion_message(a.message) + '\n' + 'expected:', a.error.expected, 'got:', a.error.actual ); } } else { if (a.error.expected || a.error.actual) { console.log('\nERROR', a.error.expected, 'vs', a.error.actual, '\n'); } console.log(a.error.message, a.error.stack, (new Error()).stack); } } else { console.log(a.message); } }); if (argv['fail-fast']) { process.exit(); } } }, done: function (assertions) { var end = new Date().getTime(); var duration = end - start; var maxWidths = { name : 0, ratio : 0, percent : 4 }; var width = 0; var keys = Object.keys(modules); var calculateMax = function(name, value) { if (!maxWidths[name] || value.length > maxWidths[name]) { maxWidths[name] = value.length; } width = 2; Object.keys(maxWidths).forEach(function(v) { width += maxWidths[v] + 2; }); } var pad = function(name, value, rightJustified) { var ret = ''; var padding = ''; var amount = maxWidths[name] - value.length; while(amount--) { padding += " "; } if (rightJustified) { return ' ' + padding + value + ' '; } else { return ' ' + value + padding + ' '; } } // First pass, calculate the max widths keys.forEach(function(v) { var module = modules[v]; var ratio = module.pass + '/' + module.total; var percentage = Math.floor((module.pass/module.total)*100) + '%'; modules[v].ratio = ratio; modules[v].percentage = percentage; calculateMax('name', v); calculateMax('ratio', ratio); calculateMax('percentage', percentage); }); var caps = ''; var gen = width; while(gen--) { caps += '-'; } console.log(''); Object.keys(modules).forEach(function(v) { var module = modules[v]; process.stdout.write(pad('name', v, false)); process.stdout.write(pad('ratio', module.ratio, true)); process.stdout.write(pad('percentage', module.percentage, true)); process.stdout.write('\n'); }); console.log(caps); var ratio = failedTests + '/' + totalTests; var percent = 0; if (totalTests === 0) { percent = '100%'; } else { percent = Math.floor((passedTests/totalTests)*100) + '%'; } console.log('TOTALS: %s failed; %s success', ratio, percent); console.log('TIME: %dms', duration); } });