removing another use of the vertical tab & form feed escapes, which are not available...
[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 escapedtitle = mw.html.escape( title ).replace( / /g, '&nbsp;&nbsp;' );
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>' );
56 return true;
57 },
58
59 /* Initialisation */
60 'initialised' : false,
61 'init' : function() {
62 if ( this.initialised === false ) {
63 this.initialised = true;
64 // jQuery document ready
65 $( function() {
66 if ( mw.config.get( 'wgCanonicalSpecialPageName' ) == 'Blankpage'
67 && mw.util.getParamValue( 'action' ) === 'mwutiltest' ) {
68
69 // Build page
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: ',
73 skinLinks = [],
74 availableSkins = mw.config.get( 'wgAvailableSkins' ),
75 skincode = '';
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] ) );
80 }
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>'
85 + '<hr />'
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>'
88 + '</table>'
89 );
90
91 mw.util.addCSS(
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
94 );
95
96 mw.test.$table = $( 'table#mw-mwutiltest-table' );
97
98 /* Populate tests */
99 // Try to roughly keep the order similar to the order in the files
100 // or alphabetical (depending on the context)
101
102 /** Main modules and their aliases **/
103 mw.test.addHead( 'Main modules and their aliases' );
104
105 mw.test.addTest( 'typeof mediaWiki',
106 'object (string)' );
107
108 mw.test.addTest( 'typeof mw',
109 'object (string)' );
110
111 mw.test.addTest( 'typeof jQuery',
112 'function (string)' );
113
114 mw.test.addTest( 'typeof $',
115 'function (string)' );
116
117 /** Prototype functions added by MediaWiki **/
118 mw.test.addHead( 'Prototype functions added by MediaWiki' );
119
120 mw.test.addTest( 'typeof $.trimLeft',
121 'function (string)' );
122
123 mw.test.addTest( '$.trimLeft( " foo bar " )',
124 'foo bar (string)' );
125
126 mw.test.addTest( 'typeof $.trimRight',
127 'function (string)' );
128
129 mw.test.addTest( '$.trimRight( " foo bar " )',
130 ' foo bar (string)' );
131
132 mw.test.addTest( 'typeof $.ucFirst',
133 'function (string)' );
134
135 mw.test.addTest( '$.ucFirst( "mediawiki" )',
136 'Mediawiki (string)' );
137
138 mw.test.addTest( 'typeof $.escapeRE',
139 'function (string)' );
140
141 mw.test.addTest( '$.escapeRE( "<!-- ([{+mW+}]) $^|?>" )',
142 '<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?> (string)' ); // double escaped
143
144 mw.test.addTest( '$.escapeRE( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" )',
145 'ABCDEFGHIJKLMNOPQRSTUVWXYZ (string)' );
146
147 mw.test.addTest( '$.escapeRE( "abcdefghijklmnopqrstuvwxyz" )',
148 'abcdefghijklmnopqrstuvwxyz (string)' );
149
150 mw.test.addTest( '$.escapeRE( "0123456789" )',
151 '0123456789 (string)' );
152
153 mw.test.addTest( 'typeof $.isEmpty',
154 'function (string)' );
155
156 mw.test.addTest( '$.isEmpty( "string" )',
157 'false (boolean)' );
158
159 mw.test.addTest( '$.isEmpty( "0" )',
160 'true (boolean)' );
161
162 mw.test.addTest( '$.isEmpty([])',
163 'true (boolean)' );
164
165 mw.test.addTest( 'typeof $.compareArray',
166 'function (string)' );
167
168 mw.test.addTest( '$.compareArray( [1, "a", [], [2, "b"] ], [1, "a", [], [2, "b"] ] )',
169 'true (boolean)' );
170
171 mw.test.addTest( '$.compareArray( [1], [2] )',
172 'false (boolean)' );
173
174 mw.test.addTest( 'typeof $.compareObject',
175 'function (string)' );
176
177 /** mediawiki.js **/
178 mw.test.addHead( 'mediawiki.js' );
179
180 mw.test.addTest( 'mw.config instanceof mw.Map',
181 'true (boolean)' );
182
183 mw.test.addTest( 'mw.config.exists()',
184 'true (boolean)' );
185
186 mw.test.addTest( 'mw.config.exists( "wgSomeName" )',
187 'false (boolean)' );
188
189 mw.test.addTest( 'mw.config.exists( ["wgCanonicalNamespace", "wgTitle"] )',
190 'true (boolean)' );
191
192 mw.test.addTest( 'mw.config.exists( ["wgSomeName", "wgTitle"] )',
193 'false (boolean)' );
194
195 mw.test.addTest( 'mw.config.get( "wgTitle" )',
196 'BlankPage (string)' );
197
198 mw.test.addTest( 'var a = mw.config.get( ["wgTitle"] ); a.wgTitle',
199 'BlankPage (string)' );
200
201 mw.test.addTest( 'typeof mw.html',
202 'object (string)' );
203
204 mw.test.addTest( 'mw.html.escape( \'<mw awesome="awesome">\' )',
205 '&lt;mw awesome=&quot;awesome&quot;&gt; (string)' );
206
207 mw.test.addTest( 'mw.html.element( "hr" )',
208 '<hr/> (string)' );
209
210 mw.test.addTest( 'mw.html.element( "img", { "src": "http://mw.org/?title=Main page&action=edit" } )',
211 '<img src="http://mw.org/?title=Main page&amp;action=edit"/> (string)' );
212
213 mw.test.addTest( 'typeof mw.loader',
214 'object (string)' );
215
216 mw.test.addTest( 'typeof mw.loader.using',
217 'function (string)' );
218
219 mw.test.addTest( 'typeof mw.Map',
220 'function (string)' );
221
222 mw.test.addTest( 'typeof mw.user',
223 'object (string)' );
224
225 mw.test.addTest( 'typeof mw.user.anonymous()',
226 'boolean (string)' );
227
228 /** mediawiki.util.js **/
229 mw.test.addHead( 'mediawiki.util.js' );
230
231 mw.test.addTest( 'typeof mw.util',
232 'object (string)' );
233
234 mw.test.addTest( 'typeof mw.util.rawurlencode',
235 'function (string)' );
236
237 mw.test.addTest( 'mw.util.rawurlencode( "Test:A & B/Here" )',
238 'Test%3AA%20%26%20B%2FHere (string)' );
239
240 mw.test.addTest( 'typeof mw.util.wikiUrlencode',
241 'function (string)' );
242
243 mw.test.addTest( 'mw.util.wikiUrlencode( "Test:A & B/Here" )',
244 'Test:A_%26_B/Here (string)' );
245
246 mw.test.addTest( 'typeof mw.util.addCSS',
247 'function (string)' );
248
249 mw.test.addTest( 'var a = mw.util.addCSS( ".plainlinks { color:green; }" ); a.disabled;',
250 'false (boolean)',
251 '(boolean)' );
252
253 mw.test.addTest( 'typeof mw.util.wikiGetlink',
254 'function (string)' );
255
256 mw.test.addTest( 'typeof mw.util.getParamValue',
257 'function (string)' );
258
259 mw.test.addTest( 'mw.util.getParamValue( "action" )',
260 'mwutiltest (string)' );
261
262 mw.test.addTest( 'mw.util.getParamValue( "foo", "http://mw.org/?foo=wrong&foo=right#&foo=bad" )',
263 'right (string)' );
264
265 mw.test.addTest( 'mw.util.tooltipAccessKeyRegexp.constructor.name',
266 'RegExp (string)' );
267
268 mw.test.addTest( 'typeof mw.util.updateTooltipAccessKeys',
269 'function (string)' );
270
271 mw.test.addTest( 'mw.util.$content instanceof jQuery',
272 'true (boolean)' );
273
274 mw.test.addTest( 'mw.util.$content.size()',
275 '1 (number)' );
276
277 mw.test.addTest( 'typeof mw.util.addPortletLink',
278 'function (string)' );
279
280 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" )',
281 'object (string)' );
282
283 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();',
284 'MediaWiki.org (string)' );
285
286 mw.test.addTest( 'typeof mw.util.jsMessage',
287 'function (string)' );
288
289 mw.test.addTest( 'mw.util.jsMessage( mw.config.get( "wgSiteName" ) + " is <b>Awesome</b>." )',
290 'true (boolean)' );
291
292 // TODO: Import tests from PHPUnit test suite for user::isValidEmailAddr
293 mw.test.addTest( 'mw.util.validateEmail( "" )',
294 'null (object)' );
295
296 mw.test.addTest( 'mw.util.validateEmail( "user@localhost" )',
297 'true (boolean)' );
298
299 // testEmailWithCommasAreInvalids
300 mw.test.addTest( 'mw.util.validateEmail( "user,foo@example.org" )',
301 'false (boolean)' );
302 mw.test.addTest( 'mw.util.validateEmail( "userfoo@ex,ample.org" )',
303 'false (boolean)' );
304 // testEmailWithHyphens
305 mw.test.addTest( 'mw.util.validateEmail( "user-foo@example.org" )',
306 'true (boolean)' );
307 mw.test.addTest( 'mw.util.validateEmail( "userfoo@ex-ample.org" )',
308 'true (boolean)' );
309
310 // From IPTest.php IPv6
311 mw.test.addTest( 'mw.util.isIPv6Address( "" )',
312 'false (boolean)' );
313 mw.test.addTest( 'mw.util.isIPv6Address( ":fc:100::" )',
314 'false (boolean)' );
315 mw.test.addTest( 'mw.util.isIPv6Address( "fc:100::" )',
316 'true (boolean)' );
317 mw.test.addTest( 'mw.util.isIPv6Address( "fc:100:a:d:1:e:ac::" )',
318 'true (boolean)' );
319 mw.test.addTest( 'mw.util.isIPv6Address( ":::" )',
320 'false (boolean)' );
321 mw.test.addTest( 'mw.util.isIPv6Address( "::0:" )',
322 'false (boolean)' );
323
324 // From IPTest.php IPv4
325 mw.test.addTest( 'mw.util.isIPv4Address( "" )',
326 'false (boolean)' );
327 mw.test.addTest( 'mw.util.isIPv4Address( "...." )',
328 'false (boolean)' );
329 mw.test.addTest( 'mw.util.isIPv4Address( "abc" )',
330 'false (boolean)' );
331 mw.test.addTest( 'mw.util.isIPv4Address( "124.24.52" )',
332 'false (boolean)' );
333 mw.test.addTest( 'mw.util.isIPv4Address( ".24.52.13" )',
334 'false (boolean)' );
335 mw.test.addTest( 'mw.util.isIPv4Address( "124.24.52.13" )',
336 'true (boolean)' );
337 mw.test.addTest( 'mw.util.isIPv4Address( "1.24.52.13" )',
338 'true (boolean)' );
339 mw.test.addTest( 'mw.util.isIPv4Address( "74.24.52.13/20" )', // Range
340 'false (boolean)' );
341 // @FIXME: The regex that's been in MW JS has never supported ranges but it should
342 // The regex is expected to return false for that reason
343
344 // jQuery plugins
345 mw.test.addHead( 'jQuery plugins' );
346
347 mw.test.addTest( 'typeof $.client',
348 'object (string)' );
349
350 mw.test.addTest( 'typeof $.client.profile',
351 'function (string)' );
352
353 mw.test.addTest( 'var a = $.client.profile(); typeof a.name',
354 'string (string)' );
355
356 mw.test.addTest( 'typeof $.fn.makeCollapsible',
357 'function (string)' );
358
359
360 // End of tests.
361 mw.test.addHead( '*** End of tests ***' );
362
363 // Run tests and compare results
364 var exec,
365 result,
366 resulttype,
367 numberOfTests = 0,
368 numberOfPasseds = 0,
369 numberOfPartials = 0,
370 numberOfErrors = 0,
371 headNumberOfTests = 0,
372 headNumberOfPasseds = 0,
373 headNumberOfPartials = 0,
374 headNumberOfErrors = 0,
375 numberOfHeaders = 0,
376 previousHeadTitle = '',
377 $testrows = mw.test.$table.find( 'tr:has(td)' );
378
379 $.each( mw.test.addedTests, function( i, item ) {
380
381 // New header
382 if( item[0] == 'HEADER' ) {
383
384 // update current header with its tests results
385 mw.test.$table.find( 'tr#mw-mwutiltest-head' + numberOfHeaders +' > th' )
386 .html( previousHeadTitle + ' <span style="float:right">('
387 + 'Tests: ' + headNumberOfTests
388 + ' OK: ' + headNumberOfPasseds
389 + ' Partial: ' + headNumberOfPartials
390 + ' Error: ' + headNumberOfErrors
391 + ')</span>' );
392
393 numberOfHeaders++;
394 // Reset values for the new header;
395 headNumberOfTests = 0;
396 headNumberOfPasseds = 0;
397 headNumberOfPartials = 0;
398 headNumberOfErrors = 0;
399
400 previousHeadTitle = item[1];
401
402 return true;
403 }
404
405 exec = item[0];
406 shouldreturn = item[1];
407 shouldcontain = item[2];
408
409 numberOfTests++;
410 headNumberOfTests++;
411 doesReturn = eval( exec );
412 doesReturn = doesReturn + ' (' + typeof doesReturn + ')';
413 $thisrow = $testrows.eq( i - numberOfHeaders ); // since headers are rows as well
414 $thisrow.find( '> td' ).eq(2).html( mw.html.escape( doesReturn ).replace(/ /g, '&nbsp;&nbsp;' ) );
415
416 if ( doesReturn.indexOf( shouldcontain ) !== -1 ) {
417 if ( doesReturn == shouldreturn ) {
418 $thisrow.find( '> td' ).eq(3).css( 'background', '#AFA' ).text( 'OK' );
419 numberOfPasseds++;
420 headNumberOfPasseds++;
421 } else {
422 $thisrow.find( '> td' ).eq(3).css( 'background', '#FFA' ).html( '<small>PARTIALLY</small>' );
423 numberOfPartials++;
424 headNumberOfPartials++;
425 }
426 } else {
427 $thisrow.find( '> td' ).eq(3).css( 'background', '#FAA' ).text( 'ERROR' );
428 numberOfErrors++;
429 headNumberOfErrors++;
430 }
431
432 } );
433 mw.test.$table.before( '<p><strong>Ran ' + numberOfTests + ' tests. ' +
434 numberOfPasseds + ' passed test(s). ' + numberOfErrors + ' error(s). ' +
435 numberOfPartials + ' partially passed test(s). </p>' );
436
437 // hide all tests. TODO hide only OK?
438 mw.test.$table.find( '.mw-mwutiltest-test' ).hide();
439 // clickable header to show/hide the tests
440 mw.test.$table.find( '.mw-mwutiltest-head' ).click(function() {
441 $(this).nextUntil( '.mw-mwutiltest-head' ).toggle();
442 });
443 }
444 } );
445 }
446 }
447 };
448
449 mw.test.init();
450
451 } )(jQuery, mediaWiki);