r88431 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r88430‎ | r88431 | r88432 >
Date:21:35, 19 May 2011
Author:krinkle
Status:ok
Tags:
Comment:
QUnit reorganization
* Moved QUnit directory from /resources/test/ to /tests/qunit/.
* Includes an .htaccess file in /tests/qunit/ to allow reading this from the browser (since /tests/.htaccess disallows this by default, as it should)
* Deleted "/unit/main.css" which wasn't used for anything (was an idea I had but redundant now)
* Renamed /qunit/unit/ to /qunit/suites/
* Re-organized structure within /suites/ to match that of MediaWiki's. (ie. /resources/jquery, /resources/mediawiki.util etc.)
This will make it easier to write a "check if all JS have a test suite" thingy.
* Added a few "Clean up" sections in the test suites to remove added elements (namely added portlet links)
Modified paths:
  • /trunk/phase3/resources/test (deleted) (history)
  • /trunk/phase3/tests/qunit (added) (history)
  • /trunk/phase3/tests/qunit/.htaccess (added) (history)
  • /trunk/phase3/tests/qunit/index.html (modified) (history)
  • /trunk/phase3/tests/qunit/suites (added) (history)
  • /trunk/phase3/tests/qunit/suites/jquery (deleted) (history)
  • /trunk/phase3/tests/qunit/suites/main.css (deleted) (history)
  • /trunk/phase3/tests/qunit/suites/mediawiki (deleted) (history)
  • /trunk/phase3/tests/qunit/suites/mediawiki.util (deleted) (history)
  • /trunk/phase3/tests/qunit/suites/resources (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/jquery (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/jquery/jquery.autoEllipsis.js (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/jquery/jquery.colorUtil.js (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/jquery/jquery.mwPrototypes.js (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/mediawiki (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/mediawiki.util (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/mediawiki.util/mediawiki.util.js (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.js (added) (history)
  • /trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.user.js (added) (history)
  • /trunk/phase3/tests/qunit/unit (deleted) (history)

Diff [purge]

Index: trunk/phase3/tests/qunit/testswarm.inject.js
@@ -0,0 +1,349 @@
 2+/*
 3+ Copyright (c) 2009 John Resig
 4+
 5+ Permission is hereby granted, free of charge, to any person
 6+ obtaining a copy of this software and associated documentation
 7+ files (the "Software"), to deal in the Software without
 8+ restriction, including without limitation the rights to use,
 9+ copy, modify, merge, publish, distribute, sublicense, and/or sell
 10+ copies of the Software, and to permit persons to whom the
 11+ Software is furnished to do so, subject to the following
 12+ conditions:
 13+
 14+ The above copyright notice and this permission notice shall be
 15+ included in all copies or substantial portions of the Software.
 16+
 17+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 18+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 19+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 20+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 21+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 22+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 23+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 24+ OTHER DEALINGS IN THE SOFTWARE.
 25+
 26+*/
 27+(function(){
 28+
 29+ var DEBUG = false;
 30+
 31+ var doPost = false;
 32+
 33+ try {
 34+ doPost = !!window.top.postMessage;
 35+ } catch(e){}
 36+
 37+ var search = window.location.search,
 38+ url, index;
 39+ if( ( index = search.indexOf( "swarmURL=" ) ) != -1 )
 40+ url = decodeURIComponent( search.slice( index + 9 ) );
 41+
 42+ if ( !DEBUG && (!url || url.indexOf("http") !== 0) ) {
 43+ return;
 44+ }
 45+
 46+ var submitTimeout = 5;
 47+
 48+ var curHeartbeat;
 49+ var beatRate = 20;
 50+
 51+ // Expose the TestSwarm API
 52+ window.TestSwarm = {
 53+ submit: submit,
 54+ heartbeat: function(){
 55+ if ( curHeartbeat ) {
 56+ clearTimeout( curHeartbeat );
 57+ }
 58+
 59+ curHeartbeat = setTimeout(function(){
 60+ submit({ fail: -1, total: -1 });
 61+ }, beatRate * 1000);
 62+ },
 63+ serialize: function(){
 64+ return trimSerialize();
 65+ }
 66+ };
 67+
 68+ // Prevent careless things from executing
 69+ window.print = window.confirm = window.alert = window.open = function(){};
 70+
 71+ window.onerror = function(e){
 72+ document.body.appendChild( document.createTextNode( "ERROR: " + e ));
 73+ submit({ fail: 0, error: 1, total: 1 });
 74+ return false;
 75+ };
 76+
 77+ // QUnit (jQuery)
 78+ // http://docs.jquery.com/QUnit
 79+ if ( typeof QUnit !== "undefined" ) {
 80+ QUnit.done = function(results){
 81+ submit({
 82+ fail: results.failed,
 83+ error: 0,
 84+ total: results.total
 85+ });
 86+ };
 87+
 88+ QUnit.log = window.TestSwarm.heartbeat;
 89+ window.TestSwarm.heartbeat();
 90+
 91+ window.TestSwarm.serialize = function(){
 92+ // Clean up the HTML (remove any un-needed test markup)
 93+ remove("nothiddendiv");
 94+ remove("loadediframe");
 95+ remove("dl");
 96+ remove("main");
 97+
 98+ // Show any collapsed results
 99+ var ol = document.getElementsByTagName("ol");
 100+ for ( var i = 0; i < ol.length; i++ ) {
 101+ ol[i].style.display = "block";
 102+ }
 103+
 104+ return trimSerialize();
 105+ };
 106+
 107+ // UnitTestJS (Prototype, Scriptaculous)
 108+ // http://github.com/tobie/unittest_js/tree/master
 109+ } else if ( typeof Test !== "undefined" && Test && Test.Unit && Test.Unit.runners ) {
 110+ var total_runners = Test.Unit.runners.length, cur_runners = 0;
 111+ var total = 0, fail = 0, error = 0;
 112+
 113+ for (var i = 0; i < Test.Unit.runners.length; i++) (function(i){
 114+ var finish = Test.Unit.runners[i].finish;
 115+ Test.Unit.runners[i].finish = function(){
 116+ finish.call( this );
 117+
 118+ var results = this.getResult();
 119+ total += results.assertions;
 120+ fail += results.failures;
 121+ error += results.errors;
 122+
 123+ if ( ++cur_runners === total_runners ) {
 124+ submit({
 125+ fail: fail,
 126+ error: error,
 127+ total: total
 128+ });
 129+ }
 130+ };
 131+ })(i);
 132+
 133+ // JSSpec (MooTools)
 134+ // http://jania.pe.kr/aw/moin.cgi/JSSpec
 135+ } else if ( typeof JSSpec !== "undefined" && JSSpec && JSSpec.Logger ) {
 136+ var onRunnerEnd = JSSpec.Logger.prototype.onRunnerEnd;
 137+ JSSpec.Logger.prototype.onRunnerEnd = function(){
 138+ onRunnerEnd.call(this);
 139+
 140+ // Show any collapsed results
 141+ var ul = document.getElementsByTagName("ul");
 142+ for ( var i = 0; i < ul.length; i++ ) {
 143+ ul[i].style.display = "block";
 144+ }
 145+
 146+ submit({
 147+ fail: JSSpec.runner.getTotalFailures(),
 148+ error: JSSpec.runner.getTotalErrors(),
 149+ total: JSSpec.runner.totalExamples
 150+ });
 151+ };
 152+
 153+ window.TestSwarm.serialize = function(){
 154+ // Show any collapsed results
 155+ var ul = document.getElementsByTagName("ul");
 156+ for ( var i = 0; i < ul.length; i++ ) {
 157+ ul[i].style.display = "block";
 158+ }
 159+
 160+ return trimSerialize();
 161+ };
 162+
 163+ // JSUnit
 164+ // http://www.jsunit.net/
 165+ // Note: Injection file must be included before the frames
 166+ // are document.write()d into the page.
 167+ } else if ( typeof JsUnitTestManager !== "undefined" ) {
 168+ var _done = JsUnitTestManager.prototype._done;
 169+ JsUnitTestManager.prototype._done = function(){
 170+ _done.call(this);
 171+
 172+ submit({
 173+ fail: this.failureCount,
 174+ error: this.errorCount,
 175+ total: this.totalCount
 176+ });
 177+ };
 178+
 179+ window.TestSwarm.serialize = function(){
 180+ return "<pre>" + this.log.join("\n") + "</pre>";
 181+ };
 182+
 183+ // Selenium Core
 184+ // http://seleniumhq.org/projects/core/
 185+ } else if ( typeof SeleniumTestResult !== "undefined" && typeof LOG !== "undefined" ) {
 186+ // Completely overwrite the postback
 187+ SeleniumTestResult.prototype.post = function(){
 188+ submit({
 189+ fail: this.metrics.numCommandFailures,
 190+ error: this.metrics.numCommandErrors,
 191+ total: this.metrics.numCommandPasses + this.metrics.numCommandFailures + this.metrics.numCommandErrors
 192+ });
 193+ };
 194+
 195+ window.TestSwarm.serialize = function(){
 196+ var results = [];
 197+ while ( LOG.pendingMessages.length ) {
 198+ var msg = LOG.pendingMessages.shift();
 199+ results.push( msg.type + ": " + msg.msg );
 200+ }
 201+
 202+ return "<pre>" + results.join("\n") + "</pre>";
 203+ };
 204+
 205+ // Dojo Objective Harness
 206+ // http://docs.dojocampus.org/quickstart/doh
 207+ } else if ( typeof doh !== "undefined" && doh._report ) {
 208+ var _report = doh._report;
 209+ doh._report = function(){
 210+ _report.apply(this, arguments);
 211+
 212+ submit({
 213+ fail: doh._failureCount,
 214+ error: doh._errorCount,
 215+ total: doh._testCount
 216+ });
 217+ };
 218+
 219+ window.TestSwarm.serialize = function(){
 220+ return "<pre>" + document.getElementById("logBody").innerHTML + "</pre>";
 221+ };
 222+ // Screw.Unit
 223+ // git://github.com/nathansobo/screw-unit.git
 224+ } else if ( typeof Screw !== "undefined" && typeof jQuery !== 'undefined' && Screw && Screw.Unit ) {
 225+ $(Screw).bind("after", function() {
 226+ var passed = $('.passed').length;
 227+ var failed = $('.failed').length;
 228+ submit({
 229+ fail: failed,
 230+ error: 0,
 231+ total: failed + passed
 232+ });
 233+ });
 234+
 235+ $(Screw).bind("loaded", function() {
 236+ $('.it')
 237+ .bind("passed", window.TestSwarm.heartbeat)
 238+ .bind("failed", window.TestSwarm.heartbeat);
 239+ window.TestSwarm.heartbeat();
 240+ });
 241+
 242+ window.TestSwarm.serialize = function(){
 243+ return trimSerialize();
 244+ };
 245+ }
 246+
 247+ function trimSerialize(doc) {
 248+ doc = doc || document;
 249+
 250+ var scripts = doc.getElementsByTagName("script");
 251+ while ( scripts.length ) {
 252+ remove( scripts[0] );
 253+ }
 254+
 255+ var root = window.location.href.replace(/(https?:\/\/.*?)\/.*/, "$1");
 256+ var cur = window.location.href.replace(/[^\/]*$/, "");
 257+
 258+ var links = doc.getElementsByTagName("link");
 259+ for ( var i = 0; i < links.length; i++ ) {
 260+ var href = links[i].href;
 261+ if ( href.indexOf("/") === 0 ) {
 262+ href = root + href;
 263+ } else if ( !/^https?:\/\//.test( href ) ) {
 264+ href = cur + href;
 265+ }
 266+ links[i].href = href;
 267+ }
 268+
 269+ return ("<html>" + doc.documentElement.innerHTML + "</html>")
 270+ .replace(/\s+/g, " ");
 271+ }
 272+
 273+ function remove(elem){
 274+ if ( typeof elem === "string" ) {
 275+ elem = document.getElementById( elem );
 276+ }
 277+
 278+ if ( elem ) {
 279+ elem.parentNode.removeChild( elem );
 280+ }
 281+ }
 282+
 283+ function submit(params){
 284+ if ( curHeartbeat ) {
 285+ clearTimeout( curHeartbeat );
 286+ }
 287+
 288+ var paramItems = (url.split("?")[1] || "").split("&");
 289+
 290+ for ( var i = 0; i < paramItems.length; i++ ) {
 291+ if ( paramItems[i] ) {
 292+ var parts = paramItems[i].split("=");
 293+ if ( !params[ parts[0] ] ) {
 294+ params[ parts[0] ] = parts[1];
 295+ }
 296+ }
 297+ }
 298+
 299+ if ( !params.state ) {
 300+ params.state = "saverun";
 301+ }
 302+
 303+ if ( !params.results ) {
 304+ params.results = window.TestSwarm.serialize();
 305+ }
 306+
 307+ if ( doPost ) {
 308+ // Build Query String
 309+ var query = "";
 310+
 311+ for ( var i in params ) {
 312+ query += ( query ? "&" : "" ) + i + "=" +
 313+ encodeURIComponent(params[i]);
 314+ }
 315+
 316+ if ( DEBUG ) {
 317+ alert( query );
 318+ } else {
 319+ window.top.postMessage( query, "*" );
 320+ }
 321+
 322+ } else {
 323+ var form = document.createElement("form");
 324+ form.action = url;
 325+ form.method = "POST";
 326+
 327+ for ( var i in params ) {
 328+ var input = document.createElement("input");
 329+ input.type = "hidden";
 330+ input.name = i;
 331+ input.value = params[i];
 332+ form.appendChild( input );
 333+ }
 334+
 335+ if ( DEBUG ) {
 336+ alert( form.innerHTML );
 337+ } else {
 338+
 339+ // Watch for the result submission timing out
 340+ setTimeout(function(){
 341+ submit( params );
 342+ }, submitTimeout * 1000);
 343+
 344+ document.body.appendChild( form );
 345+ form.submit();
 346+ }
 347+ }
 348+ }
 349+
 350+})();
Property changes on: trunk/phase3/tests/qunit/testswarm.inject.js
___________________________________________________________________
Added: svn:eol-style
1351 + native
Index: trunk/phase3/tests/qunit/sample/awesome.js
@@ -0,0 +1 @@
 2+window.awesome = true;
Property changes on: trunk/phase3/tests/qunit/sample/awesome.js
___________________________________________________________________
Added: svn:eol-style
13 + native
Index: trunk/phase3/tests/qunit/index.html
@@ -0,0 +1,75 @@
 2+<!DOCTYPE html>
 3+<html>
 4+<head>
 5+ <title>MediaWiki JavaScript Test Suite</title>
 6+
 7+ <!-- MediaWiki Modules -->
 8+
 9+ <!-- MW: startup -->
 10+ <script>
 11+ function startUp(){
 12+ mw.config = new mw.Map( false );
 13+ }
 14+ </script>
 15+
 16+ <!-- MW: jquery|mediawiki -->
 17+ <script src="../../resources/jquery/jquery.js"></script>
 18+ <script src="../../resources/mediawiki/mediawiki.js"></script>
 19+
 20+ <!-- MW: mediawiki.user|mediawiki.util -->
 21+ <script src="../../resources/mediawiki/mediawiki.user.js"></script>
 22+ <script src="../../resources/jquery/jquery.checkboxShiftClick.js"></script>
 23+ <script src="../../resources/jquery/jquery.client.js"></script>
 24+ <script src="../../resources/jquery/jquery.cookie.js"></script>
 25+ <script src="../../resources/jquery/jquery.messageBox.js"></script>
 26+ <script src="../../resources/jquery/jquery.makeCollapsible.js"></script>
 27+ <script src="../../resources/jquery/jquery.mwPrototypes.js"></script>
 28+ <script src="../../resources/jquery/jquery.placeholder.js"></script>
 29+ <script src="../../resources/mediawiki.util/mediawiki.util.js"></script>
 30+
 31+ <!-- MW: user.options -->
 32+ <script>
 33+ mw.user.options.set({"skin": "vector"});
 34+ </script>
 35+
 36+ <!-- MW: Non-default modules -->
 37+ <script src="../../resources/jquery/jquery.colorUtil.js"></script>
 38+ <script src="../../resources/jquery/jquery.autoEllipsis.js"></script>
 39+
 40+ <!-- QUnit: Load framework -->
 41+ <link rel="stylesheet" href="../../resources/jquery/jquery.qunit.css" />
 42+ <script src="../../resources/jquery/jquery.qunit.js"></script>
 43+
 44+ <!-- QUnit: Load test suites (maintain the same order as above please) -->
 45+ <script src="suites/resources/mediawiki/mediawiki.js"></script>
 46+ <script src="suites/resources/mediawiki/mediawiki.user.js"></script>
 47+ <script src="suites/resources/jquery/jquery.mwPrototypes.js"></script>
 48+ <script src="suites/resources/mediawiki.util/mediawiki.util.js"></script>
 49+ <script src="suites/resources/jquery/jquery.colorUtil.js"></script>
 50+ <script src="suites/resources/jquery/jquery.autoEllipsis.js"></script>
 51+
 52+ <!-- TestSwarm: If a test swarm is running this,
 53+ the following script will allow it to extract the results.
 54+ Harmless otherwise. -->
 55+ <script src="testswarm.inject.js"></script>
 56+</head>
 57+<body>
 58+ <h1 id="qunit-header">MediaWiki JavaScript Test Suite</h1>
 59+ <h2 id="qunit-banner"></h2>
 60+ <div id="qunit-testrunner-toolbar"></div>
 61+ <h2 id="qunit-userAgent"></h2>
 62+ <ol id="qunit-tests"></ol>
 63+
 64+<!-- Rough page structure for scripts needing it (Vector based). -->
 65+<!-- Scripts inserting stuff here shall remove it themselfs! -->
 66+<div id="mw-content">
 67+ <div id="bodyContent"></div>
 68+ <div id="mw-panel">
 69+ <div id="p-tb" class="portal">
 70+ <ul class="body">
 71+ </ul>
 72+ </div>
 73+ </div>
 74+</div>
 75+</body>
 76+</html>
Property changes on: trunk/phase3/tests/qunit/index.html
___________________________________________________________________
Added: svn:eol-style
177 + native
Index: trunk/phase3/tests/qunit/.htaccess
@@ -0,0 +1 @@
 2+Allow from all
Index: trunk/phase3/tests/qunit/suites/resources/jquery/jquery.colorUtil.js
@@ -0,0 +1,67 @@
 2+module( 'jquery.colorUtil.js' );
 3+
 4+test( '-- Initial check', function(){
 5+
 6+ ok( jQuery.colorUtil, 'jQuery.colorUtil defined' );
 7+});
 8+
 9+test( 'getRGB', function(){
 10+
 11+ equal( typeof jQuery.colorUtil.getRGB(), 'undefined', 'No arguments' );
 12+ equal( typeof jQuery.colorUtil.getRGB( '' ), 'undefined', 'Empty string' );
 13+ deepEqual( jQuery.colorUtil.getRGB( [0, 100, 255] ), [0, 100, 255], 'Array' );
 14+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0,100,255)' ), [0, 100, 255], 'Parse simple string' );
 15+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0, 100, 255)' ), [0, 100, 255], 'Parse simple string (whitespace)' );
 16+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0%,20%,40%)' ), [0, 51, 102], 'Parse percentages string' );
 17+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0%, 20%, 40%)' ), [0, 51, 102], 'Parse percentages string (whitespace)' );
 18+ deepEqual( jQuery.colorUtil.getRGB( '#f2ddee' ), [242, 221, 238], 'Hex string: 6 char lowercase' );
 19+ deepEqual( jQuery.colorUtil.getRGB( '#f2DDEE' ), [242, 221, 238], 'Hex string: 6 char uppercase' );
 20+ deepEqual( jQuery.colorUtil.getRGB( '#f2DdEe' ), [242, 221, 238], 'Hex string: 6 char mixed' );
 21+ deepEqual( jQuery.colorUtil.getRGB( '#eee' ), [238, 238, 238], 'Hex string: 3 char lowercase' );
 22+ deepEqual( jQuery.colorUtil.getRGB( '#EEE' ), [238, 238, 238], 'Hex string: 3 char uppercase' );
 23+ deepEqual( jQuery.colorUtil.getRGB( '#eEe' ), [238, 238, 238], 'Hex string: 3 char mixed' );
 24+ deepEqual( jQuery.colorUtil.getRGB( 'rgba(0, 0, 0, 0)' ), [255, 255, 255], 'Zero rgba for Safari 3; Transparent (whitespace)' );
 25+ // Perhaps this is a bug in colorUtil, but it is the current behaviour so, let's keep track
 26+ // would that ever change
 27+ equal( typeof jQuery.colorUtil.getRGB( 'rgba(0,0,0,0)' ), 'undefined', 'Zero rgba without whitespace' );
 28+
 29+ deepEqual( jQuery.colorUtil.getRGB( 'lightGreen' ), [144, 238, 144], 'Color names (lightGreen)' );
 30+ deepEqual( jQuery.colorUtil.getRGB( 'lightGreen' ), [144, 238, 144], 'Color names (transparent)' );
 31+ equal( typeof jQuery.colorUtil.getRGB( 'mediaWiki' ), 'undefined', 'Inexisting color name' );
 32+
 33+});
 34+
 35+test( 'rgbToHsl', function(){
 36+ var hsl = jQuery.colorUtil.rgbToHsl( 144, 238, 144 );
 37+ var dualDecimals = function(a,b){
 38+ return Math.round(a*100)/100;
 39+ };
 40+
 41+ ok( hsl, 'Basic return evaluation' );
 42+ deepEqual( dualDecimals(hsl[0]) , 0.33, 'rgb(144, 238, 144): H 0.33' );
 43+ deepEqual( dualDecimals(hsl[1]) , 0.73, 'rgb(144, 238, 144): S 0.73' );
 44+ deepEqual( dualDecimals(hsl[2]) , 0.75, 'rgb(144, 238, 144): L 0.75' );
 45+
 46+});
 47+
 48+test( 'hslToRgb', function(){
 49+ var rgb = jQuery.colorUtil.hslToRgb( 0.3, 0.7, 0.8 );
 50+
 51+ ok( rgb, 'Basic return evaluation' );
 52+ deepEqual( Math.round(rgb[0]) , 183, 'hsl(0.3, 0.7, 0.8): R 183' );
 53+ deepEqual( Math.round(rgb[1]) , 240, 'hsl(0.3, 0.7, 0.8): G 240' );
 54+ deepEqual( Math.round(rgb[2]) , 168, 'hsl(0.3, 0.7, 0.8): B 168' );
 55+
 56+});
 57+
 58+test( 'getColorBrightness', function(){
 59+
 60+ var a = jQuery.colorUtil.getColorBrightness( 'red', +0.1 );
 61+
 62+ equal( a, 'rgb(255,50,50)', 'Start with named color, brighten 10%' );
 63+
 64+ var b = jQuery.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
 65+
 66+ equal( b, 'rgb(118,29,29)', 'Start with rgb string, darken 10%' );
 67+
 68+});
Property changes on: trunk/phase3/tests/qunit/suites/resources/jquery/jquery.colorUtil.js
___________________________________________________________________
Added: svn:eol-style
169 + native
Index: trunk/phase3/tests/qunit/suites/resources/jquery/jquery.mwPrototypes.js
@@ -0,0 +1,58 @@
 2+module( 'jquery.mwPrototypes.js' );
 3+
 4+test( 'String functions', function(){
 5+
 6+ equal( $j.trimLeft( ' foo bar ' ), 'foo bar ', 'trimLeft' );
 7+ equal( $j.trimRight( ' foo bar ' ), ' foo bar', 'trimRight' );
 8+ equal( $j.ucFirst( 'foo'), 'Foo', 'ucFirst' );
 9+
 10+ equal( $j.escapeRE( '<!-- ([{+mW+}]) $^|?>' ),
 11+ '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?>', 'escapeRE - Escape specials' );
 12+ equal( $j.escapeRE( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ),
 13+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'escapeRE - Leave uppercase alone' );
 14+ equal( $j.escapeRE( 'abcdefghijklmnopqrstuvwxyz' ),
 15+ 'abcdefghijklmnopqrstuvwxyz', 'escapeRE - Leave lowercase alone' );
 16+ equal( $j.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
 17+
 18+});
 19+
 20+test( 'Is functions', function(){
 21+
 22+ deepEqual( $j.isDomElement( document.getElementById( 'qunit-header' ) ), true,
 23+ 'isDomElement: #qunit-header Node' );
 24+ deepEqual( $j.isDomElement( document.getElementById( 'random-name' ) ), false,
 25+ 'isDomElement: #random-name (null)' );
 26+ deepEqual( $j.isDomElement( document.getElementsByTagName( 'div' ) ), false,
 27+ 'isDomElement: getElementsByTagName Array' );
 28+ deepEqual( $j.isDomElement( document.getElementsByTagName( 'div' )[0] ), true,
 29+ 'isDomElement: getElementsByTagName(..)[0] Node' );
 30+ deepEqual( $j.isDomElement( $j( 'div' ) ), false,
 31+ 'isDomElement: jQuery object' );
 32+ deepEqual( $j.isDomElement( $j( 'div' ).get(0) ), true,
 33+ 'isDomElement: jQuery object > Get node' );
 34+ deepEqual( $j.isDomElement( document.createElement( 'div' ) ), true,
 35+ 'isDomElement: createElement' );
 36+ deepEqual( $j.isDomElement( { foo: 1 } ), false,
 37+ 'isDomElement: Object' );
 38+
 39+ equal( $j.isEmpty( 'string' ), false, 'isEmptry: "string"' );
 40+ equal( $j.isEmpty( '0' ), true, 'isEmptry: "0"' );
 41+ equal( $j.isEmpty( [] ), true, 'isEmptry: []' );
 42+ equal( $j.isEmpty( {} ), true, 'isEmptry: {}' );
 43+ // Documented behaviour
 44+ equal( $j.isEmpty( { length: 0 } ), true, 'isEmptry: { length: 0 }' );
 45+
 46+});
 47+
 48+test( 'Comparison functions', function(){
 49+
 50+ ok( $j.compareArray( [0, 'a', [], [2, 'b'] ], [0, "a", [], [2, "b"] ] ),
 51+ 'compareArray: Two deep arrays that are excactly the same' );
 52+ ok( !$j.compareArray( [1], [2] ), 'compareArray: Two different arrays (false)' );
 53+
 54+ ok( $j.compareObject( {}, {} ), 'compareObject: Two empty objects' );
 55+ ok( $j.compareObject( { foo: 1 }, { foo: 1 } ), 'compareObject: Two the same objects' );
 56+ ok( !$j.compareObject( { bar: true }, { baz: false } ),
 57+ 'compareObject: Two different objects (false)' );
 58+
 59+});
\ No newline at end of file
Property changes on: trunk/phase3/tests/qunit/suites/resources/jquery/jquery.mwPrototypes.js
___________________________________________________________________
Added: svn:eol-style
160 + native
Index: trunk/phase3/tests/qunit/suites/resources/jquery/jquery.autoEllipsis.js
@@ -0,0 +1,49 @@
 2+module( 'jquery.autoEllipsis.js' );
 3+
 4+test( '-- Initial check', function(){
 5+
 6+ ok( jQuery.fn.autoEllipsis, 'jQuery.fn.autoEllipsis defined' );
 7+});
 8+
 9+function createWrappedDiv( text ) {
 10+ var $wrapper = $( '<div />' ).css( 'width', '100px' );
 11+ var $div = $( '<div />' ).text( text );
 12+ $wrapper.append( $div );
 13+ return $wrapper;
 14+}
 15+
 16+function findDivergenceIndex( a, b ) {
 17+ var i = 0;
 18+ while ( i < a.length && i < b.length && a[i] == b[i] ) {
 19+ i++;
 20+ }
 21+ return i;
 22+}
 23+
 24+test( 'Position right', function() {
 25+ // We need this thing to be visible, so append it to the DOM
 26+ var origText = 'This is a really long random string and there is no way it fits in 100 pixels.';
 27+ var $wrapper = createWrappedDiv( origText );
 28+ $( 'body' ).append( $wrapper );
 29+ $wrapper.autoEllipsis( { position: 'right' } );
 30+
 31+ // Verify that, and only one, span element was created
 32+ var $span = $wrapper.find( '> span' );
 33+ deepEqual( $span.length, 1, 'autoEllipsis wrapped the contents in a span element' );
 34+
 35+ // Check that the text fits by turning on word wrapping
 36+ $span.css( 'whiteSpace', 'nowrap' );
 37+ ok( $span.width() <= $span.parent().width(), "Text fits (span's width is no larger than its parent's width)" );
 38+
 39+ // Add one character using scary black magic
 40+ var spanText = $span.text();
 41+ var d = findDivergenceIndex( origText, spanText );
 42+ spanText = spanText.substr( 0, d ) + origText[d] + '...';
 43+
 44+ // Put this text in the span and verify it doesn't fit
 45+ $span.text( spanText );
 46+ ok( $span.width() > $span.parent().width(), 'Fit is maximal (adding one character makes it not fit any more)' );
 47+
 48+ // Clean up
 49+ $wrapper.remove();
 50+});
Property changes on: trunk/phase3/tests/qunit/suites/resources/jquery/jquery.autoEllipsis.js
___________________________________________________________________
Added: svn:eol-style
151 + native
Index: trunk/phase3/tests/qunit/suites/resources/mediawiki.util/mediawiki.util.js
@@ -0,0 +1,216 @@
 2+module( 'mediawiki.util.js' );
 3+
 4+test( '-- Initial check', function(){
 5+
 6+ ok( mw.util, 'mw.util defined' );
 7+
 8+});
 9+
 10+test( 'rawurlencode', function(){
 11+
 12+ equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
 13+
 14+});
 15+
 16+test( 'wikiUrlencode', function(){
 17+
 18+ equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
 19+
 20+});
 21+
 22+test( 'addCSS', function(){
 23+
 24+ var a = mw.util.addCSS( '#bodyContent { visibility: hidden; }' );
 25+ ok( a, 'function works' );
 26+ deepEqual( a.disabled, false, 'property "disabled" is available and set to false' );
 27+
 28+ var $b = $('#bodyContent');
 29+ equal( $b.css('visibility'), 'hidden', 'Added style properties are in effect.' );
 30+
 31+
 32+});
 33+
 34+test( 'toggleToc', function(){
 35+
 36+ ok( mw.util.toggleToc );
 37+
 38+});
 39+
 40+test( 'wikiGetlink', function(){
 41+
 42+ // Not part of startUp module
 43+ mw.config.set( 'wgArticlePath', '/wiki/$1' );
 44+
 45+ var hrefA = mw.util.wikiGetlink( 'Sandbox' );
 46+
 47+ equal( hrefA, '/wiki/Sandbox', 'Simple title; Get link for "Sandbox"' );
 48+
 49+ var hrefB = mw.util.wikiGetlink( 'Foo:Sandbox ? 5+5=10 ! (test)/subpage' );
 50+
 51+ equal( hrefB, '/wiki/Foo:Sandbox_%3F_5%2B5%3D10_%21_%28test%29/subpage', 'Advanced title; Get link for "Foo:Sandbox ? 5+5=10 ! (test)/subpage"' );
 52+
 53+});
 54+
 55+test( 'getParamValue', function(){
 56+
 57+ var url = 'http://mediawiki.org/?foo=wrong&foo=right#&foo=bad';
 58+
 59+ equal( mw.util.getParamValue( 'foo', url ), 'right', 'Use latest one, ignore hash' );
 60+ deepEqual( mw.util.getParamValue( 'bar', url ), null, 'Return null when not found' );
 61+
 62+});
 63+
 64+test( 'getActionFrom', function(){
 65+
 66+ // Example urls
 67+ var urlA = 'http://mediawiki.org/wiki/Article',
 68+ urlB = 'http://mediawiki.org/w/index.php?title=Article&action=edit',
 69+ urlC = 'http://mediawiki.org/edit/Article',
 70+ urlD = 'http://mediawiki.org/w/index.php/Article';
 71+
 72+ // Common settings
 73+ mw.config.set( {
 74+ 'wgActionPaths': [],
 75+ 'wgArticlePath': '/wiki/$1'
 76+ });
 77+
 78+ equal( mw.util.getActionFrom( urlA ), 'view', 'wgArticlePath (/wiki/$1) support' );
 79+ equal( mw.util.getActionFrom( urlB ), 'edit', 'action-parameter support' );
 80+
 81+ // Custom settings
 82+ mw.config.set( 'wgActionPaths', {
 83+ 'view': '/view/$1',
 84+ 'edit': '/edit/$1'
 85+ });
 86+
 87+ equal( mw.util.getActionFrom( urlC ), 'edit', 'wgActionPaths support' );
 88+
 89+ // Default settings
 90+ mw.config.set( {
 91+ 'wgActionPaths': [],
 92+ 'wgArticlePath': '/w/index.php/$1'
 93+ });
 94+ equal( mw.util.getActionFrom( urlD ), 'view', 'wgArticlePath (/index.php/$1) support' );
 95+
 96+});
 97+
 98+test( 'getTitleFrom', function(){
 99+
 100+ // Example urls
 101+ var urlA = 'http://mediawiki.org/wiki/Article',
 102+ urlB = 'http://mediawiki.org/w/index.php?title=Article&action=edit',
 103+ urlC = 'http://mediawiki.org/edit/Article',
 104+ urlD = 'http://mediawiki.org/w/index.php/Article';
 105+
 106+ // Common settings
 107+ mw.config.set( {
 108+ 'wgActionPaths': [],
 109+ 'wgArticlePath': '/wiki/$1'
 110+ });
 111+
 112+ equal( mw.util.getTitleFrom( urlA ), 'Article', 'wgArticlePath (/wiki/$1) support' );
 113+ equal( mw.util.getTitleFrom( urlB ), 'Article', 'action-parameter support' );
 114+
 115+ // Custom settings
 116+ mw.config.set( 'wgActionPaths', {
 117+ 'view': '/view/$1',
 118+ 'edit': '/edit/$1'
 119+ });
 120+
 121+ equal( mw.util.getTitleFrom( urlC ), 'Article', 'wgActionPaths support' );
 122+
 123+ // Default settings
 124+ mw.config.set( {
 125+ 'wgActionPaths': [],
 126+ 'wgArticlePath': '/w/index.php/$1'
 127+ });
 128+
 129+ equal( mw.util.getTitleFrom( urlD ), 'Article', 'wgArticlePath (/index.php/$1) support' );
 130+
 131+});
 132+
 133+test( 'tooltipAccessKey', function(){
 134+
 135+ equal( typeof mw.util.tooltipAccessKeyPrefix, 'string', 'mw.util.tooltipAccessKeyPrefix must be a string' );
 136+ ok( mw.util.tooltipAccessKeyRegexp instanceof RegExp, 'mw.util.tooltipAccessKeyRegexp instance of RegExp' );
 137+ ok( mw.util.updateTooltipAccessKeys, 'mw.util.updateTooltipAccessKeys' );
 138+
 139+});
 140+
 141+test( '$content', function(){
 142+
 143+ ok( mw.util.$content instanceof jQuery, 'mw.util.$content instance of jQuery' );
 144+ deepEqual( mw.util.$content.length, 1, 'mw.util.$content must have length of 1' );
 145+
 146+});
 147+
 148+test( 'addPortletLink', function(){
 149+
 150+ var A = mw.util.addPortletLink( 'p-tb', 'http://mediawiki.org/wiki/ResourceLoader',
 151+ 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l', '#t-specialpages' );
 152+
 153+ ok( $.isDomElement( A ), 'addPortletLink returns a valid DOM Element according to $.isDomElement' );
 154+
 155+ var B = mw.util.addPortletLink( "p-tb", "http://mediawiki.org/",
 156+ "MediaWiki.org", "t-mworg", "Go to MediaWiki.org ", "m", A );
 157+
 158+ equal( $( B ).attr( 'id' ), 't-mworg', 'Link has correct ID set' );
 159+ equal( $( B ).closest( '.portal' ).attr( 'id' ), 'p-tb', 'Link was inserted within correct portlet' );
 160+ equal( $( B ).next().attr( 'id' ), 't-rl', 'Link is in the correct position (by passing nextnode)' );
 161+
 162+ var C = mw.util.addPortletLink( "p-tb", "http://mediawiki.org/wiki/RL/DM",
 163+ "Default modules", "t-rldm", "List of all default modules ", "d", "#t-rl" );
 164+
 165+ equal( $( C ).next().attr( 'id' ), 't-rl', 'Link is in the correct position (by passing CSS selector)' );
 166+
 167+ // Clean up
 168+ $( [A, B, C] ).remove();
 169+
 170+});
 171+
 172+test( 'jsMessage', function(){
 173+
 174+ var a = mw.util.jsMessage( "MediaWiki is <b>Awesome</b>." );
 175+
 176+ ok( a, 'Basic checking of return value' );
 177+
 178+ // Clean up
 179+ $( '#mw-js-message' ).remove();
 180+
 181+});
 182+
 183+test( 'validateEmail', function(){
 184+
 185+ deepEqual( mw.util.validateEmail( "" ), null, 'Empty string should return null' );
 186+ deepEqual( mw.util.validateEmail( "user@localhost" ), true );
 187+
 188+ // testEmailWithCommasAreInvalids
 189+ deepEqual( mw.util.validateEmail( "user,foo@example.org" ), false, 'Comma' );
 190+ deepEqual( mw.util.validateEmail( "userfoo@ex,ample.org" ), false, 'Comma' );
 191+
 192+ // testEmailWithHyphens
 193+ deepEqual( mw.util.validateEmail( "user-foo@example.org" ), true, 'Hyphen' );
 194+ deepEqual( mw.util.validateEmail( "userfoo@ex-ample.org" ), true, 'Hyphen' );
 195+
 196+});
 197+
 198+test( 'isIPv6Address', function(){
 199+
 200+ // Based on IPTest.php > IPv6
 201+ deepEqual( mw.util.isIPv6Address( "" ), false, 'Empty string is not an IP' );
 202+ deepEqual( mw.util.isIPv6Address( ":fc:100::" ), false, 'IPv6 starting with lone ":"' );
 203+ deepEqual( mw.util.isIPv6Address( "fc:100::" ), true );
 204+ deepEqual( mw.util.isIPv6Address( "fc:100:a:d:1:e:ac::" ), true );
 205+ deepEqual( mw.util.isIPv6Address( ":::" ), false );
 206+ deepEqual( mw.util.isIPv6Address( "::0:" ), false );
 207+
 208+});
 209+
 210+test( 'isIPv4Address', function(){
 211+
 212+ // Based on IPTest.php > IPv4
 213+ deepEqual( mw.util.isIPv4Address( "" ), false, 'Empty string is not an IP' );
 214+ deepEqual( mw.util.isIPv4Address( "...." ), false );
 215+ deepEqual( mw.util.isIPv4Address( "1.24.52.13" ), true );
 216+
 217+});
Property changes on: trunk/phase3/tests/qunit/suites/resources/mediawiki.util/mediawiki.util.js
___________________________________________________________________
Added: svn:eol-style
1218 + native
Index: trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.user.js
@@ -0,0 +1,30 @@
 2+module( 'mediawiki.user.js' );
 3+
 4+test( '-- Initial check', function(){
 5+
 6+ ok( mw.user, 'mw.user defined' );
 7+
 8+});
 9+
 10+
 11+test( 'options', function(){
 12+
 13+ ok( mw.user.options instanceof mw.Map, 'options instance of mw.Map' );
 14+
 15+});
 16+
 17+test( 'User login status', function(){
 18+
 19+ deepEqual( mw.user.name(), null, 'user.name() When anonymous' );
 20+ ok( mw.user.anonymous(), 'user.anonymous() When anonymous' );
 21+
 22+ // Not part of startUp module
 23+ mw.config.set( 'wgUserName', 'John' );
 24+
 25+ equal( mw.user.name(), 'John', 'user.name() When logged-in as John' );
 26+ ok( !mw.user.anonymous(), 'user.anonymous() When logged-in' );
 27+
 28+ equal( mw.user.id(), 'John', 'user.id() When logged-in as John' );
 29+
 30+
 31+});
\ No newline at end of file
Property changes on: trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.user.js
___________________________________________________________________
Added: svn:eol-style
132 + native
Index: trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.js
@@ -0,0 +1,107 @@
 2+module( 'mediawiki.js' );
 3+
 4+test( '-- Initial check', function(){
 5+
 6+ ok( window.jQuery, 'jQuery defined' );
 7+ ok( window.$j, '$j defined' );
 8+ equal( window.$j, window.jQuery, '$j alias to jQuery' );
 9+
 10+ ok( window.mediaWiki, 'mediaWiki defined' );
 11+ ok( window.mw, 'mw defined' );
 12+ equal( window.mw, window.mediaWiki, 'mw alias to mediaWiki' );
 13+
 14+});
 15+
 16+test( 'mw.Map / mw.config', function(){
 17+
 18+ ok( mw.config instanceof mw.Map, 'mw.config instance of mw.Map' );
 19+ ok( mw.config.get, 'get' );
 20+ ok( mw.config.set, 'set' );
 21+ ok( mw.config.exists, 'exists' );
 22+
 23+ ok( !mw.config.exists( 'lipsum' ), 'exists: lipsum (inexistant)' );
 24+ ok( mw.config.set( 'lipsum', 'Lorem ipsum' ), 'set: lipsum' );
 25+ ok( mw.config.exists( 'lipsum' ), 'exists: lipsum (existant)' );
 26+
 27+ equal( mw.config.get( 'lipsum' ), 'Lorem ipsum', 'get: lipsum' );
 28+ equal( mw.config.get( ['lipsum'] ).lipsum, 'Lorem ipsum', 'get: lipsum (multiple)' );
 29+
 30+});
 31+
 32+test( 'mw.message / mw.msg / mw.messages', function(){
 33+ ok( mw.message, 'mw.message defined' );
 34+ ok( mw.msg, 'mw.msg defined' );
 35+ ok( mw.messages, 'messages defined' );
 36+ ok( mw.messages instanceof mw.Map, 'mw.messages instance of mw.Map' );
 37+ ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
 38+
 39+ var hello = mw.message( 'hello' );
 40+ ok( hello, 'hello: Instance of Message' );
 41+
 42+ equal( hello.format, 'parse', 'Message property "format" (default value)' );
 43+ equal( hello.key, 'hello', 'Message property "key" (currect key)' );
 44+ deepEqual( hello.parameters, [], 'Message property "parameters" (default value)' );
 45+
 46+
 47+ ok( hello.params, 'Message prototype "params"');
 48+ ok( hello.toString, 'Message prototype "toString"');
 49+ ok( hello.parse, 'Message prototype "parse"');
 50+ ok( hello.plain, 'Message prototype "plain"');
 51+ ok( hello.escaped, 'Message prototype "escaped"');
 52+ ok( hello.exists, 'Message prototype "exists"');
 53+
 54+ equal( hello.toString(), 'Hello <b>awesome</b> world', 'Message.toString() test');
 55+ equal( hello.escaped(), 'Hello &lt;b&gt;awesome&lt;/b&gt; world', 'Message.escaped() test');
 56+ deepEqual( hello.exists(), true, 'Message.exists() test');
 57+
 58+ equal( mw.msg( 'random' ), '<random>', 'square brackets around inexistant messages' );
 59+ equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'get message with default options' );
 60+
 61+// params, toString, parse, plain, escaped, exists
 62+});
 63+
 64+test( 'mw.loader', function(){
 65+ expect(2);
 66+
 67+ ok( location.href.match(/[^#\?]*/) && location.href.match(/[^#\?]*/)[0], true, 'Extracting file path from location' );
 68+
 69+ stop();
 70+
 71+ mw.loader.implement( 'is.awesome', [location.href.match(/[^#\?]*/)[0] + 'sample/awesome.js'], {}, {} );
 72+ mw.loader.using( 'is.awesome', function(){
 73+ start();
 74+ deepEqual( window.awesome, true, 'Implementing a module, is the callback timed properly ?');
 75+
 76+ // Clean up
 77+ delete window.awesome;
 78+
 79+ }, function(){
 80+ start();
 81+ deepEqual( 'mw.loader.using error callback fired', true, 'Implementing a module, is the callback timed properly ?');
 82+ });
 83+
 84+});
 85+
 86+test( 'mw.html', function(){
 87+
 88+ equal( mw.html.escape( '<mw awesome="awesome" value=\'test\' />' ),
 89+ '&lt;mw awesome=&quot;awesome&quot; value=&#039;test&#039; /&gt;', 'html.escape()' );
 90+
 91+ equal( mw.html.element( 'div' ), '<div/>', 'mw.html.element() DIV (simple)' );
 92+
 93+ equal( mw.html.element( 'div',
 94+ { id: 'foobar' } ),
 95+ '<div id="foobar"/>',
 96+ 'mw.html.element() DIV (attribs)' );
 97+
 98+ equal( mw.html.element( 'div',
 99+ null, 'a' ),
 100+ '<div>a</div>',
 101+ 'mw.html.element() DIV (content)' );
 102+
 103+ equal( mw.html.element( 'a',
 104+ { href: 'http://mediawiki.org/w/index.php?title=RL&action=history' }, 'a' ),
 105+ '<a href="http://mediawiki.org/w/index.php?title=RL&amp;action=history">a</a>',
 106+ 'mw.html.element() DIV (attribs + content)' );
 107+
 108+});
Property changes on: trunk/phase3/tests/qunit/suites/resources/mediawiki/mediawiki.js
___________________________________________________________________
Added: svn:eol-style
1109 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r88509Fix the mw.loader when running test with a file:// URL...hashar09:16, 21 May 2011

Status & tagging log