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( '$content', 2, function ( assert
) {
241 assert
.ok( mw
.util
.$content
instanceof jQuery
, 'mw.util.$content instance of jQuery' );
242 assert
.strictEqual( mw
.util
.$content
.length
, 1, 'mw.util.$content must have length of 1' );
246 * Portlet names are prefixed with 'p-test' to avoid conflict with core
247 * when running the test suite under a wiki page.
248 * Previously, test elements where invisible to the selector since only
249 * one element can have a given id.
251 QUnit
.test( 'addPortletLink', 13, function ( assert
) {
252 var pTestTb
, pCustom
, vectorTabs
, tbRL
, cuQuux
, $cuQuux
, tbMW
, $tbMW
, tbRLDM
, caFoo
,
253 addedAfter
, tbRLDMnonexistentid
, tbRLDMemptyjquery
;
256 <div class="portlet" id="p-test-tb">\
258 <ul class="body"></ul>\
261 <div class="portlet" id="p-test-custom">\
264 <li id="c-foo"><a href="#">Foo</a></li>\
267 <li id="c-bar-baz"><a href="#">Baz</a></a>\
273 <div id="p-test-views" class="vectorTabs">\
278 $( '#qunit-fixture' ).append( pTestTb
, pCustom
, vectorTabs
);
280 tbRL
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/ResourceLoader',
281 'ResourceLoader', 't-rl', 'More info about ResourceLoader on MediaWiki.org ', 'l'
284 assert
.ok( tbRL
&& tbRL
.nodeType
, 'addPortletLink returns a DOM Node' );
286 tbMW
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/',
287 'MediaWiki.org', 't-mworg', 'Go to MediaWiki.org', 'm', tbRL
);
295 'Validate attributes of created element'
299 $tbMW
.find( 'a' ).getAttrs(),
301 href
: '//mediawiki.org/',
302 title
: 'Go to MediaWiki.org [test-m]',
305 'Validate attributes of anchor tag in created element'
308 assert
.equal( $tbMW
.closest( '.portlet' ).attr( 'id' ), 'p-test-tb', 'Link was inserted within correct portlet' );
309 assert
.strictEqual( $tbMW
.next()[ 0 ], tbRL
, 'Link is in the correct position (nextnode as Node object)' );
311 cuQuux
= mw
.util
.addPortletLink( 'p-test-custom', '#', 'Quux', null, 'Example [shift-x]', 'q' );
312 $cuQuux
= $( cuQuux
);
314 assert
.equal( $cuQuux
.find( 'a' ).attr( 'title' ), 'Example [test-q]', 'Existing accesskey is stripped and updated' );
317 $( '#p-test-custom #c-barmenu ul li' ).length
,
319 'addPortletLink did not add the item to all <ul> elements in the portlet (bug 35082)'
322 tbRLDM
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
323 'Default modules', 't-rldm', 'List of all default modules ', 'd', '#t-rl' );
325 assert
.strictEqual( $( tbRLDM
).next()[ 0 ], tbRL
, 'Link is in the correct position (CSS selector as nextnode)' );
327 caFoo
= mw
.util
.addPortletLink( 'p-test-views', '#', 'Foo' );
329 assert
.strictEqual( $tbMW
.find( 'span' ).length
, 0, 'No <span> element should be added for porlets without vectorTabs class.' );
330 assert
.strictEqual( $( caFoo
).find( 'span' ).length
, 1, 'A <span> element should be added for porlets with vectorTabs class.' );
332 addedAfter
= mw
.util
.addPortletLink( 'p-test-tb', '#', 'After foo', 'post-foo', 'After foo', null, $( tbRL
) );
333 assert
.strictEqual( $( addedAfter
).next()[ 0 ], tbRL
, 'Link is in the correct position (jQuery object as nextnode)' );
335 // test case - nonexistent id as next node
336 tbRLDMnonexistentid
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
337 'Default modules', 't-rldm-nonexistent', 'List of all default modules ', 'd', '#t-rl-nonexistent' );
339 assert
.equal( tbRLDMnonexistentid
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode non-matching CSS selector)' );
341 // test case - empty jquery object as next node
342 tbRLDMemptyjquery
= mw
.util
.addPortletLink( 'p-test-tb', '//mediawiki.org/wiki/RL/DM',
343 'Default modules', 't-rldm-empty-jquery', 'List of all default modules ', 'd', $( '#t-rl-nonexistent' ) );
345 assert
.equal( tbRLDMemptyjquery
, $( '#p-test-tb li:last' )[ 0 ], 'Fallback to adding at the end (nextnode as empty jQuery object)' );
348 QUnit
.test( 'validateEmail', 6, function ( assert
) {
349 assert
.strictEqual( mw
.util
.validateEmail( '' ), null, 'Should return null for empty string ' );
350 assert
.strictEqual( mw
.util
.validateEmail( 'user@localhost' ), true, 'Return true for a valid e-mail address' );
352 // testEmailWithCommasAreInvalids
353 assert
.strictEqual( mw
.util
.validateEmail( 'user,foo@example.org' ), false, 'Emails with commas are invalid' );
354 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex,ample.org' ), false, 'Emails with commas are invalid' );
356 // testEmailWithHyphens
357 assert
.strictEqual( mw
.util
.validateEmail( 'user-foo@example.org' ), true, 'Emails may contain a hyphen' );
358 assert
.strictEqual( mw
.util
.validateEmail( 'userfoo@ex-ample.org' ), true, 'Emails may contain a hyphen' );
361 QUnit
.test( 'isIPv6Address', 40, function ( assert
) {
362 $.each( IPV6_CASES
, function ( i
, ipCase
) {
363 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
367 QUnit
.test( 'isIPv4Address', 11, function ( assert
) {
368 $.each( IPV4_CASES
, function ( i
, ipCase
) {
369 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
373 QUnit
.test( 'isIPAddress', 51, function ( assert
) {
374 $.each( IPV4_CASES
, function ( i
, ipCase
) {
375 assert
.strictEqual( mw
.util
.isIPv4Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
378 $.each( IPV6_CASES
, function ( i
, ipCase
) {
379 assert
.strictEqual( mw
.util
.isIPv6Address( ipCase
[ 1 ] ), ipCase
[ 0 ], ipCase
[ 2 ] );
382 }( mediaWiki
, jQuery
) );