Skip to content

Commit

Permalink
Core: QUnit logging system uses EventEmitter
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesMGreene authored and flore77 committed Aug 2, 2016
1 parent bfff161 commit df64645
Show file tree
Hide file tree
Showing 9 changed files with 572 additions and 58 deletions.
57 changes: 57 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ grunt.initConfig( {
"test/startError.html",
"test/reorderError1.html",
"test/reorderError2.html",
"test/events.html",
"test/logs.html",
"test/setTimeout.html",
"test/amd.html",
Expand Down Expand Up @@ -185,6 +186,62 @@ grunt.initConfig( {
}
} );

// TODO: Extract this task later, if feasible
// Also spawn a separate process to keep tests atomic
grunt.registerTask( "test-on-node", function() {
var testActive = false,
runDone = false,
done = this.async(),
QUnit = require( "./dist/qunit" );

global.QUnit = QUnit;

QUnit.on( "testStart", function() {
testActive = true;
});
QUnit.on( "assert", function( details ) {
if ( !testActive || details.result ) {
return;
}
var message = "name: " + details.name + " module: " + details.module +
" message: " + details.message;
grunt.log.error( message );
});
QUnit.on( "testEnd", function() {
testActive = false;
});
QUnit.on( "runEnd", function( details ) {
if ( runDone ) {
return;
}
var succeeded = ( details.failed === 0 ),
message = details.total + " assertions in (" + details.runtime + "ms), passed: " +
details.passed + ", failed: " + details.failed;
if ( succeeded ) {
grunt.log.ok( message );
} else {
grunt.log.error( message );
}
done( succeeded );
runDone = true;
});
QUnit.config.autorun = false;

require( "./test/logs" );
require( "./test/main/test" );
require( "./test/main/assert" );
require( "./test/main/async" );
require( "./test/main/promise" );
require( "./test/main/modules" );
require( "./test/main/deepEqual" );
require( "./test/main/stack" );
require( "./test/events" );
require( "./test/globals-node" );

QUnit.load();
});
>>>>>>> Core: QUnit logging system uses EventEmitter

grunt.loadTasks( "build/tasks" );
grunt.registerTask( "build", [ "concat" ] );
grunt.registerTask( "default", [ "concurrent:build", "concurrent:test" ] );
Expand Down
3 changes: 2 additions & 1 deletion build/browserstack-current-1.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"test_path": [
"test/index.html",
"test/logs.html",
"test/seed.html"
"test/seed.html",
"test/events.html"
],
"browsers": [
"chrome_current",
Expand Down
3 changes: 2 additions & 1 deletion build/browserstack-legacy-1.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"test_path": [
"test/index.html",
"test/logs.html",
"test/seed.html"
"test/seed.html",
"test/events.html"
],
"browsers": [
"chrome_previous",
Expand Down
56 changes: 31 additions & 25 deletions reporter/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,30 +580,36 @@ function appendTest( name, testId, moduleName ) {
}

// HTML Reporter initialization and load
QUnit.begin( function( details ) {
var i, moduleObj, tests;

// Sort modules by name for the picker
for ( i = 0; i < details.modules.length; i++ ) {
moduleObj = details.modules[ i ];
if ( moduleObj.name ) {
modulesList.push( moduleObj.name );
}
}
modulesList.sort( function( a, b ) {
return a.localeCompare( b );
} );

// Initialize QUnit elements
appendInterface();
appendTestsList( details.modules );
tests = id( "qunit-tests" );
if ( tests && config.hidepassed ) {
addClass( tests, "hidepass" );
}
QUnit.on( "runStart", function( details ) {
var qunit = id( "qunit" );

// Fixture is the only one necessary to run without the #qunit element
storeFixture();

if ( qunit ) {
qunit.innerHTML =
"<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
"<h2 id='qunit-banner'></h2>" +
"<div id='qunit-testrunner-toolbar'></div>" +
appendFilteredTest() +
"<h2 id='qunit-userAgent'></h2>" +
"<ol id='qunit-tests'></ol>";
}

appendHeader();
appendBanner();
appendTestResults();
appendUserAgent();
appendToolbar();
appendTestsList( details.modules );
toolbarModuleFilter();

if ( qunit && config.hidepassed ) {
addClass( qunit.lastChild, "hidepass" );
}
} );

QUnit.done( function( details ) {
QUnit.on( "runEnd", function( details ) {
var i, key,
banner = id( "qunit-banner" ),
tests = id( "qunit-tests" ),
Expand Down Expand Up @@ -666,7 +672,7 @@ function getNameHtml( name, module ) {
return nameHtml;
}

QUnit.testStart( function( details ) {
QUnit.on( "testStart", function( details ) {
var running, testBlock, bad;

testBlock = id( "qunit-test-output-" + details.testId );
Expand Down Expand Up @@ -697,7 +703,7 @@ function stripHtml( string ) {
return string.replace( /<\/?[^>]+(>|$)/g, "" ).replace( /\&quot;/g, "" ).replace( /\s+/g, "" );
}

QUnit.log( function( details ) {
QUnit.on( "assert", function( details ) {
var assertList, assertLi,
message, expected, actual, diff,
showDiff = false,
Expand Down Expand Up @@ -782,7 +788,7 @@ QUnit.log( function( details ) {
assertList.appendChild( assertLi );
} );

QUnit.testDone( function( details ) {
QUnit.on( "testEnd", function( details ) {
var testTitle, time, testItem, assertList,
good, bad, testCounts, skipped, sourceName,
tests = id( "qunit-tests" );
Expand Down
6 changes: 3 additions & 3 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ function begin() {
}

// The test run is officially beginning now
runLoggingCallbacks( "begin", {
emit( "runStart", {
totalTests: Test.count,
modules: modulesLog
} );
Expand Down Expand Up @@ -234,7 +234,7 @@ function done() {

// Log the last module results
if ( config.previousModule ) {
runLoggingCallbacks( "moduleDone", {
emit( "suiteEnd", {
name: config.previousModule.name,
tests: config.previousModule.tests,
failed: config.moduleStats.bad,
Expand All @@ -248,7 +248,7 @@ function done() {
runtime = now() - config.started;
passed = config.stats.all - config.stats.bad;

runLoggingCallbacks( "done", {
emit( "runEnd", {
failed: config.stats.bad,
passed: passed,
total: config.stats.all,
Expand Down
106 changes: 85 additions & 21 deletions src/core/logging.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,104 @@
// Register logging callbacks
function registerLoggingCallbacks( obj ) {
var i, l, key,
callbackNames = [ "begin", "done", "log", "testStart", "testDone",
var listeners = {};
var loggingCallbacks = {};

// DEPRECATED: Register old logging callbacks
// This will be removed on QUnit 2.0.0+
// From now on use the QUnit.on( eventType, callback ) format
function registerLoggingCallbacks( QUnit ) {
var i, l, key;
var callbackNames = [ "begin", "done", "log", "testStart", "testDone",
"moduleStart", "moduleDone" ];
var dictionary = {
"begin": "runStart",
"done": "runEnd",
"log": "assert",
"testStart": "testStart",
"testDone": "testEnd",
"moduleStart": "suiteStart",
"moduleDone": "suiteEnd"
};

function registerLoggingCallback( key ) {
var loggingCallback = function( callback ) {
if ( objectType( callback ) !== "function" ) {
throw new Error(
"QUnit logging methods require a callback function as their first parameters."
);
}

config.callbacks[ key ].push( callback );
return QUnit.on( dictionary[ key ], callback );
};

// Stores the registered functions allowing restoring
// at verifyLoggingCallbacks() if modified
loggingCallbacks[ key ] = loggingCallback;

return loggingCallback;
}

for ( i = 0, l = callbackNames.length; i < l; i++ ) {
key = callbackNames[ i ];

// Initialize key collection of logging callback
if ( objectType( config.callbacks[ key ] ) === "undefined" ) {
config.callbacks[ key ] = [];
}
QUnit[ key ] = registerLoggingCallback( key );
}
}

// DEPRECATED: This will be removed on 2.0.0+
// This function verifies if the loggingCallbacks were modified by the user
// If so, it will restore it, assign the given callback and print a console warning
function verifyLoggingCallbacks() {
var loggingCallback, userCallback;

for ( loggingCallback in loggingCallbacks ) {
if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {

userCallback = QUnit[ loggingCallback ];

obj[ key ] = registerLoggingCallback( key );
// Restore the callback function
QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];

// Assign the deprecated given callback
QUnit[ loggingCallback ]( userCallback );

if ( global.console && global.console.warn ) {
global.console.warn(
"QUnit." + loggingCallback + " was replaced with a new value.\n" +
"Please, check out the documentation on how to apply logging callbacks.\n" +
"Reference: https://api.qunitjs.com/category/callbacks/"
);
}
}
}
}

function runLoggingCallbacks( key, args ) {
var i, l, callbacks;
function emit( type, data ) {
var i, len, callbacks;

callbacks = config.callbacks[ key ];
for ( i = 0, l = callbacks.length; i < l; i++ ) {
callbacks[ i ]( args );
// Validate
if ( QUnit.objectType( type ) !== "string" ) {
throw new Error( "Emitting QUnit events requires an event type" );
}

callbacks = listeners[ type ];
if ( callbacks ) {
for ( i = 0, len = callbacks.length; i < len; i++ ) {
callbacks[ i ]( data );
}
}
}

QUnit.on = function( type, listener ) {

// Validate
if ( QUnit.objectType( type ) !== "string" ) {
throw new Error( "Adding QUnit events requires an event type" );
}

if ( QUnit.objectType( listener ) !== "function" ) {
throw new Error( "Adding QUnit events requires a listener function" );
}

// Initialize collection of this logging callback
if ( !listeners[ type ] ) {
listeners[ type ] = [];
}

// Filter out duplicate listeners
if ( inArray( listener, listeners[ type ] ) < 0 ) {
listeners[ type ].push( listener );
}
};
13 changes: 6 additions & 7 deletions src/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Test.prototype = {
!hasOwn.call( config, "previousModule" )
) {
if ( hasOwn.call( config, "previousModule" ) ) {
runLoggingCallbacks( "moduleDone", {
emit( "suiteEnd", {
name: config.previousModule.name,
tests: config.previousModule.tests,
failed: config.moduleStats.bad,
Expand All @@ -67,7 +67,7 @@ Test.prototype = {
}
config.previousModule = this.module;
config.moduleStats = { all: 0, bad: 0, started: now() };
runLoggingCallbacks( "moduleStart", {
emit( "suiteStart", {
name: this.module.name,
tests: this.module.tests
} );
Expand All @@ -84,7 +84,7 @@ Test.prototype = {
this.testEnvironment = extend( {}, this.module.testEnvironment );

this.started = now();
runLoggingCallbacks( "testStart", {
emit( "testStart", {
name: this.testName,
module: this.module.name,
testId: this.testId
Expand Down Expand Up @@ -218,8 +218,7 @@ Test.prototype = {
}
}

notifyTestsRan( this.module );
runLoggingCallbacks( "testDone", {
emit( "testEnd", {
name: this.testName,
module: this.module.name,
skipped: skipped,
Expand Down Expand Up @@ -318,7 +317,7 @@ Test.prototype = {
}
}

runLoggingCallbacks( "log", details );
emit( "assert", details );

this.assertions.push( {
result: !!resultInfo.result,
Expand Down Expand Up @@ -346,7 +345,7 @@ Test.prototype = {
details.source = source;
}

runLoggingCallbacks( "log", details );
emit( "assert", details );

this.assertions.push( {
result: false,
Expand Down
Loading

0 comments on commit df64645

Please sign in to comment.