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( 'escapeId', 17, function ( assert
) {
96 mw
.config
.set( 'wgExperimentalHtmlIds', false );
113 'Test:A & B/Here': 'Test:A_.26_B.2FHere',
114 'A&B&C&D&E': 'A.26B.26amp.3BC.26amp.3Bamp.3BD.26amp.3Bamp.3Bamp.3BE'
115 }, function ( input
, output
) {
116 assert
.equal( mw
.util
.escapeId( input
), output
);
120 QUnit
.test( 'wikiUrlencode', 11, function ( assert
) {
121 assert
.equal( mw
.util
.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
122 // See also wfUrlencodeTest.php#provideURLS
128 ';@$-_.!*': ';@$-_.!*',
134 }, function ( input
, output
) {
135 assert
.equal( mw
.util
.wikiUrlencode( input
), output
);
139 QUnit
.test( 'getUrl', 13, function ( assert
) {
142 wgScript
: '/w/index.php',
143 wgArticlePath
: '/wiki/$1',
147 href
= mw
.util
.getUrl( 'Sandbox' );
148 assert
.equal( href
, '/wiki/Sandbox', 'simple title' );
150 href
= mw
.util
.getUrl( 'Foo:Sandbox? 5+5=10! (test)/sub ' );
151 assert
.equal( href
, '/wiki/Foo:Sandbox%3F_5%2B5%3D10!_(test)/sub_', 'complex title' );
153 href
= mw
.util
.getUrl();
154 assert
.equal( href
, '/wiki/Foobar', 'default title' );
156 href
= mw
.util
.getUrl( null, { action
: 'edit' } );
157 assert
.equal( href
, '/w/index.php?title=Foobar&action=edit', 'default title with query string' );
159 href
= mw
.util
.getUrl( 'Sandbox', { action
: 'edit' } );
160 assert
.equal( href
, '/w/index.php?title=Sandbox&action=edit', 'simple title with query string' );
163 href
= mw
.util
.getUrl( 'Foo:Sandbox#Fragment', { action
: 'edit' } );
164 assert
.equal( href
, '/w/index.php?title=Foo:Sandbox&action=edit#Fragment', 'namespaced title with query string and fragment' );
166 href
= mw
.util
.getUrl( 'Sandbox#', { action
: 'edit' } );
167 assert
.equal( href
, '/w/index.php?title=Sandbox&action=edit', 'title with query string and empty fragment' );
169 href
= mw
.util
.getUrl( 'Sandbox', {} );
170 assert
.equal( href
, '/wiki/Sandbox', 'title with empty query string' );
172 href
= mw
.util
.getUrl( '#Fragment' );
173 assert
.equal( href
, '/wiki/#Fragment', 'empty title with fragment' );
175 href
= mw
.util
.getUrl( '#Fragment', { action
: 'edit' } );
176 assert
.equal( href
, '/w/index.php?action=edit#Fragment', 'epmty title with query string and fragment' );
178 href
= mw
.util
.getUrl( 'Foo:Sandbox \xC4#Fragment \xC4', { action
: 'edit' } );
179 assert
.equal( href
, '/w/index.php?title=Foo:Sandbox_%C3%84&action=edit#Fragment_.C3.84', 'title with query string, fragment, and special characters' );
181 href
= mw
.util
.getUrl( 'Foo:%23#Fragment', { action
: 'edit' } );
182 assert
.equal( href
, '/w/index.php?title=Foo:%2523&action=edit#Fragment', 'title containing %23 (#), fragment, and a query string' );
184 href
= mw
.util
.getUrl( '#+&=:;@$-_.!*/[]<>\'ยง', { action
: 'edit' } );
185 assert
.equal( href
, '/w/index.php?action=edit#.2B.26.3D:.3B.40.24-_..21.2A.2F.5B.5D.3C.3E.27.C2.A7', 'fragment with various characters' );
188 QUnit
.test( 'wikiScript', 4, function ( assert
) {
190 // customized wgScript for T41103
191 wgScript
: '/w/i.php',
192 // customized wgLoadScript for T41103
193 wgLoadScript
: '/w/l.php',
197 assert
.equal( mw
.util
.wikiScript(), mw
.config
.get( 'wgScript' ),
198 'wikiScript() returns wgScript'
200 assert
.equal( mw
.util
.wikiScript( 'index' ), mw
.config
.get( 'wgScript' ),
201 'wikiScript( index ) returns wgScript'
203 assert
.equal( mw
.util
.wikiScript( 'load' ), mw
.config
.get( 'wgLoadScript' ),
204 'wikiScript( load ) returns wgLoadScript'
206 assert
.equal( mw
.util
.wikiScript( 'api' ), '/w/api.php', 'API path' );
209 QUnit
.test( 'addCSS', 3, function ( assert
) {
211 $el
= $( '<div>' ).attr( 'id', 'mw-addcsstest' ).appendTo( '#qunit-fixture' );
213 style
= mw
.util
.addCSS( '#mw-addcsstest { visibility: hidden; }' );
214 assert
.equal( typeof style
, 'object', 'addCSS returned an object' );
215 assert
.strictEqual( style
.disabled
, false, 'property "disabled" is available and set to false' );
217 assert
.equal( $el
.css( 'visibility' ), 'hidden', 'Added style properties are in effect' );
220 $( style
.ownerNode
).remove();
223 QUnit
.test( 'getParamValue', 5, function ( assert
) {
226 url
= 'http://example.org/?foo=wrong&foo=right#&foo=bad';
227 assert
.equal( mw
.util
.getParamValue( 'foo', url
), 'right', 'Use latest one, ignore hash' );
228 assert
.strictEqual( mw
.util
.getParamValue( 'bar', url
), null, 'Return null when not found' );
230 url
= 'http://example.org/#&foo=bad';
231 assert
.strictEqual( mw
.util
.getParamValue( 'foo', url
), null, 'Ignore hash if param is not in querystring but in hash (bug 27427)' );
233 url
= 'example.org?' + $.param( { TEST
: 'a b+c' } );
234 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c', 'Bug 30441: getParamValue must understand "+" encoding of space' );
236 url
= 'example.org?' + $.param( { TEST
: 'a b+c d' } ); // check for sloppy code from r95332 :)
237 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
240 QUnit
.test( 'tooltipAccessKey', 4, function ( assert
) {
241 this.suppressWarnings();
243 assert
.equal( typeof mw
.util
.tooltipAccessKeyPrefix
, 'string', 'tooltipAccessKeyPrefix must be a string' );
244 assert
.equal( $.type( mw
.util
.tooltipAccessKeyRegexp
), 'regexp', 'tooltipAccessKeyRegexp is a regexp' );
245 assert
.ok( mw
.util
.updateTooltipAccessKeys
, 'updateTooltipAccessKeys is non-empty' );
247 'Example [a]'.replace( mw
.util
.tooltipAccessKeyRegexp
, function ( sub
, m1
, m2
, m3
, m4
, m5
, m6
) {
248 assert
.equal( m6
, 'a', 'tooltipAccessKeyRegexp finds the accesskey hint' );
251 this.restoreWarnings();
254 QUnit
.test( '$content', 2, function ( assert
) {
255 assert
.ok( mw
.util
.$content
instanceof jQuery
, 'mw.util.$content instance of jQuery' );
256 assert
.strictEqual( mw
.util
.$content
.length
, 1, 'mw.util.$content must have length of 1' );
260 * Portlet names are prefixed with 'p-test' to avoid conflict with core
261 * when running the test suite under a wiki page.
262 * Previously, test elements where invisible to the selector since only
263 * one element can have a given id.
265 QUnit
.test( 'addPortletLink', 13, function ( assert
) {
266 var pTestTb
, pCustom
, vectorTabs
, tbRL
, cuQuux
, $cuQuux
, tbMW
, $tbMW
, tbRLDM
, caFoo
,
267 addedAfter
, tbRLDMnonexistentid
, tbRLDMemptyjquery
;
270 <div class="portlet" id="p-test-tb">\
272 <ul class="body"></ul>\
275 <div class="portlet" id="p-test-custom">\
278 <li id="c-foo"><a href="#">Foo</a></li>\
281 <li id="c-bar-baz"><a href="#">Baz</a></a>\
287 <div id="p-test-views" class="vectorTabs">\
292 $( '#qunit-fixture' ).append( pTestTb
, pCustom
, vectorTabs
);
294 tbRL
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/ResourceLoader',
295 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l'
298 assert
.ok( tbRL
&& tbRL
.nodeType
, 'addPortletLink returns a DOM Node' );
300 tbMW
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/',
301 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org', 'm', tbRL
);
309 'Validate attributes of created element'
313 $tbMW
.find( 'a' ).getAttrs(),
315 href
: '//mediawiki.org/',
316 title
: 'Go to MediaWiki.org [test-m]',
319 'Validate attributes of anchor tag in created element'
322 assert
.equal( $tbMW
.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
323 assert
.strictEqual( $tbMW
.next()[ 0 ], tbRL
, 'Link is in the correct position (nextnode as Node object)' );
325 cuQuux
= mw
.util
.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
326 $cuQuux
= $( cuQuux
);
328 assert
.equal( $cuQuux
.find( 'a' ).attr( 'title' ), 'Example [test-q]', 'Existing accesskey is stripped and updated' );
331 $( '#p-test-custom #c-barmenu ul li' ).length
,
333 'addPortletLink did not add the item to all <ul> elements in the portlet (bug 35082)'
336 tbRLDM
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
337 'Default modules', 't-rldm', 'List of all default modules ', 'd', '#t-rl' );
339 assert
.strictEqual( $( tbRLDM
).next()[ 0 ], tbRL
, 'Link is in the correct position (CSS selector as nextnode)' );
341 caFoo
= mw
.util
.addPortletLink( 'p-test-views', '#', 'Foo' );
343 assert
.strictEqual( $tbMW
.find( 'span' ).length
, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
344 assert
.strictEqual( $( caFoo
).find( 'span' ).length
, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
346 addedAfter
= mw
.util
.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL
) );
347 assert
.strictEqual( $( addedAfter
).next()[ 0 ], tbRL
, 'Link is in the correct position (jQuery object as nextnode)' );
349 // test case - nonexistent id as next node
350 tbRLDMnonexistentid
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
351 'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
353 assert
.equal( tbRLDMnonexistentid
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode non-matching CSS selector)' );
355 // test case - empty jquery object as next node
356 tbRLDMemptyjquery
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
357 'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
359 assert
.equal( tbRLDMemptyjquery
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
362 QUnit
.test( 'validateEmail', 6, function ( assert
) {
363 assert
.strictEqual( mw
.util
.validateEmail( '' ), null, 'Should return null for empty string ' );
364 assert
.strictEqual( mw
.util
.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
366 // testEmailWithCommasAreInvalids
367 assert
.strictEqual( mw
.util
.validateEmail( 'user,foo@example.org' ), false, 'Emails with commas are invalid' );
368 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex,ample.org' ), false, 'Emails with commas are invalid' );
370 // testEmailWithHyphens
371 assert
.strictEqual( mw
.util
.validateEmail( 'user-foo@example.org' ), true, 'Emails may contain a hyphen' );
372 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
375 QUnit
.test( 'isIPv6Address', 40, function ( assert
) {
376 $.each( IPV6_CASES
, function ( i
, ipCase
) {
377 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
381 QUnit
.test( 'isIPv4Address', 11, function ( assert
) {
382 $.each( IPV4_CASES
, function ( i
, ipCase
) {
383 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
387 QUnit
.test( 'isIPAddress', 51, function ( assert
) {
388 $.each( IPV4_CASES
, function ( i
, ipCase
) {
389 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
392 $.each( IPV6_CASES
, function ( i
, ipCase
) {
393 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
396 }( mediaWiki
, jQuery
) );