5d721795601fc85f8396135f88d452bde4d346ac
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', 12, function ( assert
) {
141 wgArticlePath
: '/wiki/$1',
145 var href
= mw
.util
.getUrl( 'Sandbox' );
146 assert
.equal( href
, '/wiki/Sandbox', 'simple title' );
148 href
= mw
.util
.getUrl( 'Foo:Sandbox? 5+5=10! (test)/sub ' );
149 assert
.equal( href
, '/wiki/Foo:Sandbox%3F_5%2B5%3D10!_(test)/sub_', 'advanced title' );
151 href
= mw
.util
.getUrl();
152 assert
.equal( href
, '/wiki/Foobar', 'default title' );
154 href
= mw
.util
.getUrl( null, { action
: 'edit' } );
155 assert
.equal( href
, '/wiki/Foobar?action=edit', 'default title with query string' );
157 href
= mw
.util
.getUrl( 'Sandbox', { action
: 'edit' } );
158 assert
.equal( href
, '/wiki/Sandbox?action=edit', 'simple title with query string' );
161 href
= mw
.util
.getUrl( 'Foo:Sandbox#Fragment', { action
: 'edit' } );
162 assert
.equal( href
, '/wiki/Foo:Sandbox?action=edit#Fragment', 'advanced title with query string and fragment' );
164 href
= mw
.util
.getUrl( 'Foo:Sandbox#', { action
: 'edit' } );
165 assert
.equal( href
, '/wiki/Foo:Sandbox?action=edit', 'title with query string and empty fragment' );
167 href
= mw
.util
.getUrl( '#Fragment' );
168 assert
.equal( href
, '/wiki/#Fragment', 'epmty title with fragment' );
170 href
= mw
.util
.getUrl( '#Fragment', { action
: 'edit' } );
171 assert
.equal( href
, '/wiki/?action=edit#Fragment', 'epmty title with query string and fragment' );
173 href
= mw
.util
.getUrl( 'Foo:Sandbox \xC4#Fragment \xC4', { action
: 'edit' } );
174 assert
.equal( href
, '/wiki/Foo:Sandbox_%C3%84?action=edit#Fragment_.C3.84', 'title with query string, fragment, and special characters' );
176 href
= mw
.util
.getUrl( 'Foo:%23#Fragment', { action
: 'edit' } );
177 assert
.equal( href
, '/wiki/Foo:%2523?action=edit#Fragment', 'title containing %23 (#), fragment, and a query string' );
179 href
= mw
.util
.getUrl( '#+&=:;@$-_.!*/[]<>\'ยง', { action
: 'edit' } );
180 assert
.equal( href
, '/wiki/?action=edit#.2B.26.3D:.3B.40.24-_..21.2A.2F.5B.5D.3C.3E.27.C2.A7', 'fragment with various characters' );
183 QUnit
.test( 'wikiScript', 4, function ( assert
) {
185 // customized wgScript for T41103
186 wgScript
: '/w/i.php',
187 // customized wgLoadScript for T41103
188 wgLoadScript
: '/w/l.php',
192 assert
.equal( mw
.util
.wikiScript(), mw
.config
.get( 'wgScript' ),
193 'wikiScript() returns wgScript'
195 assert
.equal( mw
.util
.wikiScript( 'index' ), mw
.config
.get( 'wgScript' ),
196 'wikiScript( index ) returns wgScript'
198 assert
.equal( mw
.util
.wikiScript( 'load' ), mw
.config
.get( 'wgLoadScript' ),
199 'wikiScript( load ) returns wgLoadScript'
201 assert
.equal( mw
.util
.wikiScript( 'api' ), '/w/api.php', 'API path' );
204 QUnit
.test( 'addCSS', 3, function ( assert
) {
206 $el
= $( '<div>' ).attr( 'id', 'mw-addcsstest' ).appendTo( '#qunit-fixture' );
208 style
= mw
.util
.addCSS( '#mw-addcsstest { visibility: hidden; }' );
209 assert
.equal( typeof style
, 'object', 'addCSS returned an object' );
210 assert
.strictEqual( style
.disabled
, false, 'property "disabled" is available and set to false' );
212 assert
.equal( $el
.css( 'visibility' ), 'hidden', 'Added style properties are in effect' );
215 $( style
.ownerNode
).remove();
218 QUnit
.test( 'getParamValue', 5, function ( assert
) {
221 url
= 'http://example.org/?foo=wrong&foo=right#&foo=bad';
222 assert
.equal( mw
.util
.getParamValue( 'foo', url
), 'right', 'Use latest one, ignore hash' );
223 assert
.strictEqual( mw
.util
.getParamValue( 'bar', url
), null, 'Return null when not found' );
225 url
= 'http://example.org/#&foo=bad';
226 assert
.strictEqual( mw
.util
.getParamValue( 'foo', url
), null, 'Ignore hash if param is not in querystring but in hash (bug 27427)' );
228 url
= 'example.org?' + $.param( { TEST
: 'a b+c' } );
229 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c', 'Bug 30441: getParamValue must understand "+" encoding of space' );
231 url
= 'example.org?' + $.param( { TEST
: 'a b+c d' } ); // check for sloppy code from r95332 :)
232 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
235 QUnit
.test( 'tooltipAccessKey', 4, function ( assert
) {
236 this.suppressWarnings();
238 assert
.equal( typeof mw
.util
.tooltipAccessKeyPrefix
, 'string', 'tooltipAccessKeyPrefix must be a string' );
239 assert
.equal( $.type( mw
.util
.tooltipAccessKeyRegexp
), 'regexp', 'tooltipAccessKeyRegexp is a regexp' );
240 assert
.ok( mw
.util
.updateTooltipAccessKeys
, 'updateTooltipAccessKeys is non-empty' );
242 'Example [a]'.replace( mw
.util
.tooltipAccessKeyRegexp
, function ( sub
, m1
, m2
, m3
, m4
, m5
, m6
) {
243 assert
.equal( m6
, 'a', 'tooltipAccessKeyRegexp finds the accesskey hint' );
246 this.restoreWarnings();
249 QUnit
.test( '$content', 2, function ( assert
) {
250 assert
.ok( mw
.util
.$content
instanceof jQuery
, 'mw.util.$content instance of jQuery' );
251 assert
.strictEqual( mw
.util
.$content
.length
, 1, 'mw.util.$content must have length of 1' );
255 * Portlet names are prefixed with 'p-test' to avoid conflict with core
256 * when running the test suite under a wiki page.
257 * Previously, test elements where invisible to the selector since only
258 * one element can have a given id.
260 QUnit
.test( 'addPortletLink', 13, function ( assert
) {
261 var pTestTb
, pCustom
, vectorTabs
, tbRL
, cuQuux
, $cuQuux
, tbMW
, $tbMW
, tbRLDM
, caFoo
,
262 addedAfter
, tbRLDMnonexistentid
, tbRLDMemptyjquery
;
265 <div class="portlet" id="p-test-tb">\
267 <ul class="body"></ul>\
270 <div class="portlet" id="p-test-custom">\
273 <li id="c-foo"><a href="#">Foo</a></li>\
276 <li id="c-bar-baz"><a href="#">Baz</a></a>\
282 <div id="p-test-views" class="vectorTabs">\
287 $( '#qunit-fixture' ).append( pTestTb
, pCustom
, vectorTabs
);
289 tbRL
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/ResourceLoader',
290 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l'
293 assert
.ok( tbRL
&& tbRL
.nodeType
, 'addPortletLink returns a DOM Node' );
295 tbMW
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/',
296 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org', 'm', tbRL
);
304 'Validate attributes of created element'
308 $tbMW
.find( 'a' ).getAttrs(),
310 href
: '//mediawiki.org/',
311 title
: 'Go to MediaWiki.org [test-m]',
314 'Validate attributes of anchor tag in created element'
317 assert
.equal( $tbMW
.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
318 assert
.strictEqual( $tbMW
.next()[ 0 ], tbRL
, 'Link is in the correct position (nextnode as Node object)' );
320 cuQuux
= mw
.util
.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
321 $cuQuux
= $( cuQuux
);
323 assert
.equal( $cuQuux
.find( 'a' ).attr( 'title' ), 'Example [test-q]', 'Existing accesskey is stripped and updated' );
326 $( '#p-test-custom #c-barmenu ul li' ).length
,
328 'addPortletLink did not add the item to all <ul> elements in the portlet (bug 35082)'
331 tbRLDM
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
332 'Default modules', 't-rldm', 'List of all default modules ', 'd', '#t-rl' );
334 assert
.strictEqual( $( tbRLDM
).next()[ 0 ], tbRL
, 'Link is in the correct position (CSS selector as nextnode)' );
336 caFoo
= mw
.util
.addPortletLink( 'p-test-views', '#', 'Foo' );
338 assert
.strictEqual( $tbMW
.find( 'span' ).length
, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
339 assert
.strictEqual( $( caFoo
).find( 'span' ).length
, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
341 addedAfter
= mw
.util
.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL
) );
342 assert
.strictEqual( $( addedAfter
).next()[ 0 ], tbRL
, 'Link is in the correct position (jQuery object as nextnode)' );
344 // test case - nonexistent id as next node
345 tbRLDMnonexistentid
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
346 'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
348 assert
.equal( tbRLDMnonexistentid
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode non-matching CSS selector)' );
350 // test case - empty jquery object as next node
351 tbRLDMemptyjquery
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
352 'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
354 assert
.equal( tbRLDMemptyjquery
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
357 QUnit
.test( 'validateEmail', 6, function ( assert
) {
358 assert
.strictEqual( mw
.util
.validateEmail( '' ), null, 'Should return null for empty string ' );
359 assert
.strictEqual( mw
.util
.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
361 // testEmailWithCommasAreInvalids
362 assert
.strictEqual( mw
.util
.validateEmail( 'user,foo@example.org' ), false, 'Emails with commas are invalid' );
363 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex,ample.org' ), false, 'Emails with commas are invalid' );
365 // testEmailWithHyphens
366 assert
.strictEqual( mw
.util
.validateEmail( 'user-foo@example.org' ), true, 'Emails may contain a hyphen' );
367 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
370 QUnit
.test( 'isIPv6Address', 40, function ( assert
) {
371 $.each( IPV6_CASES
, function ( i
, ipCase
) {
372 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
376 QUnit
.test( 'isIPv4Address', 11, function ( assert
) {
377 $.each( IPV4_CASES
, function ( i
, ipCase
) {
378 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
382 QUnit
.test( 'isIPAddress', 51, function ( assert
) {
383 $.each( IPV4_CASES
, function ( i
, ipCase
) {
384 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
387 $.each( IPV6_CASES
, function ( i
, ipCase
) {
388 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
391 }( mediaWiki
, jQuery
) );