summaryrefslogtreecommitdiff
path: root/tests/qunit/data/testrunner.js
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-05-01 15:32:59 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-05-01 15:32:59 -0400
commit6dc1997577fab2c366781fd7048144935afa0012 (patch)
tree8918d28c7ab4342f0738985e37af1dfc42d0e93a /tests/qunit/data/testrunner.js
parent150f94f051128f367bc89f6b7e5f57eb2a69fc62 (diff)
parentfa89acd685cb09cdbe1c64cbb721ec64975bbbc1 (diff)
Merge commit 'fa89acd'
# Conflicts: # .gitignore # extensions/ArchInterWiki.sql
Diffstat (limited to 'tests/qunit/data/testrunner.js')
-rw-r--r--tests/qunit/data/testrunner.js99
1 files changed, 58 insertions, 41 deletions
diff --git a/tests/qunit/data/testrunner.js b/tests/qunit/data/testrunner.js
index 03aaf4af..01f96252 100644
--- a/tests/qunit/data/testrunner.js
+++ b/tests/qunit/data/testrunner.js
@@ -3,20 +3,17 @@
( function ( $, mw, QUnit ) {
'use strict';
- var mwTestIgnore, mwTester,
- addons,
- ELEMENT_NODE = 1,
- TEXT_NODE = 3;
+ var mwTestIgnore, mwTester, addons;
/**
* Add bogus to url to prevent IE crazy caching
*
- * @param value {String} a relative path (eg. 'data/foo.js'
+ * @param {String} value a relative path (eg. 'data/foo.js'
* or 'data/test.php?foo=bar').
* @return {String} Such as 'data/foo.js?131031765087663960'
*/
QUnit.fixurl = function ( value ) {
- return value + (/\?/.test( value ) ? '&' : '?')
+ return value + ( /\?/.test( value ) ? '&' : '?' )
+ String( new Date().getTime() )
+ String( parseInt( Math.random() * 100000, 10 ) );
};
@@ -69,7 +66,7 @@
sinon.config = {
injectIntoThis: true,
injectInto: null,
- properties: ['spy', 'stub', 'mock', 'sandbox'],
+ properties: [ 'spy', 'stub', 'mock', 'sandbox' ],
// Don't fake timers by default
useFakeTimers: false,
useFakeServer: false
@@ -90,11 +87,11 @@
}
},
teardown: function () {
- this.sandbox.verifyAndRestore();
-
if ( localEnv.teardown ) {
localEnv.teardown.call( this );
}
+
+ this.sandbox.verifyAndRestore();
}
} );
};
@@ -165,34 +162,32 @@
}
/**
- * Test environment recommended for all QUnit test modules
- *
- * Whether to log environment changes to the console
- */
- QUnit.config.urlConfig.push( 'mwlogenv' );
-
- /**
* Reset mw.config and others to a fresh copy of the live config for each test(),
* and restore it back to the live one afterwards.
- * @param localEnv {Object} [optional]
+ *
+ * @param {Object} [localEnv]
* @example (see test suite at the bottom of this file)
* </code>
*/
QUnit.newMwEnvironment = ( function () {
- var warn, log, liveConfig, liveMessages;
+ var warn, error, liveConfig, liveMessages,
+ ajaxRequests = [];
liveConfig = mw.config.values;
liveMessages = mw.messages.values;
function suppressWarnings() {
warn = mw.log.warn;
- mw.log.warn = $.noop;
+ error = mw.log.error;
+ mw.log.warn = mw.log.error = $.noop;
}
function restoreWarnings() {
+ // Guard against calls not balanced with suppressWarnings()
if ( warn !== undefined ) {
mw.log.warn = warn;
- warn = undefined;
+ mw.log.error = error;
+ warn = error = undefined;
}
}
@@ -217,7 +212,14 @@
return $.extend( /*deep=*/true, {}, liveMessages, custom );
}
- log = QUnit.urlParams.mwlogenv ? mw.log : function () {};
+ /**
+ * @param {jQuery.Event} event
+ * @param {jqXHR} jqXHR
+ * @param {Object} ajaxOptions
+ */
+ function trackAjax( event, jqXHR, ajaxOptions ) {
+ ajaxRequests.push( { xhr: jqXHR, options: ajaxOptions } );
+ }
return function ( localEnv ) {
localEnv = $.extend( {
@@ -231,8 +233,6 @@
return {
setup: function () {
- log( 'MwEnvironment> SETUP for "' + QUnit.config.current.module
- + ': ' + QUnit.config.current.testName + '"' );
// Greetings, mock environment!
mw.config.values = freshConfigCopy( localEnv.config );
@@ -240,16 +240,20 @@
this.suppressWarnings = suppressWarnings;
this.restoreWarnings = restoreWarnings;
+ // Start tracking ajax requests
+ $( document ).on( 'ajaxSend', trackAjax );
+
localEnv.setup.call( this );
},
teardown: function () {
- var timers;
- log( 'MwEnvironment> TEARDOWN for "' + QUnit.config.current.module
- + ': ' + QUnit.config.current.testName + '"' );
+ var timers, pending, $activeLen;
localEnv.teardown.call( this );
+ // Stop tracking ajax requests
+ $( document ).off( 'ajaxSend', trackAjax );
+
// Farewell, mock environment!
mw.config.values = liveConfig;
mw.messages.values = liveMessages;
@@ -258,15 +262,14 @@
// still suppressed by the end of the test.
restoreWarnings();
- // Check for incomplete animations/requests/etc and throw
- // error if there are any.
+ // Tests should use fake timers or wait for animations to complete
+ // Check for incomplete animations/requests/etc and throw if there are any.
if ( $.timers && $.timers.length !== 0 ) {
timers = $.timers.length;
- // Tests shoulld use fake timers or wait for animations to complete
$.each( $.timers, function ( i, timer ) {
var node = timer.elem;
mw.log.warn( 'Unfinished animation #' + i + ' in ' + timer.queue + ' queue on ' +
- mw.html.element( node.nodeName.toLowerCase(), $(node).getAttrs() )
+ mw.html.element( node.nodeName.toLowerCase(), $( node ).getAttrs() )
);
} );
// Force animations to stop to give the next test a clean start
@@ -274,10 +277,24 @@
throw new Error( 'Unfinished animations: ' + timers );
}
- if ( $.active !== undefined && $.active !== 0 ) {
- // Test may need to use fake XHR, wait for requests or
- // call abort().
- throw new Error( 'Unfinished AJAX requests: ' + $.active );
+
+ // Test should use fake XHR, wait for requests, or call abort()
+ $activeLen = $.active;
+ if ( $activeLen !== undefined && $activeLen !== 0 ) {
+ pending = $.grep( ajaxRequests, function ( ajax ) {
+ return ajax.xhr.state() === 'pending';
+ } );
+ if ( pending.length !== $activeLen ) {
+ mw.log.warn( 'Pending requests does not match jQuery.active count' );
+ }
+ // Force requests to stop to give the next test a clean start
+ $.each( pending, function ( i, ajax ) {
+ mw.log.warn( 'Pending AJAX request #' + i, ajax.options );
+ ajax.xhr.abort();
+ } );
+ ajaxRequests = [];
+
+ throw new Error( 'Pending AJAX requests: ' + pending.length + ' (active: ' + $activeLen + ')' );
}
}
};
@@ -313,12 +330,12 @@
function getDomStructure( node ) {
var $node, children, processedChildren, i, len, el;
$node = $( node );
- if ( node.nodeType === ELEMENT_NODE ) {
+ if ( node.nodeType === Node.ELEMENT_NODE ) {
children = $node.contents();
processedChildren = [];
for ( i = 0, len = children.length; i < len; i++ ) {
- el = children[i];
- if ( el.nodeType === ELEMENT_NODE || el.nodeType === TEXT_NODE ) {
+ el = children[ i ];
+ if ( el.nodeType === Node.ELEMENT_NODE || el.nodeType === Node.TEXT_NODE ) {
processedChildren.push( getDomStructure( el ) );
}
}
@@ -340,7 +357,7 @@
* @param {string} html HTML markup for one or more nodes.
*/
function getHtmlStructure( html ) {
- var el = $( '<div>' ).append( html )[0];
+ var el = $( '<div>' ).append( html )[ 0 ];
return getDomStructure( el );
}
@@ -472,11 +489,11 @@
missing = [];
for ( i = 0, len = modules.length; i < len; i++ ) {
- state = mw.loader.getState( modules[i] );
+ state = mw.loader.getState( modules[ i ] );
if ( state === 'error' ) {
- error.push( modules[i] );
+ error.push( modules[ i ] );
} else if ( state === 'missing' ) {
- missing.push( modules[i] );
+ missing.push( modules[ i ] );
}
}