Merge "(bug 46751) Make Buryat (Russia) (буряад) (bxr) fallback to Russian"
[lhc/web/wiklou.git] / tests / qunit / data / testrunner.js
index 77db213..1a2bfa1 100644 (file)
@@ -5,7 +5,9 @@
 
        var mwTestIgnore, mwTester,
                addons,
-               envExecCount;
+               envExecCount,
+               ELEMENT_NODE = 1,
+               TEXT_NODE = 3;
 
        /**
         * Add bogus to url to prevent IE crazy caching
@@ -36,6 +38,8 @@
                tooltip: 'Enable debug mode in ResourceLoader'
        } );
 
+       QUnit.config.requireExpects = true;
+
        /**
         * Load TestSwarm agent
         */
        // of MediaWiki has actually been configured with the required url to that inject.js
        // script. By default it is false.
        if ( QUnit.urlParams.swarmURL && mw.config.get( 'QUnitTestSwarmInjectJSPath' ) ) {
-               document.write( '<scr' + 'ipt src="' + QUnit.fixurl( mw.config.get( 'QUnitTestSwarmInjectJSPath' ) ) + '"></scr' + 'ipt>' );
+               jQuery.getScript( QUnit.fixurl( mw.config.get( 'QUnitTestSwarmInjectJSPath' ) ) );
        }
 
        /**
         * CompletenessTest
+        *
+        * Adds toggle checkbox to header
         */
-        // Adds toggle checkbox to header
        QUnit.config.urlConfig.push( {
                id: 'completenesstest',
                label: 'Run CompletenessTest',
@@ -91,8 +96,9 @@
 
        /**
         * Test environment recommended for all QUnit test modules
+        *
+        * Whether to log environment changes to the console
         */
-        // Whether to log environment changes to the console
        QUnit.config.urlConfig.push( 'mwlogenv' );
 
        /**
                return $.when.apply( $, altPromises );
        };
 
+       /**
+        * Recursively convert a node to a plain object representing its structure.
+        * Only considers attributes and contents (elements and text nodes).
+        * Attribute values are compared strictly and not normalised.
+        *
+        * @param {Node} node
+        * @return {Object|string} Plain JavaScript value representing the node.
+        */
+       function getDomStructure( node ) {
+               var $node, children, processedChildren, i, len, el;
+               $node = $( node );
+               if ( node.nodeType === 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 ) {
+                                       processedChildren.push( getDomStructure( el ) );
+                               }
+                       }
+
+                       return {
+                               tagName: node.tagName,
+                               attributes: $node.getAttrs(),
+                               contents: processedChildren
+                       };
+               } else {
+                       // Should be text node
+                       return $node.text();
+               }
+       }
+
+       /**
+        * Gets structure of node for this HTML.
+        *
+        * @param {string} html HTML markup for one or more nodes.
+        */
+       function getHtmlStructure( html ) {
+               var el = $( '<div>' ).append( html )[0];
+               return getDomStructure( el );
+       }
+
        /**
         * Add-on assertion helpers
         */
                // Expect numerical value greater than or equal to X
                gtOrEq: function ( actual, expected, message ) {
                        QUnit.push( actual >= expected, actual, 'greater than or equal to ' + expected, message );
+               },
+
+               /**
+                * Asserts that two HTML strings are structurally equivalent.
+                *
+                * @param {string} actualHtml Actual HTML markup.
+                * @param {string} expectedHtml Expected HTML markup
+                * @param {string} message Assertion message.
+                */
+               htmlEqual: function ( actualHtml, expectedHtml, message ) {
+                       var actual = getHtmlStructure( actualHtml ),
+                               expected = getHtmlStructure( expectedHtml );
+
+                       QUnit.push(
+                               QUnit.equiv(
+                                       actual,
+                                       expected
+                               ),
+                               actual,
+                               expected,
+                               message
+                       );
+               },
+
+               /**
+                * Asserts that two HTML strings are not structurally equivalent.
+                *
+                * @param {string} actualHtml Actual HTML markup.
+                * @param {string} expectedHtml Expected HTML markup.
+                * @param {string} message Assertion message.
+                */
+               notHtmlEqual: function ( actualHtml, expectedHtml, message ) {
+                       var actual = getHtmlStructure( actualHtml ),
+                               expected = getHtmlStructure( expectedHtml );
+
+                       QUnit.push(
+                               !QUnit.equiv(
+                                       actual,
+                                       expected
+                               ),
+                               actual,
+                               expected,
+                               message
+                       );
                }
        };
 
                assert.equal( mw.messages.get( 'testMsg' ), 'Foo.', 'messages object restored and re-applied after test()' );
        } );
 
+       QUnit.test( 'Loader status', 2, function ( assert ) {
+               var i, len, state,
+                       modules = mw.loader.getModuleNames(),
+                       error = [],
+                       missing = [];
+
+               for ( i = 0, len = modules.length; i < len; i++ ) {
+                       state = mw.loader.getState( modules[i] );
+                       if ( state === 'error' ) {
+                               error.push( modules[i] );
+                       } else if ( state === 'missing' ) {
+                               missing.push( modules[i] );
+                       }
+               }
+
+               assert.deepEqual( error, [], 'Modules in error state' );
+               assert.deepEqual( missing, [], 'Modules in missing state' );
+       } );
+
+       QUnit.test( 'htmlEqual', 8, function ( assert ) {
+               assert.htmlEqual(
+                       '<div><p class="some classes" data-length="10">Child paragraph with <a href="http://example.com">A link</a></p>Regular text<span>A span</span></div>',
+                       '<div><p data-length=\'10\'  class=\'some classes\'>Child paragraph with <a href=\'http://example.com\' >A link</a></p>Regular text<span>A span</span></div>',
+                       'Attribute order, spacing and quotation marks (equal)'
+               );
+
+               assert.notHtmlEqual(
+                       '<div><p class="some classes" data-length="10">Child paragraph with <a href="http://example.com">A link</a></p>Regular text<span>A span</span></div>',
+                       '<div><p data-length=\'10\'  class=\'some more classes\'>Child paragraph with <a href=\'http://example.com\' >A link</a></p>Regular text<span>A span</span></div>',
+                       'Attribute order, spacing and quotation marks (not equal)'
+               );
+
+               assert.htmlEqual(
+                       '<label for="firstname" accesskey="f" class="important">First</label><input id="firstname" /><label for="lastname" accesskey="l" class="minor">Last</label><input id="lastname" />',
+                       '<label for="firstname" accesskey="f" class="important">First</label><input id="firstname" /><label for="lastname" accesskey="l" class="minor">Last</label><input id="lastname" />',
+                       'Multiple root nodes (equal)'
+               );
+
+               assert.notHtmlEqual(
+                       '<label for="firstname" accesskey="f" class="important">First</label><input id="firstname" /><label for="lastname" accesskey="l" class="minor">Last</label><input id="lastname" />',
+                       '<label for="firstname" accesskey="f" class="important">First</label><input id="firstname" /><label for="lastname" accesskey="l" class="important" >Last</label><input id="lastname" />',
+                       'Multiple root nodes (not equal, last label node is different)'
+               );
+
+               assert.htmlEqual(
+                       'fo&quot;o<br/>b&gt;ar',
+                       'fo"o<br/>b>ar',
+                       'Extra escaping is equal'
+               );
+               assert.notHtmlEqual(
+                       'foo&lt;br/&gt;bar',
+                       'foo<br/>bar',
+                       'Text escaping (not equal)'
+               );
+
+               assert.htmlEqual(
+                       'foo<a href="http://example.com">example</a>bar',
+                       'foo<a href="http://example.com">example</a>bar',
+                       'Outer text nodes are compared (equal)'
+               );
+
+               assert.notHtmlEqual(
+                       'foo<a href="http://example.com">example</a>bar',
+                       'foo<a href="http://example.com">example</a>quux',
+                       'Outer text nodes are compared (last text node different)'
+               );
+
+       } );
+
        QUnit.module( 'mediawiki.tests.qunit.testrunner-after', QUnit.newMwEnvironment() );
 
        QUnit.test( 'Teardown', 3, function ( assert ) {