0b981065adc7b6c6eac5b38bf4193ad440d1bf4d
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
) {
140 // Not part of startUp module
141 mw
.config
.set( 'wgArticlePath', '/wiki/$1' );
142 mw
.config
.set( 'wgPageName', 'Foobar' );
144 var href
= mw
.util
.getUrl( 'Sandbox' );
145 assert
.equal( href
, '/wiki/Sandbox', 'simple title' );
147 href
= mw
.util
.getUrl( 'Foo:Sandbox? 5+5=10! (test)/sub ' );
148 assert
.equal( href
, '/wiki/Foo:Sandbox%3F_5%2B5%3D10!_(test)/sub_', 'advanced title' );
150 href
= mw
.util
.getUrl();
151 assert
.equal( href
, '/wiki/Foobar', 'default title' );
153 href
= mw
.util
.getUrl( null, { action
: 'edit' } );
154 assert
.equal( href
, '/wiki/Foobar?action=edit', 'default title with query string' );
156 href
= mw
.util
.getUrl( 'Sandbox', { action
: 'edit' } );
157 assert
.equal( href
, '/wiki/Sandbox?action=edit', 'simple title with query string' );
160 href
= mw
.util
.getUrl( 'Foo:Sandbox#Fragment', { action
: 'edit' } );
161 assert
.equal( href
, '/wiki/Foo:Sandbox?action=edit#Fragment', 'advanced title with query string and fragment' );
163 href
= mw
.util
.getUrl( 'Foo:Sandbox#', { action
: 'edit' } );
164 assert
.equal( href
, '/wiki/Foo:Sandbox?action=edit', 'title with query string and empty fragment' );
166 href
= mw
.util
.getUrl( '#Fragment' );
167 assert
.equal( href
, '/wiki/#Fragment', 'epmty title with fragment' );
169 href
= mw
.util
.getUrl( '#Fragment', { action
: 'edit' } );
170 assert
.equal( href
, '/wiki/?action=edit#Fragment', 'epmty title with query string and fragment' );
172 href
= mw
.util
.getUrl( 'Foo:Sandbox \xC4#Fragment \xC4', { action
: 'edit' } );
173 assert
.equal( href
, '/wiki/Foo:Sandbox_%C3%84?action=edit#Fragment_.C3.84', 'title with query string, fragment, and special characters' );
175 href
= mw
.util
.getUrl( 'Foo:%23#Fragment', { action
: 'edit' } );
176 assert
.equal( href
, '/wiki/Foo:%2523?action=edit#Fragment', 'title containing %23 (#), fragment, and a query string' );
178 href
= mw
.util
.getUrl( '#+&=:;@$-_.!*/[]<>\'ยง', { action
: 'edit' } );
179 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' );
182 QUnit
.test( 'wikiScript', 4, function ( assert
) {
184 wgScript
: '/w/i.php', // customized wgScript for bug 39103
185 wgLoadScript
: '/w/l.php', // customized wgLoadScript for bug 39103
189 assert
.equal( mw
.util
.wikiScript(), mw
.config
.get( 'wgScript' ),
190 'wikiScript() returns wgScript'
192 assert
.equal( mw
.util
.wikiScript( 'index' ), mw
.config
.get( 'wgScript' ),
193 'wikiScript( index ) returns wgScript'
195 assert
.equal( mw
.util
.wikiScript( 'load' ), mw
.config
.get( 'wgLoadScript' ),
196 'wikiScript( load ) returns wgLoadScript'
198 assert
.equal( mw
.util
.wikiScript( 'api' ), '/w/api.php', 'API path' );
201 QUnit
.test( 'addCSS', 3, function ( assert
) {
203 $el
= $( '<div>' ).attr( 'id', 'mw-addcsstest' ).appendTo( '#qunit-fixture' );
205 style
= mw
.util
.addCSS( '#mw-addcsstest { visibility: hidden; }' );
206 assert
.equal( typeof style
, 'object', 'addCSS returned an object' );
207 assert
.strictEqual( style
.disabled
, false, 'property "disabled" is available and set to false' );
209 assert
.equal( $el
.css( 'visibility' ), 'hidden', 'Added style properties are in effect' );
212 $( style
.ownerNode
).remove();
215 QUnit
.test( 'getParamValue', 5, function ( assert
) {
218 url
= 'http://example.org/?foo=wrong&foo=right#&foo=bad';
219 assert
.equal( mw
.util
.getParamValue( 'foo', url
), 'right', 'Use latest one, ignore hash' );
220 assert
.strictEqual( mw
.util
.getParamValue( 'bar', url
), null, 'Return null when not found' );
222 url
= 'http://example.org/#&foo=bad';
223 assert
.strictEqual( mw
.util
.getParamValue( 'foo', url
), null, 'Ignore hash if param is not in querystring but in hash (bug 27427)' );
225 url
= 'example.org?' + $.param( { TEST
: 'a b+c' } );
226 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c', 'Bug 30441: getParamValue must understand "+" encoding of space' );
228 url
= 'example.org?' + $.param( { TEST
: 'a b+c d' } ); // check for sloppy code from r95332 :)
229 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
232 QUnit
.test( 'tooltipAccessKey', 4, function ( assert
) {
233 this.suppressWarnings();
235 assert
.equal( typeof mw
.util
.tooltipAccessKeyPrefix
, 'string', 'tooltipAccessKeyPrefix must be a string' );
236 assert
.equal( $.type( mw
.util
.tooltipAccessKeyRegexp
), 'regexp', 'tooltipAccessKeyRegexp is a regexp' );
237 assert
.ok( mw
.util
.updateTooltipAccessKeys
, 'updateTooltipAccessKeys is non-empty' );
239 'Example [a]'.replace( mw
.util
.tooltipAccessKeyRegexp
, function ( sub
, m1
, m2
, m3
, m4
, m5
, m6
) {
240 assert
.equal( m6
, 'a', 'tooltipAccessKeyRegexp finds the accesskey hint' );
243 this.restoreWarnings();
246 QUnit
.test( '$content', 2, function ( assert
) {
247 assert
.ok( mw
.util
.$content
instanceof jQuery
, 'mw.util.$content instance of jQuery' );
248 assert
.strictEqual( mw
.util
.$content
.length
, 1, 'mw.util.$content must have length of 1' );
252 * Portlet names are prefixed with 'p-test' to avoid conflict with core
253 * when running the test suite under a wiki page.
254 * Previously, test elements where invisible to the selector since only
255 * one element can have a given id.
257 QUnit
.test( 'addPortletLink', 13, function ( assert
) {
258 var pTestTb
, pCustom
, vectorTabs
, tbRL
, cuQuux
, $cuQuux
, tbMW
, $tbMW
, tbRLDM
, caFoo
,
259 addedAfter
, tbRLDMnonexistentid
, tbRLDMemptyjquery
;
262 <div class="portlet" id="p-test-tb">\
264 <ul class="body"></ul>\
267 <div class="portlet" id="p-test-custom">\
270 <li id="c-foo"><a href="#">Foo</a></li>\
273 <li id="c-bar-baz"><a href="#">Baz</a></a>\
279 <div id="p-test-views" class="vectorTabs">\
284 $( '#qunit-fixture' ).append( pTestTb
, pCustom
, vectorTabs
);
286 tbRL
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/ResourceLoader',
287 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l'
290 assert
.ok( tbRL
&& tbRL
.nodeType
, 'addPortletLink returns a DOM Node' );
292 tbMW
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/',
293 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org', 'm', tbRL
);
301 'Validate attributes of created element'
305 $tbMW
.find( 'a' ).getAttrs(),
307 href
: '//mediawiki.org/',
308 title
: 'Go to MediaWiki.org [test-m]',
311 'Validate attributes of anchor tag in created element'
314 assert
.equal( $tbMW
.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
315 assert
.strictEqual( $tbMW
.next()[ 0 ], tbRL
, 'Link is in the correct position (nextnode as Node object)' );
317 cuQuux
= mw
.util
.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
318 $cuQuux
= $( cuQuux
);
320 assert
.equal( $cuQuux
.find( 'a' ).attr( 'title' ), 'Example [test-q]', 'Existing accesskey is stripped and updated' );
323 $( '#p-test-custom #c-barmenu ul li' ).length
,
325 'addPortletLink did not add the item to all <ul> elements in the portlet (bug 35082)'
328 tbRLDM
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
329 'Default modules', 't-rldm', 'List of all default modules ', 'd', '#t-rl' );
331 assert
.strictEqual( $( tbRLDM
).next()[ 0 ], tbRL
, 'Link is in the correct position (CSS selector as nextnode)' );
333 caFoo
= mw
.util
.addPortletLink( 'p-test-views', '#', 'Foo' );
335 assert
.strictEqual( $tbMW
.find( 'span' ).length
, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
336 assert
.strictEqual( $( caFoo
).find( 'span' ).length
, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
338 addedAfter
= mw
.util
.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL
) );
339 assert
.strictEqual( $( addedAfter
).next()[ 0 ], tbRL
, 'Link is in the correct position (jQuery object as nextnode)' );
341 // test case - nonexistent id as next node
342 tbRLDMnonexistentid
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
343 'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
345 assert
.equal( tbRLDMnonexistentid
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode non-matching CSS selector)' );
347 // test case - empty jquery object as next node
348 tbRLDMemptyjquery
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
349 'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
351 assert
.equal( tbRLDMemptyjquery
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
354 QUnit
.test( 'validateEmail', 6, function ( assert
) {
355 assert
.strictEqual( mw
.util
.validateEmail( '' ), null, 'Should return null for empty string ' );
356 assert
.strictEqual( mw
.util
.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
358 // testEmailWithCommasAreInvalids
359 assert
.strictEqual( mw
.util
.validateEmail( 'user,foo@example.org' ), false, 'Emails with commas are invalid' );
360 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex,ample.org' ), false, 'Emails with commas are invalid' );
362 // testEmailWithHyphens
363 assert
.strictEqual( mw
.util
.validateEmail( 'user-foo@example.org' ), true, 'Emails may contain a hyphen' );
364 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
367 QUnit
.test( 'isIPv6Address', 40, function ( assert
) {
368 $.each( IPV6_CASES
, function ( i
, ipCase
) {
369 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
373 QUnit
.test( 'isIPv4Address', 11, function ( assert
) {
374 $.each( IPV4_CASES
, function ( i
, ipCase
) {
375 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
379 QUnit
.test( 'isIPAddress', 51, function ( assert
) {
380 $.each( IPV4_CASES
, function ( i
, ipCase
) {
381 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
384 $.each( IPV6_CASES
, function ( i
, ipCase
) {
385 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
388 }( mediaWiki
, jQuery
) );