3 // Based on IPTest.php > testisIPv4
5 [false, false, 'Boolean false is not an IP'],
6 [false, true, 'Boolean true is not an IP'],
7 [false, '', 'Empty string is not an IP'],
8 [false, 'abc', '"abc" is not an IP'],
9 [false, ':', 'Colon is not an IP'],
10 [false, '124.24.52', 'IPv4 not enough quads'],
11 [false, '24.324.52.13', 'IPv4 out of range'],
12 [false, '.24.52.13', 'IPv4 starts with period'],
14 [true, '124.24.52.13', '124.24.52.134 is a valid IP'],
15 [true, '1.24.52.13', '1.24.52.13 is a valid IP'],
16 [false, '74.24.52.13/20', 'IPv4 ranges are not recognized as valid IPs']
19 // Based on IPTest.php > testisIPv6
21 [false, ':fc:100::', 'IPv6 starting with lone ":"'],
22 [false, 'fc:100:::', 'IPv6 ending with a ":::"'],
23 [false, 'fc:300', 'IPv6 with only 2 words'],
24 [false, 'fc:100:300', 'IPv6 with only 3 words'],
26 [false, 'fc:100:a:d:1:e:ac:0::', 'IPv6 with 8 words ending with "::"'],
27 [false, 'fc:100:a:d:1:e:ac:0:1::', 'IPv6 with 9 words ending with "::"'],
30 [false, '::0:', 'IPv6 ending in a lone ":"'],
32 [true, '::', 'IPv6 zero address'],
34 [false, '::fc:100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words'],
35 [false, '::fc:100:a:d:1:e:ac:0:1', 'IPv6 with 9 words'],
37 [false, ':fc::100', 'IPv6 starting with lone ":"'],
38 [false, 'fc::100:', 'IPv6 ending with lone ":"'],
39 [false, 'fc:::100', 'IPv6 with ":::" in the middle'],
41 [true, 'fc::100', 'IPv6 with "::" and 2 words'],
42 [true, 'fc::100:a', 'IPv6 with "::" and 3 words'],
43 [true, 'fc::100:a:d', 'IPv6 with "::" and 4 words'],
44 [true, 'fc::100:a:d:1', 'IPv6 with "::" and 5 words'],
45 [true, 'fc::100:a:d:1:e', 'IPv6 with "::" and 6 words'],
46 [true, 'fc::100:a:d:1:e:ac', 'IPv6 with "::" and 7 words'],
47 [true, '2001::df', 'IPv6 with "::" and 2 words'],
48 [true, '2001:5c0:1400:a::df', 'IPv6 with "::" and 5 words'],
49 [true, '2001:5c0:1400:a::df:2', 'IPv6 with "::" and 6 words'],
51 [false, 'fc::100:a:d:1:e:ac:0', 'IPv6 with "::" and 8 words'],
52 [false, 'fc::100:a:d:1:e:ac:0:1', 'IPv6 with 9 words']
55 Array
.prototype.push
.apply( IPV6_CASES
,
62 'fc:100:a:d:1:e:ac::',
70 '::fc:100:a:d:1:e:ac',
73 return [[ true, el
, el
+ ' is a valid IP' ]];
77 QUnit
.module( 'mediawiki.util', QUnit
.newMwEnvironment( {
79 $.fn
.updateTooltipAccessKeys
.setTestMode( true );
81 teardown: function () {
82 $.fn
.updateTooltipAccessKeys
.setTestMode( false );
85 // Used by accessKeyLabel in test for addPortletLink
91 QUnit
.test( 'rawurlencode', 1, function ( assert
) {
92 assert
.equal( mw
.util
.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
95 QUnit
.test( 'wikiUrlencode', 11, function ( assert
) {
96 assert
.equal( mw
.util
.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
97 // See also wfUrlencodeTest.php#provideURLS
103 ';@$-_.!*': ';@$-_.!*',
109 }, function ( input
, output
) {
110 assert
.equal( mw
.util
.wikiUrlencode( input
), output
);
114 QUnit
.test( 'getUrl', 5, function ( assert
) {
115 // Not part of startUp module
116 mw
.config
.set( 'wgArticlePath', '/wiki/$1' );
117 mw
.config
.set( 'wgPageName', 'Foobar' );
119 var href
= mw
.util
.getUrl( 'Sandbox' );
120 assert
.equal( href
, '/wiki/Sandbox', 'simple title' );
122 href
= mw
.util
.getUrl( 'Foo:Sandbox? 5+5=10! (test)/sub ' );
123 assert
.equal( href
, '/wiki/Foo:Sandbox%3F_5%2B5%3D10!_(test)/sub_', 'advanced title' );
125 href
= mw
.util
.getUrl();
126 assert
.equal( href
, '/wiki/Foobar', 'default title' );
128 href
= mw
.util
.getUrl( null, { action
: 'edit' } );
129 assert
.equal( href
, '/wiki/Foobar?action=edit', 'default title with query string' );
131 href
= mw
.util
.getUrl( 'Sandbox', { action
: 'edit' } );
132 assert
.equal( href
, '/wiki/Sandbox?action=edit', 'simple title with query string' );
135 QUnit
.test( 'wikiScript', 4, function ( assert
) {
137 'wgScript': '/w/i.php', // customized wgScript for bug 39103
138 'wgLoadScript': '/w/l.php', // customized wgLoadScript for bug 39103
139 'wgScriptPath': '/w',
140 'wgScriptExtension': '.php'
143 assert
.equal( mw
.util
.wikiScript(), mw
.config
.get( 'wgScript' ),
144 'wikiScript() returns wgScript'
146 assert
.equal( mw
.util
.wikiScript( 'index' ), mw
.config
.get( 'wgScript' ),
147 'wikiScript( index ) returns wgScript'
149 assert
.equal( mw
.util
.wikiScript( 'load' ), mw
.config
.get( 'wgLoadScript' ),
150 'wikiScript( load ) returns wgLoadScript'
152 assert
.equal( mw
.util
.wikiScript( 'api' ), '/w/api.php', 'API path' );
155 QUnit
.test( 'addCSS', 3, function ( assert
) {
157 $el
= $( '<div>' ).attr( 'id', 'mw-addcsstest' ).appendTo( '#qunit-fixture' );
159 style
= mw
.util
.addCSS( '#mw-addcsstest { visibility: hidden; }' );
160 assert
.equal( typeof style
, 'object', 'addCSS returned an object' );
161 assert
.strictEqual( style
.disabled
, false, 'property "disabled" is available and set to false' );
163 assert
.equal( $el
.css( 'visibility' ), 'hidden', 'Added style properties are in effect' );
166 $( style
.ownerNode
).remove();
169 QUnit
.test( 'getParamValue', 5, function ( assert
) {
172 url
= 'http://example.org/?foo=wrong&foo=right#&foo=bad';
173 assert
.equal( mw
.util
.getParamValue( 'foo', url
), 'right', 'Use latest one, ignore hash' );
174 assert
.strictEqual( mw
.util
.getParamValue( 'bar', url
), null, 'Return null when not found' );
176 url
= 'http://example.org/#&foo=bad';
177 assert
.strictEqual( mw
.util
.getParamValue( 'foo', url
), null, 'Ignore hash if param is not in querystring but in hash (bug 27427)' );
179 url
= 'example.org?' + $.param( { 'TEST': 'a b+c' } );
180 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c', 'Bug 30441: getParamValue must understand "+" encoding of space' );
182 url
= 'example.org?' + $.param( { 'TEST': 'a b+c d' } ); // check for sloppy code from r95332 :)
183 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
186 QUnit
.test( 'tooltipAccessKey', 4, function ( assert
) {
187 this.suppressWarnings();
189 assert
.equal( typeof mw
.util
.tooltipAccessKeyPrefix
, 'string', 'tooltipAccessKeyPrefix must be a string' );
190 assert
.equal( $.type( mw
.util
.tooltipAccessKeyRegexp
), 'regexp', 'tooltipAccessKeyRegexp is a regexp' );
191 assert
.ok( mw
.util
.updateTooltipAccessKeys
, 'updateTooltipAccessKeys is non-empty' );
193 'Example [a]'.replace( mw
.util
.tooltipAccessKeyRegexp
, function ( sub
, m1
, m2
, m3
, m4
, m5
, m6
) {
194 assert
.equal( m6
, 'a', 'tooltipAccessKeyRegexp finds the accesskey hint' );
197 this.restoreWarnings();
200 QUnit
.test( '$content', 2, function ( assert
) {
201 assert
.ok( mw
.util
.$content
instanceof jQuery
, 'mw.util.$content instance of jQuery' );
202 assert
.strictEqual( mw
.util
.$content
.length
, 1, 'mw.util.$content must have length of 1' );
206 * Portlet names are prefixed with 'p-test' to avoid conflict with core
207 * when running the test suite under a wiki page.
208 * Previously, test elements where invisible to the selector since only
209 * one element can have a given id.
211 QUnit
.test( 'addPortletLink', 13, function ( assert
) {
212 var pTestTb
, pCustom
, vectorTabs
, tbRL
, cuQuux
, $cuQuux
, tbMW
, $tbMW
, tbRLDM
, caFoo
,
213 addedAfter
, tbRLDMnonexistentid
, tbRLDMemptyjquery
;
216 <div class="portlet" id="p-test-tb">\
218 <ul class="body"></ul>\
221 <div class="portlet" id="p-test-custom">\
224 <li id="c-foo"><a href="#">Foo</a></li>\
227 <li id="c-bar-baz"><a href="#">Baz</a></a>\
233 <div id="p-test-views" class="vectorTabs">\
238 $( '#qunit-fixture' ).append( pTestTb
, pCustom
, vectorTabs
);
240 tbRL
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/ResourceLoader',
241 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l'
244 assert
.ok( tbRL
&& tbRL
.nodeType
, 'addPortletLink returns a DOM Node' );
246 tbMW
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/',
247 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org', 'm', tbRL
);
255 'Validate attributes of created element'
259 $tbMW
.find( 'a' ).getAttrs(),
261 href
: '//mediawiki.org/',
262 title
: 'Go to MediaWiki.org [test-m]',
265 'Validate attributes of anchor tag in created element'
268 assert
.equal( $tbMW
.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
269 assert
.strictEqual( $tbMW
.next()[0], tbRL
, 'Link is in the correct position (nextnode as Node object)' );
271 cuQuux
= mw
.util
.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
272 $cuQuux
= $( cuQuux
);
274 assert
.equal( $cuQuux
.find( 'a' ).attr( 'title' ), 'Example [test-q]', 'Existing accesskey is stripped and updated' );
277 $( '#p-test-custom #c-barmenu ul li' ).length
,
279 'addPortletLink did not add the item to all <ul> elements in the portlet (bug 35082)'
282 tbRLDM
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
283 'Default modules', 't-rldm', 'List of all default modules ', 'd', '#t-rl' );
285 assert
.strictEqual( $( tbRLDM
).next()[0], tbRL
, 'Link is in the correct position (CSS selector as nextnode)' );
287 caFoo
= mw
.util
.addPortletLink( 'p-test-views', '#', 'Foo' );
289 assert
.strictEqual( $tbMW
.find( 'span' ).length
, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
290 assert
.strictEqual( $( caFoo
).find( 'span' ).length
, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
292 addedAfter
= mw
.util
.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL
) );
293 assert
.strictEqual( $( addedAfter
).next()[0], tbRL
, 'Link is in the correct position (jQuery object as nextnode)' );
295 // test case - nonexistent id as next node
296 tbRLDMnonexistentid
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
297 'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
299 assert
.equal( tbRLDMnonexistentid
, $( '#p-test-tb li:last' )[0], 'Fallback to adding at the end (nextnode non-matching CSS selector)' );
301 // test case - empty jquery object as next node
302 tbRLDMemptyjquery
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
303 'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
305 assert
.equal( tbRLDMemptyjquery
, $( '#p-test-tb li:last' )[0], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
308 QUnit
.test( 'validateEmail', 6, function ( assert
) {
309 assert
.strictEqual( mw
.util
.validateEmail( '' ), null, 'Should return null for empty string ' );
310 assert
.strictEqual( mw
.util
.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
312 // testEmailWithCommasAreInvalids
313 assert
.strictEqual( mw
.util
.validateEmail( 'user,foo@example.org' ), false, 'Emails with commas are invalid' );
314 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex,ample.org' ), false, 'Emails with commas are invalid' );
316 // testEmailWithHyphens
317 assert
.strictEqual( mw
.util
.validateEmail( 'user-foo@example.org' ), true, 'Emails may contain a hyphen' );
318 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
321 QUnit
.test( 'isIPv6Address', 40, function ( assert
) {
322 $.each( IPV6_CASES
, function ( i
, ipCase
) {
323 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[1] ), ipCase
[0], ipCase
[2] );
327 QUnit
.test( 'isIPv4Address', 11, function ( assert
) {
328 $.each( IPV4_CASES
, function ( i
, ipCase
) {
329 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[1] ), ipCase
[0], ipCase
[2] );
333 QUnit
.test( 'isIPAddress', 51, function ( assert
) {
334 $.each( IPV4_CASES
, function ( i
, ipCase
) {
335 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[1] ), ipCase
[0], ipCase
[2] );
338 $.each( IPV6_CASES
, function ( i
, ipCase
) {
339 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[1] ), ipCase
[0], ipCase
[2] );
342 }( mediaWiki
, jQuery
) );