diff --git a/.gitignore b/.gitignore index 1c3e58b..668b930 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules .DS_Store -*.log \ No newline at end of file +*.log +.project diff --git a/bin/qunit-cli b/bin/qunit-cli index 3f0399a..4aa6b58 100755 --- a/bin/qunit-cli +++ b/bin/qunit-cli @@ -1,5 +1,9 @@ #!/usr/bin/env node +var fs = require('fs'); + +var extname = require('path').extname; + // Request at least one test file as parameter var argv = require('optimist') .alias('code', 'c') @@ -46,11 +50,34 @@ if (code) { code.forEach(setGlobal); } +// Load QUnit test framework +var config = QUnit.extend({}, QUnit.config); +QUnit.load(); +QUnit.extend(QUnit.config, config) + // Run tests files.forEach(function(file) { - require(resolve(file)) -}); + file = resolve(file); + fs.stat(file, function(error, stats) + { + if(error) return console.warn(error); -// Start the suite -QUnit.load(); \ No newline at end of file + if(stats.isDirectory()) + fs.readdir(file, function(error, files) + { + if(error) return console.warn(error); + + files.forEach(function(name) + { + name = resolve(file, name); + + if(extname(name) != '.js') return console.warn('Unknown file type:',name) + + require(name) + }); + }) + else + require(file) + }) +}); diff --git a/index.js b/index.js index d5e9809..6e23a55 100644 --- a/index.js +++ b/index.js @@ -8,29 +8,110 @@ var QUnit = require('qunitjs'), colors = require('colors'); - var argv = require('optimist') + // Get user own config parameters + var optimist = require('optimist') + .describe('urlConfig', 'Add a config parameter of your own in JSON') + .string('urlConfig'); + var argv = optimist.argv; + + // Define normal config parameters + optimist + .describe('hidepassed', 'Show only the failing tests, hiding all that pass') + .default('hidepassed', false) .alias('module', 'm') .describe('module', 'Run an individual module') - .alias('test', 't') - .describe('test', 'Run an individual test by number') + .describe('requireExpects', 'Require each test to specify the number of expected assertions') + .default('requireExpects', false) + .alias('testNumber', 't') + .describe('testNumber', 'Run an individual test by number') + .describe('test', 'Run an individual test by number (deprecated)') + .describe('testTimeout', 'Global timeout in milliseconds after which all tests will fail') .alias('quiet', 'q') - .describe('quiet', 'Hide passed tests') - .boolean('quiet') - .argv; + .describe('quiet', 'Hide passed tests (deprecated)') + .boolean('quiet'); + + // Add user own config parameters and if so, override normal ones + var consts = {}; + + var urlConfig = argv.urlConfig; + if (urlConfig) { + function addConfig(urlConfig) { + urlConfig = JSON.parse(urlConfig); + + // Add config parameter to QUnit-cli so it can be checked + var id = urlConfig.id; + var value = urlConfig.value; + + optimist.describe(id, urlConfig.tooltip || urlConfig.label); + + if(value == undefined) + optimist.boolean(id); + else if(typeof value == 'string') + { + optimist.boolean(id); + + consts[id] = value; + } + else if(!(value instanceof Array)) + optimist.string(id); + + // Add config parameter to QUnit so it can be processed + QUnit.config.urlConfig.push(urlConfig); + } + + if (urlConfig instanceof Array) { + urlConfig.forEach(function(config) { + addConfig(config); + }); + } else { + addConfig(urlConfig); + } + }; + + // Check arguments + argv = optimist.argv; + + // Deprecation notices + if(argv.test != undefined) + { + console.warn('"test" parameter is deprecated, please use "testNumber" instead'); + argv.testNumber = argv.testNumber || argv.test; + delete argv.test; + }; + + if(argv.quiet) + console.warn('"quiet" parameter is deprecated, please use "hidepassed" instead'); + + // QUnit configurations + delete argv.urlConfig; // Based on qunit's test set up for node // https://github.com/jquery/qunit/blob/c0d9ad6cfc73157b03bc9bec5b0aee875150b5aa/Gruntfile.js#L176-222 QUnit.config.autorun = false; - QUnit.config.module = argv.module; + + for(var key in argv) + QUnit.config[key] = consts[key] || argv[key]; + module.exports = QUnit; var errors = [], printedModule = false; + function printModule(name) + { + // Separate each module with an empty line + console.log('\n'); + + // Only print module name if it's defined + if (name) + console.log(name.bold.blue); + } + // keep track of whether we've printed the module name yet - QUnit.moduleStart(function() { - printedModule = false; + QUnit.moduleStart(function(details) { + if (printedModule = !argv.quiet) + printModule(details.name); }); // when an individual assertion fails, add it to the list of errors to display @@ -42,8 +123,8 @@ // when a test ends, print success/failure and any errors QUnit.testDone(function(details) { // print the name of each module - if (!printedModule && (printedModule = !argv.quiet || details.failed)) - console.log('\n' + details.module.bold.blue); + if (!printedModule && details.failed) + printModule(details.module); if (details.failed) { console.log((' ✖ ' + details.name).red); @@ -72,9 +153,9 @@ else console.log((msg + '.').green.bold); - process.once('exit', function() { + process.once('exit', function() { process.exit(details.failed); }); }); -})(); \ No newline at end of file +})(); diff --git a/package.json b/package.json index bd61f84..673bfd4 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,6 @@ "optimist": ">=0.3", "qunitjs": "^1.15.0" }, - "bin": "bin/qunit-cli" + "bin": "bin/qunit-cli", + "preferGlobal": true } diff --git a/readme.md b/readme.md index 97069e2..439ba60 100644 --- a/readme.md +++ b/readme.md @@ -10,34 +10,60 @@ testing framework. There are two ways to use qunit-cli: -1. Include it at the top of your test files. First, install the module using npm. +1. Include it at the top of your test files. First, install the module using + npm. - npm install qunit-cli + ```bash + npm install qunit-cli + ``` And now, require it in your test files: - if (typeof QUnit == 'undefined') // if your tests also run in the browser... - QUnit = require('qunit-cli'); - - // use QUnit as you normally would. + ```Javascript + if (typeof QUnit == 'undefined') // if your tests also run in the browser... + QUnit = require('qunit-cli'); - Note that this module does not introduce QUnit into the global scope like QUnit - does in the browser, so you'll have to do that yourself if needed. + // use QUnit as you normally would. + ``` + + Note that this module does not introduce QUnit into the global scope like + QUnit does in the browser, so you'll have to do that yourself if needed: + + ```Javascript + // you can use directly the QUnit namespace... + QUnit.module('blah'); + + // ...or you can set the QUnit exports to variables as you normally would, + // or set them to the 'global' namespace so they can be available everywhere + // in your code, but this is considered a bad practice. + var asyncTest = QUnit.asyncTest; + global.ok = QUnit.ok; + + asyncTest('foo', function() + { + // 'ok' has been asigned to the global namespace + ok(true); + }); + ``` To run, use the `node` program. - node mytests.js + ```bash + node mytests.js + ``` -2. Use the command-line testrunner located at `bin/qunit-cli`, passing it the test files as arguments. - If you install the module globally using npm, you can use the `qunit-cli` command which will be - installed into your PATH. +2. Use the command-line testrunner located at `bin/qunit-cli`, passing it the + test files as arguments. If you install the module globally using npm, you + can use the `qunit-cli` command which will be installed into your PATH. - npm install qunit-cli -g - qunit-cli mytests.js + ```bash + npm install qunit-cli -g + qunit-cli mytests.js + ``` - This will introduce QUnit into the global scope like QUnit does in the browser, - so you don't need to modify the tests themselves. You can use both methods in - the same test files without problems. + This will introduce QUnit into the global scope like QUnit does in the + browser, so you don't need to modify the tests themselves. You can use both + methods in the same test files without problems. ## Command line options @@ -45,9 +71,13 @@ There are several command line options available when running your tests using qunit-cli that mimic some of the options in the standard browser-based QUnit testing interface. They are: - --module, -m Limits testing to an individual module - --test, -t Limits testing to a single test (by number) - --quiet, -q Flag to hide passed tests from the output + --hidepassed, Show only the failing tests, hiding all that pass + --module, -m Limits testing to an individual module + --requireExpects, Require each test to specify the number of expected assertions + --testNumber, -t Limits testing to a single test (by number) + --testTimeout, Global timeout in milliseconds after which all tests will fail + --quiet, -q Flag to hide passed tests from the output (deprecated) + --urlConfig, Add a config parameter of your own in JSON The command-line test runner has some additional options available: