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 mw.Uri object test in ' + ( strictMode ? '' : 'non-' ) + 'strict mode for a simple HTTP URI', 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( '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/' );
65
66 assert.deepEqual(
67 {
68 protocol: uri.protocol,
69 user: uri.user,
70 password: uri.password,
71 host: uri.host,
72 port: uri.port,
73 path: uri.path,
74 query: uri.query,
75 fragment: uri.fragment
76 },
77 {
78 protocol: 'ftp',
79 user: 'usr',
80 password: 'pwd',
81 host: '192.0.2.16',
82 port: undefined,
83 path: '/',
84 query: {},
85 fragment: undefined
86 },
87 'basic object properties'
88 );
89 } );
90
91 QUnit.test( 'Parse a uri with simple querystring', 1, function ( assert ) {
92 var uri = new mw.Uri( 'http://www.google.com/?q=uri' );
93
94 assert.deepEqual(
95 {
96 protocol: uri.protocol,
97 host: uri.host,
98 port: uri.port,
99 path: uri.path,
100 query: uri.query,
101 fragment: uri.fragment,
102 queryString: uri.getQueryString()
103 },
104 {
105 protocol: 'http',
106 host: 'www.google.com',
107 port: undefined,
108 path: '/',
109 query: { q: 'uri' },
110 fragment: undefined,
111 queryString: 'q=uri'
112 },
113 'basic object properties'
114 );
115 } );
116
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', {
119 overrideKeys: true
120 });
121
122 assert.equal( uri.query.n, '1', 'multiple parameters are parsed' );
123 assert.equal( uri.query.m, 'bar', 'last key overrides earlier keys' );
124
125 uri.query.n = [ 'x', 'y', 'z' ];
126
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' );
132 } );
133
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', {
136 overrideKeys: false
137 });
138
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' );
144
145 // Change query values
146 uri.query.n = [ 'x', 'y', 'z' ];
147
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' );
153
154 // Remove query values
155 uri.query.m.splice( 0, 1 );
156 delete uri.query.n;
157
158 assert.equal( uri.toString(), 'http://www.example.com/dir/?m=bar', 'deletion properties' );
159
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' );
163 } );
164
165 QUnit.test( 'All-dressed URI with everything', 11, function ( assert ) {
166 var uri, queryString, relativePath;
167
168 uri = new mw.Uri( 'http://auth@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value+%28escaped%29#top' );
169
170 assert.deepEqual(
171 {
172 protocol: uri.protocol,
173 user: uri.user,
174 password: uri.password,
175 host: uri.host,
176 port: uri.port,
177 path: uri.path,
178 query: uri.query,
179 fragment: uri.fragment
180 },
181 {
182 protocol: 'http',
183 user: 'auth',
184 password: undefined,
185 host: 'www.example.com',
186 port: '81',
187 path: '/dir/dir.2/index.htm',
188 query: { q1: '0', test1: null, test2: 'value (escaped)' },
189 fragment: 'top'
190 },
191 'basic object properties'
192 );
193
194 assert.equal( uri.getUserInfo(), 'auth', 'user info' );
195
196 assert.equal( uri.getAuthority(), 'auth@www.example.com:81', 'authority equal to auth@hostport' );
197
198 assert.equal( uri.getHostPort(), 'www.example.com:81', 'hostport equal to host:port' );
199
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' );
205
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' );
210 } );
211
212 QUnit.test( 'Cloning', 6, function ( assert ) {
213 var original, clone;
214
215 original = new mw.Uri( 'http://foo.example.org/index.php?one=1&two=2' );
216 clone = original.clone();
217
218 assert.deepEqual( clone, original, 'clone has equivalent properties' );
219 assert.equal( original.toString(), clone.toString(), 'toString matches original' );
220
221 assert.notStrictEqual( clone, original, 'clone is a different object when compared by reference' );
222
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' );
226
227 clone.query.three = 3;
228
229 assert.deepEqual(
230 original.query,
231 { 'one': '1', 'two': '2' },
232 'Properties is deep cloned (bug 37708)'
233 );
234 } );
235
236 QUnit.test( 'Constructing mw.Uri from plain object', 3, function ( assert ) {
237 var uri = new mw.Uri({
238 protocol: 'http',
239 host: 'www.foo.local',
240 path: '/this'
241 });
242 assert.equal( uri.toString(), 'http://www.foo.local/this', 'Basic properties' );
243
244 uri = new mw.Uri({
245 protocol: 'http',
246 host: 'www.foo.local',
247 path: '/this',
248 query: { hi: 'there' },
249 fragment: 'blah'
250 });
251 assert.equal( uri.toString(), 'http://www.foo.local/this?hi=there#blah', 'More complex properties' );
252
253 assert.throws(
254 function () {
255 return new mw.Uri({
256 protocol: 'http',
257 host: 'www.foo.local'
258 });
259 },
260 function ( e ) {
261 return e.message === 'Bad constructor arguments';
262 },
263 'Construction failed when missing required properties'
264 );
265 } );
266
267 QUnit.test( 'Manipulate properties', 8, function ( assert ) {
268 var uriBase, uri;
269
270 uriBase = new mw.Uri( 'http://en.wiki.local/w/api.php' );
271
272 uri = uriBase.clone();
273 uri.fragment = 'frag';
274 assert.equal( uri.toString(), 'http://en.wiki.local/w/api.php#frag', 'add a fragment' );
275
276 uri = uriBase.clone();
277 uri.host = 'fr.wiki.local';
278 uri.port = '8080';
279 assert.equal( uri.toString(), 'http://fr.wiki.local:8080/w/api.php', 'change host and port' );
280
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' );
284
285 delete uri.query.foo;
286 assert.equal( uri.toString(), 'http://en.wiki.local/w/api.php', 'delete query arguments' );
287
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' );
291 uri.extend({
292 foo: 'quux',
293 pif: 'paf'
294 });
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' );
298 } );
299
300 QUnit.test( 'Handle protocol-relative URLs', 5, function ( assert ) {
301 var UriRel, uri;
302
303 UriRel = mw.UriRelative( 'glork://en.wiki.local/foo.php' );
304
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' );
307
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' );
310
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' );
313
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' );
316
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' );
319 } );
320
321 QUnit.test( 'Bad calls', 3, function ( assert ) {
322 var uri;
323
324 assert.throws(
325 function () {
326 return new mw.Uri( 'glaswegian penguins' );
327 },
328 function ( e ) {
329 return e.message === 'Bad constructor arguments';
330 },
331 'throw error on non-URI as argument to constructor'
332 );
333
334 assert.throws(
335 function () {
336 return new mw.Uri( 'foo.com/bar/baz', {
337 strictMode: true
338 });
339 },
340 function ( e ) {
341 return e.message === 'Bad constructor arguments';
342 },
343 'throw error on URI without protocol or // or leading / in strict mode'
344 );
345
346 uri = new mw.Uri( 'foo.com/bar/baz', {
347 strictMode: false
348 });
349 assert.equal( uri.toString(), 'http://foo.com/bar/baz', 'normalize URI without protocol or // in loose mode' );
350 });
351
352 QUnit.test( 'bug 35658', 2, function ( assert ) {
353 var testProtocol, testServer, testPort, testPath, UriClass, uri, href;
354
355 testProtocol = 'https://';
356 testServer = 'foo.example.org';
357 testPort = '3004';
358 testPath = '/!1qy';
359
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' );
364
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' );
369
370 } );
371
372 QUnit.test( 'Constructor falls back to default location', 4, function ( assert ) {
373 var testuri, MyUri, uri;
374
375 testuri = 'http://example.org/w/index.php';
376 MyUri = mw.UriRelative( testuri );
377
378 uri = new MyUri();
379 assert.equal( uri.toString(), testuri, 'no arguments' );
380
381 uri = new MyUri( undefined );
382 assert.equal( uri.toString(), testuri, 'undefined' );
383
384 uri = new MyUri( null );
385 assert.equal( uri.toString(), testuri, 'null' );
386
387 uri = new MyUri( '' );
388 assert.equal( uri.toString(), testuri, 'empty string' );
389 } );
390 }( mediaWiki, jQuery ) );