* 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)
+++ /dev/null
-<!DOCTYPE html>
-<html>
-<head>
- <title>MediaWiki JavaScript Test Suite</title>
-
- <!-- MediaWiki Modules -->
- <script>
- function startUp(){
- mw.config = new mw.Map( false );
- }
- </script>
- <script src="../jquery/jquery.js"></script>
- <script src="../mediawiki/mediawiki.js"></script>
- <script src="../mediawiki/mediawiki.user.js"></script>
-
- <script src="../jquery/jquery.autoEllipsis.js"></script>
-
- <script>
- mw.user.options.set({"skin": "vector"});
- </script>
-
- <script src="../jquery/jquery.checkboxShiftClick.js"></script>
- <script src="../jquery/jquery.client.js"></script>
- <script src="../jquery/jquery.cookie.js"></script>
- <script src="../jquery/jquery.messageBox.js"></script>
- <script src="../jquery/jquery.makeCollapsible.js"></script>
- <script src="../jquery/jquery.mwPrototypes.js"></script>
- <script src="../jquery/jquery.placeholder.js"></script>
- <script src="../mediawiki.util/mediawiki.util.js"></script>
-
- <script src="../jquery/jquery.colorUtil.js"></script>
-
- <meta name="ResourceLoaderDynamicStyles" content="" />
-
- <!-- QUnit -->
- <link rel="stylesheet" href="../jquery/jquery.qunit.css" />
- <script src="../jquery/jquery.qunit.js"></script>
-
- <!-- Custom CSS used for tests -->
- <link rel="stylesheet" href="unit/main.css" />
-
- <!-- Load test suitss -->
- <script src="unit/mediawiki/mediawiki.js"></script>
- <script src="unit/mediawiki/mediawiki.user.js"></script>
- <script src="unit/jquery/jquery.mwPrototypes.js"></script>
- <script src="unit/mediawiki.util/mediawiki.util.js"></script>
- <script src="unit/jquery/jquery.colorUtil.js"></script>
- <script src="unit/jquery/jquery.autoEllipsis.js"></script>
-
- <!-- TestSwarm -->
- <script src="testswarm.inject.js"></script>
-</head>
-<body>
- <h1 id="qunit-header">MediaWiki JavaScript Test Suite</h1>
- <h2 id="qunit-banner"></h2>
- <div id="qunit-testrunner-toolbar"></div>
- <h2 id="qunit-userAgent"></h2>
- <ol id="qunit-tests"></ol>
-
-<div id="mw-content">
- <div id="bodyContent"></div>
- <div id="mw-panel">
- <div id="p-tb" class="portal">
- <ul class="body">
- <li id="t-specialpages"><a href="#">Special pages</a></li>
- </ul>
- </div>
- </div>
-</div>
-</body>
-</html>
+++ /dev/null
-window.awesome = true;
+++ /dev/null
-/*
- Copyright (c) 2009 John Resig
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use,
- copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following
- conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
-*/
-(function(){
-
- var DEBUG = false;
-
- var doPost = false;
-
- try {
- doPost = !!window.top.postMessage;
- } catch(e){}
-
- var search = window.location.search,
- url, index;
- if( ( index = search.indexOf( "swarmURL=" ) ) != -1 )
- url = decodeURIComponent( search.slice( index + 9 ) );
-
- if ( !DEBUG && (!url || url.indexOf("http") !== 0) ) {
- return;
- }
-
- var submitTimeout = 5;
-
- var curHeartbeat;
- var beatRate = 20;
-
- // Expose the TestSwarm API
- window.TestSwarm = {
- submit: submit,
- heartbeat: function(){
- if ( curHeartbeat ) {
- clearTimeout( curHeartbeat );
- }
-
- curHeartbeat = setTimeout(function(){
- submit({ fail: -1, total: -1 });
- }, beatRate * 1000);
- },
- serialize: function(){
- return trimSerialize();
- }
- };
-
- // Prevent careless things from executing
- window.print = window.confirm = window.alert = window.open = function(){};
-
- window.onerror = function(e){
- document.body.appendChild( document.createTextNode( "ERROR: " + e ));
- submit({ fail: 0, error: 1, total: 1 });
- return false;
- };
-
- // QUnit (jQuery)
- // http://docs.jquery.com/QUnit
- if ( typeof QUnit !== "undefined" ) {
- QUnit.done = function(results){
- submit({
- fail: results.failed,
- error: 0,
- total: results.total
- });
- };
-
- QUnit.log = window.TestSwarm.heartbeat;
- window.TestSwarm.heartbeat();
-
- window.TestSwarm.serialize = function(){
- // Clean up the HTML (remove any un-needed test markup)
- remove("nothiddendiv");
- remove("loadediframe");
- remove("dl");
- remove("main");
-
- // Show any collapsed results
- var ol = document.getElementsByTagName("ol");
- for ( var i = 0; i < ol.length; i++ ) {
- ol[i].style.display = "block";
- }
-
- return trimSerialize();
- };
-
- // UnitTestJS (Prototype, Scriptaculous)
- // http://github.com/tobie/unittest_js/tree/master
- } else if ( typeof Test !== "undefined" && Test && Test.Unit && Test.Unit.runners ) {
- var total_runners = Test.Unit.runners.length, cur_runners = 0;
- var total = 0, fail = 0, error = 0;
-
- for (var i = 0; i < Test.Unit.runners.length; i++) (function(i){
- var finish = Test.Unit.runners[i].finish;
- Test.Unit.runners[i].finish = function(){
- finish.call( this );
-
- var results = this.getResult();
- total += results.assertions;
- fail += results.failures;
- error += results.errors;
-
- if ( ++cur_runners === total_runners ) {
- submit({
- fail: fail,
- error: error,
- total: total
- });
- }
- };
- })(i);
-
- // JSSpec (MooTools)
- // http://jania.pe.kr/aw/moin.cgi/JSSpec
- } else if ( typeof JSSpec !== "undefined" && JSSpec && JSSpec.Logger ) {
- var onRunnerEnd = JSSpec.Logger.prototype.onRunnerEnd;
- JSSpec.Logger.prototype.onRunnerEnd = function(){
- onRunnerEnd.call(this);
-
- // Show any collapsed results
- var ul = document.getElementsByTagName("ul");
- for ( var i = 0; i < ul.length; i++ ) {
- ul[i].style.display = "block";
- }
-
- submit({
- fail: JSSpec.runner.getTotalFailures(),
- error: JSSpec.runner.getTotalErrors(),
- total: JSSpec.runner.totalExamples
- });
- };
-
- window.TestSwarm.serialize = function(){
- // Show any collapsed results
- var ul = document.getElementsByTagName("ul");
- for ( var i = 0; i < ul.length; i++ ) {
- ul[i].style.display = "block";
- }
-
- return trimSerialize();
- };
-
- // JSUnit
- // http://www.jsunit.net/
- // Note: Injection file must be included before the frames
- // are document.write()d into the page.
- } else if ( typeof JsUnitTestManager !== "undefined" ) {
- var _done = JsUnitTestManager.prototype._done;
- JsUnitTestManager.prototype._done = function(){
- _done.call(this);
-
- submit({
- fail: this.failureCount,
- error: this.errorCount,
- total: this.totalCount
- });
- };
-
- window.TestSwarm.serialize = function(){
- return "<pre>" + this.log.join("\n") + "</pre>";
- };
-
- // Selenium Core
- // http://seleniumhq.org/projects/core/
- } else if ( typeof SeleniumTestResult !== "undefined" && typeof LOG !== "undefined" ) {
- // Completely overwrite the postback
- SeleniumTestResult.prototype.post = function(){
- submit({
- fail: this.metrics.numCommandFailures,
- error: this.metrics.numCommandErrors,
- total: this.metrics.numCommandPasses + this.metrics.numCommandFailures + this.metrics.numCommandErrors
- });
- };
-
- window.TestSwarm.serialize = function(){
- var results = [];
- while ( LOG.pendingMessages.length ) {
- var msg = LOG.pendingMessages.shift();
- results.push( msg.type + ": " + msg.msg );
- }
-
- return "<pre>" + results.join("\n") + "</pre>";
- };
-
- // Dojo Objective Harness
- // http://docs.dojocampus.org/quickstart/doh
- } else if ( typeof doh !== "undefined" && doh._report ) {
- var _report = doh._report;
- doh._report = function(){
- _report.apply(this, arguments);
-
- submit({
- fail: doh._failureCount,
- error: doh._errorCount,
- total: doh._testCount
- });
- };
-
- window.TestSwarm.serialize = function(){
- return "<pre>" + document.getElementById("logBody").innerHTML + "</pre>";
- };
- // Screw.Unit
- // git://github.com/nathansobo/screw-unit.git
- } else if ( typeof Screw !== "undefined" && typeof jQuery !== 'undefined' && Screw && Screw.Unit ) {
- $(Screw).bind("after", function() {
- var passed = $('.passed').length;
- var failed = $('.failed').length;
- submit({
- fail: failed,
- error: 0,
- total: failed + passed
- });
- });
-
- $(Screw).bind("loaded", function() {
- $('.it')
- .bind("passed", window.TestSwarm.heartbeat)
- .bind("failed", window.TestSwarm.heartbeat);
- window.TestSwarm.heartbeat();
- });
-
- window.TestSwarm.serialize = function(){
- return trimSerialize();
- };
- }
-
- function trimSerialize(doc) {
- doc = doc || document;
-
- var scripts = doc.getElementsByTagName("script");
- while ( scripts.length ) {
- remove( scripts[0] );
- }
-
- var root = window.location.href.replace(/(https?:\/\/.*?)\/.*/, "$1");
- var cur = window.location.href.replace(/[^\/]*$/, "");
-
- var links = doc.getElementsByTagName("link");
- for ( var i = 0; i < links.length; i++ ) {
- var href = links[i].href;
- if ( href.indexOf("/") === 0 ) {
- href = root + href;
- } else if ( !/^https?:\/\//.test( href ) ) {
- href = cur + href;
- }
- links[i].href = href;
- }
-
- return ("<html>" + doc.documentElement.innerHTML + "</html>")
- .replace(/\s+/g, " ");
- }
-
- function remove(elem){
- if ( typeof elem === "string" ) {
- elem = document.getElementById( elem );
- }
-
- if ( elem ) {
- elem.parentNode.removeChild( elem );
- }
- }
-
- function submit(params){
- if ( curHeartbeat ) {
- clearTimeout( curHeartbeat );
- }
-
- var paramItems = (url.split("?")[1] || "").split("&");
-
- for ( var i = 0; i < paramItems.length; i++ ) {
- if ( paramItems[i] ) {
- var parts = paramItems[i].split("=");
- if ( !params[ parts[0] ] ) {
- params[ parts[0] ] = parts[1];
- }
- }
- }
-
- if ( !params.state ) {
- params.state = "saverun";
- }
-
- if ( !params.results ) {
- params.results = window.TestSwarm.serialize();
- }
-
- if ( doPost ) {
- // Build Query String
- var query = "";
-
- for ( var i in params ) {
- query += ( query ? "&" : "" ) + i + "=" +
- encodeURIComponent(params[i]);
- }
-
- if ( DEBUG ) {
- alert( query );
- } else {
- window.top.postMessage( query, "*" );
- }
-
- } else {
- var form = document.createElement("form");
- form.action = url;
- form.method = "POST";
-
- for ( var i in params ) {
- var input = document.createElement("input");
- input.type = "hidden";
- input.name = i;
- input.value = params[i];
- form.appendChild( input );
- }
-
- if ( DEBUG ) {
- alert( form.innerHTML );
- } else {
-
- // Watch for the result submission timing out
- setTimeout(function(){
- submit( params );
- }, submitTimeout * 1000);
-
- document.body.appendChild( form );
- form.submit();
- }
- }
- }
-
-})();
+++ /dev/null
-module( 'jquery.autoEllipsis.js' );
-
-test( '-- Initial check', function(){
-
- ok( jQuery.fn.autoEllipsis, 'jQuery.fn.autoEllipsis defined' );
-});
-
-function createWrappedDiv( text ) {
- var $wrapper = $( '<div />' ).css( 'width', '100px' );
- var $div = $( '<div />' ).text( text );
- $wrapper.append( $div );
- return $wrapper;
-}
-
-function findDivergenceIndex( a, b ) {
- var i = 0;
- while ( i < a.length && i < b.length && a[i] == b[i] ) {
- i++;
- }
- return i;
-}
-
-test( 'Position right', function() {
- // We need this thing to be visible, so append it to the DOM
- var origText = 'This is a really long random string and there is no way it fits in 100 pixels.';
- var $wrapper = createWrappedDiv( origText );
- $( 'body' ).append( $wrapper );
- $wrapper.autoEllipsis( { position: 'right' } );
-
- // Verify that, and only one, span element was created
- var $span = $wrapper.find( '> span' );
- deepEqual( $span.length, 1, 'autoEllipsis wrapped the contents in a span element' );
-
- // Check that the text fits by turning on word wrapping
- $span.css( 'whiteSpace', 'nowrap' );
- ok( $span.width() <= $span.parent().width(), "Text fits (span's width is no larger than its parent's width)" );
-
- // Add one character using scary black magic
- var spanText = $span.text();
- var d = findDivergenceIndex( origText, spanText );
- spanText = spanText.substr( 0, d ) + origText[d] + '...';
-
- // Put this text in the span and verify it doesn't fit
- $span.text( spanText );
- ok( $span.width() > $span.parent().width(), 'Fit is maximal (adding one character makes it not fit any more)' );
-
- // Clean up
- $wrapper.remove();
-});
+++ /dev/null
-module( 'jquery.colorUtil.js' );
-
-test( '-- Initial check', function(){
-
- ok( jQuery.colorUtil, 'jQuery.colorUtil defined' );
-});
-
-test( 'getRGB', function(){
-
- equal( typeof jQuery.colorUtil.getRGB(), 'undefined', 'No arguments' );
- equal( typeof jQuery.colorUtil.getRGB( '' ), 'undefined', 'Empty string' );
- deepEqual( jQuery.colorUtil.getRGB( [0, 100, 255] ), [0, 100, 255], 'Array' );
- deepEqual( jQuery.colorUtil.getRGB( 'rgb(0,100,255)' ), [0, 100, 255], 'Parse simple string' );
- deepEqual( jQuery.colorUtil.getRGB( 'rgb(0, 100, 255)' ), [0, 100, 255], 'Parse simple string (whitespace)' );
- deepEqual( jQuery.colorUtil.getRGB( 'rgb(0%,20%,40%)' ), [0, 51, 102], 'Parse percentages string' );
- deepEqual( jQuery.colorUtil.getRGB( 'rgb(0%, 20%, 40%)' ), [0, 51, 102], 'Parse percentages string (whitespace)' );
- deepEqual( jQuery.colorUtil.getRGB( '#f2ddee' ), [242, 221, 238], 'Hex string: 6 char lowercase' );
- deepEqual( jQuery.colorUtil.getRGB( '#f2DDEE' ), [242, 221, 238], 'Hex string: 6 char uppercase' );
- deepEqual( jQuery.colorUtil.getRGB( '#f2DdEe' ), [242, 221, 238], 'Hex string: 6 char mixed' );
- deepEqual( jQuery.colorUtil.getRGB( '#eee' ), [238, 238, 238], 'Hex string: 3 char lowercase' );
- deepEqual( jQuery.colorUtil.getRGB( '#EEE' ), [238, 238, 238], 'Hex string: 3 char uppercase' );
- deepEqual( jQuery.colorUtil.getRGB( '#eEe' ), [238, 238, 238], 'Hex string: 3 char mixed' );
- deepEqual( jQuery.colorUtil.getRGB( 'rgba(0, 0, 0, 0)' ), [255, 255, 255], 'Zero rgba for Safari 3; Transparent (whitespace)' );
- // Perhaps this is a bug in colorUtil, but it is the current behaviour so, let's keep track
- // would that ever change
- equal( typeof jQuery.colorUtil.getRGB( 'rgba(0,0,0,0)' ), 'undefined', 'Zero rgba without whitespace' );
-
- deepEqual( jQuery.colorUtil.getRGB( 'lightGreen' ), [144, 238, 144], 'Color names (lightGreen)' );
- deepEqual( jQuery.colorUtil.getRGB( 'lightGreen' ), [144, 238, 144], 'Color names (transparent)' );
- equal( typeof jQuery.colorUtil.getRGB( 'mediaWiki' ), 'undefined', 'Inexisting color name' );
-
-});
-
-test( 'rgbToHsl', function(){
- var hsl = jQuery.colorUtil.rgbToHsl( 144, 238, 144 );
- var dualDecimals = function(a,b){
- return Math.round(a*100)/100;
- };
-
- ok( hsl, 'Basic return evaluation' );
- deepEqual( dualDecimals(hsl[0]) , 0.33, 'rgb(144, 238, 144): H 0.33' );
- deepEqual( dualDecimals(hsl[1]) , 0.73, 'rgb(144, 238, 144): S 0.73' );
- deepEqual( dualDecimals(hsl[2]) , 0.75, 'rgb(144, 238, 144): L 0.75' );
-
-});
-
-test( 'hslToRgb', function(){
- var rgb = jQuery.colorUtil.hslToRgb( 0.3, 0.7, 0.8 );
-
- ok( rgb, 'Basic return evaluation' );
- deepEqual( Math.round(rgb[0]) , 183, 'hsl(0.3, 0.7, 0.8): R 183' );
- deepEqual( Math.round(rgb[1]) , 240, 'hsl(0.3, 0.7, 0.8): G 240' );
- deepEqual( Math.round(rgb[2]) , 168, 'hsl(0.3, 0.7, 0.8): B 168' );
-
-});
-
-test( 'getColorBrightness', function(){
-
- var a = jQuery.colorUtil.getColorBrightness( 'red', +0.1 );
-
- equal( a, 'rgb(255,50,50)', 'Start with named color, brighten 10%' );
-
- var b = jQuery.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
-
- equal( b, 'rgb(118,29,29)', 'Start with rgb string, darken 10%' );
-
-});
+++ /dev/null
-module( 'jquery.mwPrototypes.js' );
-
-test( 'String functions', function(){
-
- equal( $j.trimLeft( ' foo bar ' ), 'foo bar ', 'trimLeft' );
- equal( $j.trimRight( ' foo bar ' ), ' foo bar', 'trimRight' );
- equal( $j.ucFirst( 'foo'), 'Foo', 'ucFirst' );
-
- equal( $j.escapeRE( '<!-- ([{+mW+}]) $^|?>' ),
- '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?>', 'escapeRE - Escape specials' );
- equal( $j.escapeRE( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ),
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'escapeRE - Leave uppercase alone' );
- equal( $j.escapeRE( 'abcdefghijklmnopqrstuvwxyz' ),
- 'abcdefghijklmnopqrstuvwxyz', 'escapeRE - Leave lowercase alone' );
- equal( $j.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
-
-});
-
-test( 'Is functions', function(){
-
- deepEqual( $j.isDomElement( document.getElementById( 'qunit-header' ) ), true,
- 'isDomElement: #qunit-header Node' );
- deepEqual( $j.isDomElement( document.getElementById( 'random-name' ) ), false,
- 'isDomElement: #random-name (null)' );
- deepEqual( $j.isDomElement( document.getElementsByTagName( 'div' ) ), false,
- 'isDomElement: getElementsByTagName Array' );
- deepEqual( $j.isDomElement( document.getElementsByTagName( 'div' )[0] ), true,
- 'isDomElement: getElementsByTagName(..)[0] Node' );
- deepEqual( $j.isDomElement( $j( 'div' ) ), false,
- 'isDomElement: jQuery object' );
- deepEqual( $j.isDomElement( $j( 'div' ).get(0) ), true,
- 'isDomElement: jQuery object > Get node' );
- deepEqual( $j.isDomElement( document.createElement( 'div' ) ), true,
- 'isDomElement: createElement' );
- deepEqual( $j.isDomElement( { foo: 1 } ), false,
- 'isDomElement: Object' );
-
- equal( $j.isEmpty( 'string' ), false, 'isEmptry: "string"' );
- equal( $j.isEmpty( '0' ), true, 'isEmptry: "0"' );
- equal( $j.isEmpty( [] ), true, 'isEmptry: []' );
- equal( $j.isEmpty( {} ), true, 'isEmptry: {}' );
- // Documented behaviour
- equal( $j.isEmpty( { length: 0 } ), true, 'isEmptry: { length: 0 }' );
-
-});
-
-test( 'Comparison functions', function(){
-
- ok( $j.compareArray( [0, 'a', [], [2, 'b'] ], [0, "a", [], [2, "b"] ] ),
- 'compareArray: Two deep arrays that are excactly the same' );
- ok( !$j.compareArray( [1], [2] ), 'compareArray: Two different arrays (false)' );
-
- ok( $j.compareObject( {}, {} ), 'compareObject: Two empty objects' );
- ok( $j.compareObject( { foo: 1 }, { foo: 1 } ), 'compareObject: Two the same objects' );
- ok( !$j.compareObject( { bar: true }, { baz: false } ),
- 'compareObject: Two different objects (false)' );
-
-});
\ No newline at end of file
+++ /dev/null
-/* Hide mediawiki elements */
-div#mw-js-message,
-#mw-content {
- display: none !important;
-}
\ No newline at end of file
+++ /dev/null
-module( 'mediawiki.util.js' );
-
-test( '-- Initial check', function(){
-
- ok( mw.util, 'mw.util defined' );
-
-});
-
-test( 'rawurlencode', function(){
-
- equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
-
-});
-
-test( 'wikiUrlencode', function(){
-
- equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
-
-});
-
-test( 'addCSS', function(){
-
- var a = mw.util.addCSS( '#bodyContent { visibility: hidden; }' );
- ok( a, 'function works' );
- deepEqual( a.disabled, false, 'property "disabled" is available and set to false' );
-
- var $b = $('#bodyContent');
- equal( $b.css('visibility'), 'hidden', 'Added style properties are in effect.' );
-
-
-});
-
-test( 'toggleToc', function(){
-
- ok( mw.util.toggleToc );
-
-});
-
-test( 'wikiGetlink', function(){
-
- // Not part of startUp module
- mw.config.set( 'wgArticlePath', '/wiki/$1' );
-
- var hrefA = mw.util.wikiGetlink( 'Sandbox' );
-
- equal( hrefA, '/wiki/Sandbox', 'Simple title; Get link for "Sandbox"' );
-
- var hrefB = mw.util.wikiGetlink( 'Foo:Sandbox ? 5+5=10 ! (test)/subpage' );
-
- 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"' );
-
-});
-
-test( 'getParamValue', function(){
-
- var url = 'http://mediawiki.org/?foo=wrong&foo=right#&foo=bad';
-
- equal( mw.util.getParamValue( 'foo', url ), 'right', 'Use latest one, ignore hash' );
- deepEqual( mw.util.getParamValue( 'bar', url ), null, 'Return null when not found' );
-
-});
-
-test( 'getActionFrom', function(){
-
- // Example urls
- var urlA = 'http://mediawiki.org/wiki/Article',
- urlB = 'http://mediawiki.org/w/index.php?title=Article&action=edit',
- urlC = 'http://mediawiki.org/edit/Article',
- urlD = 'http://mediawiki.org/w/index.php/Article';
-
- // Common settings
- mw.config.set( {
- 'wgActionPaths': [],
- 'wgArticlePath': '/wiki/$1'
- });
-
- equal( mw.util.getActionFrom( urlA ), 'view', 'wgArticlePath (/wiki/$1) support' );
- equal( mw.util.getActionFrom( urlB ), 'edit', 'action-parameter support' );
-
- // Custom settings
- mw.config.set( 'wgActionPaths', {
- 'view': '/view/$1',
- 'edit': '/edit/$1'
- });
-
- equal( mw.util.getActionFrom( urlC ), 'edit', 'wgActionPaths support' );
-
- // Default settings
- mw.config.set( {
- 'wgActionPaths': [],
- 'wgArticlePath': '/w/index.php/$1'
- });
- equal( mw.util.getActionFrom( urlD ), 'view', 'wgArticlePath (/index.php/$1) support' );
-
-});
-
-test( 'getTitleFrom', function(){
-
- // Example urls
- var urlA = 'http://mediawiki.org/wiki/Article',
- urlB = 'http://mediawiki.org/w/index.php?title=Article&action=edit',
- urlC = 'http://mediawiki.org/edit/Article',
- urlD = 'http://mediawiki.org/w/index.php/Article';
-
- // Common settings
- mw.config.set( {
- 'wgActionPaths': [],
- 'wgArticlePath': '/wiki/$1'
- });
-
- equal( mw.util.getTitleFrom( urlA ), 'Article', 'wgArticlePath (/wiki/$1) support' );
- equal( mw.util.getTitleFrom( urlB ), 'Article', 'action-parameter support' );
-
- // Custom settings
- mw.config.set( 'wgActionPaths', {
- 'view': '/view/$1',
- 'edit': '/edit/$1'
- });
-
- equal( mw.util.getTitleFrom( urlC ), 'Article', 'wgActionPaths support' );
-
- // Default settings
- mw.config.set( {
- 'wgActionPaths': [],
- 'wgArticlePath': '/w/index.php/$1'
- });
-
- equal( mw.util.getTitleFrom( urlD ), 'Article', 'wgArticlePath (/index.php/$1) support' );
-
-});
-
-test( 'tooltipAccessKey', function(){
-
- equal( typeof mw.util.tooltipAccessKeyPrefix, 'string', 'mw.util.tooltipAccessKeyPrefix must be a string' );
- ok( mw.util.tooltipAccessKeyRegexp instanceof RegExp, 'mw.util.tooltipAccessKeyRegexp instance of RegExp' );
- ok( mw.util.updateTooltipAccessKeys, 'mw.util.updateTooltipAccessKeys' );
-
-});
-
-test( '$content', function(){
-
- ok( mw.util.$content instanceof jQuery, 'mw.util.$content instance of jQuery' );
- deepEqual( mw.util.$content.length, 1, 'mw.util.$content must have length of 1' );
-
-});
-
-test( 'addPortletLink', function(){
-
- var a = mw.util.addPortletLink( 'p-tb', 'http://mediawiki.org/wiki/ResourceLoader', 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l', '#t-specialpages' );
-
- ok( $.isDomElement(a), 'addPortletLink returns a DomElement' );
-
- var b = mw.util.addPortletLink( "p-tb", "http://mediawiki.org/", "MediaWiki.org", "t-mworg", "Go to MediaWiki.org ", "m", "#t-rl" );
-
- equal( $(a).text(), 'ResourceLoader', 'Link contains correct text' );
- equal( $(b).next().text(), 'ResourceLoader', 'Link was inserted in correct nextnode position' );
-
-});
-
-test( 'jsMessage', function(){
-
- var a = mw.util.jsMessage( "MediaWiki is <b>Awesome</b>." );
-
- ok( a, 'Basic return value checking' );
-
-});
-
-test( 'validateEmail', function(){
-
- deepEqual( mw.util.validateEmail( "" ), null, 'Empty string should return null' );
- deepEqual( mw.util.validateEmail( "user@localhost" ), true );
-
- // testEmailWithCommasAreInvalids
- deepEqual( mw.util.validateEmail( "user,foo@example.org" ), false, 'Comma' );
- deepEqual( mw.util.validateEmail( "userfoo@ex,ample.org" ), false, 'Comma' );
-
- // testEmailWithHyphens
- deepEqual( mw.util.validateEmail( "user-foo@example.org" ), true, 'Hyphen' );
- deepEqual( mw.util.validateEmail( "userfoo@ex-ample.org" ), true, 'Hyphen' );
-
-});
-
-test( 'isIPv6Address', function(){
-
- // Based on IPTest.php > IPv6
- deepEqual( mw.util.isIPv6Address( "" ), false, 'Empty string is not an IP' );
- deepEqual( mw.util.isIPv6Address( ":fc:100::" ), false, 'IPv6 starting with lone ":"' );
- deepEqual( mw.util.isIPv6Address( "fc:100::" ), true );
- deepEqual( mw.util.isIPv6Address( "fc:100:a:d:1:e:ac::" ), true );
- deepEqual( mw.util.isIPv6Address( ":::" ), false );
- deepEqual( mw.util.isIPv6Address( "::0:" ), false );
-
-});
-
-test( 'isIPv4Address', function(){
-
- // Based on IPTest.php > IPv4
- deepEqual( mw.util.isIPv4Address( "" ), false, 'Empty string is not an IP' );
- deepEqual( mw.util.isIPv4Address( "...." ), false );
- deepEqual( mw.util.isIPv4Address( "1.24.52.13" ), true );
-
-});
+++ /dev/null
-module( 'mediawiki.js' );
-
-test( '-- Initial check', function(){
-
- ok( window.jQuery, 'jQuery defined' );
- ok( window.$j, '$j defined' );
- equal( window.$j, window.jQuery, '$j alias to jQuery' );
-
- ok( window.mediaWiki, 'mediaWiki defined' );
- ok( window.mw, 'mw defined' );
- equal( window.mw, window.mediaWiki, 'mw alias to mediaWiki' );
-
-});
-
-test( 'mw.Map / mw.config', function(){
-
- ok( mw.config instanceof mw.Map, 'mw.config instance of mw.Map' );
- ok( mw.config.get, 'get' );
- ok( mw.config.set, 'set' );
- ok( mw.config.exists, 'exists' );
-
- ok( !mw.config.exists( 'lipsum' ), 'exists: lipsum (inexistant)' );
- ok( mw.config.set( 'lipsum', 'Lorem ipsum' ), 'set: lipsum' );
- ok( mw.config.exists( 'lipsum' ), 'exists: lipsum (existant)' );
-
- equal( mw.config.get( 'lipsum' ), 'Lorem ipsum', 'get: lipsum' );
- equal( mw.config.get( ['lipsum'] ).lipsum, 'Lorem ipsum', 'get: lipsum (multiple)' );
-
-});
-
-test( 'mw.message / mw.msg / mw.messages', function(){
- ok( mw.message, 'mw.message defined' );
- ok( mw.msg, 'mw.msg defined' );
- ok( mw.messages, 'messages defined' );
- ok( mw.messages instanceof mw.Map, 'mw.messages instance of mw.Map' );
- ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
-
- var hello = mw.message( 'hello' );
- ok( hello, 'hello: Instance of Message' );
-
- equal( hello.format, 'parse', 'Message property "format" (default value)' );
- equal( hello.key, 'hello', 'Message property "key" (currect key)' );
- deepEqual( hello.parameters, [], 'Message property "parameters" (default value)' );
-
-
- ok( hello.params, 'Message prototype "params"');
- ok( hello.toString, 'Message prototype "toString"');
- ok( hello.parse, 'Message prototype "parse"');
- ok( hello.plain, 'Message prototype "plain"');
- ok( hello.escaped, 'Message prototype "escaped"');
- ok( hello.exists, 'Message prototype "exists"');
-
- equal( hello.toString(), 'Hello <b>awesome</b> world', 'Message.toString() test');
- equal( hello.escaped(), 'Hello <b>awesome</b> world', 'Message.escaped() test');
- deepEqual( hello.exists(), true, 'Message.exists() test');
-
- equal( mw.msg( 'random' ), '<random>', 'square brackets around inexistant messages' );
- equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'get message with default options' );
-
-// params, toString, parse, plain, escaped, exists
-});
-
-test( 'mw.loader', function(){
- expect(2);
-
- ok( location.href.match(/[^#\?]*/) && location.href.match(/[^#\?]*/)[0], true, 'Extracting file path from location' );
-
- stop();
-
- mw.loader.implement( 'is.awesome', [location.href.match(/[^#\?]*/)[0] + 'sample/awesome.js'], {}, {} );
- mw.loader.using( 'is.awesome', function(){
- start();
- deepEqual( window.awesome, true, 'Implementing a module, is the callback timed properly ?');
-
- // Clean up
- delete window.awesome;
-
- }, function(){
- start();
- deepEqual( 'mw.loader.using error callback fired', true, 'Implementing a module, is the callback timed properly ?');
- });
-
-});
-
-test( 'mw.html', function(){
-
- equal( mw.html.escape( '<mw awesome="awesome" value=\'test\' />' ),
- '<mw awesome="awesome" value='test' />', 'html.escape()' );
-
- equal( mw.html.element( 'div' ), '<div/>', 'mw.html.element() DIV (simple)' );
-
- equal( mw.html.element( 'div',
- { id: 'foobar' } ),
- '<div id="foobar"/>',
- 'mw.html.element() DIV (attribs)' );
-
- equal( mw.html.element( 'div',
- null, 'a' ),
- '<div>a</div>',
- 'mw.html.element() DIV (content)' );
-
- equal( mw.html.element( 'a',
- { href: 'http://mediawiki.org/w/index.php?title=RL&action=history' }, 'a' ),
- '<a href="http://mediawiki.org/w/index.php?title=RL&action=history">a</a>',
- 'mw.html.element() DIV (attribs + content)' );
-
-});
+++ /dev/null
-module( 'mediawiki.user.js' );
-
-test( '-- Initial check', function(){
-
- ok( mw.user, 'mw.user defined' );
-
-});
-
-
-test( 'options', function(){
-
- ok( mw.user.options instanceof mw.Map, 'options instance of mw.Map' );
-
-});
-
-test( 'User login status', function(){
-
- deepEqual( mw.user.name(), null, 'user.name() When anonymous' );
- ok( mw.user.anonymous(), 'user.anonymous() When anonymous' );
-
- // Not part of startUp module
- mw.config.set( 'wgUserName', 'John' );
-
- equal( mw.user.name(), 'John', 'user.name() When logged-in as John' );
- ok( !mw.user.anonymous(), 'user.anonymous() When logged-in' );
-
- equal( mw.user.id(), 'John', 'user.id() When logged-in as John' );
-
-
-});
\ No newline at end of file
--- /dev/null
+Allow from all
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+ <title>MediaWiki JavaScript Test Suite</title>
+
+ <!-- MediaWiki Modules -->
+
+ <!-- MW: startup -->
+ <script>
+ function startUp(){
+ mw.config = new mw.Map( false );
+ }
+ </script>
+
+ <!-- MW: jquery|mediawiki -->
+ <script src="../../resources/jquery/jquery.js"></script>
+ <script src="../../resources/mediawiki/mediawiki.js"></script>
+
+ <!-- MW: mediawiki.user|mediawiki.util -->
+ <script src="../../resources/mediawiki/mediawiki.user.js"></script>
+ <script src="../../resources/jquery/jquery.checkboxShiftClick.js"></script>
+ <script src="../../resources/jquery/jquery.client.js"></script>
+ <script src="../../resources/jquery/jquery.cookie.js"></script>
+ <script src="../../resources/jquery/jquery.messageBox.js"></script>
+ <script src="../../resources/jquery/jquery.makeCollapsible.js"></script>
+ <script src="../../resources/jquery/jquery.mwPrototypes.js"></script>
+ <script src="../../resources/jquery/jquery.placeholder.js"></script>
+ <script src="../../resources/mediawiki.util/mediawiki.util.js"></script>
+
+ <!-- MW: user.options -->
+ <script>
+ mw.user.options.set({"skin": "vector"});
+ </script>
+
+ <!-- MW: Non-default modules -->
+ <script src="../../resources/jquery/jquery.colorUtil.js"></script>
+ <script src="../../resources/jquery/jquery.autoEllipsis.js"></script>
+
+ <!-- QUnit: Load framework -->
+ <link rel="stylesheet" href="../../resources/jquery/jquery.qunit.css" />
+ <script src="../../resources/jquery/jquery.qunit.js"></script>
+
+ <!-- QUnit: Load test suites (maintain the same order as above please) -->
+ <script src="suites/resources/mediawiki/mediawiki.js"></script>
+ <script src="suites/resources/mediawiki/mediawiki.user.js"></script>
+ <script src="suites/resources/jquery/jquery.mwPrototypes.js"></script>
+ <script src="suites/resources/mediawiki.util/mediawiki.util.js"></script>
+ <script src="suites/resources/jquery/jquery.colorUtil.js"></script>
+ <script src="suites/resources/jquery/jquery.autoEllipsis.js"></script>
+
+ <!-- TestSwarm: If a test swarm is running this,
+ the following script will allow it to extract the results.
+ Harmless otherwise. -->
+ <script src="testswarm.inject.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">MediaWiki JavaScript Test Suite</h1>
+ <h2 id="qunit-banner"></h2>
+ <div id="qunit-testrunner-toolbar"></div>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+
+<!-- Rough page structure for scripts needing it (Vector based). -->
+<!-- Scripts inserting stuff here shall remove it themselfs! -->
+<div id="mw-content">
+ <div id="bodyContent"></div>
+ <div id="mw-panel">
+ <div id="p-tb" class="portal">
+ <ul class="body">
+ </ul>
+ </div>
+ </div>
+</div>
+</body>
+</html>
--- /dev/null
+window.awesome = true;
--- /dev/null
+module( 'jquery.autoEllipsis.js' );
+
+test( '-- Initial check', function(){
+
+ ok( jQuery.fn.autoEllipsis, 'jQuery.fn.autoEllipsis defined' );
+});
+
+function createWrappedDiv( text ) {
+ var $wrapper = $( '<div />' ).css( 'width', '100px' );
+ var $div = $( '<div />' ).text( text );
+ $wrapper.append( $div );
+ return $wrapper;
+}
+
+function findDivergenceIndex( a, b ) {
+ var i = 0;
+ while ( i < a.length && i < b.length && a[i] == b[i] ) {
+ i++;
+ }
+ return i;
+}
+
+test( 'Position right', function() {
+ // We need this thing to be visible, so append it to the DOM
+ var origText = 'This is a really long random string and there is no way it fits in 100 pixels.';
+ var $wrapper = createWrappedDiv( origText );
+ $( 'body' ).append( $wrapper );
+ $wrapper.autoEllipsis( { position: 'right' } );
+
+ // Verify that, and only one, span element was created
+ var $span = $wrapper.find( '> span' );
+ deepEqual( $span.length, 1, 'autoEllipsis wrapped the contents in a span element' );
+
+ // Check that the text fits by turning on word wrapping
+ $span.css( 'whiteSpace', 'nowrap' );
+ ok( $span.width() <= $span.parent().width(), "Text fits (span's width is no larger than its parent's width)" );
+
+ // Add one character using scary black magic
+ var spanText = $span.text();
+ var d = findDivergenceIndex( origText, spanText );
+ spanText = spanText.substr( 0, d ) + origText[d] + '...';
+
+ // Put this text in the span and verify it doesn't fit
+ $span.text( spanText );
+ ok( $span.width() > $span.parent().width(), 'Fit is maximal (adding one character makes it not fit any more)' );
+
+ // Clean up
+ $wrapper.remove();
+});
--- /dev/null
+module( 'jquery.colorUtil.js' );
+
+test( '-- Initial check', function(){
+
+ ok( jQuery.colorUtil, 'jQuery.colorUtil defined' );
+});
+
+test( 'getRGB', function(){
+
+ equal( typeof jQuery.colorUtil.getRGB(), 'undefined', 'No arguments' );
+ equal( typeof jQuery.colorUtil.getRGB( '' ), 'undefined', 'Empty string' );
+ deepEqual( jQuery.colorUtil.getRGB( [0, 100, 255] ), [0, 100, 255], 'Array' );
+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0,100,255)' ), [0, 100, 255], 'Parse simple string' );
+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0, 100, 255)' ), [0, 100, 255], 'Parse simple string (whitespace)' );
+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0%,20%,40%)' ), [0, 51, 102], 'Parse percentages string' );
+ deepEqual( jQuery.colorUtil.getRGB( 'rgb(0%, 20%, 40%)' ), [0, 51, 102], 'Parse percentages string (whitespace)' );
+ deepEqual( jQuery.colorUtil.getRGB( '#f2ddee' ), [242, 221, 238], 'Hex string: 6 char lowercase' );
+ deepEqual( jQuery.colorUtil.getRGB( '#f2DDEE' ), [242, 221, 238], 'Hex string: 6 char uppercase' );
+ deepEqual( jQuery.colorUtil.getRGB( '#f2DdEe' ), [242, 221, 238], 'Hex string: 6 char mixed' );
+ deepEqual( jQuery.colorUtil.getRGB( '#eee' ), [238, 238, 238], 'Hex string: 3 char lowercase' );
+ deepEqual( jQuery.colorUtil.getRGB( '#EEE' ), [238, 238, 238], 'Hex string: 3 char uppercase' );
+ deepEqual( jQuery.colorUtil.getRGB( '#eEe' ), [238, 238, 238], 'Hex string: 3 char mixed' );
+ deepEqual( jQuery.colorUtil.getRGB( 'rgba(0, 0, 0, 0)' ), [255, 255, 255], 'Zero rgba for Safari 3; Transparent (whitespace)' );
+ // Perhaps this is a bug in colorUtil, but it is the current behaviour so, let's keep track
+ // would that ever change
+ equal( typeof jQuery.colorUtil.getRGB( 'rgba(0,0,0,0)' ), 'undefined', 'Zero rgba without whitespace' );
+
+ deepEqual( jQuery.colorUtil.getRGB( 'lightGreen' ), [144, 238, 144], 'Color names (lightGreen)' );
+ deepEqual( jQuery.colorUtil.getRGB( 'lightGreen' ), [144, 238, 144], 'Color names (transparent)' );
+ equal( typeof jQuery.colorUtil.getRGB( 'mediaWiki' ), 'undefined', 'Inexisting color name' );
+
+});
+
+test( 'rgbToHsl', function(){
+ var hsl = jQuery.colorUtil.rgbToHsl( 144, 238, 144 );
+ var dualDecimals = function(a,b){
+ return Math.round(a*100)/100;
+ };
+
+ ok( hsl, 'Basic return evaluation' );
+ deepEqual( dualDecimals(hsl[0]) , 0.33, 'rgb(144, 238, 144): H 0.33' );
+ deepEqual( dualDecimals(hsl[1]) , 0.73, 'rgb(144, 238, 144): S 0.73' );
+ deepEqual( dualDecimals(hsl[2]) , 0.75, 'rgb(144, 238, 144): L 0.75' );
+
+});
+
+test( 'hslToRgb', function(){
+ var rgb = jQuery.colorUtil.hslToRgb( 0.3, 0.7, 0.8 );
+
+ ok( rgb, 'Basic return evaluation' );
+ deepEqual( Math.round(rgb[0]) , 183, 'hsl(0.3, 0.7, 0.8): R 183' );
+ deepEqual( Math.round(rgb[1]) , 240, 'hsl(0.3, 0.7, 0.8): G 240' );
+ deepEqual( Math.round(rgb[2]) , 168, 'hsl(0.3, 0.7, 0.8): B 168' );
+
+});
+
+test( 'getColorBrightness', function(){
+
+ var a = jQuery.colorUtil.getColorBrightness( 'red', +0.1 );
+
+ equal( a, 'rgb(255,50,50)', 'Start with named color, brighten 10%' );
+
+ var b = jQuery.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
+
+ equal( b, 'rgb(118,29,29)', 'Start with rgb string, darken 10%' );
+
+});
--- /dev/null
+module( 'jquery.mwPrototypes.js' );
+
+test( 'String functions', function(){
+
+ equal( $j.trimLeft( ' foo bar ' ), 'foo bar ', 'trimLeft' );
+ equal( $j.trimRight( ' foo bar ' ), ' foo bar', 'trimRight' );
+ equal( $j.ucFirst( 'foo'), 'Foo', 'ucFirst' );
+
+ equal( $j.escapeRE( '<!-- ([{+mW+}]) $^|?>' ),
+ '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?>', 'escapeRE - Escape specials' );
+ equal( $j.escapeRE( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ),
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'escapeRE - Leave uppercase alone' );
+ equal( $j.escapeRE( 'abcdefghijklmnopqrstuvwxyz' ),
+ 'abcdefghijklmnopqrstuvwxyz', 'escapeRE - Leave lowercase alone' );
+ equal( $j.escapeRE( '0123456789' ), '0123456789', 'escapeRE - Leave numbers alone' );
+
+});
+
+test( 'Is functions', function(){
+
+ deepEqual( $j.isDomElement( document.getElementById( 'qunit-header' ) ), true,
+ 'isDomElement: #qunit-header Node' );
+ deepEqual( $j.isDomElement( document.getElementById( 'random-name' ) ), false,
+ 'isDomElement: #random-name (null)' );
+ deepEqual( $j.isDomElement( document.getElementsByTagName( 'div' ) ), false,
+ 'isDomElement: getElementsByTagName Array' );
+ deepEqual( $j.isDomElement( document.getElementsByTagName( 'div' )[0] ), true,
+ 'isDomElement: getElementsByTagName(..)[0] Node' );
+ deepEqual( $j.isDomElement( $j( 'div' ) ), false,
+ 'isDomElement: jQuery object' );
+ deepEqual( $j.isDomElement( $j( 'div' ).get(0) ), true,
+ 'isDomElement: jQuery object > Get node' );
+ deepEqual( $j.isDomElement( document.createElement( 'div' ) ), true,
+ 'isDomElement: createElement' );
+ deepEqual( $j.isDomElement( { foo: 1 } ), false,
+ 'isDomElement: Object' );
+
+ equal( $j.isEmpty( 'string' ), false, 'isEmptry: "string"' );
+ equal( $j.isEmpty( '0' ), true, 'isEmptry: "0"' );
+ equal( $j.isEmpty( [] ), true, 'isEmptry: []' );
+ equal( $j.isEmpty( {} ), true, 'isEmptry: {}' );
+ // Documented behaviour
+ equal( $j.isEmpty( { length: 0 } ), true, 'isEmptry: { length: 0 }' );
+
+});
+
+test( 'Comparison functions', function(){
+
+ ok( $j.compareArray( [0, 'a', [], [2, 'b'] ], [0, "a", [], [2, "b"] ] ),
+ 'compareArray: Two deep arrays that are excactly the same' );
+ ok( !$j.compareArray( [1], [2] ), 'compareArray: Two different arrays (false)' );
+
+ ok( $j.compareObject( {}, {} ), 'compareObject: Two empty objects' );
+ ok( $j.compareObject( { foo: 1 }, { foo: 1 } ), 'compareObject: Two the same objects' );
+ ok( !$j.compareObject( { bar: true }, { baz: false } ),
+ 'compareObject: Two different objects (false)' );
+
+});
\ No newline at end of file
--- /dev/null
+module( 'mediawiki.util.js' );
+
+test( '-- Initial check', function(){
+
+ ok( mw.util, 'mw.util defined' );
+
+});
+
+test( 'rawurlencode', function(){
+
+ equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
+
+});
+
+test( 'wikiUrlencode', function(){
+
+ equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
+
+});
+
+test( 'addCSS', function(){
+
+ var a = mw.util.addCSS( '#bodyContent { visibility: hidden; }' );
+ ok( a, 'function works' );
+ deepEqual( a.disabled, false, 'property "disabled" is available and set to false' );
+
+ var $b = $('#bodyContent');
+ equal( $b.css('visibility'), 'hidden', 'Added style properties are in effect.' );
+
+
+});
+
+test( 'toggleToc', function(){
+
+ ok( mw.util.toggleToc );
+
+});
+
+test( 'wikiGetlink', function(){
+
+ // Not part of startUp module
+ mw.config.set( 'wgArticlePath', '/wiki/$1' );
+
+ var hrefA = mw.util.wikiGetlink( 'Sandbox' );
+
+ equal( hrefA, '/wiki/Sandbox', 'Simple title; Get link for "Sandbox"' );
+
+ var hrefB = mw.util.wikiGetlink( 'Foo:Sandbox ? 5+5=10 ! (test)/subpage' );
+
+ 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"' );
+
+});
+
+test( 'getParamValue', function(){
+
+ var url = 'http://mediawiki.org/?foo=wrong&foo=right#&foo=bad';
+
+ equal( mw.util.getParamValue( 'foo', url ), 'right', 'Use latest one, ignore hash' );
+ deepEqual( mw.util.getParamValue( 'bar', url ), null, 'Return null when not found' );
+
+});
+
+test( 'getActionFrom', function(){
+
+ // Example urls
+ var urlA = 'http://mediawiki.org/wiki/Article',
+ urlB = 'http://mediawiki.org/w/index.php?title=Article&action=edit',
+ urlC = 'http://mediawiki.org/edit/Article',
+ urlD = 'http://mediawiki.org/w/index.php/Article';
+
+ // Common settings
+ mw.config.set( {
+ 'wgActionPaths': [],
+ 'wgArticlePath': '/wiki/$1'
+ });
+
+ equal( mw.util.getActionFrom( urlA ), 'view', 'wgArticlePath (/wiki/$1) support' );
+ equal( mw.util.getActionFrom( urlB ), 'edit', 'action-parameter support' );
+
+ // Custom settings
+ mw.config.set( 'wgActionPaths', {
+ 'view': '/view/$1',
+ 'edit': '/edit/$1'
+ });
+
+ equal( mw.util.getActionFrom( urlC ), 'edit', 'wgActionPaths support' );
+
+ // Default settings
+ mw.config.set( {
+ 'wgActionPaths': [],
+ 'wgArticlePath': '/w/index.php/$1'
+ });
+ equal( mw.util.getActionFrom( urlD ), 'view', 'wgArticlePath (/index.php/$1) support' );
+
+});
+
+test( 'getTitleFrom', function(){
+
+ // Example urls
+ var urlA = 'http://mediawiki.org/wiki/Article',
+ urlB = 'http://mediawiki.org/w/index.php?title=Article&action=edit',
+ urlC = 'http://mediawiki.org/edit/Article',
+ urlD = 'http://mediawiki.org/w/index.php/Article';
+
+ // Common settings
+ mw.config.set( {
+ 'wgActionPaths': [],
+ 'wgArticlePath': '/wiki/$1'
+ });
+
+ equal( mw.util.getTitleFrom( urlA ), 'Article', 'wgArticlePath (/wiki/$1) support' );
+ equal( mw.util.getTitleFrom( urlB ), 'Article', 'action-parameter support' );
+
+ // Custom settings
+ mw.config.set( 'wgActionPaths', {
+ 'view': '/view/$1',
+ 'edit': '/edit/$1'
+ });
+
+ equal( mw.util.getTitleFrom( urlC ), 'Article', 'wgActionPaths support' );
+
+ // Default settings
+ mw.config.set( {
+ 'wgActionPaths': [],
+ 'wgArticlePath': '/w/index.php/$1'
+ });
+
+ equal( mw.util.getTitleFrom( urlD ), 'Article', 'wgArticlePath (/index.php/$1) support' );
+
+});
+
+test( 'tooltipAccessKey', function(){
+
+ equal( typeof mw.util.tooltipAccessKeyPrefix, 'string', 'mw.util.tooltipAccessKeyPrefix must be a string' );
+ ok( mw.util.tooltipAccessKeyRegexp instanceof RegExp, 'mw.util.tooltipAccessKeyRegexp instance of RegExp' );
+ ok( mw.util.updateTooltipAccessKeys, 'mw.util.updateTooltipAccessKeys' );
+
+});
+
+test( '$content', function(){
+
+ ok( mw.util.$content instanceof jQuery, 'mw.util.$content instance of jQuery' );
+ deepEqual( mw.util.$content.length, 1, 'mw.util.$content must have length of 1' );
+
+});
+
+test( 'addPortletLink', function(){
+
+ var A = mw.util.addPortletLink( 'p-tb', 'http://mediawiki.org/wiki/ResourceLoader',
+ 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l', '#t-specialpages' );
+
+ ok( $.isDomElement( A ), 'addPortletLink returns a valid DOM Element according to $.isDomElement' );
+
+ var B = mw.util.addPortletLink( "p-tb", "http://mediawiki.org/",
+ "MediaWiki.org", "t-mworg", "Go to MediaWiki.org ", "m", A );
+
+ equal( $( B ).attr( 'id' ), 't-mworg', 'Link has correct ID set' );
+ equal( $( B ).closest( '.portal' ).attr( 'id' ), 'p-tb', 'Link was inserted within correct portlet' );
+ equal( $( B ).next().attr( 'id' ), 't-rl', 'Link is in the correct position (by passing nextnode)' );
+
+ var C = mw.util.addPortletLink( "p-tb", "http://mediawiki.org/wiki/RL/DM",
+ "Default modules", "t-rldm", "List of all default modules ", "d", "#t-rl" );
+
+ equal( $( C ).next().attr( 'id' ), 't-rl', 'Link is in the correct position (by passing CSS selector)' );
+
+ // Clean up
+ $( [A, B, C] ).remove();
+
+});
+
+test( 'jsMessage', function(){
+
+ var a = mw.util.jsMessage( "MediaWiki is <b>Awesome</b>." );
+
+ ok( a, 'Basic checking of return value' );
+
+ // Clean up
+ $( '#mw-js-message' ).remove();
+
+});
+
+test( 'validateEmail', function(){
+
+ deepEqual( mw.util.validateEmail( "" ), null, 'Empty string should return null' );
+ deepEqual( mw.util.validateEmail( "user@localhost" ), true );
+
+ // testEmailWithCommasAreInvalids
+ deepEqual( mw.util.validateEmail( "user,foo@example.org" ), false, 'Comma' );
+ deepEqual( mw.util.validateEmail( "userfoo@ex,ample.org" ), false, 'Comma' );
+
+ // testEmailWithHyphens
+ deepEqual( mw.util.validateEmail( "user-foo@example.org" ), true, 'Hyphen' );
+ deepEqual( mw.util.validateEmail( "userfoo@ex-ample.org" ), true, 'Hyphen' );
+
+});
+
+test( 'isIPv6Address', function(){
+
+ // Based on IPTest.php > IPv6
+ deepEqual( mw.util.isIPv6Address( "" ), false, 'Empty string is not an IP' );
+ deepEqual( mw.util.isIPv6Address( ":fc:100::" ), false, 'IPv6 starting with lone ":"' );
+ deepEqual( mw.util.isIPv6Address( "fc:100::" ), true );
+ deepEqual( mw.util.isIPv6Address( "fc:100:a:d:1:e:ac::" ), true );
+ deepEqual( mw.util.isIPv6Address( ":::" ), false );
+ deepEqual( mw.util.isIPv6Address( "::0:" ), false );
+
+});
+
+test( 'isIPv4Address', function(){
+
+ // Based on IPTest.php > IPv4
+ deepEqual( mw.util.isIPv4Address( "" ), false, 'Empty string is not an IP' );
+ deepEqual( mw.util.isIPv4Address( "...." ), false );
+ deepEqual( mw.util.isIPv4Address( "1.24.52.13" ), true );
+
+});
--- /dev/null
+module( 'mediawiki.js' );
+
+test( '-- Initial check', function(){
+
+ ok( window.jQuery, 'jQuery defined' );
+ ok( window.$j, '$j defined' );
+ equal( window.$j, window.jQuery, '$j alias to jQuery' );
+
+ ok( window.mediaWiki, 'mediaWiki defined' );
+ ok( window.mw, 'mw defined' );
+ equal( window.mw, window.mediaWiki, 'mw alias to mediaWiki' );
+
+});
+
+test( 'mw.Map / mw.config', function(){
+
+ ok( mw.config instanceof mw.Map, 'mw.config instance of mw.Map' );
+ ok( mw.config.get, 'get' );
+ ok( mw.config.set, 'set' );
+ ok( mw.config.exists, 'exists' );
+
+ ok( !mw.config.exists( 'lipsum' ), 'exists: lipsum (inexistant)' );
+ ok( mw.config.set( 'lipsum', 'Lorem ipsum' ), 'set: lipsum' );
+ ok( mw.config.exists( 'lipsum' ), 'exists: lipsum (existant)' );
+
+ equal( mw.config.get( 'lipsum' ), 'Lorem ipsum', 'get: lipsum' );
+ equal( mw.config.get( ['lipsum'] ).lipsum, 'Lorem ipsum', 'get: lipsum (multiple)' );
+
+});
+
+test( 'mw.message / mw.msg / mw.messages', function(){
+ ok( mw.message, 'mw.message defined' );
+ ok( mw.msg, 'mw.msg defined' );
+ ok( mw.messages, 'messages defined' );
+ ok( mw.messages instanceof mw.Map, 'mw.messages instance of mw.Map' );
+ ok( mw.messages.set( 'hello', 'Hello <b>awesome</b> world' ), 'mw.messages.set: Register' );
+
+ var hello = mw.message( 'hello' );
+ ok( hello, 'hello: Instance of Message' );
+
+ equal( hello.format, 'parse', 'Message property "format" (default value)' );
+ equal( hello.key, 'hello', 'Message property "key" (currect key)' );
+ deepEqual( hello.parameters, [], 'Message property "parameters" (default value)' );
+
+
+ ok( hello.params, 'Message prototype "params"');
+ ok( hello.toString, 'Message prototype "toString"');
+ ok( hello.parse, 'Message prototype "parse"');
+ ok( hello.plain, 'Message prototype "plain"');
+ ok( hello.escaped, 'Message prototype "escaped"');
+ ok( hello.exists, 'Message prototype "exists"');
+
+ equal( hello.toString(), 'Hello <b>awesome</b> world', 'Message.toString() test');
+ equal( hello.escaped(), 'Hello <b>awesome</b> world', 'Message.escaped() test');
+ deepEqual( hello.exists(), true, 'Message.exists() test');
+
+ equal( mw.msg( 'random' ), '<random>', 'square brackets around inexistant messages' );
+ equal( mw.msg( 'hello' ), 'Hello <b>awesome</b> world', 'get message with default options' );
+
+// params, toString, parse, plain, escaped, exists
+});
+
+test( 'mw.loader', function(){
+ expect(2);
+
+ ok( location.href.match(/[^#\?]*/) && location.href.match(/[^#\?]*/)[0], true, 'Extracting file path from location' );
+
+ stop();
+
+ mw.loader.implement( 'is.awesome', [location.href.match(/[^#\?]*/)[0] + 'sample/awesome.js'], {}, {} );
+ mw.loader.using( 'is.awesome', function(){
+ start();
+ deepEqual( window.awesome, true, 'Implementing a module, is the callback timed properly ?');
+
+ // Clean up
+ delete window.awesome;
+
+ }, function(){
+ start();
+ deepEqual( 'mw.loader.using error callback fired', true, 'Implementing a module, is the callback timed properly ?');
+ });
+
+});
+
+test( 'mw.html', function(){
+
+ equal( mw.html.escape( '<mw awesome="awesome" value=\'test\' />' ),
+ '<mw awesome="awesome" value='test' />', 'html.escape()' );
+
+ equal( mw.html.element( 'div' ), '<div/>', 'mw.html.element() DIV (simple)' );
+
+ equal( mw.html.element( 'div',
+ { id: 'foobar' } ),
+ '<div id="foobar"/>',
+ 'mw.html.element() DIV (attribs)' );
+
+ equal( mw.html.element( 'div',
+ null, 'a' ),
+ '<div>a</div>',
+ 'mw.html.element() DIV (content)' );
+
+ equal( mw.html.element( 'a',
+ { href: 'http://mediawiki.org/w/index.php?title=RL&action=history' }, 'a' ),
+ '<a href="http://mediawiki.org/w/index.php?title=RL&action=history">a</a>',
+ 'mw.html.element() DIV (attribs + content)' );
+
+});
--- /dev/null
+module( 'mediawiki.user.js' );
+
+test( '-- Initial check', function(){
+
+ ok( mw.user, 'mw.user defined' );
+
+});
+
+
+test( 'options', function(){
+
+ ok( mw.user.options instanceof mw.Map, 'options instance of mw.Map' );
+
+});
+
+test( 'User login status', function(){
+
+ deepEqual( mw.user.name(), null, 'user.name() When anonymous' );
+ ok( mw.user.anonymous(), 'user.anonymous() When anonymous' );
+
+ // Not part of startUp module
+ mw.config.set( 'wgUserName', 'John' );
+
+ equal( mw.user.name(), 'John', 'user.name() When logged-in as John' );
+ ok( !mw.user.anonymous(), 'user.anonymous() When logged-in' );
+
+ equal( mw.user.id(), 'John', 'user.id() When logged-in as John' );
+
+
+});
\ No newline at end of file
--- /dev/null
+/*
+ Copyright (c) 2009 John Resig
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+(function(){
+
+ var DEBUG = false;
+
+ var doPost = false;
+
+ try {
+ doPost = !!window.top.postMessage;
+ } catch(e){}
+
+ var search = window.location.search,
+ url, index;
+ if( ( index = search.indexOf( "swarmURL=" ) ) != -1 )
+ url = decodeURIComponent( search.slice( index + 9 ) );
+
+ if ( !DEBUG && (!url || url.indexOf("http") !== 0) ) {
+ return;
+ }
+
+ var submitTimeout = 5;
+
+ var curHeartbeat;
+ var beatRate = 20;
+
+ // Expose the TestSwarm API
+ window.TestSwarm = {
+ submit: submit,
+ heartbeat: function(){
+ if ( curHeartbeat ) {
+ clearTimeout( curHeartbeat );
+ }
+
+ curHeartbeat = setTimeout(function(){
+ submit({ fail: -1, total: -1 });
+ }, beatRate * 1000);
+ },
+ serialize: function(){
+ return trimSerialize();
+ }
+ };
+
+ // Prevent careless things from executing
+ window.print = window.confirm = window.alert = window.open = function(){};
+
+ window.onerror = function(e){
+ document.body.appendChild( document.createTextNode( "ERROR: " + e ));
+ submit({ fail: 0, error: 1, total: 1 });
+ return false;
+ };
+
+ // QUnit (jQuery)
+ // http://docs.jquery.com/QUnit
+ if ( typeof QUnit !== "undefined" ) {
+ QUnit.done = function(results){
+ submit({
+ fail: results.failed,
+ error: 0,
+ total: results.total
+ });
+ };
+
+ QUnit.log = window.TestSwarm.heartbeat;
+ window.TestSwarm.heartbeat();
+
+ window.TestSwarm.serialize = function(){
+ // Clean up the HTML (remove any un-needed test markup)
+ remove("nothiddendiv");
+ remove("loadediframe");
+ remove("dl");
+ remove("main");
+
+ // Show any collapsed results
+ var ol = document.getElementsByTagName("ol");
+ for ( var i = 0; i < ol.length; i++ ) {
+ ol[i].style.display = "block";
+ }
+
+ return trimSerialize();
+ };
+
+ // UnitTestJS (Prototype, Scriptaculous)
+ // http://github.com/tobie/unittest_js/tree/master
+ } else if ( typeof Test !== "undefined" && Test && Test.Unit && Test.Unit.runners ) {
+ var total_runners = Test.Unit.runners.length, cur_runners = 0;
+ var total = 0, fail = 0, error = 0;
+
+ for (var i = 0; i < Test.Unit.runners.length; i++) (function(i){
+ var finish = Test.Unit.runners[i].finish;
+ Test.Unit.runners[i].finish = function(){
+ finish.call( this );
+
+ var results = this.getResult();
+ total += results.assertions;
+ fail += results.failures;
+ error += results.errors;
+
+ if ( ++cur_runners === total_runners ) {
+ submit({
+ fail: fail,
+ error: error,
+ total: total
+ });
+ }
+ };
+ })(i);
+
+ // JSSpec (MooTools)
+ // http://jania.pe.kr/aw/moin.cgi/JSSpec
+ } else if ( typeof JSSpec !== "undefined" && JSSpec && JSSpec.Logger ) {
+ var onRunnerEnd = JSSpec.Logger.prototype.onRunnerEnd;
+ JSSpec.Logger.prototype.onRunnerEnd = function(){
+ onRunnerEnd.call(this);
+
+ // Show any collapsed results
+ var ul = document.getElementsByTagName("ul");
+ for ( var i = 0; i < ul.length; i++ ) {
+ ul[i].style.display = "block";
+ }
+
+ submit({
+ fail: JSSpec.runner.getTotalFailures(),
+ error: JSSpec.runner.getTotalErrors(),
+ total: JSSpec.runner.totalExamples
+ });
+ };
+
+ window.TestSwarm.serialize = function(){
+ // Show any collapsed results
+ var ul = document.getElementsByTagName("ul");
+ for ( var i = 0; i < ul.length; i++ ) {
+ ul[i].style.display = "block";
+ }
+
+ return trimSerialize();
+ };
+
+ // JSUnit
+ // http://www.jsunit.net/
+ // Note: Injection file must be included before the frames
+ // are document.write()d into the page.
+ } else if ( typeof JsUnitTestManager !== "undefined" ) {
+ var _done = JsUnitTestManager.prototype._done;
+ JsUnitTestManager.prototype._done = function(){
+ _done.call(this);
+
+ submit({
+ fail: this.failureCount,
+ error: this.errorCount,
+ total: this.totalCount
+ });
+ };
+
+ window.TestSwarm.serialize = function(){
+ return "<pre>" + this.log.join("\n") + "</pre>";
+ };
+
+ // Selenium Core
+ // http://seleniumhq.org/projects/core/
+ } else if ( typeof SeleniumTestResult !== "undefined" && typeof LOG !== "undefined" ) {
+ // Completely overwrite the postback
+ SeleniumTestResult.prototype.post = function(){
+ submit({
+ fail: this.metrics.numCommandFailures,
+ error: this.metrics.numCommandErrors,
+ total: this.metrics.numCommandPasses + this.metrics.numCommandFailures + this.metrics.numCommandErrors
+ });
+ };
+
+ window.TestSwarm.serialize = function(){
+ var results = [];
+ while ( LOG.pendingMessages.length ) {
+ var msg = LOG.pendingMessages.shift();
+ results.push( msg.type + ": " + msg.msg );
+ }
+
+ return "<pre>" + results.join("\n") + "</pre>";
+ };
+
+ // Dojo Objective Harness
+ // http://docs.dojocampus.org/quickstart/doh
+ } else if ( typeof doh !== "undefined" && doh._report ) {
+ var _report = doh._report;
+ doh._report = function(){
+ _report.apply(this, arguments);
+
+ submit({
+ fail: doh._failureCount,
+ error: doh._errorCount,
+ total: doh._testCount
+ });
+ };
+
+ window.TestSwarm.serialize = function(){
+ return "<pre>" + document.getElementById("logBody").innerHTML + "</pre>";
+ };
+ // Screw.Unit
+ // git://github.com/nathansobo/screw-unit.git
+ } else if ( typeof Screw !== "undefined" && typeof jQuery !== 'undefined' && Screw && Screw.Unit ) {
+ $(Screw).bind("after", function() {
+ var passed = $('.passed').length;
+ var failed = $('.failed').length;
+ submit({
+ fail: failed,
+ error: 0,
+ total: failed + passed
+ });
+ });
+
+ $(Screw).bind("loaded", function() {
+ $('.it')
+ .bind("passed", window.TestSwarm.heartbeat)
+ .bind("failed", window.TestSwarm.heartbeat);
+ window.TestSwarm.heartbeat();
+ });
+
+ window.TestSwarm.serialize = function(){
+ return trimSerialize();
+ };
+ }
+
+ function trimSerialize(doc) {
+ doc = doc || document;
+
+ var scripts = doc.getElementsByTagName("script");
+ while ( scripts.length ) {
+ remove( scripts[0] );
+ }
+
+ var root = window.location.href.replace(/(https?:\/\/.*?)\/.*/, "$1");
+ var cur = window.location.href.replace(/[^\/]*$/, "");
+
+ var links = doc.getElementsByTagName("link");
+ for ( var i = 0; i < links.length; i++ ) {
+ var href = links[i].href;
+ if ( href.indexOf("/") === 0 ) {
+ href = root + href;
+ } else if ( !/^https?:\/\//.test( href ) ) {
+ href = cur + href;
+ }
+ links[i].href = href;
+ }
+
+ return ("<html>" + doc.documentElement.innerHTML + "</html>")
+ .replace(/\s+/g, " ");
+ }
+
+ function remove(elem){
+ if ( typeof elem === "string" ) {
+ elem = document.getElementById( elem );
+ }
+
+ if ( elem ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+
+ function submit(params){
+ if ( curHeartbeat ) {
+ clearTimeout( curHeartbeat );
+ }
+
+ var paramItems = (url.split("?")[1] || "").split("&");
+
+ for ( var i = 0; i < paramItems.length; i++ ) {
+ if ( paramItems[i] ) {
+ var parts = paramItems[i].split("=");
+ if ( !params[ parts[0] ] ) {
+ params[ parts[0] ] = parts[1];
+ }
+ }
+ }
+
+ if ( !params.state ) {
+ params.state = "saverun";
+ }
+
+ if ( !params.results ) {
+ params.results = window.TestSwarm.serialize();
+ }
+
+ if ( doPost ) {
+ // Build Query String
+ var query = "";
+
+ for ( var i in params ) {
+ query += ( query ? "&" : "" ) + i + "=" +
+ encodeURIComponent(params[i]);
+ }
+
+ if ( DEBUG ) {
+ alert( query );
+ } else {
+ window.top.postMessage( query, "*" );
+ }
+
+ } else {
+ var form = document.createElement("form");
+ form.action = url;
+ form.method = "POST";
+
+ for ( var i in params ) {
+ var input = document.createElement("input");
+ input.type = "hidden";
+ input.name = i;
+ input.value = params[i];
+ form.appendChild( input );
+ }
+
+ if ( DEBUG ) {
+ alert( form.innerHTML );
+ } else {
+
+ // Watch for the result submission timing out
+ setTimeout(function(){
+ submit( params );
+ }, submitTimeout * 1000);
+
+ document.body.appendChild( form );
+ form.submit();
+ }
+ }
+ }
+
+})();