Update jquery.qunit from upstream v1.9.0 to v1.10.0
[lhc/web/wiklou.git] / resources / jquery / jquery.qunit.js
index c1570c2..d4f17b5 100644 (file)
@@ -1,11 +1,11 @@
 /**
- * QUnit v1.8.0 - A JavaScript Unit Testing Framework
+ * QUnit v1.10.0 - A JavaScript Unit Testing Framework
  *
- * http://docs.jquery.com/QUnit
+ * http://qunitjs.com
  *
- * Copyright (c) 2012 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * or GPL (GPL-LICENSE.txt) licenses.
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
  */
 
 (function( window ) {
@@ -17,6 +17,8 @@ var QUnit,
        fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
        toString = Object.prototype.toString,
        hasOwn = Object.prototype.hasOwnProperty,
+       // Keep a local reference to Date (GH-283)
+       Date = window.Date,
        defined = {
        setTimeout: typeof window.setTimeout !== "undefined",
        sessionStorage: (function() {
@@ -304,7 +306,8 @@ QUnit = {
        // call on start of module test to prepend name to all tests
        module: function( name, testEnvironment ) {
                config.currentModule = name;
-               config.currentModuleTestEnviroment = testEnvironment;
+               config.currentModuleTestEnvironment = testEnvironment;
+               config.modules[name] = true;
        },
 
        asyncTest: function( testName, expected, callback ) {
@@ -336,7 +339,7 @@ QUnit = {
                        async: async,
                        callback: callback,
                        module: config.currentModule,
-                       moduleTestEnvironment: config.currentModuleTestEnviroment,
+                       moduleTestEnvironment: config.currentModuleTestEnvironment,
                        stack: sourceFromStacktrace( 2 )
                });
 
@@ -349,7 +352,11 @@ QUnit = {
 
        // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
        expect: function( asserts ) {
-               config.current.expected = asserts;
+               if (arguments.length === 1) {
+                       config.current.expected = asserts;
+               } else {
+                       return config.current.expected;
+               }
        },
 
        start: function( count ) {
@@ -403,6 +410,8 @@ QUnit = {
 QUnit.assert = {
        /**
         * Asserts rough true-ish result.
+        * @name ok
+        * @function
         * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
         */
        ok: function( result, msg ) {
@@ -413,6 +422,8 @@ QUnit.assert = {
 
                var source,
                        details = {
+                               module: config.current.module,
+                               name: config.current.testName,
                                result: result,
                                message: msg
                        };
@@ -437,36 +448,59 @@ QUnit.assert = {
        /**
         * Assert that the first two arguments are equal, with an optional message.
         * Prints out both actual and expected values.
+        * @name equal
+        * @function
         * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
         */
        equal: function( actual, expected, message ) {
                QUnit.push( expected == actual, actual, expected, message );
        },
 
+       /**
+        * @name notEqual
+        * @function
+        */
        notEqual: function( actual, expected, message ) {
                QUnit.push( expected != actual, actual, expected, message );
        },
 
+       /**
+        * @name deepEqual
+        * @function
+        */
        deepEqual: function( actual, expected, message ) {
                QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
        },
 
+       /**
+        * @name notDeepEqual
+        * @function
+        */
        notDeepEqual: function( actual, expected, message ) {
                QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
        },
 
+       /**
+        * @name strictEqual
+        * @function
+        */
        strictEqual: function( actual, expected, message ) {
                QUnit.push( expected === actual, actual, expected, message );
        },
 
+       /**
+        * @name notStrictEqual
+        * @function
+        */
        notStrictEqual: function( actual, expected, message ) {
                QUnit.push( expected !== actual, actual, expected, message );
        },
 
-       raises: function( block, expected, message ) {
+       throws: function( block, expected, message ) {
                var actual,
                        ok = false;
 
+               // 'expected' is optional
                if ( typeof expected === "string" ) {
                        message = expected;
                        expected = null;
@@ -494,18 +528,29 @@ QUnit.assert = {
                        } else if ( expected.call( {}, actual ) === true ) {
                                ok = true;
                        }
-               }
 
-               QUnit.push( ok, actual, null, message );
+                       QUnit.push( ok, actual, null, message );
+               } else {
+                       QUnit.pushFailure( message, null, 'No exception was thrown.' );
+               }
        }
 };
 
-// @deprecated: Kept assertion helpers in root for backwards compatibility
+/**
+ * @deprecate since 1.8.0
+ * Kept assertion helpers in root for backwards compatibility
+ */
 extend( QUnit, QUnit.assert );
 
 /**
- * @deprecated: Kept for backwards compatibility
- * next step: remove entirely
+ * @deprecated since 1.9.0
+ * Kept global "raises()" for backwards compatibility
+ */
+QUnit.raises = QUnit.assert.throws;
+
+/**
+ * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
+ * Kept to avoid TypeErrors for undefined methods.
  */
 QUnit.equals = function() {
        QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
@@ -549,7 +594,23 @@ config = {
        // when enabled, all tests must call expect()
        requireExpects: false,
 
-       urlConfig: [ "noglobals", "notrycatch" ],
+       // add checkboxes that are persisted in the query-string
+       // when enabled, the id is set to `true` as a `QUnit.config` property
+       urlConfig: [
+               {
+                       id: "noglobals",
+                       label: "Check for Globals",
+                       tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
+               },
+               {
+                       id: "notrycatch",
+                       label: "No try-catch",
+                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
+               }
+       ],
+
+       // Set of all modules.
+       modules: {},
 
        // logging callback queues
        begin: [],
@@ -661,17 +722,10 @@ extend( QUnit, {
        },
 
        // Resets the test setup. Useful for tests that modify the DOM.
-       // If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
        reset: function() {
-               var fixture;
-
-               if ( window.jQuery ) {
-                       jQuery( "#qunit-fixture" ).html( config.fixture );
-               } else {
-                       fixture = id( "qunit-fixture" );
-                       if ( fixture ) {
-                               fixture.innerHTML = config.fixture;
-                       }
+               var fixture = id( "qunit-fixture" );
+               if ( fixture ) {
+                       fixture.innerHTML = config.fixture;
                }
        },
 
@@ -732,6 +786,8 @@ extend( QUnit, {
 
                var output, source,
                        details = {
+                               module: config.current.module,
+                               name: config.current.testName,
                                result: result,
                                message: message,
                                actual: actual,
@@ -770,26 +826,36 @@ extend( QUnit, {
                });
        },
 
-       pushFailure: function( message, source ) {
+       pushFailure: function( message, source, actual ) {
                if ( !config.current ) {
                        throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
                }
 
                var output,
                        details = {
+                               module: config.current.module,
+                               name: config.current.testName,
                                result: false,
                                message: message
                        };
 
-               message = escapeInnerText(message ) || "error";
+               message = escapeInnerText( message ) || "error";
                message = "<span class='test-message'>" + message + "</span>";
                output = message;
 
+               output += "<table>";
+
+               if ( actual ) {
+                       output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeInnerText( actual ) + "</pre></td></tr>";
+               }
+
                if ( source ) {
                        details.source = source;
-                       output += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr></table>";
+                       output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>";
                }
 
+               output += "</table>";
+
                runLoggingCallbacks( "log", QUnit, details );
 
                config.current.assertions.push({
@@ -859,7 +925,9 @@ QUnit.load = function() {
        runLoggingCallbacks( "begin", QUnit, {} );
 
        // Initialize the config, saving the execution queue
-       var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
+       var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter,
+           numModules = 0,
+           moduleFilterHtml = "",
                urlConfigHtml = "",
                oldconfig = extend( {}, config );
 
@@ -872,9 +940,25 @@ QUnit.load = function() {
 
        for ( i = 0; i < len; i++ ) {
                val = config.urlConfig[i];
-               config[val] = QUnit.urlParams[val];
-               urlConfigHtml += "<label><input name='" + val + "' type='checkbox'" + ( config[val] ? " checked='checked'" : "" ) + ">" + val + "</label>";
+               if ( typeof val === "string" ) {
+                       val = {
+                               id: val,
+                               label: val,
+                               tooltip: "[no tooltip available]"
+                       };
+               }
+               config[ val.id ] = QUnit.urlParams[ val.id ];
+               urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
+       }
+
+       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined  ? "selected" : "" ) + ">< All Modules ></option>";
+       for ( i in config.modules ) {
+               if ( config.modules.hasOwnProperty( i ) ) {
+                       numModules += 1;
+                       moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>";
+               }
        }
+       moduleFilterHtml += "</select>";
 
        // `userAgent` initialized at top of scope
        userAgent = id( "qunit-userAgent" );
@@ -885,12 +969,7 @@ QUnit.load = function() {
        // `banner` initialized at top of scope
        banner = id( "qunit-header" );
        if ( banner ) {
-               banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined }) + "'>" + banner.innerHTML + "</a> " + urlConfigHtml;
-               addEvent( banner, "change", function( event ) {
-                       var params = {};
-                       params[ event.target.name ] = event.target.checked ? true : undefined;
-                       window.location = QUnit.url( params );
-               });
+               banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
        }
 
        // `toolbar` initialized at top of scope
@@ -931,8 +1010,31 @@ QUnit.load = function() {
                // `label` initialized at top of scope
                label = document.createElement( "label" );
                label.setAttribute( "for", "qunit-filter-pass" );
+               label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
                label.innerHTML = "Hide passed tests";
                toolbar.appendChild( label );
+
+               urlConfigCheckboxes = document.createElement( 'span' );
+               urlConfigCheckboxes.innerHTML = urlConfigHtml;
+               addEvent( urlConfigCheckboxes, "change", function( event ) {
+                       var params = {};
+                       params[ event.target.name ] = event.target.checked ? true : undefined;
+                       window.location = QUnit.url( params );
+               });
+               toolbar.appendChild( urlConfigCheckboxes );
+
+               if (numModules > 1) {
+                       moduleFilter = document.createElement( 'span' );
+                       moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
+                       moduleFilter.innerHTML = moduleFilterHtml;
+                       addEvent( moduleFilter, "change", function() {
+                               var selectBox = moduleFilter.getElementsByTagName("select")[0],
+                                   selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+
+                               window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
+                       });
+                       toolbar.appendChild(moduleFilter);
+               }
        }
 
        // `main` initialized at top of scope
@@ -970,9 +1072,9 @@ window.onerror = function ( error, filePath, linerNr ) {
                        }
                        QUnit.pushFailure( error, filePath + ":" + linerNr );
                } else {
-                       QUnit.test( "global failure", function() {
+                       QUnit.test( "global failure", extend( function() {
                                QUnit.pushFailure( error, filePath + ":" + linerNr );
-                       });
+                       }, { validTest: validTest } ) );
                }
                return false;
        }
@@ -1039,6 +1141,11 @@ function done() {
                }
        }
 
+       // scroll back to top to show results
+       if ( window.scrollTo ) {
+               window.scrollTo(0, 0);
+       }
+
        runLoggingCallbacks( "done", QUnit, {
                failed: config.stats.bad,
                passed: passed,
@@ -1051,14 +1158,20 @@ function done() {
 function validTest( test ) {
        var include,
                filter = config.filter && config.filter.toLowerCase(),
-               module = config.module,
+               module = config.module && config.module.toLowerCase(),
                fullName = (test.module + ": " + test.testName).toLowerCase();
 
+       // Internally-generated tests are always valid
+       if ( test.callback && test.callback.validTest === validTest ) {
+               delete test.callback.validTest;
+               return true;
+       }
+
        if ( config.testNumber ) {
                return test.testNumber === config.testNumber;
        }
 
-       if ( module && test.module !== module ) {
+       if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
                return false;
        }
 
@@ -1335,7 +1448,8 @@ QUnit.equiv = (function() {
                                                a.global === b.global &&
                                                // (gmi) ...
                                                a.ignoreCase === b.ignoreCase &&
-                                               a.multiline === b.multiline;
+                                               a.multiline === b.multiline &&
+                                               a.sticky === b.sticky;
                                },
 
                                // - skip when the property is a method of an instance (OOP)