Merge "(bug 47070) check content model namespace on import."
[lhc/web/wiklou.git] / tests / qunit / suites / resources / mediawiki / mediawiki.Uri.test.js
1 ( function ( mw, $ ) {
2 QUnit.module( 'mediawiki.Uri', QUnit.newMwEnvironment( {
3 setup: function () {
4 this.mwUriOrg = mw.Uri;
5 mw.Uri = mw.UriRelative( 'http://example.org/w/index.php' );
6 },
7 teardown: function () {
8 mw.Uri = this.mwUriOrg;
9 delete this.mwUriOrg;
10 }
11 } ) );
12
13 $.each( [true, false], function ( i, strictMode ) {
14 QUnit.test( 'Basic construction and properties (' + ( strictMode ? '' : 'non-' ) + 'strict mode)', 2, function ( assert ) {
15 var uriString, uri;
16 uriString = 'http://www.ietf.org/rfc/rfc2396.txt';
17 uri = new mw.Uri( uriString, {
18 strictMode: strictMode
19 } );
20
21 assert.deepEqual(
22 {
23 protocol: uri.protocol,
24 host: uri.host,
25 port: uri.port,
26 path: uri.path,
27 query: uri.query,
28 fragment: uri.fragment
29 }, {
30 protocol: 'http',
31 host: 'www.ietf.org',
32 port: undefined,
33 path: '/rfc/rfc2396.txt',
34 query: {},
35 fragment: undefined
36 },
37 'basic object properties'
38 );
39
40 assert.deepEqual(
41 {
42 userInfo: uri.getUserInfo(),
43 authority: uri.getAuthority(),
44 hostPort: uri.getHostPort(),
45 queryString: uri.getQueryString(),
46 relativePath: uri.getRelativePath(),
47 toString: uri.toString()
48 },
49 {
50 userInfo: '',
51 authority: 'www.ietf.org',
52 hostPort: 'www.ietf.org',
53 queryString: '',
54 relativePath: '/rfc/rfc2396.txt',
55 toString: uriString
56 },
57 'construct composite components of URI on request'
58 );
59 } );
60 } );
61
62 QUnit.test( 'Constructor( String[, Object ] )', 10, function ( assert ) {
63 var uri;
64
65 uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
66 overrideKeys: true
67 } );
68
69 // Strict comparison to assert that numerical values stay strings
70 assert.strictEqual( uri.query.n, '1', 'Simple parameter with overrideKeys:true' );
71 assert.strictEqual( uri.query.m, 'bar', 'Last key overrides earlier keys with overrideKeys:true' );
72
73 uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
74 overrideKeys: false
75 } );
76
77 assert.strictEqual( uri.query.n, '1', 'Simple parameter with overrideKeys:false' );
78 assert.strictEqual( uri.query.m[0], 'foo', 'Order of multi-value parameters with overrideKeys:true' );
79 assert.strictEqual( uri.query.m[1], 'bar', 'Order of multi-value parameters with overrideKeys:true' );
80 assert.strictEqual( uri.query.m.length, 2, 'Number of mult-value field is correct' );
81
82 uri = new mw.Uri( 'ftp://usr:pwd@192.0.2.16/' );
83
84 assert.deepEqual(
85 {
86 protocol: uri.protocol,
87 user: uri.user,
88 password: uri.password,
89 host: uri.host,
90 port: uri.port,
91 path: uri.path,
92 query: uri.query,
93 fragment: uri.fragment
94 },
95 {
96 protocol: 'ftp',
97 user: 'usr',
98 password: 'pwd',
99 host: '192.0.2.16',
100 port: undefined,
101 path: '/',
102 query: {},
103 fragment: undefined
104 },
105 'Parse an ftp URI correctly with user and password'
106 );
107
108 assert.throws(
109 function () {
110 return new mw.Uri( 'glaswegian penguins' );
111 },
112 function ( e ) {
113 return e.message === 'Bad constructor arguments';
114 },
115 'throw error on non-URI as argument to constructor'
116 );
117
118 assert.throws(
119 function () {
120 return new mw.Uri( 'example.com/bar/baz', {
121 strictMode: true
122 } );
123 },
124 function ( e ) {
125 return e.message === 'Bad constructor arguments';
126 },
127 'throw error on URI without protocol or // or leading / in strict mode'
128 );
129
130 uri = new mw.Uri( 'example.com/bar/baz', {
131 strictMode: false
132 } );
133 assert.equal( uri.toString(), 'http://example.com/bar/baz', 'normalize URI without protocol or // in loose mode' );
134 } );
135
136 QUnit.test( 'Constructor( Object )', 3, function ( assert ) {
137 var uri = new mw.Uri( {
138 protocol: 'http',
139 host: 'www.foo.local',
140 path: '/this'
141 } );
142 assert.equal( uri.toString(), 'http://www.foo.local/this', 'Basic properties' );
143
144 uri = new mw.Uri( {
145 protocol: 'http',
146 host: 'www.foo.local',
147 path: '/this',
148 query: { hi: 'there' },
149 fragment: 'blah'
150 } );
151 assert.equal( uri.toString(), 'http://www.foo.local/this?hi=there#blah', 'More complex properties' );
152
153 assert.throws(
154 function () {
155 return new mw.Uri( {
156 protocol: 'http',
157 host: 'www.foo.local'
158 } );
159 },
160 function ( e ) {
161 return e.message === 'Bad constructor arguments';
162 },
163 'Construction failed when missing required properties'
164 );
165 } );
166
167 QUnit.test( 'Constructor( empty )', 4, function ( assert ) {
168 var testuri, MyUri, uri;
169
170 testuri = 'http://example.org/w/index.php';
171 MyUri = mw.UriRelative( testuri );
172
173 uri = new MyUri();
174 assert.equal( uri.toString(), testuri, 'no arguments' );
175
176 uri = new MyUri( undefined );
177 assert.equal( uri.toString(), testuri, 'undefined' );
178
179 uri = new MyUri( null );
180 assert.equal( uri.toString(), testuri, 'null' );
181
182 uri = new MyUri( '' );
183 assert.equal( uri.toString(), testuri, 'empty string' );
184 } );
185
186 QUnit.test( 'Properties', 8, function ( assert ) {
187 var uriBase, uri;
188
189 uriBase = new mw.Uri( 'http://en.wiki.local/w/api.php' );
190
191 uri = uriBase.clone();
192 uri.fragment = 'frag';
193 assert.equal( uri.toString(), 'http://en.wiki.local/w/api.php#frag', 'add a fragment' );
194
195 uri = uriBase.clone();
196 uri.host = 'fr.wiki.local';
197 uri.port = '8080';
198 assert.equal( uri.toString(), 'http://fr.wiki.local:8080/w/api.php', 'change host and port' );
199
200 uri = uriBase.clone();
201 uri.query.foo = 'bar';
202 assert.equal( uri.toString(), 'http://en.wiki.local/w/api.php?foo=bar', 'add query arguments' );
203
204 delete uri.query.foo;
205 assert.equal( uri.toString(), 'http://en.wiki.local/w/api.php', 'delete query arguments' );
206
207 uri = uriBase.clone();
208 uri.query.foo = 'bar';
209 assert.equal( uri.toString(), 'http://en.wiki.local/w/api.php?foo=bar', 'extend query arguments' );
210 uri.extend( {
211 foo: 'quux',
212 pif: 'paf'
213 } );
214 assert.ok( uri.toString().indexOf( 'foo=quux' ) >= 0, 'extend query arguments' );
215 assert.ok( uri.toString().indexOf( 'foo=bar' ) === -1, 'extend query arguments' );
216 assert.ok( uri.toString().indexOf( 'pif=paf' ) >= 0, 'extend query arguments' );
217 } );
218
219 QUnit.test( '.getQueryString()', 2, function ( assert ) {
220 var uri = new mw.Uri( 'http://search.example.com/?q=uri' );
221
222 assert.deepEqual(
223 {
224 protocol: uri.protocol,
225 host: uri.host,
226 port: uri.port,
227 path: uri.path,
228 query: uri.query,
229 fragment: uri.fragment,
230 queryString: uri.getQueryString()
231 },
232 {
233 protocol: 'http',
234 host: 'search.example.com',
235 port: undefined,
236 path: '/',
237 query: { q: 'uri' },
238 fragment: undefined,
239 queryString: 'q=uri'
240 },
241 'basic object properties'
242 );
243
244 uri = new mw.Uri( 'https://example.com/mw/index.php?title=Sandbox/7&other=Sandbox/7&foo' );
245 assert.equal(
246 uri.getQueryString(),
247 'title=Sandbox/7&other=Sandbox%2F7&foo',
248 'title parameter is escaped the wiki-way'
249 );
250
251 } );
252
253 QUnit.test( '.clone()', 6, function ( assert ) {
254 var original, clone;
255
256 original = new mw.Uri( 'http://foo.example.org/index.php?one=1&two=2' );
257 clone = original.clone();
258
259 assert.deepEqual( clone, original, 'clone has equivalent properties' );
260 assert.equal( original.toString(), clone.toString(), 'toString matches original' );
261
262 assert.notStrictEqual( clone, original, 'clone is a different object when compared by reference' );
263
264 clone.host = 'bar.example.org';
265 assert.notEqual( original.host, clone.host, 'manipulating clone did not effect original' );
266 assert.notEqual( original.toString(), clone.toString(), 'Stringified url no longer matches original' );
267
268 clone.query.three = 3;
269
270 assert.deepEqual(
271 original.query,
272 { 'one': '1', 'two': '2' },
273 'Properties is deep cloned (bug 37708)'
274 );
275 } );
276
277 QUnit.test( '.toString() after query manipulation', 8, function ( assert ) {
278 var uri;
279
280 uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
281 overrideKeys: true
282 } );
283
284 uri.query.n = [ 'x', 'y', 'z' ];
285
286 // Verify parts and total length instead of entire string because order
287 // of iteration can vary.
288 assert.ok( uri.toString().indexOf( 'm=bar' ), 'toString preserves other values' );
289 assert.ok( uri.toString().indexOf( 'n=x&n=y&n=z' ), 'toString parameter includes all values of an array query parameter' );
290 assert.equal( uri.toString().length, 'http://www.example.com/dir/?m=bar&n=x&n=y&n=z'.length, 'toString matches expected string' );
291
292 uri = new mw.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', {
293 overrideKeys: false
294 } );
295
296 // Change query values
297 uri.query.n = [ 'x', 'y', 'z' ];
298
299 // Verify parts and total length instead of entire string because order
300 // of iteration can vary.
301 assert.ok( uri.toString().indexOf( 'm=foo&m=bar' ) >= 0, 'toString preserves other values' );
302 assert.ok( uri.toString().indexOf( 'n=x&n=y&n=z' ) >= 0, 'toString parameter includes all values of an array query parameter' );
303 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' );
304
305 // Remove query values
306 uri.query.m.splice( 0, 1 );
307 delete uri.query.n;
308
309 assert.equal( uri.toString(), 'http://www.example.com/dir/?m=bar', 'deletion properties' );
310
311 // Remove more query values, leaving an empty array
312 uri.query.m.splice( 0, 1 );
313 assert.equal( uri.toString(), 'http://www.example.com/dir/', 'empty array value is ommitted' );
314 } );
315
316 QUnit.test( 'Advanced URL', 11, function ( assert ) {
317 var uri, queryString, relativePath;
318
319 uri = new mw.Uri( 'http://auth@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value+%28escaped%29#top' );
320
321 assert.deepEqual(
322 {
323 protocol: uri.protocol,
324 user: uri.user,
325 password: uri.password,
326 host: uri.host,
327 port: uri.port,
328 path: uri.path,
329 query: uri.query,
330 fragment: uri.fragment
331 },
332 {
333 protocol: 'http',
334 user: 'auth',
335 password: undefined,
336 host: 'www.example.com',
337 port: '81',
338 path: '/dir/dir.2/index.htm',
339 query: { q1: '0', test1: null, test2: 'value (escaped)' },
340 fragment: 'top'
341 },
342 'basic object properties'
343 );
344
345 assert.equal( uri.getUserInfo(), 'auth', 'user info' );
346
347 assert.equal( uri.getAuthority(), 'auth@www.example.com:81', 'authority equal to auth@hostport' );
348
349 assert.equal( uri.getHostPort(), 'www.example.com:81', 'hostport equal to host:port' );
350
351 queryString = uri.getQueryString();
352 assert.ok( queryString.indexOf( 'q1=0' ) >= 0, 'query param with numbers' );
353 assert.ok( queryString.indexOf( 'test1' ) >= 0, 'query param with null value is included' );
354 assert.ok( queryString.indexOf( 'test1=' ) === -1, 'query param with null value does not generate equals sign' );
355 assert.ok( queryString.indexOf( 'test2=value+%28escaped%29' ) >= 0, 'query param is url escaped' );
356
357 relativePath = uri.getRelativePath();
358 assert.ok( relativePath.indexOf( uri.path ) >= 0, 'path in relative path' );
359 assert.ok( relativePath.indexOf( uri.getQueryString() ) >= 0, 'query string in relative path' );
360 assert.ok( relativePath.indexOf( uri.fragment ) >= 0, 'fragement in relative path' );
361 } );
362
363 QUnit.test( 'Parse a uri with an @ symbol in the path and query', 1, function ( assert ) {
364 var uri = new mw.Uri( 'http://www.example.com/test@test?x=@uri&y@=uri&z@=@' );
365
366 assert.deepEqual(
367 {
368 protocol: uri.protocol,
369 user: uri.user,
370 password: uri.password,
371 host: uri.host,
372 port: uri.port,
373 path: uri.path,
374 query: uri.query,
375 fragment: uri.fragment,
376 queryString: uri.getQueryString()
377 },
378 {
379 protocol: 'http',
380 user: undefined,
381 password: undefined,
382 host: 'www.example.com',
383 port: undefined,
384 path: '/test@test',
385 query: { x: '@uri', 'y@': 'uri', 'z@': '@' },
386 fragment: undefined,
387 queryString: 'x=%40uri&y%40=uri&z%40=%40'
388 },
389 'basic object properties'
390 );
391 } );
392
393 QUnit.test( 'Handle protocol-relative URLs', 5, function ( assert ) {
394 var UriRel, uri;
395
396 UriRel = mw.UriRelative( 'glork://en.wiki.local/foo.php' );
397
398 uri = new UriRel( '//en.wiki.local/w/api.php' );
399 assert.equal( uri.protocol, 'glork', 'create protocol-relative URLs with same protocol as document' );
400
401 uri = new UriRel( '/foo.com' );
402 assert.equal( uri.toString(), 'glork://en.wiki.local/foo.com', 'handle absolute paths by supplying protocol and host from document in loose mode' );
403
404 uri = new UriRel( 'http:/foo.com' );
405 assert.equal( uri.toString(), 'http://en.wiki.local/foo.com', 'handle absolute paths by supplying host from document in loose mode' );
406
407 uri = new UriRel( '/foo.com', true );
408 assert.equal( uri.toString(), 'glork://en.wiki.local/foo.com', 'handle absolute paths by supplying protocol and host from document in strict mode' );
409
410 uri = new UriRel( 'http:/foo.com', true );
411 assert.equal( uri.toString(), 'http://en.wiki.local/foo.com', 'handle absolute paths by supplying host from document in strict mode' );
412 } );
413
414 QUnit.test( 'bug 35658', 2, function ( assert ) {
415 var testProtocol, testServer, testPort, testPath, UriClass, uri, href;
416
417 testProtocol = 'https://';
418 testServer = 'foo.example.org';
419 testPort = '3004';
420 testPath = '/!1qy';
421
422 UriClass = mw.UriRelative( testProtocol + testServer + '/some/path/index.html' );
423 uri = new UriClass( testPath );
424 href = uri.toString();
425 assert.equal( href, testProtocol + testServer + testPath, 'Root-relative URL gets host & protocol supplied' );
426
427 UriClass = mw.UriRelative( testProtocol + testServer + ':' + testPort + '/some/path.php' );
428 uri = new UriClass( testPath );
429 href = uri.toString();
430 assert.equal( href, testProtocol + testServer + ':' + testPort + testPath, 'Root-relative URL gets host, protocol, and port supplied' );
431
432 } );
433 }( mediaWiki, jQuery ) );