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