Localisation updates from http://translatewiki.net.
[mediawiki.git] / tests / qunit / suites / resources / jquery / jquery.tablesorter.test.js
blobf028dbc936b9a0b3469d2b42876d73ab52bb61be
1 ( function ( $ ) {
3 var config = {
4         wgMonthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
5         wgMonthNamesShort: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
6         wgDefaultDateFormat: 'dmy',
7         wgContentLanguage: 'en'
8 };
10 module( 'jquery.tablesorter', QUnit.newMwEnvironment({ config: config }) );
12 test( '-- Initial check', function() {
13         expect(1);
14         ok( $.tablesorter, '$.tablesorter defined' );
15 });
17 /**
18  * Create an HTML table from an array of row arrays containing text strings.
19  * First row will be header row. No fancy rowspan/colspan stuff.
20  *
21  * @param {String[]} header
22  * @param {String[][]} data
23  * @return jQuery
24  */
25 var tableCreate = function( header, data ) {
26         var $table = $( '<table class="sortable"><thead></thead><tbody></tbody></table>' ),
27                 $thead = $table.find( 'thead' ),
28                 $tbody = $table.find( 'tbody' ),
29                 $tr = $( '<tr>' );
31         $.each( header, function( i, str ) {
32                 var $th = $( '<th>' );
33                 $th.text( str ).appendTo( $tr );
34         });
35         $tr.appendTo( $thead );
37         for (var i = 0; i < data.length; i++) {
38                 $tr = $( '<tr>' );
39                 $.each( data[i], function( j, str ) {
40                         var $td = $( '<td>' );
41                         $td.text( str ).appendTo( $tr );
42                 });
43                 $tr.appendTo( $tbody );
44         }
45         return $table;
48 /**
49  * Extract text from table.
50  *
51  * @param {jQuery} $table
52  * @return String[][]
53  */
54 var tableExtract = function( $table ) {
55         var data = [];
57         $table.find( 'tbody' ).find( 'tr' ).each( function( i, tr ) {
58                 var row = [];
59                 $( tr ).find( 'td,th' ).each( function( i, td ) {
60                         row.push( $( td ).text() );
61                 });
62                 data.push( row );
63         });
64         return data;
67 /**
68  * Run a table test by building a table with the given data,
69  * running some callback on it, then checking the results.
70  *
71  * @param {String} msg text to pass on to qunit for the comparison
72  * @param {String[]} header cols to make the table
73  * @param {String[][]} data rows/cols to make the table
74  * @param {String[][]} expected rows/cols to compare against at end
75  * @param {function($table)} callback something to do with the table before we compare
76  */
77 var tableTest = function( msg, header, data, expected, callback ) {
78         test( msg, function() {
79                 expect(1);
81                 var $table = tableCreate( header, data );
83                 // Give caller a chance to set up sorting and manipulate the table.
84                 callback( $table );
86                 // Table sorting is done synchronously; if it ever needs to change back
87                 // to asynchronous, we'll need a timeout or a callback here.
88                 var extracted = tableExtract( $table );
89                 deepEqual( extracted, expected, msg );
90         });
93 var reversed = function(arr) {
94         var arr2 = arr.slice(0);
95         arr2.reverse();
96         return arr2;
99 // Sample data set using planets named and their radius
100 var header  = [ 'Planet' , 'Radius (km)'],
101         mercury = [ 'Mercury', '2439.7' ],
102         venus   = [ 'Venus'  , '6051.8' ],
103         earth   = [ 'Earth'  , '6371.0' ],
104         mars    = [ 'Mars'   , '3390.0' ],
105         jupiter = [ 'Jupiter',  '69911' ],
106         saturn  = [ 'Saturn' ,  '58232' ];
108 // Initial data set
109 var planets         = [mercury, venus, earth, mars, jupiter, saturn];
110 var ascendingName   = [earth, jupiter, mars, mercury, saturn, venus];
111 var ascendingRadius = [mercury, mars, venus, earth, saturn, jupiter];
113 tableTest(
114         'Basic planet table: ascending by name',
115         header,
116         planets,
117         ascendingName,
118         function( $table ) {
119                 $table.tablesorter();
120                 $table.find( '.headerSort:eq(0)' ).click();
121         }
123 tableTest(
124         'Basic planet table: ascending by name a second time',
125         header,
126         planets,
127         ascendingName,
128         function( $table ) {
129                 $table.tablesorter();
130                 $table.find( '.headerSort:eq(0)' ).click();
131         }
133 tableTest(
134         'Basic planet table: descending by name',
135         header,
136         planets,
137         reversed(ascendingName),
138         function( $table ) {
139                 $table.tablesorter();
140                 $table.find( '.headerSort:eq(0)' ).click().click();
141         }
143 tableTest(
144         'Basic planet table: ascending radius',
145         header,
146         planets,
147         ascendingRadius,
148         function( $table ) {
149                 $table.tablesorter();
150                 $table.find( '.headerSort:eq(1)' ).click();
151         }
153 tableTest(
154         'Basic planet table: descending radius',
155         header,
156         planets,
157         reversed(ascendingRadius),
158         function( $table ) {
159                 $table.tablesorter();
160                 $table.find( '.headerSort:eq(1)' ).click().click();
161         }
165 // Regression tests!
166 tableTest(
167         'Bug 28775: German-style (dmy) short numeric dates',
168         ['Date'],
169         [ // German-style dates are day-month-year
170                 ['11.11.2011'],
171                 ['01.11.2011'],
172                 ['02.10.2011'],
173                 ['03.08.2011'],
174                 ['09.11.2011']
175         ],
176         [ // Sorted by ascending date
177                 ['03.08.2011'],
178                 ['02.10.2011'],
179                 ['01.11.2011'],
180                 ['09.11.2011'],
181                 ['11.11.2011']
182         ],
183         function( $table ) {
184                 mw.config.set( 'wgDefaultDateFormat', 'dmy' );
185                 mw.config.set( 'wgContentLanguage', 'de' );
187                 $table.tablesorter();
188                 $table.find( '.headerSort:eq(0)' ).click();
189         }
192 tableTest(
193         'Bug 28775: American-style (mdy) short numeric dates',
194         ['Date'],
195         [ // American-style dates are month-day-year
196                 ['11.11.2011'],
197                 ['01.11.2011'],
198                 ['02.10.2011'],
199                 ['03.08.2011'],
200                 ['09.11.2011']
201         ],
202         [ // Sorted by ascending date
203                 ['01.11.2011'],
204                 ['02.10.2011'],
205                 ['03.08.2011'],
206                 ['09.11.2011'],
207                 ['11.11.2011']
208         ],
209         function( $table ) {
210                 mw.config.set( 'wgDefaultDateFormat', 'mdy' );
212                 $table.tablesorter();
213                 $table.find( '.headerSort:eq(0)' ).click();
214         }
217 var ipv4 = [
218         // Some randomly generated fake IPs
219         ['45.238.27.109'],
220         ['44.172.9.22'],
221         ['247.240.82.209'],
222         ['204.204.132.158'],
223         ['170.38.91.162'],
224         ['197.219.164.9'],
225         ['45.68.154.72'],
226         ['182.195.149.80']
228 var ipv4Sorted = [
229         // Sort order should go octet by octet
230         ['44.172.9.22'],
231         ['45.68.154.72'],
232         ['45.238.27.109'],
233         ['170.38.91.162'],
234         ['182.195.149.80'],
235         ['197.219.164.9'],
236         ['204.204.132.158'],
237         ['247.240.82.209']
240 tableTest(
241         'Bug 17141: IPv4 address sorting',
242         ['IP'],
243         ipv4,
244         ipv4Sorted,
245         function( $table ) {
246                 $table.tablesorter();
247                 $table.find( '.headerSort:eq(0)' ).click();
248         }
250 tableTest(
251         'Bug 17141: IPv4 address sorting (reverse)',
252         ['IP'],
253         ipv4,
254         reversed(ipv4Sorted),
255         function( $table ) {
256                 $table.tablesorter();
257                 $table.find( '.headerSort:eq(0)' ).click().click();
258         }
261 var umlautWords = [
262         // Some words with Umlauts
263         ['Günther'],
264         ['Peter'],
265         ['Björn'],
266         ['Bjorn'],
267         ['Apfel'],
268         ['Äpfel'],
269         ['Strasse'],
270         ['Sträßschen']
273 var umlautWordsSorted = [
274         // Some words with Umlauts
275         ['Äpfel'],
276         ['Apfel'],
277         ['Björn'],
278         ['Bjorn'],
279         ['Günther'],
280         ['Peter'],
281         ['Sträßschen'],
282         ['Strasse']
285 tableTest(
286         'Accented Characters with custom collation',
287         ['Name'],
288         umlautWords,
289         umlautWordsSorted,
290         function( $table ) {
291                 mw.config.set( 'tableSorterCollation', {
292                         'ä': 'ae',
293                         'ö': 'oe',
294                         'ß': 'ss',
295                         'ü':'ue'
296                 } );
298                 $table.tablesorter();
299                 $table.find( '.headerSort:eq(0)' ).click();
300         }
303 var planetsRowspan = [["Earth","6051.8"], jupiter, ["Mars","6051.8"], mercury, saturn, venus];
304 var planetsRowspanII = [jupiter, mercury, saturn, ['Venus', '6371.0'], venus, ['Venus', '3390.0']];
306 tableTest(
307         'Basic planet table: same value for multiple rows via rowspan',
308         header,
309         planets,
310         planetsRowspan,
311         function( $table ) {
312                 // Modify the table to have a multiuple-row-spanning cell:
313                 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
314                 $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
315                 // - Set rowspan for 2nd cell of 3rd row to 3.
316                 //   This covers the removed cell in the 4th and 5th row.
317                 $table.find( 'tr:eq(2) td:eq(1)' ).prop( 'rowspan', '3' );
319                 $table.tablesorter();
320                 $table.find( '.headerSort:eq(0)' ).click();
321         }
323 tableTest(
324         'Basic planet table: Same value for multiple rows via rowspan II',
325         header,
326         planets,
327         planetsRowspanII,
328         function( $table ) {
329                 // Modify the table to have a multiuple-row-spanning cell:
330                 // - Remove 1st cell of 4th row, and, 1st cell or 5th row.
331                 $table.find( 'tr:eq(3) td:eq(0), tr:eq(4) td:eq(0)' ).remove();
332                 // - Set rowspan for 1st cell of 3rd row to 3.
333                 //   This covers the removed cell in the 4th and 5th row.
334                 $table.find( 'tr:eq(2) td:eq(0)' ).prop( 'rowspan', '3' );
336                 $table.tablesorter();
337                 $table.find( '.headerSort:eq(0)' ).click();
338         }
341 var complexMDYDates = [
342         // Some words with Umlauts
343         ['January, 19 2010'],
344         ['April 21 1991'],
345         ['04 22 1991'],
346         ['5.12.1990'],
347         ['December 12 \'10']
350 var complexMDYSorted = [
351         ["5.12.1990"],
352         ["April 21 1991"],
353         ["04 22 1991"],
354         ["January, 19 2010"],
355         ["December 12 '10"]
358 tableTest(
359         'Complex date parsing I',
360         ['date'],
361         complexMDYDates,
362         complexMDYSorted,
363         function( $table ) {
364                 mw.config.set( 'wgDefaultDateFormat', 'mdy' );
366                 $table.tablesorter();
367                 $table.find( '.headerSort:eq(0)' ).click();
368         }
371 var ascendingNameLegacy = ascendingName.slice(0);
372 ascendingNameLegacy[4] = ascendingNameLegacy[5];
373 ascendingNameLegacy.pop();
375 tableTest(
376         'Legacy compat with .sortbottom',
377         header,
378         planets,
379         ascendingNameLegacy,
380         function( $table ) {
381                 $table.find( 'tr:last' ).addClass( 'sortbottom' );
382                 $table.tablesorter();
383                 $table.find( '.headerSort:eq(0)' ).click();
384         }
387 /** FIXME: the diff output is not very readeable. */
388 test( 'bug 32047 - caption must be before thead', function() {
389         var $table;
390         $table = $(
391                 '<table class="sortable">' +
392                 '<caption>CAPTION</caption>' +
393                 '<tr><th>THEAD</th></tr>' +
394                 '<tr><td>A</td></tr>' +
395                 '<tr><td>B</td></tr>' +
396                 '<tr class="sortbottom"><td>TFOOT</td></tr>' +
397                 '</table>'
398                 );
399         $table.tablesorter();
401         equals(
402                 $table.children( ).get( 0 ).nodeName,
403                 'CAPTION',
404                 'First element after <thead> must be <caption> (bug 32047)'
405         );
408 test( 'data-sort-value attribute, when available, should override sorting position', function() {
409         var $table, data;
411         // Simple example, one without data-sort-value which should be sorted at it's text.
412         $table = $(
413                 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
414                         '<tbody>' +
415                         '<tr><td>Cheetah</td></tr>' +
416                         '<tr><td data-sort-value="Apple">Bird</td></tr>' +
417                         '<tr><td data-sort-value="Bananna">Ferret</td></tr>' +
418                         '<tr><td data-sort-value="Drupe">Elephant</td></tr>' +
419                         '<tr><td data-sort-value="Cherry">Dolphin</td></tr>' +
420                 '</tbody></table>'
421         );
422         $table.tablesorter().find( '.headerSort:eq(0)' ).click();
424         data = [];
425         $table.find( 'tbody > tr' ).each( function( i, tr ) {
426                 $( tr ).find( 'td' ).each( function( i, td ) {
427                         data.push( { data: $( td ).data( 'sort-value' ), text: $( td ).text() } );
428                 });
429         });
431         deepEqual( data, [
432                 {
433                         "data": "Apple",
434                         "text": "Bird"
435                 }, {
436                         "data": "Bananna",
437                         "text": "Ferret"
438                 }, {
439                         "data": undefined,
440                         "text": "Cheetah"
441                 }, {
442                         "data": "Cherry",
443                         "text": "Dolphin"
444                 }, {
445                         "data": "Drupe",
446                         "text": "Elephant"
447                 }
448         ] );
450         // Another example
451         $table = $(
452                 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
453                         '<tbody>' +
454                         '<tr><td>D</td></tr>' +
455                         '<tr><td data-sort-value="E">A</td></tr>' +
456                         '<tr><td>B</td></tr>' +
457                         '<tr><td>G</td></tr>' +
458                         '<tr><td data-sort-value="F">C</td></tr>' +
459                 '</tbody></table>'
460         );
461         $table.tablesorter().find( '.headerSort:eq(0)' ).click();
463         data = [];
464         $table.find( 'tbody > tr' ).each( function( i, tr ) {
465                 $( tr ).find( 'td' ).each( function( i, td ) {
466                         data.push( { data: $( td ).data( 'sort-value' ), text: $( td ).text() } );
467                 });
468         });
470         deepEqual( data, [
471                 {
472                         "data": undefined,
473                         "text": "B"
474                 }, {
475                         "data": undefined,
476                         "text": "D"
477                 }, {
478                         "data": "E",
479                         "text": "A"
480                 }, {
481                         "data": "F",
482                         "text": "C"
483                 }, {
484                         "data": undefined,
485                         "text": "G"
486                 }
487         ] );
491 var numbers = [
492         [ '12'    ],
493         [  '7'    ],
494         [ '13,000'],
495         [  '9'    ],
496         [ '14'    ],
497         [  '8.0'  ]
499 var numbersAsc = [
500         [  '7'    ],
501         [  '8.0'  ],
502         [  '9'    ],
503         [ '12'    ],
504         [ '14'    ],
505         [ '13,000']
508 tableTest( 'bug 8115: sort numbers with commas (ascending)',
509         ['Numbers'], numbers, numbersAsc,
510         function( $table ) {
511                 $table.tablesorter();
512                 $table.find( '.headerSort:eq(0)' ).click();
513         }
516 tableTest( 'bug 8115: sort numbers with commas (descending)',
517         ['Numbers'], numbers, reversed(numbersAsc),
518         function( $table ) {
519                 $table.tablesorter();
520                 $table.find( '.headerSort:eq(0)' ).click().click();
521         }
523 // TODO add numbers sorting tests for bug 8115 with a different language
525 test( 'bug 32888 - Tables inside a tableheader cell', function() {
526         expect(2);
528         var $table;
529         $table = $(
530                 '<table class="sortable" id="32888">' +
531                 '<tr><th>header<table id="32888-2">'+
532                         '<tr><th>1</th><th>2</th></tr>' +
533                 '</table></th></tr>' +
534                 '<tr><td>A</td></tr>' +
535                 '<tr><td>B</td></tr>' +
536                 '</table>'
537                 );
538         $table.tablesorter();
540         equals(
541                 $table.find('> thead:eq(0) > tr > th.headerSort').length,
542                 1,
543                 'Child tables inside a headercell should not interfere with sortable headers (bug 32888)'
544         );
545         equals(
546                 $('#32888-2').find('th.headerSort').length,
547                 0,
548                 'The headers of child tables inside a headercell should not be sortable themselves (bug 32888)'
549         );
552 })( jQuery );