be06a632fc08dbc83a12a1222349512e23e5da87
2 * mediaWiki JavaScript library test suite
4 * Available on Special:BlankPage?action=mwutiltest&debug=true
6 * @author Krinkle <krinklemail@gmail.com>
15 // contains either a header or a test
16 // test: [ code, result, contain ] see addTest
17 // header: [ 'HEADER', escapedtitle, id ] see addHead
25 * Adds a row to the test-table
27 * @param code String Code of the test to be executed
28 * @param result String Expected result in 'var (vartype)' form
29 * @param contain String Important part of the result,
30 * if result is different but does contain this it will not return ERROR but PARTIALLY
32 'addTest' : function( code
, result
, contain
) {
36 this.addedTests
.push( [code
, result
, contain
] );
37 this.$table
.append( '<tr class="mw-mwutiltest-test">'
38 + '<td>' + mw
.html
.escape( code
).replace( / /g
, ' ' )
39 + '</td><td>' + mw
.html
.escape( result
).replace( / /g
, ' ' )
40 + '</td><td></td><td>?</td></tr>' );
45 * Adds a heading to the test-table
47 * @param title String Title of the section
49 'addHead' : function( title
) {
53 var escapedtitle
= mw
.html
.escape( title
).replace( / /g
, ' ' );
54 this.addedTests
.push( [ 'HEADER', escapedtitle
, mw
.test
.numberOfHeader
++ ] );
55 this.$table
.append( '<tr class="mw-mwutiltest-head" id="mw-mwutiltest-head'+mw
.test
.numberOfHeader
+'"><th colspan="4">' + escapedtitle
+ '</th></tr>' );
60 'initialised' : false,
62 if ( this.initialised
=== false ) {
63 this.initialised
= true;
64 // jQuery document ready
66 if ( mw
.config
.get( 'wgCanonicalSpecialPageName' ) == 'Blankpage'
67 && mw
.util
.getParamValue( 'action' ) === 'mwutiltest' ) {
70 document
.title
= 'mediaWiki JavaScript library test suite - ' + mw
.config
.get( 'wgSiteName' );
71 $( '#firstHeading' ).text( 'mediaWiki JavaScript library test suite' );
72 var skinLinksText
= 'Test in: ',
74 availableSkins
= mw
.config
.get( 'wgAvailableSkins' ),
76 for ( skincode
in availableSkins
) {
77 skinLinks
.push( mw
.html
.element( 'a', {
78 'href': mw
.util
.wikiGetlink( wgPageName
) + '?action=mwutiltest&debug=true&useskin=' + encodeURIComponent( skincode
)
79 }, availableSkins
[skincode
] ) );
81 skinLinksText
+= skinLinks
.join( ' | ' ) + '.';
82 mw
.util
.$content
.html(
83 '<p>Below is a list of tests to confirm proper functionality of the mediaWiki JavaScript library</p>'
84 + '<p>' + skinLinksText
+ '</p>'
86 + '<table id="mw-mwutiltest-table" class="wikitable" style="white-space:break; font-family:monospace,\'Courier New\'; width:100%;">'
87 + '<tr><th>Exec</th><th>Should return</th><th>Does return</th><th>Equal ?</th></tr>'
92 '#mw-mwutiltest-table tr td { padding:0 !important; }' // Override wikitable padding for <td>
95 mw
.test
.$table
= $( 'table#mw-mwutiltest-table' );
98 // Try to roughly keep the order similar to the order in the files
99 // or alphabetical (depending on the context)
101 /** Main modules and their aliases **/
102 mw
.test
.addHead( 'Main modules and their aliases' );
104 mw
.test
.addTest( 'typeof mediaWiki',
107 mw
.test
.addTest( 'typeof mw',
110 mw
.test
.addTest( 'typeof jQuery',
111 'function (string)' );
113 mw
.test
.addTest( 'typeof $',
114 'function (string)' );
116 /** Prototype functions added by MediaWiki **/
117 mw
.test
.addHead( 'Prototype functions added by MediaWiki' );
119 mw
.test
.addTest( 'typeof $.trimLeft',
120 'function (string)' );
122 mw
.test
.addTest( '$.trimLeft( " foo bar " )',
123 'foo bar (string)' );
125 mw
.test
.addTest( 'typeof $.trimRight',
126 'function (string)' );
128 mw
.test
.addTest( '$.trimRight( " foo bar " )',
129 ' foo bar (string)' );
131 mw
.test
.addTest( 'typeof $.ucFirst',
132 'function (string)' );
134 mw
.test
.addTest( '$.ucFirst( "mediawiki" )',
135 'Mediawiki (string)' );
137 mw
.test
.addTest( 'typeof $.escapeRE',
138 'function (string)' );
140 mw
.test
.addTest( '$.escapeRE( "<!-- ([{+mW+}]) $^|?>" )',
141 '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?> (string)' ); // double escaped
143 mw
.test
.addTest( '$.escapeRE( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" )',
144 'ABCDEFGHIJKLMNOPQRSTUVWXYZ (string)' );
146 mw
.test
.addTest( '$.escapeRE( "abcdefghijklmnopqrstuvwxyz" )',
147 'abcdefghijklmnopqrstuvwxyz (string)' );
149 mw
.test
.addTest( '$.escapeRE( "0123456789" )',
150 '0123456789 (string)' );
152 mw
.test
.addTest( '$.isDomElement( document.getElementById("mw-mwutiltest-table") )',
155 mw
.test
.addTest( '$.isDomElement( document.getElementById("not-existant-id") )',
156 'false (boolean)' ); // returns null
158 mw
.test
.addTest( '$.isDomElement( document.getElementsByClassName("wikitable") )',
159 'false (boolean)' ); // returns an array
161 mw
.test
.addTest( '$.isDomElement( document.getElementsByClassName("wikitable")[0] )',
164 mw
.test
.addTest( '$.isDomElement( jQuery( "#mw-mwutiltest-table" ) )',
165 'false (boolean)' ); // returns jQuery object
167 mw
.test
.addTest( '$.isDomElement( jQuery( "#mw-mwutiltest-table" ).get(0) )',
170 mw
.test
.addTest( '$.isDomElement( document.createElement( "div" ) )',
173 mw
.test
.addTest( '$.isDomElement( {some: "thing" } )',
176 mw
.test
.addTest( 'typeof $.isEmpty',
177 'function (string)' );
179 mw
.test
.addTest( '$.isEmpty( "string" )',
182 mw
.test
.addTest( '$.isEmpty( "0" )',
185 mw
.test
.addTest( '$.isEmpty([])',
188 mw
.test
.addTest( 'typeof $.compareArray',
189 'function (string)' );
191 mw
.test
.addTest( '$.compareArray( [1, "a", [], [2, "b"] ], [1, "a", [], [2, "b"] ] )',
194 mw
.test
.addTest( '$.compareArray( [1], [2] )',
197 mw
.test
.addTest( 'typeof $.compareObject',
198 'function (string)' );
201 mw
.test
.addHead( 'mediawiki.js' );
203 mw
.test
.addTest( 'mw.config instanceof mw.Map',
206 mw
.test
.addTest( 'mw.config.exists()',
209 mw
.test
.addTest( 'mw.config.exists( "wgSomeName" )',
212 mw
.test
.addTest( 'mw.config.exists( ["wgCanonicalNamespace", "wgTitle"] )',
215 mw
.test
.addTest( 'mw.config.exists( ["wgSomeName", "wgTitle"] )',
218 mw
.test
.addTest( 'mw.config.get( "wgCanonicalNamespace" )',
219 'Special (string)' );
221 mw
.test
.addTest( 'var a = mw.config.get( ["wgCanonicalNamespace"] ); a.wgCanonicalNamespace',
222 'Special (string)' );
224 mw
.test
.addTest( 'typeof mw.html',
227 mw
.test
.addTest( 'mw.html.escape( \'<mw awesome="awesome">\' )',
228 '<mw awesome="awesome"> (string)' );
230 mw
.test
.addTest( 'mw.html.element( "hr" )',
233 mw
.test
.addTest( 'mw.html.element( "img", { "src": "http://mw.org/?title=Main page&action=edit" } )',
234 '<img src="http://mw.org/?title=Main page&action=edit"/> (string)' );
236 mw
.test
.addTest( 'typeof mw.loader',
239 mw
.test
.addTest( 'typeof mw.loader.using',
240 'function (string)' );
242 mw
.test
.addTest( 'typeof mw.Map',
243 'function (string)' );
245 mw
.test
.addTest( 'typeof mw.user',
248 mw
.test
.addTest( 'typeof mw.user.anonymous()',
249 'boolean (string)' );
251 /** mediawiki.util.js **/
252 mw
.test
.addHead( 'mediawiki.util.js' );
254 mw
.test
.addTest( 'typeof mw.util',
257 mw
.test
.addTest( 'typeof mw.util.rawurlencode',
258 'function (string)' );
260 mw
.test
.addTest( 'mw.util.rawurlencode( "Test:A & B/Here" )',
261 'Test%3AA%20%26%20B%2FHere (string)' );
263 mw
.test
.addTest( 'typeof mw.util.wikiUrlencode',
264 'function (string)' );
266 mw
.test
.addTest( 'mw.util.wikiUrlencode( "Test:A & B/Here" )',
267 'Test:A_%26_B/Here (string)' );
269 mw
.test
.addTest( 'typeof mw.util.addCSS',
270 'function (string)' );
272 mw
.test
.addTest( 'var a = mw.util.addCSS( "#mw-js-message { background-color: #AFA !important; }" ); a.disabled;',
276 mw
.test
.addTest( 'typeof mw.util.toggleToc',
277 'function (string)' );
279 mw
.test
.addTest( 'typeof mw.util.wikiGetlink',
280 'function (string)' );
282 mw
.test
.addTest( 'typeof mw.util.getParamValue',
283 'function (string)' );
285 mw
.test
.addTest( 'mw.util.getParamValue( "action" )',
286 'mwutiltest (string)' );
288 mw
.test
.addTest( 'mw.util.getParamValue( "foo", "http://mw.org/?foo=wrong&foo=right#&foo=bad" )',
291 mw
.test
.addTest( 'typeof mw.util.tooltipAccessKeyPrefix',
294 mw
.test
.addTest( 'mw.util.tooltipAccessKeyRegexp.constructor.name',
297 mw
.test
.addTest( 'typeof mw.util.updateTooltipAccessKeys',
298 'function (string)' );
300 mw
.test
.addTest( 'mw.util.$content instanceof jQuery',
303 mw
.test
.addTest( 'mw.util.$content.size()',
306 mw
.test
.addTest( 'mw.util.isMainPage()',
309 mw
.test
.addTest( 'typeof mw.util.addPortletLink',
310 'function (string)' );
312 mw
.test
.addTest( 'typeof mw.util.addPortletLink( "p-tb", "http://mediawiki.org/wiki/ResourceLoader", "ResourceLoader", "t-rl", "More info about ResourceLoader on MediaWiki.org ", "l", "#t-specialpages" )',
315 mw
.test
.addTest( 'var a = mw.util.addPortletLink( "p-tb", "http://mediawiki.org/", "MediaWiki.org", "t-mworg", "Go to MediaWiki.org ", "m", "#t-rl" ); $(a).text();',
316 'MediaWiki.org (string)' );
318 mw
.test
.addTest( 'typeof mw.util.jsMessage',
319 'function (string)' );
321 mw
.test
.addTest( 'mw.util.jsMessage( mw.config.get( "wgSiteName" ) + " is <b>Awesome</b>." )',
324 // TODO: Import tests from PHPUnit test suite for user::isValidEmailAddr
325 mw
.test
.addTest( 'mw.util.validateEmail( "" )',
328 mw
.test
.addTest( 'mw.util.validateEmail( "user@localhost" )',
331 // testEmailWithCommasAreInvalids
332 mw
.test
.addTest( 'mw.util.validateEmail( "user,foo@example.org" )',
334 mw
.test
.addTest( 'mw.util.validateEmail( "userfoo@ex,ample.org" )',
336 // testEmailWithHyphens
337 mw
.test
.addTest( 'mw.util.validateEmail( "user-foo@example.org" )',
339 mw
.test
.addTest( 'mw.util.validateEmail( "userfoo@ex-ample.org" )',
342 // From IPTest.php IPv6
343 mw
.test
.addTest( 'mw.util.isIPv6Address( "" )',
345 mw
.test
.addTest( 'mw.util.isIPv6Address( ":fc:100::" )',
347 mw
.test
.addTest( 'mw.util.isIPv6Address( "fc:100::" )',
349 mw
.test
.addTest( 'mw.util.isIPv6Address( "fc:100:a:d:1:e:ac::" )',
351 mw
.test
.addTest( 'mw.util.isIPv6Address( ":::" )',
353 mw
.test
.addTest( 'mw.util.isIPv6Address( "::0:" )',
356 // From IPTest.php IPv4
357 mw
.test
.addTest( 'mw.util.isIPv4Address( "" )',
359 mw
.test
.addTest( 'mw.util.isIPv4Address( "...." )',
361 mw
.test
.addTest( 'mw.util.isIPv4Address( "abc" )',
363 mw
.test
.addTest( 'mw.util.isIPv4Address( "124.24.52" )',
365 mw
.test
.addTest( 'mw.util.isIPv4Address( ".24.52.13" )',
367 mw
.test
.addTest( 'mw.util.isIPv4Address( "124.24.52.13" )',
369 mw
.test
.addTest( 'mw.util.isIPv4Address( "1.24.52.13" )',
371 mw
.test
.addTest( 'mw.util.isIPv4Address( "74.24.52.13/20" )', // Range
373 // @FIXME: The regex that's been in MW JS has never supported ranges but it should
374 // The regex is expected to return false for that reason
377 mw
.test
.addHead( 'jQuery plugins' );
379 mw
.test
.addTest( 'typeof $.client',
382 mw
.test
.addTest( 'typeof $.client.profile',
383 'function (string)' );
385 mw
.test
.addTest( 'var a = $.client.profile(); typeof a.name',
388 mw
.test
.addTest( 'typeof $.fn.makeCollapsible',
389 'function (string)' );
393 mw
.test
.addHead( '*** End of tests ***' );
395 // Run tests and compare results
401 numberOfPartials
= 0,
403 headNumberOfTests
= 0,
404 headNumberOfPasseds
= 0,
405 headNumberOfPartials
= 0,
406 headNumberOfErrors
= 0,
408 previousHeadTitle
= '',
409 $testrows
= mw
.test
.$table
.find( 'tr:has(td)' );
411 $.each( mw
.test
.addedTests
, function( i
, item
) {
414 if( item
[0] == 'HEADER' ) {
416 // update current header with its tests results
417 mw
.test
.$table
.find( 'tr#mw-mwutiltest-head' + numberOfHeaders
+' > th' )
418 .html( previousHeadTitle
+ ' <span style="float:right">('
419 + 'Tests: ' + headNumberOfTests
420 + ' OK: ' + headNumberOfPasseds
421 + ' Partial: ' + headNumberOfPartials
422 + ' Error: ' + headNumberOfErrors
426 // Reset values for the new header;
427 headNumberOfTests
= 0;
428 headNumberOfPasseds
= 0;
429 headNumberOfPartials
= 0;
430 headNumberOfErrors
= 0;
432 previousHeadTitle
= item
[1];
438 var shouldreturn
= item
[1];
439 var shouldcontain
= item
[2];
444 var doesReturn
= eval( exec
);
446 mw
.log ('mw.util.test> ' + e
);
448 doesReturn
= doesReturn
+ ' (' + typeof doesReturn
+ ')';
449 var $thisrow
= $testrows
.eq( i
- numberOfHeaders
); // since headers are rows as well
450 $thisrow
.find( '> td' ).eq(2).html( mw
.html
.escape( doesReturn
).replace(/ /g
, ' ' ) );
452 if ( doesReturn
.indexOf( shouldcontain
) !== -1 ) {
453 if ( doesReturn
== shouldreturn
) {
454 $thisrow
.find( '> td' ).eq(3).css( 'background', '#AFA' ).text( 'OK' );
456 headNumberOfPasseds
++;
458 $thisrow
.find( '> td' ).eq(3).css( 'background', '#FFA' ).html( '<small>PARTIALLY</small>' );
460 headNumberOfPartials
++;
463 $thisrow
.css( 'background', '#FAA' ).find( '> td' ).eq(3).text( 'ERROR' );
465 headNumberOfErrors
++;
469 mw
.test
.$table
.before( '<p><strong>Ran ' + numberOfTests
+ ' tests. ' +
470 numberOfPasseds
+ ' passed test(s). ' + numberOfErrors
+ ' error(s). ' +
471 numberOfPartials
+ ' partially passed test(s). </p>' );
481 } )(jQuery
, mediaWiki
);