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', 14, 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' );
154 href
= mw
.util
.getUrl( 'My$$test$$$$$title' );
155 assert
.equal( href
, '/wiki/My$$test$$$$$title', 'title with multiple consecutive dollar signs' );
157 href
= mw
.util
.getUrl();
158 assert
.equal( href
, '/wiki/Foobar', 'default title' );
160 href
= mw
.util
.getUrl( null, { action
: 'edit' } );
161 assert
.equal( href
, '/w/index.php?title=Foobar&action=edit', 'default title with query string' );
163 href
= mw
.util
.getUrl( 'Sandbox', { action
: 'edit' } );
164 assert
.equal( href
, '/w/index.php?title=Sandbox&action=edit', 'simple title with query string' );
167 href
= mw
.util
.getUrl( 'Foo:Sandbox#Fragment', { action
: 'edit' } );
168 assert
.equal( href
, '/w/index.php?title=Foo:Sandbox&action=edit#Fragment', 'namespaced title with query string and fragment' );
170 href
= mw
.util
.getUrl( 'Sandbox#', { action
: 'edit' } );
171 assert
.equal( href
, '/w/index.php?title=Sandbox&action=edit', 'title with query string and empty fragment' );
173 href
= mw
.util
.getUrl( 'Sandbox', {} );
174 assert
.equal( href
, '/wiki/Sandbox', 'title with empty query string' );
176 href
= mw
.util
.getUrl( '#Fragment' );
177 assert
.equal( href
, '/wiki/#Fragment', 'empty title with fragment' );
179 href
= mw
.util
.getUrl( '#Fragment', { action
: 'edit' } );
180 assert
.equal( href
, '/w/index.php?action=edit#Fragment', 'epmty title with query string and fragment' );
182 href
= mw
.util
.getUrl( 'Foo:Sandbox \xC4#Fragment \xC4', { action
: 'edit' } );
183 assert
.equal( href
, '/w/index.php?title=Foo:Sandbox_%C3%84&action=edit#Fragment_.C3.84', 'title with query string, fragment, and special characters' );
185 href
= mw
.util
.getUrl( 'Foo:%23#Fragment', { action
: 'edit' } );
186 assert
.equal( href
, '/w/index.php?title=Foo:%2523&action=edit#Fragment', 'title containing %23 (#), fragment, and a query string' );
188 href
= mw
.util
.getUrl( '#+&=:;@$-_.!*/[]<>\'ยง', { action
: 'edit' } );
189 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' );
192 QUnit
.test( 'wikiScript', 4, function ( assert
) {
194 // customized wgScript for T41103
195 wgScript
: '/w/i.php',
196 // customized wgLoadScript for T41103
197 wgLoadScript
: '/w/l.php',
201 assert
.equal( mw
.util
.wikiScript(), mw
.config
.get( 'wgScript' ),
202 'wikiScript() returns wgScript'
204 assert
.equal( mw
.util
.wikiScript( 'index' ), mw
.config
.get( 'wgScript' ),
205 'wikiScript( index ) returns wgScript'
207 assert
.equal( mw
.util
.wikiScript( 'load' ), mw
.config
.get( 'wgLoadScript' ),
208 'wikiScript( load ) returns wgLoadScript'
210 assert
.equal( mw
.util
.wikiScript( 'api' ), '/w/api.php', 'API path' );
213 QUnit
.test( 'addCSS', 3, function ( assert
) {
215 $el
= $( '<div>' ).attr( 'id', 'mw-addcsstest' ).appendTo( '#qunit-fixture' );
217 style
= mw
.util
.addCSS( '#mw-addcsstest { visibility: hidden; }' );
218 assert
.equal( typeof style
, 'object', 'addCSS returned an object' );
219 assert
.strictEqual( style
.disabled
, false, 'property "disabled" is available and set to false' );
221 assert
.equal( $el
.css( 'visibility' ), 'hidden', 'Added style properties are in effect' );
224 $( style
.ownerNode
).remove();
227 QUnit
.test( 'getParamValue', 5, function ( assert
) {
230 url
= 'http://example.org/?foo=wrong&foo=right#&foo=bad';
231 assert
.equal( mw
.util
.getParamValue( 'foo', url
), 'right', 'Use latest one, ignore hash' );
232 assert
.strictEqual( mw
.util
.getParamValue( 'bar', url
), null, 'Return null when not found' );
234 url
= 'http://example.org/#&foo=bad';
235 assert
.strictEqual( mw
.util
.getParamValue( 'foo', url
), null, 'Ignore hash if param is not in querystring but in hash (bug 27427)' );
237 url
= 'example.org?' + $.param( { TEST
: 'a b+c' } );
238 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c', 'Bug 30441: getParamValue must understand "+" encoding of space' );
240 url
= 'example.org?' + $.param( { TEST
: 'a b+c d' } ); // check for sloppy code from r95332 :)
241 assert
.strictEqual( mw
.util
.getParamValue( 'TEST', url
), 'a b+c d', 'Bug 30441: getParamValue must understand "+" encoding of space (multiple spaces)' );
244 QUnit
.test( '$content', 2, function ( assert
) {
245 assert
.ok( mw
.util
.$content
instanceof jQuery
, 'mw.util.$content instance of jQuery' );
246 assert
.strictEqual( mw
.util
.$content
.length
, 1, 'mw.util.$content must have length of 1' );
250 * Portlet names are prefixed with 'p-test' to avoid conflict with core
251 * when running the test suite under a wiki page.
252 * Previously, test elements where invisible to the selector since only
253 * one element can have a given id.
255 QUnit
.test( 'addPortletLink', 13, function ( assert
) {
256 var pTestTb
, pCustom
, vectorTabs
, tbRL
, cuQuux
, $cuQuux
, tbMW
, $tbMW
, tbRLDM
, caFoo
,
257 addedAfter
, tbRLDMnonexistentid
, tbRLDMemptyjquery
;
260 <div class="portlet" id="p-test-tb">\
262 <ul class="body"></ul>\
265 <div class="portlet" id="p-test-custom">\
268 <li id="c-foo"><a href="#">Foo</a></li>\
271 <li id="c-bar-baz"><a href="#">Baz</a></a>\
277 <div id="p-test-views" class="vectorTabs">\
282 $( '#qunit-fixture' ).append( pTestTb
, pCustom
, vectorTabs
);
284 tbRL
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/ResourceLoader',
285 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l'
288 assert
.ok( tbRL
&& tbRL
.nodeType
, 'addPortletLink returns a DOM Node' );
290 tbMW
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/',
291 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org', 'm', tbRL
);
299 'Validate attributes of created element'
303 $tbMW
.find( 'a' ).getAttrs(),
305 href
: '//mediawiki.org/',
306 title
: 'Go to MediaWiki.org [test-m]',
309 'Validate attributes of anchor tag in created element'
312 assert
.equal( $tbMW
.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
313 assert
.strictEqual( $tbMW
.next()[ 0 ], tbRL
, 'Link is in the correct position (nextnode as Node object)' );
315 cuQuux
= mw
.util
.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
316 $cuQuux
= $( cuQuux
);
318 assert
.equal( $cuQuux
.find( 'a' ).attr( 'title' ), 'Example [test-q]', 'Existing accesskey is stripped and updated' );
321 $( '#p-test-custom #c-barmenu ul li' ).length
,
323 'addPortletLink did not add the item to all <ul> elements in the portlet (bug 35082)'
326 tbRLDM
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
327 'Default modules', 't-rldm', 'List of all default modules ', 'd', '#t-rl' );
329 assert
.strictEqual( $( tbRLDM
).next()[ 0 ], tbRL
, 'Link is in the correct position (CSS selector as nextnode)' );
331 caFoo
= mw
.util
.addPortletLink( 'p-test-views', '#', 'Foo' );
333 assert
.strictEqual( $tbMW
.find( 'span' ).length
, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
334 assert
.strictEqual( $( caFoo
).find( 'span' ).length
, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
336 addedAfter
= mw
.util
.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL
) );
337 assert
.strictEqual( $( addedAfter
).next()[ 0 ], tbRL
, 'Link is in the correct position (jQuery object as nextnode)' );
339 // test case - nonexistent id as next node
340 tbRLDMnonexistentid
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
341 'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
343 assert
.equal( tbRLDMnonexistentid
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode non-matching CSS selector)' );
345 // test case - empty jquery object as next node
346 tbRLDMemptyjquery
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
347 'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
349 assert
.equal( tbRLDMemptyjquery
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
352 QUnit
.test( 'validateEmail', 6, function ( assert
) {
353 assert
.strictEqual( mw
.util
.validateEmail( '' ), null, 'Should return null for empty string ' );
354 assert
.strictEqual( mw
.util
.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
356 // testEmailWithCommasAreInvalids
357 assert
.strictEqual( mw
.util
.validateEmail( 'user,foo@example.org' ), false, 'Emails with commas are invalid' );
358 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex,ample.org' ), false, 'Emails with commas are invalid' );
360 // testEmailWithHyphens
361 assert
.strictEqual( mw
.util
.validateEmail( 'user-foo@example.org' ), true, 'Emails may contain a hyphen' );
362 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
365 QUnit
.test( 'isIPv6Address', 40, function ( assert
) {
366 $.each( IPV6_CASES
, function ( i
, ipCase
) {
367 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
371 QUnit
.test( 'isIPv4Address', 11, function ( assert
) {
372 $.each( IPV4_CASES
, function ( i
, ipCase
) {
373 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
377 QUnit
.test( 'isIPAddress', 51, function ( assert
) {
378 $.each( IPV4_CASES
, function ( i
, ipCase
) {
379 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
382 $.each( IPV6_CASES
, function ( i
, ipCase
) {
383 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
386 }( mediaWiki
, jQuery
) );