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