Follow-up r87176 use wfLocalFile instead of wfFindFile
[lhc/web/wiklou.git] / resources / mediawiki.util / mediawiki.util.test.js
1 /**
2 * mediaWiki JavaScript library test suite
3 *
4 * Available on Special:BlankPage?action=mwutiltest&debug=true
5 *
6 * @author Krinkle <krinklemail@gmail.com>
7 */
8
9 ( function( $, mw ) {
10
11 mw.test = {
12
13 /* Variables */
14 '$table' : null,
15 // contains either a header or a test
16 // test: [ code, result, contain ] see addTest
17 // header: [ 'HEADER', escapedtitle, id ] see addHead
18 'addedTests' : [],
19 'headResults' : [],
20 'numberOfHeader' : 0,
21
22 /* Functions */
23
24 /**
25 * Adds a row to the test-table
26 *
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
31 */
32 'addTest' : function( code, result, contain ) {
33 if ( !contain ) {
34 contain = result;
35 }
36 this.addedTests.push( [code, result, contain] );
37 this.$table.append( '<tr class="mw-mwutiltest-test">'
38 + '<td>' + mw.html.escape( code ).replace( / /g, '&nbsp;&nbsp;' )
39 + '</td><td>' + mw.html.escape( result ).replace( / /g, '&nbsp;&nbsp;' )
40 + '</td><td></td><td>?</td></tr>' );
41 return true;
42 },
43
44 /**
45 * Adds a heading to the test-table
46 *
47 * @param title String Title of the section
48 */
49 'addHead' : function( title ) {
50 if ( !title ) {
51 return false;
52 }
53 var escapedtitle = mw.html.escape( title ).replace( / /g, '&nbsp;&nbsp;' );
54 this.addedTests.push( [ 'HEADER', escapedtitle, mw.test.numberOfHeader++ ] );
55 this.$table.append(
56 '<tr class="mw-mwutiltest-head" id="mw-mwutiltest-head'
57 + mw.test.numberOfHeader + '"><th colspan="4">'
58 + escapedtitle + '</th></tr>'
59 );
60 return true;
61 },
62
63 /* Initialisation */
64 'initialised' : false,
65 'init' : function() {
66 if ( this.initialised === false ) {
67 this.initialised = true;
68
69 $(document).ready( function() {
70 if ( mw.config.get( 'wgCanonicalSpecialPageName' ) == 'Blankpage'
71 && mw.util.getParamValue( 'action' ) === 'mwutiltest' ) {
72
73 // Build page
74 document.title = 'mediaWiki JavaScript library test suite - ' + mw.config.get( 'wgSiteName' );
75 $( '#firstHeading' ).text( 'mediaWiki JavaScript library test suite' );
76 var skinLinksHtml = 'Test in: ',
77 skinLinks = [],
78 availableSkins = mw.config.get( 'wgAvailableSkins' ),
79 skincode = '';
80 for ( skincode in availableSkins ) {
81 skinLinks.push(
82 mw.html.element(
83 'a', {
84 'href': mw.util.wikiGetlink( mw.config.get( 'wgPageName' ) )
85 + '?action=mwutiltest&debug=true&useskin=' + encodeURIComponent( skincode )
86 },
87 availableSkins[skincode]
88 )
89 );
90 }
91 skinLinksHtml += skinLinks.join( ' | ' ) + '.';
92 mw.util.$content.html(
93 '<p>Below is a list of tests to confirm proper functionality of the mediaWiki JavaScript library</p>'
94 + '<p>' + skinLinksHtml + '</p>'
95 + '<hr />'
96 + '<table id="mw-mwutiltest-table" class="wikitable"'
97 + ' style="white-space:break; font-family:monospace,\'Courier New\'; width:100%;">'
98 + '<tr><th>Exec</th><th>Should return</th><th>Does return</th><th>Equal ?</th></tr>'
99 + '</table>'
100 );
101
102 mw.util.addCSS(
103 // Override wikitable padding for <td>
104 '#mw-mwutiltest-table tr td { padding:0 !important; }'
105 );
106
107 mw.test.$table = $( 'table#mw-mwutiltest-table' );
108
109 /* Populate tests */
110 // Try to roughly keep the order similar to the order in the files
111 // or alphabetical (depending on the context)
112
113 /** Main modules and their aliases **/
114 mw.test.addHead( 'Main modules and their aliases' );
115
116 mw.test.addTest( 'typeof mediaWiki',
117 'object (string)' );
118
119 mw.test.addTest( 'typeof mw',
120 'object (string)' );
121
122 mw.test.addTest( 'typeof jQuery',
123 'function (string)' );
124
125 mw.test.addTest( 'typeof $',
126 'function (string)' );
127
128 /** Prototype functions added by MediaWiki **/
129 mw.test.addHead( 'Prototype functions added by MediaWiki' );
130
131 mw.test.addTest( 'typeof $.trimLeft',
132 'function (string)' );
133
134 mw.test.addTest( '$.trimLeft( " foo bar " )',
135 'foo bar (string)' );
136
137 mw.test.addTest( 'typeof $.trimRight',
138 'function (string)' );
139
140 mw.test.addTest( '$.trimRight( " foo bar " )',
141 ' foo bar (string)' );
142
143 mw.test.addTest( 'typeof $.ucFirst',
144 'function (string)' );
145
146 mw.test.addTest( '$.ucFirst( "mediawiki" )',
147 'Mediawiki (string)' );
148
149 mw.test.addTest( 'typeof $.escapeRE',
150 'function (string)' );
151
152 mw.test.addTest( '$.escapeRE( "<!-- ([{+mW+}]) $^|?>" )',
153 '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?> (string)' ); // double escaped
154
155 mw.test.addTest( '$.escapeRE( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" )',
156 'ABCDEFGHIJKLMNOPQRSTUVWXYZ (string)' );
157
158 mw.test.addTest( '$.escapeRE( "abcdefghijklmnopqrstuvwxyz" )',
159 'abcdefghijklmnopqrstuvwxyz (string)' );
160
161 mw.test.addTest( '$.escapeRE( "0123456789" )',
162 '0123456789 (string)' );
163
164 mw.test.addTest( '$.isDomElement( document.getElementById("mw-mwutiltest-table") )',
165 'true (boolean)' );
166
167 mw.test.addTest( '$.isDomElement( document.getElementById("not-existant-id") )',
168 'false (boolean)' ); // returns null
169
170 mw.test.addTest( '$.isDomElement( document.getElementsByClassName("wikitable") )',
171 'false (boolean)' ); // returns an array
172
173 mw.test.addTest( '$.isDomElement( document.getElementsByClassName("wikitable")[0] )',
174 'true (boolean)' );
175
176 mw.test.addTest( '$.isDomElement( jQuery( "#mw-mwutiltest-table" ) )',
177 'false (boolean)' ); // returns jQuery object
178
179 mw.test.addTest( '$.isDomElement( jQuery( "#mw-mwutiltest-table" ).get(0) )',
180 'true (boolean)' );
181
182 mw.test.addTest( '$.isDomElement( document.createElement( "div" ) )',
183 'true (boolean)' );
184
185 mw.test.addTest( '$.isDomElement( {some: "thing" } )',
186 'false (boolean)' );
187
188 mw.test.addTest( 'typeof $.isEmpty',
189 'function (string)' );
190
191 mw.test.addTest( '$.isEmpty( "string" )',
192 'false (boolean)' );
193
194 mw.test.addTest( '$.isEmpty( "0" )',
195 'true (boolean)' );
196
197 mw.test.addTest( '$.isEmpty([])',
198 'true (boolean)' );
199
200 mw.test.addTest( 'typeof $.compareArray',
201 'function (string)' );
202
203 mw.test.addTest( '$.compareArray( [1, "a", [], [2, "b"] ], [1, "a", [], [2, "b"] ] )',
204 'true (boolean)' );
205
206 mw.test.addTest( '$.compareArray( [1], [2] )',
207 'false (boolean)' );
208
209 mw.test.addTest( 'typeof $.compareObject',
210 'function (string)' );
211
212 /** mediawiki.js **/
213 mw.test.addHead( 'mediawiki.js' );
214
215 mw.test.addTest( 'mw.config instanceof mw.Map',
216 'true (boolean)' );
217
218 mw.test.addTest( 'mw.config.exists()',
219 'true (boolean)' );
220
221 mw.test.addTest( 'mw.config.exists( "wgSomeName" )',
222 'false (boolean)' );
223
224 mw.test.addTest( 'mw.config.exists( ["wgCanonicalNamespace", "wgTitle"] )',
225 'true (boolean)' );
226
227 mw.test.addTest( 'mw.config.exists( ["wgSomeName", "wgTitle"] )',
228 'false (boolean)' );
229
230 mw.test.addTest( 'mw.config.get( "wgCanonicalNamespace" )',
231 'Special (string)' );
232
233 mw.test.addTest( 'var a = mw.config.get( ["wgCanonicalNamespace"] ); a.wgCanonicalNamespace',
234 'Special (string)' );
235
236 mw.test.addTest( 'typeof mw.html',
237 'object (string)' );
238
239 mw.test.addTest( 'mw.html.escape( \'<mw awesome="awesome">\' )',
240 '&lt;mw awesome=&quot;awesome&quot;&gt; (string)' );
241
242 mw.test.addTest( 'mw.html.element( "hr" )',
243 '<hr/> (string)' );
244
245 mw.test.addTest( 'mw.html.element( "img", { "src": "http://mw.org/?title=Main page&action=edit" } )',
246 '<img src="http://mw.org/?title=Main page&amp;action=edit"/> (string)' );
247
248 mw.test.addTest( 'typeof mw.loader',
249 'object (string)' );
250
251 mw.test.addTest( 'typeof mw.loader.using',
252 'function (string)' );
253
254 mw.test.addTest( 'typeof mw.Map',
255 'function (string)' );
256
257 mw.test.addTest( 'typeof mw.user',
258 'object (string)' );
259
260 mw.test.addTest( 'typeof mw.user.anonymous()',
261 'boolean (string)' );
262
263 /** mediawiki.util.js **/
264 mw.test.addHead( 'mediawiki.util.js' );
265
266 mw.test.addTest( 'typeof mw.util',
267 'object (string)' );
268
269 mw.test.addTest( 'typeof mw.util.rawurlencode',
270 'function (string)' );
271
272 mw.test.addTest( 'mw.util.rawurlencode( "Test:A & B/Here" )',
273 'Test%3AA%20%26%20B%2FHere (string)' );
274
275 mw.test.addTest( 'typeof mw.util.wikiUrlencode',
276 'function (string)' );
277
278 mw.test.addTest( 'mw.util.wikiUrlencode( "Test:A & B/Here" )',
279 'Test:A_%26_B/Here (string)' );
280
281 mw.test.addTest( 'typeof mw.util.addCSS',
282 'function (string)' );
283
284 mw.test.addTest( 'var a = mw.util.addCSS( "div#mw-js-message { background-color: rgb(170,255,170); }" ); a.disabled',
285 'false (boolean)' );
286
287 mw.test.addTest( 'typeof mw.util.toggleToc',
288 'function (string)' );
289
290 mw.test.addTest( 'typeof mw.util.wikiGetlink',
291 'function (string)' );
292
293 mw.test.addTest( 'typeof mw.util.getParamValue',
294 'function (string)' );
295
296 mw.test.addTest( 'mw.util.getParamValue( "action" )',
297 'mwutiltest (string)' );
298
299 mw.test.addTest( 'mw.util.getParamValue( "foo", "http://mw.org/?foo=wrong&foo=right#&foo=bad" )',
300 'right (string)' );
301
302 mw.test.addTest( 'typeof mw.util.tooltipAccessKeyPrefix',
303 'string (string)' );
304
305 mw.test.addTest( 'mw.util.tooltipAccessKeyRegexp.constructor.name',
306 'RegExp (string)' );
307
308 mw.test.addTest( 'typeof mw.util.updateTooltipAccessKeys',
309 'function (string)' );
310
311 mw.test.addTest( 'mw.util.$content instanceof jQuery',
312 'true (boolean)' );
313
314 mw.test.addTest( 'mw.util.$content.size()',
315 '1 (number)' );
316
317 mw.test.addTest( 'typeof mw.util.addPortletLink',
318 'function (string)' );
319
320 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" )',
321 'object (string)' );
322
323 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();',
324 'MediaWiki.org (string)' );
325
326 mw.test.addTest( 'typeof mw.util.addPortletLink( "p-tb", "http://www.mediawiki.org/wiki/ResourceLoader/Default_modules", "Default modules", "t-rl", "All default modules present in MediaWiki" )',
327 'object (string)' );
328
329 mw.test.addTest( 'typeof mw.util.jsMessage',
330 'function (string)' );
331
332 mw.test.addTest( 'mw.util.jsMessage( mw.config.get( "wgSiteName" ) + " is <b>Awesome</b>." )',
333 'true (boolean)' );
334
335 mw.test.addTest( 'jQuery( "#mw-js-message" ).css( "background-color" )',
336 'rgb(170, 255, 170) (string)' );
337
338 // TODO: Import tests from PHPUnit test suite for user::isValidEmailAddr
339 mw.test.addTest( 'mw.util.validateEmail( "" )',
340 'null (object)' );
341
342 mw.test.addTest( 'mw.util.validateEmail( "user@localhost" )',
343 'true (boolean)' );
344
345 // testEmailWithCommasAreInvalids
346 mw.test.addTest( 'mw.util.validateEmail( "user,foo@example.org" )',
347 'false (boolean)' );
348 mw.test.addTest( 'mw.util.validateEmail( "userfoo@ex,ample.org" )',
349 'false (boolean)' );
350 // testEmailWithHyphens
351 mw.test.addTest( 'mw.util.validateEmail( "user-foo@example.org" )',
352 'true (boolean)' );
353 mw.test.addTest( 'mw.util.validateEmail( "userfoo@ex-ample.org" )',
354 'true (boolean)' );
355
356 // From IPTest.php IPv6
357 mw.test.addTest( 'mw.util.isIPv6Address( "" )',
358 'false (boolean)' );
359 mw.test.addTest( 'mw.util.isIPv6Address( ":fc:100::" )',
360 'false (boolean)' );
361 mw.test.addTest( 'mw.util.isIPv6Address( "fc:100::" )',
362 'true (boolean)' );
363 mw.test.addTest( 'mw.util.isIPv6Address( "fc:100:a:d:1:e:ac::" )',
364 'true (boolean)' );
365 mw.test.addTest( 'mw.util.isIPv6Address( ":::" )',
366 'false (boolean)' );
367 mw.test.addTest( 'mw.util.isIPv6Address( "::0:" )',
368 'false (boolean)' );
369
370 // From IPTest.php IPv4
371 mw.test.addTest( 'mw.util.isIPv4Address( "" )',
372 'false (boolean)' );
373 mw.test.addTest( 'mw.util.isIPv4Address( "...." )',
374 'false (boolean)' );
375 mw.test.addTest( 'mw.util.isIPv4Address( "abc" )',
376 'false (boolean)' );
377 mw.test.addTest( 'mw.util.isIPv4Address( "124.24.52" )',
378 'false (boolean)' );
379 mw.test.addTest( 'mw.util.isIPv4Address( ".24.52.13" )',
380 'false (boolean)' );
381 mw.test.addTest( 'mw.util.isIPv4Address( "124.24.52.13" )',
382 'true (boolean)' );
383 mw.test.addTest( 'mw.util.isIPv4Address( "1.24.52.13" )',
384 'true (boolean)' );
385 mw.test.addTest( 'mw.util.isIPv4Address( "74.24.52.13/20" )', // Range
386 'false (boolean)' );
387 // @FIXME: The regex that's been in MW JS has never supported ranges but it should
388 // The regex is expected to return false for that reason
389
390 // jQuery plugins
391 mw.test.addHead( 'jQuery plugins' );
392
393 mw.test.addTest( 'typeof $.client',
394 'object (string)' );
395
396 mw.test.addTest( 'typeof $.client.profile',
397 'function (string)' );
398
399 mw.test.addTest( 'var a = $.client.profile(); typeof a.name',
400 'string (string)' );
401
402 mw.test.addTest( 'typeof $.fn.makeCollapsible',
403 'function (string)' );
404
405
406 // End of tests.
407 mw.test.addHead( '*** End of tests ***' );
408
409 // Run tests and compare results
410 var exec,
411 result,
412 resulttype,
413 numberOfTests = 0,
414 numberOfPasseds = 0,
415 numberOfPartials = 0,
416 numberOfErrors = 0,
417 headNumberOfTests = 0,
418 headNumberOfPasseds = 0,
419 headNumberOfPartials = 0,
420 headNumberOfErrors = 0,
421 numberOfHeaders = 0,
422 previousHeadTitle = '',
423 $testrows = mw.test.$table.find( 'tr:has(td)' );
424
425 $.each( mw.test.addedTests, function( i, item ) {
426
427 // New header
428 if( item[0] == 'HEADER' ) {
429
430 // update current header with its tests results
431 mw.test.$table.find( 'tr#mw-mwutiltest-head' + numberOfHeaders +' > th' )
432 .html( previousHeadTitle + ' <span style="float:right">('
433 + 'Tests: ' + headNumberOfTests
434 + ' OK: ' + headNumberOfPasseds
435 + ' Partial: ' + headNumberOfPartials
436 + ' Error: ' + headNumberOfErrors
437 + ')</span>' );
438
439 numberOfHeaders++;
440 // Reset values for the new header;
441 headNumberOfTests = 0;
442 headNumberOfPasseds = 0;
443 headNumberOfPartials = 0;
444 headNumberOfErrors = 0;
445
446 previousHeadTitle = item[1];
447
448 return true;
449 }
450
451 exec = item[0];
452 var shouldreturn = item[1];
453 var shouldcontain = item[2];
454
455 numberOfTests++;
456 headNumberOfTests++;
457 try {
458 var doesReturn = eval( exec );
459 } catch (e){
460 mw.log ('mw.util.test> ' + e );
461 }
462 doesReturn = doesReturn + ' (' + typeof doesReturn + ')';
463 var $thisrow = $testrows.eq( i - numberOfHeaders ); // since headers are rows as well
464 $thisrow.find( '> td' )
465 .eq(2)
466 .html( mw.html.escape( doesReturn ).replace(/ /g, '&nbsp;&nbsp;' ) );
467
468 if ( doesReturn.indexOf( shouldcontain ) !== -1 ) {
469 if ( doesReturn == shouldreturn ) {
470 $thisrow.find( '>td' ).eq(3).css( 'background', '#AFA' ).text( 'OK' );
471 numberOfPasseds++;
472 headNumberOfPasseds++;
473 } else {
474 $thisrow.find( '>td' ).eq(3).css( 'background', '#FFA' ).html( '<small>PARTIALLY</small>' );
475 numberOfPartials++;
476 headNumberOfPartials++;
477 }
478 } else {
479 $thisrow.css( 'background', '#FAA' ).find( '>td' ).eq(3).text( 'ERROR' );
480 numberOfErrors++;
481 headNumberOfErrors++;
482 }
483
484 } );
485 mw.test.$table.before( '<p><strong>Ran ' + numberOfTests + ' tests. ' +
486 numberOfPasseds + ' passed test(s). ' + numberOfErrors + ' error(s). ' +
487 numberOfPartials + ' partially passed test(s). </p>' );
488
489 }
490 } );
491 }
492 }
493 };
494
495 mw.test.init();
496
497 } )(jQuery, mediaWiki);