-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e732493
commit 98d1970
Showing
7 changed files
with
252 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/** | ||
* Test runner for QUnit tests powered by requireJS. | ||
* The test runner may be instantiated and started on a plain HTML page. After starting the test | ||
* runner, an iframe for every test module is created and attached to the DOM one after another as | ||
* soon as the tests of the currently run test module have finished. The iframe loads the HTML | ||
* testRunner specified in the config parameters. This concept ensures loading only the dependencies | ||
* specified for the particular tests. | ||
* | ||
* @option {string[]} queue Set of test modules to run as defined via requireJS. | ||
* @option {string} testRunner The path to the testRunner HTML file that executes QUnit tests. | ||
* | ||
* Example: | ||
* testRunner = new tests.TestRunner( { | ||
* queue: tests.modules, | ||
* testRunner: './testRunner.html' | ||
* } ); | ||
* testRunner.start(); | ||
* | ||
* @licence GNU GPL v2+ | ||
* @author H. Snater < [email protected] > | ||
*/ | ||
|
||
/* global tests, console */ | ||
this.tests = this.tests || {}; | ||
|
||
tests.TestRunner = ( function( console ) { | ||
'use strict'; | ||
|
||
/** | ||
* Test runner for QUnit tests powered by requrieJS. | ||
* | ||
* @param {Object} options | ||
* @constructor | ||
* | ||
* @throws {Error} if a required configuration option is not set | ||
*/ | ||
var TestRunner = function( options ) { | ||
if( !options.queue ) { | ||
throw new Error( 'No tests specified' ); | ||
} else if( !options.testRunner ) { | ||
throw new Error( 'No HTML test runner specified' ); | ||
} | ||
|
||
this._options = options; | ||
this._interval = null; | ||
this._iFrames = []; | ||
}; | ||
|
||
/** | ||
* Starts running a set of test modules. | ||
*/ | ||
TestRunner.prototype.start = function() { | ||
var self = this, | ||
currentModule, | ||
globalFailures = 0, | ||
queue = this._options.queue; | ||
|
||
console.log( 'TEST START' ); | ||
|
||
// Interval polling the most recently add iframe whether its test(s) have been finished: | ||
this._interval = setInterval( function() { | ||
if( self._iFrames.length === 0 ) { | ||
currentModule = queue.pop(); | ||
self._generateFrame( currentModule ); | ||
} | ||
|
||
var currentFrame = self._iFrames[self._iFrames.length - 1], | ||
frameWindow = currentFrame.contentWindow, | ||
frameBody = currentFrame.contentDocument.body; | ||
|
||
if( !frameBody || !currentFrame.contentWindow.require ) { | ||
return; | ||
} | ||
|
||
var testResult = frameWindow.document.getElementById( 'qunit-testresult' ); | ||
|
||
if( !testResult ) { | ||
return; | ||
} | ||
|
||
var failed = testResult.getElementsByClassName( 'failed' ); | ||
|
||
if( failed.length > 0 ) { | ||
// Test hast finished. | ||
var localFailures = parseInt( failed[0].firstChild.nodeValue, 10 ); | ||
|
||
if( localFailures === 0 ) { | ||
console.log( currentModule + ': passed' ); | ||
} else { | ||
console.error( currentModule + ': FAILED (' + localFailures + ' failures)' ); | ||
globalFailures += localFailures; | ||
} | ||
|
||
if( queue.length === 0 ) { | ||
clearInterval( self._interval ); | ||
console.log( 'TEST END (' + globalFailures + ' failure(s))' ); | ||
} else { | ||
currentModule = queue.pop(); | ||
self._generateFrame( currentModule ); | ||
} | ||
} | ||
}, 100 ); | ||
|
||
}; | ||
|
||
/** | ||
* Creates an iframe to run a test module in. | ||
* | ||
* @param {string} module | ||
*/ | ||
TestRunner.prototype._generateFrame = function( module ) { | ||
var iFrame = document.createElement( 'iframe' ); | ||
|
||
document.body.appendChild( iFrame ); | ||
|
||
iFrame.setAttribute( 'src', this._options.testRunner + '?test=' + module ); | ||
iFrame.setAttribute( 'id', 'testFrame-' + module.replace( /\./g, '-' ) ); | ||
iFrame.setAttribute( 'style', 'width: 100%' ); | ||
|
||
this._iFrames.push( iFrame ); | ||
}; | ||
|
||
/** | ||
* Extracts the module to test from the URI. Returns an array with the module name as single | ||
* value. If the module is not within the list of modules passed to the function, the array | ||
* of test modules is returned. | ||
* | ||
* @return {string[]} | ||
*/ | ||
TestRunner.filterTestModules = function( testModules ) { | ||
var queryString = ( function( urlParams ) { | ||
var params = {}; | ||
if( urlParams.length === 1 && urlParams[0] === '' ) { | ||
return params; | ||
} | ||
for( var i = 0; i < urlParams.length; i++ ) { | ||
var param = urlParams[i].split( '=' ); | ||
if( param.length === 2 ) { | ||
params[param[0]] = decodeURIComponent( param[1].replace( /\+/g, ' ' ) ); | ||
} | ||
} | ||
return params; | ||
} )( window.location.search.substr( 1 ).split( '&' ) ); | ||
|
||
for( var i = 0; i < testModules.length; i++ ) { | ||
if( testModules[i] === queryString.test ) { | ||
return [queryString.test]; | ||
} | ||
} | ||
|
||
return testModules; | ||
}; | ||
|
||
return TestRunner; | ||
|
||
}( console ) ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* PhantomJS test runner module corresponding to the native test runner implementation. | ||
* | ||
* @licence GNU GPL v2+ | ||
* @author H. Snater < [email protected] > | ||
*/ | ||
|
||
/* global tests, exports, console */ | ||
this.tests = this.tests || {}; | ||
|
||
this.tests.TestRunner = this.tests.TestRunner || {}; | ||
|
||
this.tests.TestRunner.phantom = ( function( console ) { | ||
'use strict'; | ||
|
||
var TestRunner = function() {}; | ||
|
||
/** | ||
* Evaluates the console messages generated in the native TestRunner. | ||
* | ||
* @param {string} msg | ||
* @return {boolean|undefined} | ||
*/ | ||
TestRunner.prototype.onConsoleMessage = function( msg ) { | ||
console.log( msg ); | ||
|
||
if( msg.indexOf( 'TEST END' ) === 0 ) { | ||
var msgParts = msg.match( /(\d{1,}) failure/ ); | ||
return ( parseInt( msgParts[1], 10 ) > 0 ); | ||
} | ||
|
||
return undefined; | ||
}; | ||
|
||
return TestRunner; | ||
|
||
}( console ) ); | ||
|
||
exports.tests = this.tests; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,5 @@ | ||
<!-- | ||
Main entrance point for running QUnit tests. | ||
Accessing this file will run all QUnit tests one after another by simply adding iframes to the body | ||
node. Loading the tests in iframes ensures that only the necessary dependencies are loaded for the | ||
individual tests. | ||
@licence GNU GPL v2+ | ||
@author: H. Snater < [email protected] > | ||
--> | ||
<!DOCTYPE html> | ||
<html> | ||
|
@@ -14,69 +8,20 @@ | |
<title>QUnit tests</title> | ||
</head> | ||
<body> | ||
|
||
<script src="./testConfig.js"></script> | ||
<script src="../lib/jquery/jquery.js"></script> | ||
|
||
<script src="../lib/tests/tests.TestRunner.js"></script> | ||
<script> | ||
$( document ).ready( function() { | ||
var queue = [], | ||
currentModule, | ||
$iFrame, | ||
globalFailures = 0; | ||
|
||
/** | ||
* Triggers running a test by adding an iframe to the body element. Within the iframe, only | ||
* the required dependencies to run the test are loaded. | ||
* @param {string} module | ||
*/ | ||
function triggerTest( module ) { | ||
currentModule = module; | ||
|
||
$iFrame = $( '<iframe/>' ) | ||
.attr( 'id', 'testFrame' + module.replace( /\./g, '-' ) ) | ||
.attr( 'src', './testRunner.html?testModule=' + module ) | ||
.attr( 'style', 'width:100%;' ); | ||
|
||
$( 'body' ).append( $iFrame ); | ||
} | ||
|
||
for( var module in testConfig.paths ) { | ||
if( /\.tests$/.test( module ) ) { | ||
queue.unshift( module ); | ||
} | ||
} | ||
( function( window, tests ) { | ||
window.onload = function() { | ||
|
||
console.log( 'TEST START' ); | ||
var testRunner = new tests.TestRunner( { | ||
queue: tests.modules, | ||
testRunner: './testRunner.html' | ||
} ); | ||
|
||
triggerTest( queue.pop() ); | ||
|
||
var testInterval = setInterval( function() { | ||
var $failed = $iFrame.contents().find( '#qunit-testresult .failed' ); | ||
|
||
if( $failed.length > 0 ) { | ||
// Test has finished. | ||
|
||
var localFailures = parseInt( $failed.text() ); | ||
|
||
if( localFailures === 0 ) { | ||
console.log( currentModule + ': passed' ); | ||
} else { | ||
console.error( currentModule + ': FAILED (' + localFailures + ' failures)' ); | ||
globalFailures += localFailures; | ||
} | ||
|
||
if( queue.length === 0 ) { | ||
clearInterval( testInterval ); | ||
console.log( 'TEST END (' + globalFailures + ' failure(s))' ); | ||
} else { | ||
triggerTest( queue.pop() ); | ||
} | ||
} | ||
}, 100 ); | ||
|
||
} ); | ||
testRunner.start(); | ||
}; | ||
}( window, tests ) ); | ||
</script> | ||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,11 @@ | |
* @licence GNU GPL v2+ | ||
* @author H. Snater < [email protected] > | ||
*/ | ||
var testConfig = ( function() { | ||
|
||
/* global tests */ | ||
this.tests = this.tests || {}; | ||
|
||
tests.config = ( function() { | ||
'use strict'; | ||
|
||
return { | ||
|
@@ -147,7 +151,7 @@ var testConfig = ( function() { | |
}, | ||
'time.Time': { | ||
exports: 'time.Time', | ||
deps: ['time', 'time.Parser'] | ||
deps: ['time', 'jquery', 'time.Parser'] | ||
}, | ||
'time.Time.validate': { | ||
exports: 'time.Time.validate', | ||
|
@@ -280,3 +284,22 @@ var testConfig = ( function() { | |
}; | ||
|
||
} )(); | ||
|
||
/** | ||
* Array of all QUnit test modules. | ||
* @type {string[]} | ||
*/ | ||
tests.modules = ( function( tests ) { | ||
'use strict'; | ||
|
||
var modules = []; | ||
|
||
for( var module in tests.config.paths ) { | ||
if( /\.tests$/.test( module ) ) { | ||
modules.unshift( module ); | ||
} | ||
} | ||
|
||
return modules; | ||
|
||
}( tests ) ); |
Oops, something went wrong.