721ccb38012479d616460d63a9910e32195ed61f
3 // ensure we have a generic URI parser if not running in a browser
5 mw
.Uri
= mw
.UriRelative( 'http://example.com/' );
8 describe( "mw.Uri", function() {
10 describe( "should work well in loose and strict mode", function() {
12 function basicTests( strict
) {
14 describe( "should parse a simple HTTP URI correctly", function() {
16 var uriString
= 'http://www.ietf.org/rfc/rfc2396.txt';
19 uri
= new mw
.Uri( uriString
, strict
);
21 uri
= new mw
.Uri( uriString
);
24 it( "should have basic object properties", function() {
25 expect( uri
.protocol
).toEqual( 'http' );
26 expect( uri
.host
).toEqual( 'www.ietf.org' );
27 expect( uri
.port
).not
.toBeDefined();
28 expect( uri
.path
).toEqual( '/rfc/rfc2396.txt' );
29 expect( uri
.query
).toEqual( {} );
30 expect( uri
.fragment
).not
.toBeDefined();
33 describe( "should construct composite components of URI on request", function() {
34 it( "should have empty userinfo", function() {
35 expect( uri
.getUserInfo() ).toEqual( '' );
38 it( "should have authority equal to host", function() {
39 expect( uri
.getAuthority() ).toEqual( 'www.ietf.org' );
42 it( "should have hostport equal to host", function() {
43 expect( uri
.getHostPort() ).toEqual( 'www.ietf.org' );
46 it( "should have empty string as query string", function() {
47 expect( uri
.getQueryString() ).toEqual( '' );
50 it( "should have path as relative path", function() {
51 expect( uri
.getRelativePath() ).toEqual( '/rfc/rfc2396.txt' );
54 it( "should return a uri string equivalent to original", function() {
55 expect( uri
.toString() ).toEqual( uriString
);
61 describe( "should work in loose mode", function() {
65 describe( "should work in strict mode", function() {
71 it( "should parse a simple ftp URI correctly with user and password", function() {
72 var uri
= new mw
.Uri( 'ftp://usr:pwd@192.0.2.16/' );
73 expect( uri
.protocol
).toEqual( 'ftp' );
74 expect( uri
.user
).toEqual( 'usr' );
75 expect( uri
.password
).toEqual( 'pwd' );
76 expect( uri
.host
).toEqual( '192.0.2.16' );
77 expect( uri
.port
).not
.toBeDefined();
78 expect( uri
.path
).toEqual( '/' );
79 expect( uri
.query
).toEqual( {} );
80 expect( uri
.fragment
).not
.toBeDefined();
83 it( "should parse a simple querystring", function() {
84 var uri
= new mw
.Uri( 'http://www.google.com/?q=uri' );
85 expect( uri
.protocol
).toEqual( 'http' );
86 expect( uri
.host
).toEqual( 'www.google.com' );
87 expect( uri
.port
).not
.toBeDefined();
88 expect( uri
.path
).toEqual( '/' );
89 expect( uri
.query
).toBeDefined();
90 expect( uri
.query
).toEqual( { q
: 'uri' } );
91 expect( uri
.fragment
).not
.toBeDefined();
92 expect( uri
.getQueryString() ).toEqual( 'q=uri' );
95 describe( "should handle multiple value query args (overrideKeys on)", function() {
96 var uri
= new mw
.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', { overrideKeys
: true } );
97 it ( "should parse with multiple values", function() {
98 expect( uri
.query
.m
).toEqual( 'bar' );
99 expect( uri
.query
.n
).toEqual( '1' );
101 it ( "should accept multiple values", function() {
102 uri
.query
.n
= [ "x", "y", "z" ];
103 expect( uri
.toString() ).toContain( 'm=bar' );
104 expect( uri
.toString() ).toContain( 'n=x&n=y&n=z' );
105 expect( uri
.toString().length
).toEqual( 'http://www.example.com/dir/?m=bar&n=x&n=y&n=z'.length
);
109 describe( "should handle multiple value query args (overrideKeys off)", function() {
110 var uri
= new mw
.Uri( 'http://www.example.com/dir/?m=foo&m=bar&n=1', { overrideKeys
: false } );
111 it ( "should parse with multiple values", function() {
112 expect( uri
.query
.m
.length
).toEqual( 2 );
113 expect( uri
.query
.m
[0] ).toEqual( 'foo' );
114 expect( uri
.query
.m
[1] ).toEqual( 'bar' );
115 expect( uri
.query
.n
).toEqual( '1' );
117 it ( "should accept multiple values", function() {
118 uri
.query
.n
= [ "x", "y", "z" ];
119 expect( uri
.toString() ).toContain( 'm=foo&m=bar' );
120 expect( uri
.toString() ).toContain( 'n=x&n=y&n=z' );
121 expect( uri
.toString().length
).toEqual( 'http://www.example.com/dir/?m=foo&m=bar&n=x&n=y&n=z'.length
);
123 it ( "should be okay with removing values", function() {
124 uri
.query
.m
.splice( 0, 1 );
126 expect( uri
.toString() ).toEqual( 'http://www.example.com/dir/?m=bar' );
127 uri
.query
.m
.splice( 0, 1 );
128 expect( uri
.toString() ).toEqual( 'http://www.example.com/dir/' );
132 describe( "should deal with an all-dressed URI with everything", function() {
133 var uri
= new mw
.Uri( 'http://auth@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=value+%28escaped%29#top' );
135 it( "should have basic object properties", function() {
136 expect( uri
.protocol
).toEqual( 'http' );
137 expect( uri
.user
).toEqual( 'auth' );
138 expect( uri
.password
).not
.toBeDefined();
139 expect( uri
.host
).toEqual( 'www.example.com' );
140 expect( uri
.port
).toEqual( '81' );
141 expect( uri
.path
).toEqual( '/dir/dir.2/index.htm' );
142 expect( uri
.query
).toEqual( { q1
: '0', test1
: null, test2
: 'value (escaped)' } );
143 expect( uri
.fragment
).toEqual( 'top' );
146 describe( "should construct composite components of URI on request", function() {
147 it( "should have userinfo", function() {
148 expect( uri
.getUserInfo() ).toEqual( 'auth' );
151 it( "should have authority equal to auth@hostport", function() {
152 expect( uri
.getAuthority() ).toEqual( 'auth@www.example.com:81' );
155 it( "should have hostport equal to host:port", function() {
156 expect( uri
.getHostPort() ).toEqual( 'www.example.com:81' );
159 it( "should have query string which contains all components", function() {
160 var queryString
= uri
.getQueryString();
161 expect( queryString
).toContain( 'q1=0' );
162 expect( queryString
).toContain( 'test1' );
163 expect( queryString
).not
.toContain( 'test1=' );
164 expect( queryString
).toContain( 'test2=value+%28escaped%29' );
167 it( "should have path as relative path", function() {
168 expect( uri
.getRelativePath() ).toContain( uri
.path
);
169 expect( uri
.getRelativePath() ).toContain( uri
.getQueryString() );
170 expect( uri
.getRelativePath() ).toContain( uri
.fragment
);
176 describe( "should be able to clone itself", function() {
177 var original
= new mw
.Uri( 'http://en.wiki.local/w/api.php?action=query&foo=bar' );
178 var clone
= original
.clone();
180 it( "should make clones equivalent", function() {
181 expect( original
).toEqual( clone
);
182 expect( original
.toString() ).toEqual( clone
.toString() );
185 it( "should be able to manipulate clones independently", function() {
186 // but they are still different objects
187 expect( original
).not
.toBe( clone
);
189 clone
.host
= 'fr.wiki.local';
190 expect( original
.host
).not
.toEqual( clone
.host
);
191 expect( original
.toString() ).not
.toEqual( clone
.toString() );
195 describe( "should be able to construct URL from object", function() {
196 it ( "should construct given basic arguments", function() {
197 var uri
= new mw
.Uri( { protocol
: 'http', host
: 'www.foo.local', path
: '/this' } );
198 expect( uri
.toString() ).toEqual( 'http://www.foo.local/this' );
201 it ( "should construct given more complex arguments", function() {
202 var uri
= new mw
.Uri( {
204 host
: 'www.foo.local',
206 query
: { hi
: 'there' },
209 expect( uri
.toString() ).toEqual( 'http://www.foo.local/this?hi=there#blah' );
212 it ( "should fail to construct without required properties", function() {
214 var uri
= new mw
.Uri( { protocol
: 'http', host
: 'www.foo.local' } );
215 } ).toThrow( "Bad constructor arguments" );
219 describe( "should be able to manipulate properties", function() {
222 beforeEach( function() {
223 uri
= new mw
.Uri( 'http://en.wiki.local/w/api.php' );
226 it( "can add a fragment", function() {
227 uri
.fragment
= 'frag';
228 expect( uri
.toString() ).toEqual( 'http://en.wiki.local/w/api.php#frag' );
231 it( "can change host and port", function() {
232 uri
.host
= 'fr.wiki.local';
234 expect( uri
.toString() ).toEqual( 'http://fr.wiki.local:8080/w/api.php' );
237 it ( "can add query arguments", function() {
238 uri
.query
.foo
= 'bar';
239 expect( uri
.toString() ).toEqual( 'http://en.wiki.local/w/api.php?foo=bar' );
242 it ( "can extend query arguments", function() {
243 uri
.query
.foo
= 'bar';
244 expect( uri
.toString() ).toEqual( 'http://en.wiki.local/w/api.php?foo=bar' );
245 uri
.extend( { foo
: 'quux', pif
: 'paf' } );
246 expect( uri
.toString() ).toContain( 'foo=quux' );
247 expect( uri
.toString() ).not
.toContain( 'foo=bar' );
248 expect( uri
.toString() ).toContain( 'pif=paf' );
251 it ( "can remove query arguments", function() {
252 uri
.query
.foo
= 'bar';
253 expect( uri
.toString() ).toEqual( 'http://en.wiki.local/w/api.php?foo=bar' );
254 delete( uri
.query
.foo
);
255 expect( uri
.toString() ).toEqual( 'http://en.wiki.local/w/api.php' );
260 describe( "should handle protocol-relative URLs", function() {
262 it ( "should create protocol-relative URLs with same protocol as document", function() {
263 var uriRel
= mw
.UriRelative( 'glork://en.wiki.local/foo.php' );
264 var uri
= new uriRel( '//en.wiki.local/w/api.php' );
265 expect( uri
.protocol
).toEqual( 'glork' );
270 it( "should throw error on no arguments to constructor", function() {
272 var uri
= new mw
.Uri();
273 } ).toThrow( "Bad constructor arguments" );
276 it( "should throw error on empty string as argument to constructor", function() {
278 var uri
= new mw
.Uri( '' );
279 } ).toThrow( "Bad constructor arguments" );
282 it( "should throw error on non-URI as argument to constructor", function() {
284 var uri
= new mw
.Uri( 'glaswegian penguins' );
285 } ).toThrow( "Bad constructor arguments" );
288 it( "should throw error on improper URI as argument to constructor", function() {
290 var uri
= new mw
.Uri( 'http:/foo.com' );
291 } ).toThrow( "Bad constructor arguments" );
294 it( "should throw error on URI without protocol or // in strict mode", function() {
296 var uri
= new mw
.Uri( 'foo.com/bar/baz', true );
297 } ).toThrow( "Bad constructor arguments" );
300 it( "should normalize URI without protocol or // in loose mode", function() {
301 var uri
= new mw
.Uri( 'foo.com/bar/baz', false );
302 expect( uri
.toString() ).toEqual( 'http://foo.com/bar/baz' );