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