2 QUnit
.module( 'mediawiki.Uri', QUnit
.newMwEnvironment({
4 this.mwUriOrg
= mw
.Uri
;
5 mw
.Uri
= mw
.UriRelative( 'http://example.org/w/index.php' );
7 teardown: function () {
8 mw
.Uri
= this.mwUriOrg
;
13 $.each( [true, false], function ( i
, strictMode
) {
14 QUnit
.test( 'Basic mw.Uri object test in ' + ( strictMode
? '' : 'non-' ) + 'strict mode for a simple HTTP URI', 2, function ( assert
) {
16 uriString
= 'http://www.ietf.org/rfc/rfc2396.txt';
17 uri
= new mw
.Uri( uriString
, {
18 strictMode
: strictMode
23 protocol
: uri
.protocol
,
28 fragment
: uri
.fragment
33 path
: '/rfc/rfc2396.txt',
37 'basic object properties'
42 userInfo
: uri
.getUserInfo(),
43 authority
: uri
.getAuthority(),
44 hostPort
: uri
.getHostPort(),
45 queryString
: uri
.getQueryString(),
46 relativePath
: uri
.getRelativePath(),
47 toString
: uri
.toString()
51 authority
: 'www.ietf.org',
52 hostPort
: 'www.ietf.org',
54 relativePath
: '/rfc/rfc2396.txt',
57 'construct composite components of URI on request'
63 QUnit
.test( 'Parse an ftp URI correctly with user and password', 1, function ( assert
) {
64 var uri
= new mw
.Uri( 'ftp://usr:pwd@192.0.2.16/' );
68 protocol
: uri
.protocol
,
70 password
: uri
.password
,
75 fragment
: uri
.fragment
87 'basic object properties'
91 QUnit
.test( 'Parse a uri with simple querystring', 1, function ( assert
) {
92 var uri
= new mw
.Uri( 'http://www.google.com/?q=uri' );
96 protocol
: uri
.protocol
,
101 fragment
: uri
.fragment
,
102 queryString
: uri
.getQueryString()
106 host
: 'www.google.com',
113 'basic object properties'
117 QUnit
.test( 'Handle multiple query parameter (overrideKeys on)', 5, function ( assert
) {
118 var uri
= new mw
.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
122 assert
.equal( uri
.query
.n
, '1', 'multiple parameters are parsed' );
123 assert
.equal( uri
.query
.m
, 'bar', 'last key overrides earlier keys' );
125 uri
.query
.n
= [ 'x', 'y', 'z' ];
127 // Verify parts and total length instead of entire string because order
128 // of iteration can vary.
129 assert
.ok( uri
.toString().indexOf( 'm=bar' ), 'toString preserves other values' );
130 assert
.ok( uri
.toString().indexOf( 'n=x&n=y&n=z' ), 'toString parameter includes all values of an array query parameter' );
131 assert
.equal( uri
.toString().length
, 'http://www.example.com/dir/?m=bar&n=x&n=y&n=z'.length
, 'toString matches expected string' );
134 QUnit
.test( 'Handle multiple query parameter (overrideKeys off)', 9, function ( assert
) {
135 var uri
= new mw
.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
139 // Strict comparison so that types are also verified (n should be string '1')
140 assert
.strictEqual( uri
.query
.m
.length
, 2, 'multi-value query should be an array with 2 items' );
141 assert
.strictEqual( uri
.query
.m
[0], 'foo', 'order and value is correct' );
142 assert
.strictEqual( uri
.query
.m
[1], 'bar', 'order and value is correct' );
143 assert
.strictEqual( uri
.query
.n
, '1', 'n=1 is parsed with the correct value of the expected type' );
145 // Change query values
146 uri
.query
.n
= [ 'x', 'y', 'z' ];
148 // Verify parts and total length instead of entire string because order
149 // of iteration can vary.
150 assert
.ok( uri
.toString().indexOf( 'm=foo&m=bar' ) >= 0, 'toString preserves other values' );
151 assert
.ok( uri
.toString().indexOf( 'n=x&n=y&n=z' ) >= 0, 'toString parameter includes all values of an array query parameter' );
152 assert
.equal( uri
.toString().length
, 'http://www.example.com/dir/?m=foo&m=bar&n=x&n=y&n=z'.length
, 'toString matches expected string' );
154 // Remove query values
155 uri
.query
.m
.splice( 0, 1 );
158 assert
.equal( uri
.toString(), 'http://www.example.com/dir/?m=bar', 'deletion properties' );
160 // Remove more query values, leaving an empty array
161 uri
.query
.m
.splice( 0, 1 );
162 assert
.equal( uri
.toString(), 'http://www.example.com/dir/', 'empty array value is ommitted' );
165 QUnit
.test( 'All-dressed URI with everything', 11, function ( assert
) {
166 var uri
, queryString
, relativePath
;
168 uri
= new mw
.Uri( 'http://auth@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value+%28escaped%29#top' );
172 protocol
: uri
.protocol
,
174 password
: uri
.password
,
179 fragment
: uri
.fragment
185 host
: 'www.example.com',
187 path
: '/dir/dir.2/index.htm',
188 query
: { q1
: '0', test1
: null, test2
: 'value (escaped)' },
191 'basic object properties'
194 assert
.equal( uri
.getUserInfo(), 'auth', 'user info' );
196 assert
.equal( uri
.getAuthority(), 'auth@www.example.com:81', 'authority equal to auth@hostport' );
198 assert
.equal( uri
.getHostPort(), 'www.example.com:81', 'hostport equal to host:port' );
200 queryString
= uri
.getQueryString();
201 assert
.ok( queryString
.indexOf( 'q1=0' ) >= 0, 'query param with numbers' );
202 assert
.ok( queryString
.indexOf( 'test1' ) >= 0, 'query param with null value is included' );
203 assert
.ok( queryString
.indexOf( 'test1=' ) === -1, 'query param with null value does not generate equals sign' );
204 assert
.ok( queryString
.indexOf( 'test2=value+%28escaped%29' ) >= 0, 'query param is url escaped' );
206 relativePath
= uri
.getRelativePath();
207 assert
.ok( relativePath
.indexOf( uri
.path
) >= 0, 'path in relative path' );
208 assert
.ok( relativePath
.indexOf( uri
.getQueryString() ) >= 0, 'query string in relative path' );
209 assert
.ok( relativePath
.indexOf( uri
.fragment
) >= 0, 'fragement in relative path' );
212 QUnit
.test( 'Cloning', 6, function ( assert
) {
215 original
= new mw
.Uri( 'http://foo.example.org/index.php?one=1&two=2' );
216 clone
= original
.clone();
218 assert
.deepEqual( clone
, original
, 'clone has equivalent properties' );
219 assert
.equal( original
.toString(), clone
.toString(), 'toString matches original' );
221 assert
.notStrictEqual( clone
, original
, 'clone is a different object when compared by reference' );
223 clone
.host
= 'bar.example.org';
224 assert
.notEqual( original
.host
, clone
.host
, 'manipulating clone did not effect original' );
225 assert
.notEqual( original
.toString(), clone
.toString(), 'Stringified url no longer matches original' );
227 clone
.query
.three
= 3;
231 { 'one': '1', 'two': '2' },
232 'Properties is deep cloned (bug 37708)'
236 QUnit
.test( 'Constructing mw.Uri from plain object', 3, function ( assert
) {
237 var uri
= new mw
.Uri({
239 host
: 'www.foo.local',
242 assert
.equal( uri
.toString(), 'http://www.foo.local/this', 'Basic properties' );
246 host
: 'www.foo.local',
248 query
: { hi
: 'there' },
251 assert
.equal( uri
.toString(), 'http://www.foo.local/this?hi=there#blah', 'More complex properties' );
257 host
: 'www.foo.local'
261 return e
.message
=== 'Bad constructor arguments';
263 'Construction failed when missing required properties'
267 QUnit
.test( 'Manipulate properties', 8, function ( assert
) {
270 uriBase
= new mw
.Uri( 'http://en.wiki.local/w/api.php' );
272 uri
= uriBase
.clone();
273 uri
.fragment
= 'frag';
274 assert
.equal( uri
.toString(), 'http://en.wiki.local/w/api.php#frag', 'add a fragment' );
276 uri
= uriBase
.clone();
277 uri
.host
= 'fr.wiki.local';
279 assert
.equal( uri
.toString(), 'http://fr.wiki.local:8080/w/api.php', 'change host and port' );
281 uri
= uriBase
.clone();
282 uri
.query
.foo
= 'bar';
283 assert
.equal( uri
.toString(), 'http://en.wiki.local/w/api.php?foo=bar', 'add query arguments' );
285 delete uri
.query
.foo
;
286 assert
.equal( uri
.toString(), 'http://en.wiki.local/w/api.php', 'delete query arguments' );
288 uri
= uriBase
.clone();
289 uri
.query
.foo
= 'bar';
290 assert
.equal( uri
.toString(), 'http://en.wiki.local/w/api.php?foo=bar', 'extend query arguments' );
295 assert
.ok( uri
.toString().indexOf( 'foo=quux' ) >= 0, 'extend query arguments' );
296 assert
.ok( uri
.toString().indexOf( 'foo=bar' ) === -1, 'extend query arguments' );
297 assert
.ok( uri
.toString().indexOf( 'pif=paf' ) >= 0 , 'extend query arguments' );
300 QUnit
.test( 'Handle protocol-relative URLs', 5, function ( assert
) {
303 UriRel
= mw
.UriRelative( 'glork://en.wiki.local/foo.php' );
305 uri
= new UriRel( '//en.wiki.local/w/api.php' );
306 assert
.equal( uri
.protocol
, 'glork', 'create protocol-relative URLs with same protocol as document' );
308 uri
= new UriRel( '/foo.com' );
309 assert
.equal( uri
.toString(), 'glork://en.wiki.local/foo.com', 'handle absolute paths by supplying protocol and host from document in loose mode' );
311 uri
= new UriRel( 'http:/foo.com' );
312 assert
.equal( uri
.toString(), 'http://en.wiki.local/foo.com', 'handle absolute paths by supplying host from document in loose mode' );
314 uri
= new UriRel( '/foo.com', true );
315 assert
.equal( uri
.toString(), 'glork://en.wiki.local/foo.com', 'handle absolute paths by supplying protocol and host from document in strict mode' );
317 uri
= new UriRel( 'http:/foo.com', true );
318 assert
.equal( uri
.toString(), 'http://en.wiki.local/foo.com', 'handle absolute paths by supplying host from document in strict mode' );
321 QUnit
.test( 'Bad calls', 3, function ( assert
) {
326 return new mw
.Uri( 'glaswegian penguins' );
329 return e
.message
=== 'Bad constructor arguments';
331 'throw error on non-URI as argument to constructor'
336 return new mw
.Uri( 'foo.com/bar/baz', {
341 return e
.message
=== 'Bad constructor arguments';
343 'throw error on URI without protocol or // or leading / in strict mode'
346 uri
= new mw
.Uri( 'foo.com/bar/baz', {
349 assert
.equal( uri
.toString(), 'http://foo.com/bar/baz', 'normalize URI without protocol or // in loose mode' );
352 QUnit
.test( 'bug 35658', 2, function ( assert
) {
353 var testProtocol
, testServer
, testPort
, testPath
, UriClass
, uri
, href
;
355 testProtocol
= 'https://';
356 testServer
= 'foo.example.org';
360 UriClass
= mw
.UriRelative( testProtocol
+ testServer
+ '/some/path/index.html' );
361 uri
= new UriClass( testPath
);
362 href
= uri
.toString();
363 assert
.equal( href
, testProtocol
+ testServer
+ testPath
, 'Root-relative URL gets host & protocol supplied' );
365 UriClass
= mw
.UriRelative( testProtocol
+ testServer
+ ':' + testPort
+ '/some/path.php' );
366 uri
= new UriClass( testPath
);
367 href
= uri
.toString();
368 assert
.equal( href
, testProtocol
+ testServer
+ ':' + testPort
+ testPath
, 'Root-relative URL gets host, protocol, and port supplied' );
372 QUnit
.test( 'Constructor falls back to default location', 4, function ( assert
) {
373 var testuri
, MyUri
, uri
;
375 testuri
= 'http://example.org/w/index.php';
376 MyUri
= mw
.UriRelative( testuri
);
379 assert
.equal( uri
.toString(), testuri
, 'no arguments' );
381 uri
= new MyUri( undefined );
382 assert
.equal( uri
.toString(), testuri
, 'undefined' );
384 uri
= new MyUri( null );
385 assert
.equal( uri
.toString(), testuri
, 'null' );
387 uri
= new MyUri( '' );
388 assert
.equal( uri
.toString(), testuri
, 'empty string' );
390 }( mediaWiki
, jQuery
) );