Skip to content

Commit

Permalink
CLI: Implement --require option
Browse files Browse the repository at this point in the history
  • Loading branch information
trentmwillis committed Mar 6, 2018
1 parent dfe4cfc commit c6365ed
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 25 deletions.
8 changes: 8 additions & 0 deletions bin/qunit
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ const description = `Runs tests using the QUnit framework.
For more info on working with QUnit, check out http://qunitjs.com.`;

function collect( val, collection ) {
collection.push( val );
return collection;
}

program._name = "qunit";
program
.version( pkg.version )
Expand All @@ -26,6 +31,8 @@ program
.option( "-r, --reporter [name]", "specify the reporter to use; " +
"if no match is found or no name is provided, a list of available " +
"reporters will be displayed" )
.option( "--require <module>", "specify a module to require prior to running " +
"any tests.", collect, [] )
.option( "--seed [value]", "specify a seed to order your tests; " +
"if option is specified without a value, one will be generated" )
.option( "-w, --watch", "Watch files for changes and re-run the test suite" )
Expand All @@ -39,6 +46,7 @@ const args = program.args;
const options = {
filter: program.filter,
reporter: findReporter( program.reporter ),
requires: program.require,
seed: program.seed
};

Expand Down
6 changes: 6 additions & 0 deletions bin/require-from-cwd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const resolve = require( "resolve" );

module.exports = function requireFromCWD( mod ) {
const resolvedPath = resolve.sync( mod, { basedir: process.cwd() } );
return require( resolvedPath );
};
52 changes: 28 additions & 24 deletions bin/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const path = require( "path" );
const walkSync = require( "walk-sync" );

const requireFromCWD = require( "./require-from-cwd" );
const requireQUnit = require( "./require-qunit" );
const utils = require( "./utils" );

Expand All @@ -14,34 +15,10 @@ const RESTART_DEBOUNCE_LENGTH = 200;
let QUnit;

function run( args, options ) {
let running = true;

// Default to non-zero exit code to avoid false positives
process.exitCode = 1;

process.on( "exit", function() {
if ( running ) {
console.error( "Error: Process exited before tests finished running" );

const currentTest = QUnit.config.current;
if ( currentTest && currentTest.semaphore ) {
const name = currentTest.testName;
console.error( "Last test to run (" + name + ") has an async hold. " +
"Ensure all assert.async() callbacks are invoked and Promises resolve. " +
"You should also set a standard timeout via QUnit.config.testTimeout." );
}
}
} );

// Listen for unhandled rejections, and call QUnit.onUnhandledRejection
process.on( "unhandledRejection", function( reason ) {
QUnit.onUnhandledRejection( reason );
} );

process.on( "uncaughtException", function( error ) {
QUnit.onError( error );
} );

const files = utils.getFilesFromArgs( args );

QUnit = requireQUnit();
Expand All @@ -65,6 +42,8 @@ function run( args, options ) {
// still done automatically.
global.QUnit = QUnit;

options.requires.forEach( requireFromCWD );

options.reporter.init( QUnit );

for ( let i = 0; i < files.length; i++ ) {
Expand All @@ -85,6 +64,31 @@ function run( args, options ) {
}
}

let running = true;

// Listen for unhandled rejections, and call QUnit.onUnhandledRejection
process.on( "unhandledRejection", function( reason ) {
QUnit.onUnhandledRejection( reason );
} );

process.on( "uncaughtException", function( error ) {
QUnit.onError( error );
} );

process.on( "exit", function() {
if ( running ) {
console.error( "Error: Process exited before tests finished running" );

const currentTest = QUnit.config.current;
if ( currentTest && currentTest.semaphore ) {
const name = currentTest.testName;
console.error( "Last test to run (" + name + ") has an async hold. " +
"Ensure all assert.async() callbacks are invoked and Promises resolve. " +
"You should also set a standard timeout via QUnit.config.testTimeout." );
}
}
} );

QUnit.start();

QUnit.on( "runEnd", function setExitCode( data ) {
Expand Down
13 changes: 12 additions & 1 deletion test/cli/fixtures/expected/tap-outputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,16 @@ not ok 1 global failure
# skip 0
# todo 0
# fail 1
`
`,

"qunit single.js --require require-dep --require './node_modules/require-dep/module.js'":
`required require-dep/index.js
required require-dep/module.js
TAP version 13
ok 1 Single > has a test
1..1
# pass 1
# skip 0
# todo 0
# fail 0`
};
1 change: 1 addition & 0 deletions test/cli/fixtures/node_modules/require-dep/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test/cli/fixtures/node_modules/require-dep/module.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions test/cli/fixtures/node_modules/require-dep/package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions test/cli/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,28 @@ QUnit.module( "CLI Main", function() {
} ) );
} );

QUnit.module( "require", function() {
QUnit.test( "can properly require dependencies and modules", co.wrap( function* ( assert ) {
const command = "qunit single.js --require require-dep --require './node_modules/require-dep/module.js'";
const execution = yield execute( command );

assert.equal( execution.code, 0 );
assert.equal( execution.stderr, "" );
assert.equal( execution.stdout, expectedOutput[ command ] );
} ) );

QUnit.test( "displays helpful error when failing to require a file", co.wrap( function* ( assert ) {
const command = "qunit single.js --require 'does-not-exist-at-all'";
try {
yield execute( command );
} catch ( e ) {
assert.equal( e.code, 1 );
assert.ok( e.stderr.includes( "Error: Cannot find module 'does-not-exist-at-all'" ) );
assert.equal( e.stdout, "" );
}
} ) );
} );

QUnit.module( "seed", function() {
QUnit.test( "can properly seed tests", co.wrap( function* ( assert ) {
const command = "qunit --seed 's33d' test single.js 'glob/**/*-test.js'";
Expand Down

0 comments on commit c6365ed

Please sign in to comment.