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 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>
93 '.mw-mwutiltest-head:hover { cursor: pointer; } ' // Header-clicks hide/show the below rows
96 mw
.test
.$table
= $( 'table#mw-mwutiltest-table' );
99 // Try to roughly keep the order similar to the order in the files
100 // or alphabetical (depending on the context)
102 // Main modules and their aliases
103 mw
.test
.addHead( 'Main modules and their aliases' );
105 mw
.test
.addTest( 'typeof mediaWiki',
108 mw
.test
.addTest( 'typeof mw',
111 mw
.test
.addTest( 'typeof jQuery',
112 'function (string)' );
114 mw
.test
.addTest( 'typeof $',
115 'function (string)' );
117 // Prototype functions added by MediaWiki
118 mw
.test
.addHead( 'Prototype functions added by MediaWiki' );
120 mw
.test
.addTest( 'typeof $.trimLeft',
121 'function (string)' );
123 mw
.test
.addTest( '$.trimLeft( " foo bar " )',
124 'foo bar (string)' );
126 mw
.test
.addTest( 'typeof $.trimRight',
127 'function (string)' );
129 mw
.test
.addTest( '$.trimRight( " foo bar " )',
130 ' foo bar (string)' );
132 mw
.test
.addTest( 'typeof $.ucFirst',
133 'function (string)' );
135 mw
.test
.addTest( '$.ucFirst( "mediawiki" )',
136 'Mediawiki (string)' );
138 mw
.test
.addTest( 'typeof $.escapeRE',
139 'function (string)' );
141 mw
.test
.addTest( '$.escapeRE( ".st{e}$st" )',
142 '\\.st\\{e\\}\\$st (string)' );
144 mw
.test
.addTest( 'typeof $.isEmpty',
145 'function (string)' );
147 mw
.test
.addTest( '$.isEmpty( "string" )',
150 mw
.test
.addTest( '$.isEmpty( "0" )',
153 mw
.test
.addTest( '$.isEmpty([])',
156 mw
.test
.addTest( 'typeof $.compareArray',
157 'function (string)' );
159 mw
.test
.addTest( '$.compareArray( [1, "a", [], [2, "b"] ], [1, "a", [], [2, "b"] ] )',
162 mw
.test
.addTest( '$.compareArray( [1], [2] )',
165 mw
.test
.addTest( 'typeof $.compareObject',
166 'function (string)' );
169 mw
.test
.addHead( 'mediawiki.js' );
171 mw
.test
.addTest( 'mw.config instanceof mw.Map',
174 mw
.test
.addTest( 'mw.config.exists()',
177 mw
.test
.addTest( 'mw.config.exists( "wgSomeName" )',
180 mw
.test
.addTest( 'mw.config.exists( ["wgCanonicalNamespace", "wgTitle"] )',
183 mw
.test
.addTest( 'mw.config.exists( ["wgSomeName", "wgTitle"] )',
186 mw
.test
.addTest( 'mw.config.get( "wgTitle" )',
187 'BlankPage (string)' );
189 mw
.test
.addTest( 'var a = mw.config.get( ["wgTitle"] ); a.wgTitle',
190 'BlankPage (string)' );
192 mw
.test
.addTest( 'typeof mw.html',
195 mw
.test
.addTest( 'mw.html.escape( \'<mw awesome="awesome">\' )',
196 '<mw awesome="awesome"> (string)' );
198 mw
.test
.addTest( 'mw.html.element( "hr" )',
201 mw
.test
.addTest( 'mw.html.element( "img", { "src": "http://mw.org/?title=Main page&action=edit" } )',
202 '<img src="http://mw.org/?title=Main page&action=edit"/> (string)' );
204 mw
.test
.addTest( 'typeof mw.loader',
207 mw
.test
.addTest( 'typeof mw.loader.using',
208 'function (string)' );
210 mw
.test
.addTest( 'typeof mw.Map',
211 'function (string)' );
213 mw
.test
.addTest( 'typeof mw.user',
216 mw
.test
.addTest( 'typeof mw.user.anonymous()',
217 'boolean (string)' );
220 mw
.test
.addHead( 'mediawiki.util.js' );
222 mw
.test
.addTest( 'typeof mw.util',
225 mw
.test
.addTest( 'typeof mw.util.rawurlencode',
226 'function (string)' );
228 mw
.test
.addTest( 'mw.util.rawurlencode( "Test:A & B/Here" )',
229 'Test%3AA%20%26%20B%2FHere (string)' );
231 mw
.test
.addTest( 'typeof mw.util.wikiUrlencode',
232 'function (string)' );
234 mw
.test
.addTest( 'mw.util.wikiUrlencode( "Test:A & B/Here" )',
235 'Test:A_%26_B/Here (string)' );
237 mw
.test
.addTest( 'typeof mw.util.addCSS',
238 'function (string)' );
240 mw
.test
.addTest( 'var a = mw.util.addCSS( ".plainlinks { color:green; }" ); a.disabled;',
244 mw
.test
.addTest( 'typeof mw.util.wikiGetlink',
245 'function (string)' );
247 mw
.test
.addTest( 'typeof mw.util.getParamValue',
248 'function (string)' );
250 mw
.test
.addTest( 'mw.util.getParamValue( "action" )',
251 'mwutiltest (string)' );
253 mw
.test
.addTest( 'mw.util.getParamValue( "foo", "http://mw.org/?foo=wrong&foo=right#&foo=bad" )',
256 mw
.test
.addTest( 'mw.util.tooltipAccessKeyRegexp.constructor.name',
259 mw
.test
.addTest( 'typeof mw.util.updateTooltipAccessKeys',
260 'function (string)' );
262 mw
.test
.addTest( 'mw.util.$content instanceof jQuery',
265 mw
.test
.addTest( 'mw.util.$content.size()',
268 mw
.test
.addTest( 'typeof mw.util.addPortletLink',
269 'function (string)' );
271 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" )',
274 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();',
275 'MediaWiki.org (string)' );
277 mw
.test
.addTest( 'typeof mw.util.jsMessage',
278 'function (string)' );
280 mw
.test
.addTest( 'mw.util.jsMessage( mw.config.get( "wgSiteName" ) + " is <b>Awesome</b>." )',
283 // TODO: Import tests from PHPUnit test suite for user::isValidEmailAddr
284 mw
.test
.addTest( 'mw.util.validateEmail( "" )',
287 mw
.test
.addTest( 'mw.util.validateEmail( "user@localhost" )',
290 // testEmailWithCommasAreInvalids
291 mw
.test
.addTest( 'mw.util.validateEmail( "user,foo@example.org" )',
293 mw
.test
.addTest( 'mw.util.validateEmail( "userfoo@ex,ample.org" )',
295 // testEmailWithHyphens
296 mw
.test
.addTest( 'mw.util.validateEmail( "user-foo@example.org" )',
298 mw
.test
.addTest( 'mw.util.validateEmail( "userfoo@ex-ample.org" )',
302 mw
.test
.addHead( 'jQuery plugins' );
304 mw
.test
.addTest( 'typeof $.client',
307 mw
.test
.addTest( 'typeof $.client.profile',
308 'function (string)' );
310 mw
.test
.addTest( 'var a = $.client.profile(); typeof a.name',
313 mw
.test
.addTest( 'typeof $.fn.makeCollapsible',
314 'function (string)' );
318 mw
.test
.addHead( '*** End of tests ***' );
320 // Run tests and compare results
326 numberOfPartials
= 0,
328 headNumberOfTests
= 0,
329 headNumberOfPasseds
= 0,
330 headNumberOfPartials
= 0,
331 headNumberOfErrors
= 0,
333 previousHeadTitle
= '',
334 $testrows
= mw
.test
.$table
.find( 'tr:has(td)' );
336 $.each( mw
.test
.addedTests
, function( i
, item
) {
339 if( item
[0] == 'HEADER' ) {
341 // update current header with its tests results
342 mw
.test
.$table
.find( 'tr#mw-mwutiltest-head' + numberOfHeaders
+' > th' )
343 .html( previousHeadTitle
+ ' <span style="float:right">('
344 + 'T: ' + headNumberOfTests
345 + ' ok: ' + headNumberOfPasseds
346 + ' partial: ' + headNumberOfPartials
347 + ' err: ' + headNumberOfErrors
351 // Reset values for the new header;
352 headNumberOfTests
= 0;
353 headNumberOfPasseds
= 0;
354 headNumberOfPartials
= 0;
355 headNumberOfErrors
= 0;
357 previousHeadTitle
= item
[1];
363 shouldreturn
= item
[1];
364 shouldcontain
= item
[2];
368 doesReturn
= eval( exec
);
369 doesReturn
= doesReturn
+ ' (' + typeof doesReturn
+ ')';
370 $thisrow
= $testrows
.eq( i
- numberOfHeaders
); // since headers are rows as well
371 $thisrow
.find( '> td' ).eq(2).html( mw
.html
.escape( doesReturn
).replace(/ /g
, ' ' ) );
373 if ( doesReturn
.indexOf( shouldcontain
) !== -1 ) {
374 if ( doesReturn
== shouldreturn
) {
375 $thisrow
.find( '> td' ).eq(3).css( 'background', '#AFA' ).text( 'OK' );
377 headNumberOfPasseds
++;
379 $thisrow
.find( '> td' ).eq(3).css( 'background', '#FFA' ).html( '<small>PARTIALLY</small>' );
381 headNumberOfPartials
++;
384 $thisrow
.find( '> td' ).eq(3).css( 'background', '#FAA' ).text( 'ERROR' );
386 headNumberOfErrors
++;
390 mw
.test
.$table
.before( '<p><strong>Ran ' + numberOfTests
+ ' tests. ' +
391 numberOfPasseds
+ ' passed test(s). ' + numberOfErrors
+ ' error(s). ' +
392 numberOfPartials
+ ' partially passed test(s). </p>' );
394 // hide all tests. TODO hide only OK?
395 mw
.test
.$table
.find( '.mw-mwutiltest-test' ).hide();
396 // clickable header to show/hide the tests
397 mw
.test
.$table
.find( '.mw-mwutiltest-head' ).click(function() {
398 $(this).nextUntil( '.mw-mwutiltest-head' ).toggle();
408 } )(jQuery
, mediaWiki
);