summaryrefslogtreecommitdiff
path: root/tests/qunit/suites/resources/jquery
diff options
context:
space:
mode:
Diffstat (limited to 'tests/qunit/suites/resources/jquery')
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.autoEllipsis.js)13
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.byteLength.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.byteLength.js)4
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.byteLimit.js)136
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.client.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.client.js)164
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.colorUtil.js)2
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js4
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.getAttrs.js)2
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.highlightText.test.js239
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.localize.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.localize.js)2
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.mwPrototypes.js)6
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js (renamed from tests/qunit/suites/resources/jquery/jquery.tabIndex.js)12
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js227
-rw-r--r--tests/qunit/suites/resources/jquery/jquery.textSelection.test.js279
13 files changed, 907 insertions, 183 deletions
diff --git a/tests/qunit/suites/resources/jquery/jquery.autoEllipsis.js b/tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js
index caf5a6f1..6e371384 100644
--- a/tests/qunit/suites/resources/jquery/jquery.autoEllipsis.js
+++ b/tests/qunit/suites/resources/jquery/jquery.autoEllipsis.test.js
@@ -1,4 +1,4 @@
-module( 'jquery.autoEllipsis.js' );
+module( 'jquery.autoEllipsis', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(1);
@@ -6,8 +6,8 @@ test( '-- Initial check', function() {
});
function createWrappedDiv( text, width ) {
- var $wrapper = $( '<div />' ).css( 'width', width );
- var $div = $( '<div />' ).text( text );
+ var $wrapper = $( '<div>' ).css( 'width', width );
+ var $div = $( '<div>' ).text( text );
$wrapper.append( $div );
return $wrapper;
}
@@ -26,7 +26,7 @@ test( 'Position right', function() {
// We need this thing to be visible, so append it to the DOM
var origText = 'This is a really long random string and there is no way it fits in 100 pixels.';
var $wrapper = createWrappedDiv( origText, '100px' );
- $( 'body' ).append( $wrapper );
+ $( '#qunit-fixture' ).append( $wrapper );
$wrapper.autoEllipsis( { position: 'right' } );
// Verify that, and only one, span element was created
@@ -47,12 +47,9 @@ test( 'Position right', function() {
// Put this text in the span and verify it doesn't fit
$span.text( spanTextNew );
// In IE6 width works like min-width, allow IE6's width to be "equal to"
- if ( $.browser.msie && Number( $.browser.version ) == 6 ) {
+ if ( $.browser.msie && Number( $.browser.version ) === 6 ) {
gtOrEq( $span.width(), $span.parent().width(), 'Fit is maximal (adding two characters makes it not fit any more) - IE6: Maybe equal to as well due to width behaving like min-width in IE6' );
} else {
gt( $span.width(), $span.parent().width(), 'Fit is maximal (adding two characters makes it not fit any more)' );
}
-
- // Clean up
- $wrapper.remove();
});
diff --git a/tests/qunit/suites/resources/jquery/jquery.byteLength.js b/tests/qunit/suites/resources/jquery/jquery.byteLength.test.js
index f82fda27..15fac691 100644
--- a/tests/qunit/suites/resources/jquery/jquery.byteLength.js
+++ b/tests/qunit/suites/resources/jquery/jquery.byteLength.test.js
@@ -1,4 +1,4 @@
-module( 'jquery.byteLength.js' );
+module( 'jquery.byteLength', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(1);
@@ -25,7 +25,7 @@ test( 'Simple text', function() {
test( 'Special text', window.foo = function() {
expect(5);
- // http://en.wikipedia.org/wiki/UTF-8
+ // http://en.wikipedia.org/wiki/UTF-8
var U_0024 = '\u0024',
U_00A2 = '\u00A2',
U_20AC = '\u20AC',
diff --git a/tests/qunit/suites/resources/jquery/jquery.byteLimit.js b/tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
index 461ea49b..3346c2d5 100644
--- a/tests/qunit/suites/resources/jquery/jquery.byteLimit.js
+++ b/tests/qunit/suites/resources/jquery/jquery.byteLimit.test.js
@@ -1,4 +1,6 @@
-module( 'jquery.byteLimit.js' );
+( function () {
+
+module( 'jquery.byteLimit', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(1);
@@ -23,46 +25,47 @@ $.addChars = function( $input, charstr ) {
}
}
};
-var blti = 0;
+
/**
* Test factory for $.fn.byteLimit
*
* @param $input {jQuery} jQuery object in an input element
- * @param useLimit {Boolean} Wether a limit should apply at all
+ * @param hasLimit {Boolean} Wether a limit should apply at all
* @param limit {Number} Limit (if used) otherwise undefined
- * The limit should be less than 20 (the sample data's length)
+ * The limit should be less than 20 (the sample data's length)
*/
var byteLimitTest = function( options ) {
var opt = $.extend({
description: '',
$input: null,
sample: '',
- useLimit: false,
- expected: 0,
+ hasLimit: false,
+ expected: '',
limit: null
}, options);
- var i = blti++;
test( opt.description, function() {
- opt.$input.appendTo( 'body' );
-
+ opt.$input.appendTo( '#qunit-fixture' );
+
// Simulate pressing keys for each of the sample characters
$.addChars( opt.$input, opt.sample );
- var newVal = opt.$input.val();
-
- if ( opt.useLimit ) {
- expect(2);
-
+ var rawVal = opt.$input.val(),
+ fn = opt.$input.data( 'byteLimit-callback' ),
+ newVal = $.isFunction( fn ) ? fn( rawVal ) : rawVal;
+
+ if ( opt.hasLimit ) {
+ expect(3);
+
ltOrEq( $.byteLength( newVal ), opt.limit, 'Prevent keypresses after byteLimit was reached, length never exceeded the limit' );
- equal( $.byteLength( newVal ), opt.expected, 'Not preventing keypresses too early, length has reached the expected length' );
-
+ equal( $.byteLength( rawVal ), $.byteLength( opt.expected ), 'Not preventing keypresses too early, length has reached the expected length' );
+ equal( rawVal, opt.expected, 'New value matches the expected string' );
+
} else {
- expect(1);
- equal( $.byteLength( newVal ), opt.expected, 'Unlimited scenarios are not affected, expected length reached' );
+ expect(2);
+ equal( newVal, opt.expected, 'New value matches the expected string' );
+ equal( $.byteLength( newVal ), $.byteLength( opt.expected ), 'Unlimited scenarios are not affected, expected length reached' );
}
-
- opt.$input.remove();
} );
};
@@ -79,77 +82,106 @@ var
byteLimitTest({
description: 'Plain text input',
$input: $( '<input>' )
- .attr( {
- 'type': 'text'
- }),
+ .attr( 'type', 'text' ),
sample: simpleSample,
- useLimit: false,
- expected: $.byteLength( simpleSample )
+ hasLimit: false,
+ expected: simpleSample
});
byteLimitTest({
description: 'Limit using the maxlength attribute',
$input: $( '<input>' )
- .attr( {
- 'type': 'text',
- 'maxlength': '10'
- })
+ .attr( 'type', 'text' )
+ .prop( 'maxLength', '10' )
.byteLimit(),
sample: simpleSample,
- useLimit: true,
+ hasLimit: true,
limit: 10,
- expected: 10
+ expected: '1234567890'
});
byteLimitTest({
description: 'Limit using a custom value',
$input: $( '<input>' )
- .attr( {
- 'type': 'text'
- })
+ .attr( 'type', 'text' )
.byteLimit( 10 ),
sample: simpleSample,
- useLimit: true,
+ hasLimit: true,
limit: 10,
- expected: 10
+ expected: '1234567890'
});
byteLimitTest({
description: 'Limit using a custom value, overriding maxlength attribute',
$input: $( '<input>' )
- .attr( {
- 'type': 'text',
- 'maxLength': '10'
- })
+ .attr( 'type', 'text' )
+ .prop( 'maxLength', '10' )
.byteLimit( 15 ),
sample: simpleSample,
- useLimit: true,
+ hasLimit: true,
limit: 15,
- expected: 15
+ expected: '123456789012345'
});
byteLimitTest({
description: 'Limit using a custom value (multibyte)',
$input: $( '<input>' )
- .attr( {
- 'type': 'text'
- })
+ .attr( 'type', 'text' )
.byteLimit( 14 ),
sample: mbSample,
- useLimit: true,
+ hasLimit: true,
limit: 14,
- expected: 14 // (10 x 1-byte char) + (1 x 3-byte char) + (1 x 1-byte char)
+ expected: '1234567890' + U_20AC + '1'
});
byteLimitTest({
description: 'Limit using a custom value (multibyte) overlapping a byte',
$input: $( '<input>' )
- .attr( {
- 'type': 'text'
- })
+ .attr( 'type', 'text' )
.byteLimit( 12 ),
sample: mbSample,
- useLimit: true,
+ hasLimit: true,
limit: 12,
- expected: 12 // 10 x 1-byte char. The next 3-byte char exceeds limit of 12, but 2 more 1-byte chars come in after.
+ expected: '1234567890' + '12'
});
+
+byteLimitTest({
+ description: 'Pass the limit and a callback as input filter',
+ $input: $( '<input>' )
+ .attr( 'type', 'text' )
+ .byteLimit( 6, function( val ) {
+ // Invalid title
+ if ( val == '' ) {
+ return '';
+ }
+
+ // Return without namespace prefix
+ return new mw.Title( '' + val ).getMain();
+ } ),
+ sample: 'User:Sample',
+ hasLimit: true,
+ limit: 6, // 'Sample' length
+ expected: 'User:Sample'
+});
+
+byteLimitTest({
+ description: 'Limit using the maxlength attribute and pass a callback as input filter',
+ $input: $( '<input>' )
+ .attr( 'type', 'text' )
+ .prop( 'maxLength', '6' )
+ .byteLimit( function( val ) {
+ // Invalid title
+ if ( val === '' ) {
+ return '';
+ }
+
+ // Return without namespace prefix
+ return new mw.Title( '' + val ).getMain();
+ } ),
+ sample: 'User:Sample',
+ hasLimit: true,
+ limit: 6, // 'Sample' length
+ expected: 'User:Sample'
+});
+
+}() ); \ No newline at end of file
diff --git a/tests/qunit/suites/resources/jquery/jquery.client.js b/tests/qunit/suites/resources/jquery/jquery.client.test.js
index 50df2928..7be41971 100644
--- a/tests/qunit/suites/resources/jquery/jquery.client.js
+++ b/tests/qunit/suites/resources/jquery/jquery.client.test.js
@@ -1,12 +1,14 @@
-module( 'jquery.client.js' );
+module( 'jquery.client', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(1);
ok( jQuery.client, 'jQuery.client defined' );
});
-test( 'profile userAgent support', function() {
- expect(8);
+/** Number of user-agent defined */
+var uacount = 0;
+
+var uas = (function() {
// Object keyed by userAgent. Value is an array (human-readable name, client-profile object, navigator.platform value)
// Info based on results from http://toolserver.org/~krinkle/testswarm/job/174/
@@ -24,11 +26,32 @@ test( 'profile userAgent support', function() {
"version": "7.0",
"versionBase": "7",
"versionNumber": 7
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: false
}
},
// Internet Explorer 8
// Internet Explorer 9
// Internet Explorer 10
+ 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)': {
+ title: 'Internet Explorer 10',
+ platform: 'Win32',
+ profile: {
+ "name": "msie",
+ "layout": "trident",
+ "layoutVersion": "unknown", // should be able to report 6?
+ "platform": "win",
+ "version": "10.0",
+ "versionBase": "10",
+ "versionNumber": 10
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
+ }
+ },
// Firefox 2
// Firefox 3.5
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.19) Gecko/20110420 Firefox/3.5.19': {
@@ -42,6 +65,10 @@ test( 'profile userAgent support', function() {
"version": "3.5.19",
"versionBase": "3",
"versionNumber": 3.5
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
}
},
// Firefox 3.6
@@ -56,6 +83,10 @@ test( 'profile userAgent support', function() {
"version": "3.6.17",
"versionBase": "3",
"versionNumber": 3.6
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
}
},
// Firefox 4
@@ -70,7 +101,29 @@ test( 'profile userAgent support', function() {
"version": "4.0.1",
"versionBase": "4",
"versionNumber": 4
- }
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
+ }
+ },
+ // Firefox 10 nightly build
+ 'Mozilla/5.0 (X11; Linux x86_64; rv:10.0a1) Gecko/20111103 Firefox/10.0a1': {
+ title: 'Firefox 10 nightly',
+ platform: 'Linux',
+ profile: {
+ "name": "firefox",
+ "layout": "gecko",
+ "layoutVersion": 20111103,
+ "platform": "linux",
+ "version": "10.0a1",
+ "versionBase": "10",
+ "versionNumber": 10
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
+ }
},
// Firefox 5
// Safari 3
@@ -86,7 +139,11 @@ test( 'profile userAgent support', function() {
"version": "4.0.5",
"versionBase": "4",
"versionNumber": 4
- }
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
+ }
},
'Mozilla/5.0 (Windows; U; Windows NT 6.0; cs-CZ) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7': {
title: 'Safari 4',
@@ -99,6 +156,10 @@ test( 'profile userAgent support', function() {
"version": "4.0.5",
"versionBase": "4",
"versionNumber": 4
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
}
},
// Safari 5
@@ -122,6 +183,10 @@ test( 'profile userAgent support', function() {
"version": "12.0.742.112",
"versionBase": "12",
"versionNumber": 12
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
}
},
'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.68 Safari/534.30': {
@@ -135,9 +200,19 @@ test( 'profile userAgent support', function() {
"version": "12.0.742.68",
"versionBase": "12",
"versionNumber": 12
+ },
+ wikiEditor: {
+ ltr: true,
+ rtl: true
}
}
};
+ $.each( uas, function() { uacount++ });
+ return uas;
+})();
+
+test( 'profile userAgent support', function() {
+ expect(uacount);
// Generate a client profile object and compare recursively
var uaTest = function( rawUserAgent, data ) {
@@ -168,34 +243,37 @@ test( 'profile return validation for current user agent', function() {
equal( typeof p.versionNumber, 'number', 'p.versionNumber is a number' );
});
+// Example from WikiEditor
+// Make sure to use raw numbers, a string like "7.0" would fail on a
+// version 10 browser since in string comparaison "10" is before "7.0" :)
+var testMap = {
+ 'ltr': {
+ 'msie': [['>=', 7.0]],
+ 'firefox': [['>=', 2]],
+ 'opera': [['>=', 9.6]],
+ 'safari': [['>=', 3]],
+ 'chrome': [['>=', 3]],
+ 'netscape': [['>=', 9]],
+ 'blackberry': false,
+ 'ipod': false,
+ 'iphone': false
+ },
+ 'rtl': {
+ 'msie': [['>=', 8]],
+ 'firefox': [['>=', 2]],
+ 'opera': [['>=', 9.6]],
+ 'safari': [['>=', 3]],
+ 'chrome': [['>=', 3]],
+ 'netscape': [['>=', 9]],
+ 'blackberry': false,
+ 'ipod': false,
+ 'iphone': false
+ }
+};
+
test( 'test', function() {
expect(1);
- // Example from WikiEditor
- var testMap = {
- 'ltr': {
- 'msie': [['>=', 7]],
- 'firefox': [['>=', 2]],
- 'opera': [['>=', 9.6]],
- 'safari': [['>=', 3]],
- 'chrome': [['>=', 3]],
- 'netscape': [['>=', 9]],
- 'blackberry': false,
- 'ipod': false,
- 'iphone': false
- },
- 'rtl': {
- 'msie': [['>=', 8]],
- 'firefox': [['>=', 2]],
- 'opera': [['>=', 9.6]],
- 'safari': [['>=', 3]],
- 'chrome': [['>=', 3]],
- 'netscape': [['>=', 9]],
- 'blackberry': false,
- 'ipod': false,
- 'iphone': false
- }
- };
// .test() uses eval, make sure no exceptions are thrown
// then do a basic return value type check
var testMatch = $.client.test( testMap );
@@ -203,3 +281,29 @@ test( 'test', function() {
equal( typeof testMatch, 'boolean', 'test returns a boolean value' );
});
+
+test( 'User-agent matches against WikiEditor\'s compatibility map', function() {
+ expect( uacount * 2 ); // double since we test both LTR and RTL
+
+ var $body = $( 'body' ),
+ bodyClasses = $body.attr( 'class' );
+
+ // Loop through and run tests
+ $.each( uas, function ( agent, data ) {
+ $.each( ['ltr', 'rtl'], function ( i, dir ) {
+ $body.removeClass( 'ltr rtl' ).addClass( dir );
+ var profile = $.client.profile( {
+ userAgent: agent,
+ platform: data.platform
+ } );
+ var testMatch = $.client.test( testMap, profile );
+ $body.removeClass( dir );
+
+ equal( testMatch, data.wikiEditor[dir], 'testing comparison based on ' + dir + ', ' + agent );
+ });
+ });
+
+ // Restore body classes
+ $body.attr( 'class', bodyClasses );
+});
+
diff --git a/tests/qunit/suites/resources/jquery/jquery.colorUtil.js b/tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js
index 93f12b82..655ee564 100644
--- a/tests/qunit/suites/resources/jquery/jquery.colorUtil.js
+++ b/tests/qunit/suites/resources/jquery/jquery.colorUtil.test.js
@@ -1,4 +1,4 @@
-module( 'jquery.colorUtil.js' );
+module( 'jquery.colorUtil', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(1);
diff --git a/tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js b/tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js
index 8688f12e..6489a1f1 100644
--- a/tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.delayedBind.test.js
@@ -1,5 +1,5 @@
test('jquery.delayedBind with data option', function() {
- var $fixture = $('<div>').appendTo('body'),
+ var $fixture = $('<div>').appendTo('#qunit-fixture'),
data = { magic: "beeswax" },
delay = 50;
@@ -20,7 +20,7 @@ test('jquery.delayedBind with data option', function() {
});
test('jquery.delayedBind without data option', function() {
- var $fixture = $('<div>').appendTo('body'),
+ var $fixture = $('<div>').appendTo('#qunit-fixture'),
data = { magic: "beeswax" },
delay = 50;
diff --git a/tests/qunit/suites/resources/jquery/jquery.getAttrs.js b/tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js
index 3d3d01e1..9377a2f6 100644
--- a/tests/qunit/suites/resources/jquery/jquery.getAttrs.js
+++ b/tests/qunit/suites/resources/jquery/jquery.getAttrs.test.js
@@ -1,4 +1,4 @@
-module( 'jquery.getAttrs.js' );
+module( 'jquery.getAttrs', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(1);
diff --git a/tests/qunit/suites/resources/jquery/jquery.highlightText.test.js b/tests/qunit/suites/resources/jquery/jquery.highlightText.test.js
new file mode 100644
index 00000000..4750d2b8
--- /dev/null
+++ b/tests/qunit/suites/resources/jquery/jquery.highlightText.test.js
@@ -0,0 +1,239 @@
+module( 'jquery.highlightText', QUnit.newMwEnvironment() );
+
+test( '-- Initial check', function() {
+ expect(1);
+ ok( $.fn.highlightText, 'jQuery.fn.highlightText defined' );
+} );
+
+test( 'Check', function() {
+ var cases = [
+ {
+ desc: 'Test 001',
+ text: 'Blue Öyster Cult',
+ highlight: 'Blue',
+ expected: '<span class="highlight">Blue</span> Öyster Cult'
+ },
+ {
+ desc: 'Test 002',
+ text: 'Blue Öyster Cult',
+ highlight: 'Blue ',
+ expected: '<span class="highlight">Blue</span> Öyster Cult'
+ },
+ {
+ desc: 'Test 003',
+ text: 'Blue Öyster Cult',
+ highlight: 'Blue Ö',
+ expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
+ },
+ {
+ desc: 'Test 004',
+ text: 'Blue Öyster Cult',
+ highlight: 'Blue Öy',
+ expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
+ },
+ {
+ desc: 'Test 005',
+ text: 'Blue Öyster Cult',
+ highlight: ' Blue',
+ expected: '<span class="highlight">Blue</span> Öyster Cult'
+ },
+ {
+ desc: 'Test 006',
+ text: 'Blue Öyster Cult',
+ highlight: ' Blue ',
+ expected: '<span class="highlight">Blue</span> Öyster Cult'
+ },
+ {
+ desc: 'Test 007',
+ text: 'Blue Öyster Cult',
+ highlight: ' Blue Ö',
+ expected: '<span class="highlight">Blue</span> <span class="highlight">Ö</span>yster Cult'
+ },
+ {
+ desc: 'Test 008',
+ text: 'Blue Öyster Cult',
+ highlight: ' Blue Öy',
+ expected: '<span class="highlight">Blue</span> <span class="highlight">Öy</span>ster Cult'
+ },
+ {
+ desc: 'Test 009: Highlighter broken on starting Umlaut?',
+ text: 'Österreich',
+ highlight: 'Österreich',
+ expected: '<span class="highlight">Österreich</span>'
+ },
+ {
+ desc: 'Test 010: Highlighter broken on starting Umlaut?',
+ text: 'Österreich',
+ highlight: 'Ö',
+ expected: '<span class="highlight">Ö</span>sterreich'
+ },
+ {
+ desc: 'Test 011: Highlighter broken on starting Umlaut?',
+ text: 'Österreich',
+ highlight: 'Öst',
+ expected: '<span class="highlight">Öst</span>erreich'
+ },
+ {
+ desc: 'Test 012: Highlighter broken on starting Umlaut?',
+ text: 'Österreich',
+ highlight: 'Oe',
+ expected: 'Österreich'
+ },
+ {
+ desc: 'Test 013: Highlighter broken on punctuation mark?',
+ text: 'So good. To be there',
+ highlight: 'good',
+ expected: 'So <span class="highlight">good</span>. To be there'
+ },
+ {
+ desc: 'Test 014: Highlighter broken on space?',
+ text: 'So good. To be there',
+ highlight: 'be',
+ expected: 'So good. To <span class="highlight">be</span> there'
+ },
+ {
+ desc: 'Test 015: Highlighter broken on space?',
+ text: 'So good. To be there',
+ highlight: ' be',
+ expected: 'So good. To <span class="highlight">be</span> there'
+ },
+ {
+ desc: 'Test 016: Highlighter broken on space?',
+ text: 'So good. To be there',
+ highlight: 'be ',
+ expected: 'So good. To <span class="highlight">be</span> there'
+ },
+ {
+ desc: 'Test 017: Highlighter broken on space?',
+ text: 'So good. To be there',
+ highlight: ' be ',
+ expected: 'So good. To <span class="highlight">be</span> there'
+ },
+ {
+ desc: 'Test 018: en de Highlighter broken on special character at the end?',
+ text: 'So good. xbß',
+ highlight: 'xbß',
+ expected: 'So good. <span class="highlight">xbß</span>'
+ },
+ {
+ desc: 'Test 019: en de Highlighter broken on special character at the end?',
+ text: 'So good. xbß.',
+ highlight: 'xbß.',
+ expected: 'So good. <span class="highlight">xbß.</span>'
+ },
+ {
+ desc: 'Test 020: RTL he Hebrew',
+ text: 'חסיד אומות העולם',
+ highlight: 'חסיד אומות העולם',
+ expected: '<span class="highlight">חסיד</span> <span class="highlight">אומות</span> <span class="highlight">העולם</span>'
+ },
+ {
+ desc: 'Test 021: RTL he Hebrew',
+ text: 'חסיד אומות העולם',
+ highlight: 'חסי',
+ expected: '<span class="highlight">חסי</span>ד אומות העולם'
+ },
+ {
+ desc: 'Test 022: ja Japanese',
+ text: '諸国民の中の正義の人',
+ highlight: '諸国民の中の正義の人',
+ expected: '<span class="highlight">諸国民の中の正義の人</span>'
+ },
+ {
+ desc: 'Test 023: ja Japanese',
+ text: '諸国民の中の正義の人',
+ highlight: '諸国',
+ expected: '<span class="highlight">諸国</span>民の中の正義の人'
+ },
+ {
+ desc: 'Test 024: fr French text and « french quotes » (guillemets)',
+ text: "« L'oiseau est sur l’île »",
+ highlight: "« L'oiseau est sur l’île »",
+ expected: '<span class="highlight">«</span> <span class="highlight">L\'oiseau</span> <span class="highlight">est</span> <span class="highlight">sur</span> <span class="highlight">l’île</span> <span class="highlight">»</span>'
+ },
+ {
+ desc: 'Test 025: fr French text and « french quotes » (guillemets)',
+ text: "« L'oiseau est sur l’île »",
+ highlight: "« L'oise",
+ expected: '<span class="highlight">«</span> <span class="highlight">L\'oise</span>au est sur l’île »'
+ },
+ {
+ desc: 'Test 025a: fr French text and « french quotes » (guillemets) - does it match the single strings "«" and "L" separately?',
+ text: "« L'oiseau est sur l’île »",
+ highlight: "« L",
+ expected: '<span class="highlight">«</span> <span class="highlight">L</span>\'oiseau est sur <span class="highlight">l</span>’île »'
+ },
+ {
+ desc: 'Test 026: ru Russian',
+ text: 'Праведники мира',
+ highlight: 'Праведники мира',
+ expected: '<span class="highlight">Праведники</span> <span class="highlight">мира</span>'
+ },
+ {
+ desc: 'Test 027: ru Russian',
+ text: 'Праведники мира',
+ highlight: 'Праве',
+ expected: '<span class="highlight">Праве</span>дники мира'
+ },
+ {
+ desc: 'Test 028 ka Georgian',
+ text: 'მთავარი გვერდი',
+ highlight: 'მთავარი გვერდი',
+ expected: '<span class="highlight">მთავარი</span> <span class="highlight">გვერდი</span>'
+ },
+ {
+ desc: 'Test 029 ka Georgian',
+ text: 'მთავარი გვერდი',
+ highlight: 'მთა',
+ expected: '<span class="highlight">მთა</span>ვარი გვერდი'
+ },
+ {
+ desc: 'Test 030 hy Armenian',
+ text: 'Նոնա Գափրինդաշվիլի',
+ highlight: 'Նոնա Գափրինդաշվիլի',
+ expected: '<span class="highlight">Նոնա</span> <span class="highlight">Գափրինդաշվիլի</span>'
+ },
+ {
+ desc: 'Test 031 hy Armenian',
+ text: 'Նոնա Գափրինդաշվիլի',
+ highlight: 'Նոն',
+ expected: '<span class="highlight">Նոն</span>ա Գափրինդաշվիլի'
+ },
+ {
+ desc: 'Test 032: th Thai',
+ text: 'พอล แอร์ดิช',
+ highlight: 'พอล แอร์ดิช',
+ expected: '<span class="highlight">พอล</span> <span class="highlight">แอร์ดิช</span>'
+ },
+ {
+ desc: 'Test 033: th Thai',
+ text: 'พอล แอร์ดิช',
+ highlight: 'พอ',
+ expected: '<span class="highlight">พอ</span>ล แอร์ดิช'
+ },
+ {
+ desc: 'Test 034: RTL ar Arabic',
+ text: 'بول إيردوس',
+ highlight: 'بول إيردوس',
+ expected: '<span class="highlight">بول</span> <span class="highlight">إيردوس</span>'
+ },
+ {
+ desc: 'Test 035: RTL ar Arabic',
+ text: 'بول إيردوس',
+ highlight: 'بو',
+ expected: '<span class="highlight">بو</span>ل إيردوس'
+ }
+ ];
+ expect(cases.length);
+ var $fixture;
+
+ $.each(cases, function( i, item ) {
+ $fixture = $( '<p></p>' ).text( item.text );
+ $fixture.highlightText( item.highlight );
+ equals(
+ $fixture.html(),
+ $('<p>' + item.expected + '</p>').html(), // re-parse to normalize!
+ item.desc || undefined
+ );
+ } );
+} );
diff --git a/tests/qunit/suites/resources/jquery/jquery.localize.js b/tests/qunit/suites/resources/jquery/jquery.localize.test.js
index 40b58687..cd828634 100644
--- a/tests/qunit/suites/resources/jquery/jquery.localize.js
+++ b/tests/qunit/suites/resources/jquery/jquery.localize.test.js
@@ -1,4 +1,4 @@
-module( 'jquery.localize.js' );
+module( 'jquery.localize', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(1);
diff --git a/tests/qunit/suites/resources/jquery/jquery.mwPrototypes.js b/tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js
index bb6d2a1b..3a2d0d83 100644
--- a/tests/qunit/suites/resources/jquery/jquery.mwPrototypes.js
+++ b/tests/qunit/suites/resources/jquery/jquery.mwExtension.test.js
@@ -1,10 +1,10 @@
-module( 'jquery.mwPrototypes.js' );
+module( 'jquery.mwExtension', QUnit.newMwEnvironment() );
test( 'String functions', function() {
equal( $.trimLeft( ' foo bar ' ), 'foo bar ', 'trimLeft' );
equal( $.trimRight( ' foo bar ' ), ' foo bar', 'trimRight' );
- equal( $.ucFirst( 'foo'), 'Foo', 'ucFirst' );
+ equal( $.ucFirst( 'foo' ), 'Foo', 'ucFirst' );
equal( $.escapeRE( '<!-- ([{+mW+}]) $^|?>' ),
'<!\\-\\- \\(\\[\\{\\+mW\\+\\}\\]\\) \\$\\^\\|\\?>', 'escapeRE - Escape specials' );
@@ -36,6 +36,8 @@ test( 'Is functions', function() {
strictEqual( $.isEmpty( 'string' ), false, 'isEmptry: "string"' );
strictEqual( $.isEmpty( '0' ), true, 'isEmptry: "0"' );
+ strictEqual( $.isEmpty( '' ), true, 'isEmptry: ""' );
+ strictEqual( $.isEmpty( 1 ), false, 'isEmptry: 1' );
strictEqual( $.isEmpty( [] ), true, 'isEmptry: []' );
strictEqual( $.isEmpty( {} ), true, 'isEmptry: {}' );
diff --git a/tests/qunit/suites/resources/jquery/jquery.tabIndex.js b/tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js
index 1ff81e58..98ff5508 100644
--- a/tests/qunit/suites/resources/jquery/jquery.tabIndex.js
+++ b/tests/qunit/suites/resources/jquery/jquery.tabIndex.test.js
@@ -1,4 +1,4 @@
-module( 'jquery.tabIndex.js' );
+module( 'jquery.tabIndex', QUnit.newMwEnvironment() );
test( '-- Initial check', function() {
expect(2);
@@ -18,14 +18,11 @@ test( 'firstTabIndex', function() {
'<textarea tabindex="5">Foobar</textarea>' +
'</form>';
- var $testA = $( '<div>' ).html( testEnvironment ).appendTo( 'body' );
+ var $testA = $( '<div>' ).html( testEnvironment ).appendTo( '#qunit-fixture' );
strictEqual( $testA.firstTabIndex(), 2, 'First tabindex should be 2 within this context.' );
var $testB = $( '<div>' );
strictEqual( $testB.firstTabIndex(), null, 'Return null if none available.' );
-
- // Clean up
- $testA.add( $testB ).remove();
});
test( 'lastTabIndex', function() {
@@ -39,12 +36,9 @@ test( 'lastTabIndex', function() {
'<textarea tabindex="5">Foobar</textarea>' +
'</form>';
- var $testA = $( '<div>' ).html( testEnvironment ).appendTo( 'body' );
+ var $testA = $( '<div>' ).html( testEnvironment ).appendTo( '#qunit-fixture' );
strictEqual( $testA.lastTabIndex(), 9, 'Last tabindex should be 9 within this context.' );
var $testB = $( '<div>' );
strictEqual( $testB.lastTabIndex(), null, 'Return null if none available.' );
-
- // Clean up
- $testA.add( $testB ).remove();
});
diff --git a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
index f47b7f40..7ecdc4b1 100644
--- a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
+++ b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js
@@ -1,11 +1,13 @@
-(function() {
+( function () {
-module( 'jquery.tablesorter.test.js' );
+var config = {
+ wgMonthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
+ wgMonthNamesShort: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ wgDefaultDateFormat: 'dmy',
+ wgContentLanguage: 'en'
+};
-// setup hack
-mw.config.set('wgMonthNames', window.wgMonthNames = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']);
-mw.config.set('wgMonthNamesShort', window.wgMonthNamesShort = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
-mw.config.set('wgDefaultDateFormat', window.wgDefaultDateFormat = 'dmy');
+module( 'jquery.tablesorter', QUnit.newMwEnvironment( config ) );
test( '-- Initial check', function() {
expect(1);
@@ -21,23 +23,24 @@ test( '-- Initial check', function() {
* @return jQuery
*/
var tableCreate = function( header, data ) {
- var $table = $('<table class="sortable"><thead></thead><tbody></tbody></table>'),
- $thead = $table.find('thead'),
- $tbody = $table.find('tbody');
- var $tr = $('<tr>');
- $.each(header, function(i, str) {
- var $th = $('<th>');
- $th.text(str).appendTo($tr);
+ var $table = $( '<table class="sortable"><thead></thead><tbody></tbody></table>' ),
+ $thead = $table.find( 'thead' ),
+ $tbody = $table.find( 'tbody' ),
+ $tr = $( '<tr>' );
+
+ $.each( header, function( i, str ) {
+ var $th = $( '<th>' );
+ $th.text( str ).appendTo( $tr );
});
- $tr.appendTo($thead);
+ $tr.appendTo( $thead );
for (var i = 0; i < data.length; i++) {
- $tr = $('<tr>');
- $.each(data[i], function(j, str) {
- var $td = $('<td>');
- $td.text(str).appendTo($tr);
+ $tr = $( '<tr>' );
+ $.each( data[i], function( j, str ) {
+ var $td = $( '<td>' );
+ $td.text( str ).appendTo( $tr );
});
- $tr.appendTo($tbody);
+ $tr.appendTo( $tbody );
}
return $table;
};
@@ -50,12 +53,13 @@ var tableCreate = function( header, data ) {
*/
var tableExtract = function( $table ) {
var data = [];
- $table.find('tbody').find('tr').each(function(i, tr) {
+
+ $table.find( 'tbody' ).find( 'tr' ).each( function( i, tr ) {
var row = [];
- $(tr).find('td,th').each(function(i, td) {
- row.push($(td).text());
+ $( tr ).find( 'td,th' ).each( function( i, td ) {
+ row.push( $( td ).text() );
});
- data.push(row);
+ data.push( row );
});
return data;
};
@@ -75,7 +79,6 @@ var tableTest = function( msg, header, data, expected, callback ) {
expect(1);
var $table = tableCreate( header, data );
- //$('body').append($table);
// Give caller a chance to set up sorting and manipulate the table.
callback( $table );
@@ -93,18 +96,18 @@ var reversed = function(arr) {
return arr2;
};
-// Sample data set: some planets!
-var header = ['Planet', 'Radius (km)'],
- mercury = ['Mercury', '2439.7'],
- venus = ['Venus', '6051.8'],
- earth = ['Earth', '6371.0'],
- mars = ['Mars', '3390.0'],
- jupiter = ['Jupiter', '69911'],
- saturn = ['Saturn', '58232'];
+// Sample data set using planets named and their radius
+var header = [ 'Planet' , 'Radius (km)'],
+ mercury = [ 'Mercury', '2439.7' ],
+ venus = [ 'Venus' , '6051.8' ],
+ earth = [ 'Earth' , '6371.0' ],
+ mars = [ 'Mars' , '3390.0' ],
+ jupiter = [ 'Jupiter', '69911' ],
+ saturn = [ 'Saturn' , '58232' ];
// Initial data set
-var planets = [mercury, venus, earth, mars, jupiter, saturn];
-var ascendingName = [earth, jupiter, mars, mercury, saturn, venus];
+var planets = [mercury, venus, earth, mars, jupiter, saturn];
+var ascendingName = [earth, jupiter, mars, mercury, saturn, venus];
var ascendingRadius = [mercury, mars, venus, earth, saturn, jupiter];
tableTest(
@@ -114,7 +117,7 @@ tableTest(
ascendingName,
function( $table ) {
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
tableTest(
@@ -124,7 +127,7 @@ tableTest(
ascendingName,
function( $table ) {
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
tableTest(
@@ -134,7 +137,7 @@ tableTest(
reversed(ascendingName),
function( $table ) {
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click().click();
+ $table.find( '.headerSort:eq(0)' ).click().click();
}
);
tableTest(
@@ -144,7 +147,7 @@ tableTest(
ascendingRadius,
function( $table ) {
$table.tablesorter();
- $table.find('.headerSort:eq(1)').click();
+ $table.find( '.headerSort:eq(1)' ).click();
}
);
tableTest(
@@ -154,25 +157,23 @@ tableTest(
reversed(ascendingRadius),
function( $table ) {
$table.tablesorter();
- $table.find('.headerSort:eq(1)').click().click();
+ $table.find( '.headerSort:eq(1)' ).click().click();
}
);
// Regression tests!
tableTest(
- 'Bug 28775: German-style short numeric dates',
+ 'Bug 28775: German-style (dmy) short numeric dates',
['Date'],
- [
- // German-style dates are day-month-year
+ [ // German-style dates are day-month-year
['11.11.2011'],
['01.11.2011'],
['02.10.2011'],
['03.08.2011'],
['09.11.2011']
],
- [
- // Sorted by ascending date
+ [ // Sorted by ascending date
['03.08.2011'],
['02.10.2011'],
['01.11.2011'],
@@ -180,25 +181,25 @@ tableTest(
['11.11.2011']
],
function( $table ) {
- // @fixme reset it at end or change module to allow us to override it
- mw.config.set('wgDefaultDateFormat', window.wgDefaultDateFormat = 'dmy');
+ mw.config.set( 'wgDefaultDateFormat', 'dmy' );
+ mw.config.set( 'wgContentLanguage', 'de' );
+
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
+
tableTest(
- 'Bug 28775: American-style short numeric dates',
+ 'Bug 28775: American-style (mdy) short numeric dates',
['Date'],
- [
- // American-style dates are month-day-year
+ [ // American-style dates are month-day-year
['11.11.2011'],
['01.11.2011'],
['02.10.2011'],
['03.08.2011'],
['09.11.2011']
],
- [
- // Sorted by ascending date
+ [ // Sorted by ascending date
['01.11.2011'],
['02.10.2011'],
['03.08.2011'],
@@ -206,10 +207,10 @@ tableTest(
['11.11.2011']
],
function( $table ) {
- // @fixme reset it at end or change module to allow us to override it
- mw.config.set('wgDefaultDateFormat', window.wgDefaultDateFormat = 'mdy');
+ mw.config.set( 'wgDefaultDateFormat', 'mdy' );
+
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
@@ -235,6 +236,7 @@ var ipv4Sorted = [
['204.204.132.158'],
['247.240.82.209']
];
+
tableTest(
'Bug 17141: IPv4 address sorting',
['IP'],
@@ -242,7 +244,7 @@ tableTest(
ipv4Sorted,
function( $table ) {
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
tableTest(
@@ -252,7 +254,7 @@ tableTest(
reversed(ipv4Sorted),
function( $table ) {
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click().click();
+ $table.find( '.headerSort:eq(0)' ).click().click();
}
);
@@ -286,27 +288,36 @@ tableTest(
umlautWords,
umlautWordsSorted,
function( $table ) {
- mw.config.set('tableSorterCollation', {'ä':'ae', 'ö' : 'oe', 'ß': 'ss', 'ü':'ue'});
+ mw.config.set( 'tableSorterCollation', {
+ 'ä': 'ae',
+ 'ö': 'oe',
+ 'ß': 'ss',
+ 'ü':'ue'
+ } );
+
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
- mw.config.set('tableSorterCollation', {});
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
-var planetsRowspan =[["Earth","6051.8"], jupiter, ["Mars","6051.8"], mercury, saturn, venus];
-var planetsRowspanII =[jupiter, mercury, saturn, ['Venus', '6371.0'], venus, ['Venus', '3390.0']];
+var planetsRowspan = [["Earth","6051.8"], jupiter, ["Mars","6051.8"], mercury, saturn, venus];
+var planetsRowspanII = [jupiter, mercury, saturn, ['Venus', '6371.0'], venus, ['Venus', '3390.0']];
tableTest(
- 'Basic planet table: Same value for multiple rows via rowspan',
+ 'Basic planet table: same value for multiple rows via rowspan',
header,
planets,
planetsRowspan,
function( $table ) {
- //Quick&Dirty mod
- $table.find('tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)').remove();
- $table.find('tr:eq(2) td:eq(1)').attr('rowspan', '3');
+ // Modify the table to have a multiuple-row-spanning cell:
+ // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
+ $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
+ // - Set rowspan for 2nd cell of 3rd row to 3.
+ // This covers the removed cell in the 4th and 5th row.
+ $table.find( 'tr:eq(2) td:eq(1)' ).prop( 'rowspan', '3' );
+
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
tableTest(
@@ -315,11 +326,15 @@ tableTest(
planets,
planetsRowspanII,
function( $table ) {
- //Quick&Dirty mod
- $table.find('tr:eq(3) td:eq(0), tr:eq(4) td:eq(0)').remove();
- $table.find('tr:eq(2) td:eq(0)').attr('rowspan', '3');
+ // Modify the table to have a multiuple-row-spanning cell:
+ // - Remove 1st cell of 4th row, and, 1st cell or 5th row.
+ $table.find( 'tr:eq(3) td:eq(0), tr:eq(4) td:eq(0)' ).remove();
+ // - Set rowspan for 1st cell of 3rd row to 3.
+ // This covers the removed cell in the 4th and 5th row.
+ $table.find( 'tr:eq(2) td:eq(0)' ).prop( 'rowspan', '3' );
+
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
@@ -346,9 +361,10 @@ tableTest(
complexMDYDates,
complexMDYSorted,
function( $table ) {
- mw.config.set('wgDefaultDateFormat', window.wgDefaultDateFormat = 'mdy');
+ mw.config.set( 'wgDefaultDateFormat', 'mdy' );
+
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
@@ -362,9 +378,9 @@ tableTest(
planets,
ascendingNameLegacy,
function( $table ) {
- $table.find('tr:last').addClass('sortbottom');
+ $table.find( 'tr:last' ).addClass( 'sortbottom' );
$table.tablesorter();
- $table.find('.headerSort:eq(0)').click();
+ $table.find( '.headerSort:eq(0)' ).click();
}
);
@@ -472,4 +488,65 @@ test( 'data-sort-value attribute, when available, should override sorting positi
});
+var numbers = [
+ [ '12' ],
+ [ '7' ],
+ [ '13,000'],
+ [ '9' ],
+ [ '14' ],
+ [ '8.0' ]
+];
+var numbersAsc = [
+ [ '7' ],
+ [ '8.0' ],
+ [ '9' ],
+ [ '12' ],
+ [ '14' ],
+ [ '13,000']
+];
+
+tableTest( 'bug 8115: sort numbers with commas (ascending)',
+ ['Numbers'], numbers, numbersAsc,
+ function( $table ) {
+ $table.tablesorter();
+ $table.find( '.headerSort:eq(0)' ).click();
+ }
+);
+
+tableTest( 'bug 8115: sort numbers with commas (descending)',
+ ['Numbers'], numbers, reversed(numbersAsc),
+ function( $table ) {
+ $table.tablesorter();
+ $table.find( '.headerSort:eq(0)' ).click().click();
+ }
+);
+// TODO add numbers sorting tests for bug 8115 with a different language
+
+test( 'bug 32888 - Tables inside a tableheader cell', function() {
+ expect(2);
+
+ var $table;
+ $table = $(
+ '<table class="sortable" id="32888">' +
+ '<tr><th>header<table id="32888-2">'+
+ '<tr><th>1</th><th>2</th></tr>' +
+ '</table></th></tr>' +
+ '<tr><td>A</td></tr>' +
+ '<tr><td>B</td></tr>' +
+ '</table>'
+ );
+ $table.tablesorter();
+
+ equals(
+ $table.find('> thead:eq(0) > tr > th.headerSort').length,
+ 1,
+ 'Child tables inside a headercell should not interfere with sortable headers (bug 32888)'
+ );
+ equals(
+ $('#32888-2').find('th.headerSort').length,
+ 0,
+ 'The headers of child tables inside a headercell should not be sortable themselves (bug 32888)'
+ );
+});
+
})();
diff --git a/tests/qunit/suites/resources/jquery/jquery.textSelection.test.js b/tests/qunit/suites/resources/jquery/jquery.textSelection.test.js
new file mode 100644
index 00000000..1b2f3024
--- /dev/null
+++ b/tests/qunit/suites/resources/jquery/jquery.textSelection.test.js
@@ -0,0 +1,279 @@
+module( 'jquery.textSelection', QUnit.newMwEnvironment() );
+
+test( '-- Initial check', function() {
+ expect(1);
+ ok( $.fn.textSelection, 'jQuery.fn.textSelection defined' );
+} );
+
+/**
+ * Test factory for $.fn.textSelection( 'encapsulateText' )
+ *
+ * @param options {object} associative array containing:
+ * description {string}
+ * input {string}
+ * output {string}
+ * start {int} starting char for selection
+ * end {int} ending char for selection
+ * params {object} add'l parameters for $().textSelection( 'encapsulateText' )
+ */
+var encapsulateTest = function( options ) {
+ var opt = $.extend({
+ description: '',
+ before: {},
+ after: {},
+ replace: {}
+ }, options);
+
+ opt.before = $.extend({
+ text: '',
+ start: 0,
+ end: 0
+ }, opt.before);
+ opt.after = $.extend({
+ text: '',
+ selected: null
+ }, opt.after);
+
+ test( opt.description, function() {
+ var tests = 1;
+ if ( opt.after.selected !== null ) {
+ tests++;
+ }
+ expect( tests );
+
+ var $textarea = $( '<textarea>' );
+
+ $( '#qunit-fixture' ).append( $textarea );
+
+ //$textarea.textSelection( 'setContents', opt.before.text); // this method is actually missing atm...
+ $textarea.val( opt.before.text ); // won't work with the WikiEditor iframe?
+
+ var start = opt.before.start,
+ end = opt.before.end;
+ if ( window.opera ) {
+ // Compensate for Opera's craziness converting "\n" to "\r\n" and counting that as two chars
+ var newLinesBefore = opt.before.text.substring( 0, start ).split( "\n" ).length - 1,
+ newLinesInside = opt.before.text.substring( start, end ).split( "\n" ).length - 1;
+ start += newLinesBefore;
+ end += newLinesBefore + newLinesInside;
+ }
+
+ var options = $.extend( {}, opt.replace ); // Clone opt.replace
+ options.selectionStart = start;
+ options.selectionEnd = end;
+ $textarea.textSelection( 'encapsulateSelection', options );
+
+ var text = $textarea.textSelection( 'getContents' ).replace( /\r\n/g, "\n" );
+
+ equal( text, opt.after.text, 'Checking full text after encapsulation' );
+
+ if (opt.after.selected !== null) {
+ var selected = $textarea.textSelection( 'getSelection' );
+ equal( selected, opt.after.selected, 'Checking selected text after encapsulation.' );
+ }
+
+ } );
+};
+
+var sig = {
+ 'pre': "--~~~~"
+}, bold = {
+ pre: "'''",
+ peri: 'Bold text',
+ post: "'''"
+}, h2 = {
+ 'pre': '== ',
+ 'peri': 'Heading 2',
+ 'post': ' ==',
+ 'regex': /^(\s*)(={1,6})(.*?)\2(\s*)$/,
+ 'regexReplace': "\$1==\$3==\$4",
+ 'ownline': true
+}, ulist = {
+ 'pre': "* ",
+ 'peri': 'Bulleted list item',
+ 'post': "",
+ 'ownline': true,
+ 'splitlines': true
+};
+
+encapsulateTest({
+ description: "Adding sig to end of text",
+ before: {
+ text: "Wikilove dude! ",
+ start: 15,
+ end: 15
+ },
+ after: {
+ text: "Wikilove dude! --~~~~",
+ selected: ""
+ },
+ replace: sig
+});
+
+encapsulateTest({
+ description: "Adding bold to empty",
+ before: {
+ text: "",
+ start: 0,
+ end: 0
+ },
+ after: {
+ text: "'''Bold text'''",
+ selected: "Bold text" // selected because it's the default
+ },
+ replace: bold
+});
+
+encapsulateTest({
+ description: "Adding bold to existing text",
+ before: {
+ text: "Now is the time for all good men to come to the aid of their country",
+ start: 20,
+ end: 32
+ },
+ after: {
+ text: "Now is the time for '''all good men''' to come to the aid of their country",
+ selected: "" // empty because it's not the default'
+ },
+ replace: bold
+});
+
+encapsulateTest({
+ description: "ownline option: adding new h2",
+ before: {
+ text:"Before\nAfter",
+ start: 7,
+ end: 7
+ },
+ after: {
+ text: "Before\n== Heading 2 ==\nAfter",
+ selected: "Heading 2"
+ },
+ replace: h2
+});
+
+encapsulateTest({
+ description: "ownline option: turn a whole line into new h2",
+ before: {
+ text:"Before\nMy heading\nAfter",
+ start: 7,
+ end: 17
+ },
+ after: {
+ text: "Before\n== My heading ==\nAfter",
+ selected: ""
+ },
+ replace: h2
+});
+
+
+encapsulateTest({
+ description: "ownline option: turn a partial line into new h2",
+ before: {
+ text:"BeforeMy headingAfter",
+ start: 6,
+ end: 16
+ },
+ after: {
+ text: "Before\n== My heading ==\nAfter",
+ selected: ""
+ },
+ replace: h2
+});
+
+
+encapsulateTest({
+ description: "splitlines option: no selection, insert new list item",
+ before: {
+ text: "Before\nAfter",
+ start: 7,
+ end: 7
+ },
+ after: {
+ text: "Before\n* Bulleted list item\nAfter"
+ },
+ replace: ulist
+});
+
+encapsulateTest({
+ description: "splitlines option: single partial line selection, insert new list item",
+ before: {
+ text: "BeforeMy List ItemAfter",
+ start: 6,
+ end: 18
+ },
+ after: {
+ text: "Before\n* My List Item\nAfter"
+ },
+ replace: ulist
+});
+
+encapsulateTest({
+ description: "splitlines option: multiple lines",
+ before: {
+ text: "Before\nFirst\nSecond\nThird\nAfter",
+ start: 7,
+ end: 25
+ },
+ after: {
+ text: "Before\n* First\n* Second\n* Third\nAfter"
+ },
+ replace: ulist
+});
+
+
+var caretTest = function(options) {
+ test(options.description, function() {
+ expect(2);
+
+ var $textarea = $( '<textarea>' ).text(options.text);
+
+ $( '#qunit-fixture' ).append( $textarea );
+
+ if (options.mode == 'set') {
+ $textarea.textSelection('setSelection', {
+ start: options.start,
+ end: options.end
+ });
+ }
+
+ var among = function(actual, expected, message) {
+ if ($.isArray(expected)) {
+ ok($.inArray(actual, expected) !== -1 , message + ' (got ' + actual + '; expected one of ' + expected.join(', ') + ')');
+ } else {
+ equal(actual, expected, message);
+ }
+ };
+
+ var pos = $textarea.textSelection('getCaretPosition', {startAndEnd: true});
+ among(pos[0], options.start, 'Caret start should be where we set it.');
+ among(pos[1], options.end, 'Caret end should be where we set it.');
+ });
+}
+
+var caretSample = "Some big text that we like to work with. Nothing fancy... you know what I mean?";
+
+caretTest({
+ description: 'getCaretPosition with original/empty selection - bug 31847 with IE 6/7/8',
+ text: caretSample,
+ start: [0, caretSample.length], // Opera and Firefox (prior to FF 6.0) default caret to the end of the box (caretSample.length)
+ end: [0, caretSample.length], // Other browsers default it to the beginning (0), so check both.
+ mode: 'get'
+});
+
+caretTest({
+ description: 'set/getCaretPosition with forced empty selection',
+ text: caretSample,
+ start: 7,
+ end: 7,
+ mode: 'set'
+});
+
+caretTest({
+ description: 'set/getCaretPosition with small selection',
+ text: caretSample,
+ start: 6,
+ end: 11,
+ mode: 'set'
+});
+