addressable 1.0.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,12 +21,15 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- module Addressable
25
- module ADDRESSABLE_VERSION #:nodoc:
26
- MAJOR = 1
27
- MINOR = 0
28
- TINY = 4
24
+ # Used to prevent the class/module from being loaded more than once
25
+ if !defined?(Addressable::VERSION)
26
+ module Addressable
27
+ module VERSION #:nodoc:
28
+ MAJOR = 2
29
+ MINOR = 0
30
+ TINY = 0
29
31
 
30
- STRING = [MAJOR, MINOR, TINY].join('.')
32
+ STRING = [MAJOR, MINOR, TINY].join('.')
33
+ end
31
34
  end
32
35
  end
@@ -0,0 +1,196 @@
1
+ # coding:utf-8
2
+ #--
3
+ # Addressable, Copyright (c) 2006-2007 Bob Aman
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #++
24
+
25
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
26
+ $:.uniq!
27
+
28
+ require "addressable/idna"
29
+
30
+ describe Addressable::IDNA, "when converting from unicode to ASCII" do
31
+ it "should convert 'www.google.com' correctly" do
32
+ Addressable::IDNA.to_ascii("www.google.com").should == "www.google.com"
33
+ end
34
+
35
+ it "should convert 'www.詹姆斯.com' correctly" do
36
+ Addressable::IDNA.to_ascii(
37
+ "www.詹姆斯.com"
38
+ ).should == "www.xn--8ws00zhy3a.com"
39
+ end
40
+
41
+ it "should convert 'www.Iñtërnâtiônàlizætiøn.com' correctly" do
42
+ Addressable::IDNA.to_ascii(
43
+ "www.I\303\261t\303\253rn\303\242ti\303\264" +
44
+ "n\303\240liz\303\246ti\303\270n.com"
45
+ ).should == "www.xn--itrntinliztin-vdb0a5exd8ewcye.com"
46
+ end
47
+
48
+ it "should convert 'www.Iñtërnâtiônàlizætiøn.com' correctly" do
49
+ Addressable::IDNA.to_ascii(
50
+ "www.In\314\203te\314\210rna\314\202tio\314\202n" +
51
+ "a\314\200liz\303\246ti\303\270n.com"
52
+ ).should == "www.xn--itrntinliztin-vdb0a5exd8ewcye.com"
53
+ end
54
+
55
+ it "should convert " +
56
+ "'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
57
+ "correctly" do
58
+ Addressable::IDNA.to_ascii(
59
+ "www.\343\201\273\343\202\223\343\201\250\343\201\206\343\201\253\343" +
60
+ "\201\252\343\201\214\343\201\204\343\202\217\343\201\221\343\201\256" +
61
+ "\343\202\217\343\201\213\343\202\211\343\201\252\343\201\204\343\201" +
62
+ "\251\343\202\201\343\201\204\343\202\223\343\202\201\343\201\204\343" +
63
+ "\201\256\343\202\211\343\201\271\343\202\213\343\201\276\343\201\240" +
64
+ "\343\201\252\343\201\214\343\201\217\343\201\227\343\201\252\343\201" +
65
+ "\204\343\201\250\343\201\237\343\202\212\343\201\252\343\201\204." +
66
+ "w3.mag.keio.ac.jp"
67
+ ).should ==
68
+ "www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3" +
69
+ "fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp"
70
+ end
71
+
72
+ it "should convert " +
73
+ "'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
74
+ "correctly" do
75
+ Addressable::IDNA.to_ascii(
76
+ "www.\343\201\273\343\202\223\343\201\250\343\201\206\343\201\253\343" +
77
+ "\201\252\343\201\213\343\202\231\343\201\204\343\202\217\343\201\221" +
78
+ "\343\201\256\343\202\217\343\201\213\343\202\211\343\201\252\343\201" +
79
+ "\204\343\201\250\343\202\231\343\202\201\343\201\204\343\202\223\343" +
80
+ "\202\201\343\201\204\343\201\256\343\202\211\343\201\270\343\202\231" +
81
+ "\343\202\213\343\201\276\343\201\237\343\202\231\343\201\252\343\201" +
82
+ "\213\343\202\231\343\201\217\343\201\227\343\201\252\343\201\204\343" +
83
+ "\201\250\343\201\237\343\202\212\343\201\252\343\201\204." +
84
+ "w3.mag.keio.ac.jp"
85
+ ).should ==
86
+ "www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3" +
87
+ "fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp"
88
+ end
89
+
90
+ it "should convert '点心和烤鸭.w3.mag.keio.ac.jp' correctly" do
91
+ Addressable::IDNA.to_ascii(
92
+ "点心和烤鸭.w3.mag.keio.ac.jp"
93
+ ).should == "xn--0trv4xfvn8el34t.w3.mag.keio.ac.jp"
94
+ end
95
+
96
+ it "should convert '가각갂갃간갅갆갇갈갉힢힣.com' correctly" do
97
+ Addressable::IDNA.to_ascii(
98
+ "가각갂갃간갅갆갇갈갉힢힣.com"
99
+ ).should == "xn--o39acdefghijk5883jma.com"
100
+ end
101
+
102
+ it "should convert " +
103
+ "'\347\242\274\346\250\231\346\272\226\350" +
104
+ "\220\254\345\234\213\347\242\274.com' correctly" do
105
+ Addressable::IDNA.to_ascii(
106
+ "\347\242\274\346\250\231\346\272\226\350" +
107
+ "\220\254\345\234\213\347\242\274.com"
108
+ ).should == "xn--9cs565brid46mda086o.com"
109
+ end
110
+
111
+ it "should convert 'リ宠퐱〹.com' correctly" do
112
+ Addressable::IDNA.to_ascii(
113
+ "\357\276\230\345\256\240\355\220\261\343\200\271.com"
114
+ ).should == "xn--eek174hoxfpr4k.com"
115
+ end
116
+
117
+ it "should convert 'リ宠퐱卄.com' correctly" do
118
+ Addressable::IDNA.to_ascii(
119
+ "\343\203\252\345\256\240\355\220\261\345\215\204.com"
120
+ ).should == "xn--eek174hoxfpr4k.com"
121
+ end
122
+
123
+ it "should convert 'ᆵ' correctly" do
124
+ Addressable::IDNA.to_ascii(
125
+ "\341\206\265"
126
+ ).should == "xn--4ud"
127
+ end
128
+
129
+ it "should convert 'ᆵ' correctly" do
130
+ Addressable::IDNA.to_ascii(
131
+ "\357\276\257"
132
+ ).should == "xn--4ud"
133
+ end
134
+ end
135
+
136
+ describe Addressable::IDNA, "when converting from ASCII to unicode" do
137
+ it "should convert 'www.google.com' correctly" do
138
+ Addressable::IDNA.to_unicode("www.google.com").should == "www.google.com"
139
+ end
140
+
141
+ it "should convert 'www.詹姆斯.com' correctly" do
142
+ Addressable::IDNA.to_unicode(
143
+ "www.xn--8ws00zhy3a.com"
144
+ ).should == "www.詹姆斯.com"
145
+ end
146
+
147
+ it "should convert 'www.iñtërnâtiônàlizætiøn.com' correctly" do
148
+ Addressable::IDNA.to_unicode(
149
+ "www.xn--itrntinliztin-vdb0a5exd8ewcye.com"
150
+ ).should == "www.iñtërnâtiônàlizætiøn.com"
151
+ end
152
+
153
+ it "should convert " +
154
+ "'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
155
+ "correctly" do
156
+ Addressable::IDNA.to_unicode(
157
+ "www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3" +
158
+ "fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp"
159
+ ).should ==
160
+ "www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp"
161
+ end
162
+
163
+ it "should convert '点心和烤鸭.w3.mag.keio.ac.jp' correctly" do
164
+ Addressable::IDNA.to_unicode(
165
+ "xn--0trv4xfvn8el34t.w3.mag.keio.ac.jp"
166
+ ).should == "点心和烤鸭.w3.mag.keio.ac.jp"
167
+ end
168
+
169
+ it "should convert '가각갂갃간갅갆갇갈갉힢힣.com' correctly" do
170
+ Addressable::IDNA.to_unicode(
171
+ "xn--o39acdefghijk5883jma.com"
172
+ ).should == "가각갂갃간갅갆갇갈갉힢힣.com"
173
+ end
174
+
175
+ it "should convert " +
176
+ "'\347\242\274\346\250\231\346\272\226\350" +
177
+ "\220\254\345\234\213\347\242\274.com' correctly" do
178
+ Addressable::IDNA.to_unicode(
179
+ "xn--9cs565brid46mda086o.com"
180
+ ).should ==
181
+ "\347\242\274\346\250\231\346\272\226\350" +
182
+ "\220\254\345\234\213\347\242\274.com"
183
+ end
184
+
185
+ it "should convert 'リ宠퐱卄.com' correctly" do
186
+ Addressable::IDNA.to_unicode(
187
+ "xn--eek174hoxfpr4k.com"
188
+ ).should == "\343\203\252\345\256\240\355\220\261\345\215\204.com"
189
+ end
190
+
191
+ it "should convert 'ᆵ' correctly" do
192
+ Addressable::IDNA.to_unicode(
193
+ "xn--4ud"
194
+ ).should == "\341\206\265"
195
+ end
196
+ end
@@ -1,3 +1,4 @@
1
+ # coding:utf-8
1
2
  #--
2
3
  # Addressable, Copyright (c) 2006-2007 Bob Aman
3
4
  #
@@ -24,24 +25,38 @@
24
25
  $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
25
26
  $:.uniq!
26
27
 
27
- require 'addressable/uri'
28
+ require "addressable/uri"
29
+
30
+ if !"".respond_to?("force_encoding")
31
+ class String
32
+ def force_encoding(encoding)
33
+ # Do nothing, just make sure this gets called.
34
+ end
35
+ end
36
+
37
+ class Encoding
38
+ UTF_8 = Encoding.new
39
+ ASCII_8BIT = Encoding.new
40
+ end
41
+ end
28
42
 
29
43
  class ExampleProcessor
30
44
  def self.validate(name, value)
31
45
  return !!(value =~ /^[\w ]+$/) if name == "query"
32
46
  return true
33
47
  end
34
-
48
+
35
49
  def self.transform(name, value)
36
50
  return value.gsub(/ /, "+") if name == "query"
37
51
  return value
38
52
  end
39
-
53
+
40
54
  def self.restore(name, value)
41
55
  return value.gsub(/\+/, " ") if name == "query"
56
+ return value.tr("A-Za-z", "N-ZA-Mn-za-m") if name == "rot13"
42
57
  return value
43
58
  end
44
-
59
+
45
60
  def self.match(name)
46
61
  return ".*?" if name == "first"
47
62
  return ".*"
@@ -57,7 +72,7 @@ end
57
72
  describe Addressable::URI, "when created with a non-numeric port number" do
58
73
  it "should raise an error" do
59
74
  (lambda do
60
- Addressable::URI.new(nil, nil, nil, nil, "bogus", nil, nil, nil)
75
+ Addressable::URI.new(:port => "bogus")
61
76
  end).should raise_error(Addressable::URI::InvalidURIError)
62
77
  end
63
78
  end
@@ -73,9 +88,9 @@ end
73
88
 
74
89
  describe Addressable::URI, "when created from nil components" do
75
90
  before do
76
- @uri = Addressable::URI.new(nil, nil, nil, nil, nil, nil, nil, nil)
91
+ @uri = Addressable::URI.new
77
92
  end
78
-
93
+
79
94
  it "should have an empty path" do
80
95
  @uri.path.should == ""
81
96
  end
@@ -88,28 +103,65 @@ end
88
103
  describe Addressable::URI, "when created from string components" do
89
104
  before do
90
105
  @uri = Addressable::URI.new(
91
- "http", nil, nil, "example.com", nil, nil, nil, nil)
106
+ :scheme => "http", :host => "example.com"
107
+ )
92
108
  end
93
109
 
94
110
  it "should be equal to the equivalent parsed URI" do
95
111
  @uri.should == Addressable::URI.parse("http://example.com")
96
112
  end
113
+
114
+ it "should raise an error if invalid components omitted" do
115
+ (lambda do
116
+ @uri.omit(:bogus)
117
+ end).should raise_error(ArgumentError)
118
+ (lambda do
119
+ @uri.omit(:scheme, :bogus, :path)
120
+ end).should raise_error(ArgumentError)
121
+ end
97
122
  end
98
123
 
99
124
  describe Addressable::URI, "when created with a nil host but " +
100
125
  "non-nil authority components" do
101
126
  it "should raise an error" do
102
127
  (lambda do
103
- Addressable::URI.new(nil, "user", "pass", nil, 80, nil, nil, nil)
128
+ Addressable::URI.new(:user => "user", :password => "pass", :port => 80)
104
129
  end).should raise_error(Addressable::URI::InvalidURIError)
105
130
  end
106
131
  end
107
132
 
133
+ describe Addressable::URI, "when created with both an authority and a user" do
134
+ it "should raise an error" do
135
+ (lambda do
136
+ Addressable::URI.new(:user => "user", :authority => "user@example.com:80")
137
+ end).should raise_error(ArgumentError)
138
+ end
139
+ end
140
+
141
+ describe Addressable::URI, "when created with an authority and no port" do
142
+ before do
143
+ @uri = Addressable::URI.new(:authority => "user@example.com")
144
+ end
145
+
146
+ it "should not infer a port" do
147
+ @uri.port.should == nil
148
+ @uri.inferred_port.should == nil
149
+ end
150
+ end
151
+
152
+ describe Addressable::URI, "when created with both a userinfo and a user" do
153
+ it "should raise an error" do
154
+ (lambda do
155
+ Addressable::URI.new(:user => "user", :userinfo => "user:pass")
156
+ end).should raise_error(ArgumentError)
157
+ end
158
+ end
159
+
108
160
  describe Addressable::URI, "when created with a path that hasn't been " +
109
161
  "prefixed with a '/' but a host specified" do
110
162
  it "should prefix a '/' to the path" do
111
163
  Addressable::URI.new(
112
- "http", nil, nil, "example.com", nil, "path", nil, nil
164
+ :scheme => "http", :host => "example.com", :path => "path"
113
165
  ).should == Addressable::URI.parse("http://example.com/path")
114
166
  end
115
167
  end
@@ -118,7 +170,7 @@ describe Addressable::URI, "when created with a path that hasn't been " +
118
170
  "prefixed with a '/' but no host specified" do
119
171
  it "should prefix a '/' to the path" do
120
172
  Addressable::URI.new(
121
- "http", nil, nil, nil, nil, "path", nil, nil
173
+ :scheme => "http", :path => "path"
122
174
  ).should == Addressable::URI.parse("http:path")
123
175
  end
124
176
  end
@@ -177,6 +229,16 @@ describe Addressable::URI, " when parsed from " +
177
229
  it "should be considered to be in normal form" do
178
230
  @uri.normalize.should be_eql(@uri)
179
231
  end
232
+
233
+ it "should correctly omit components" do
234
+ @uri.omit(:scheme).to_s.should == "//www.ietf.org/rfc/rfc2396.txt"
235
+ @uri.omit(:path).to_s.should == "http://www.ietf.org"
236
+ end
237
+
238
+ it "should correctly omit components destructively" do
239
+ @uri.omit!(:scheme)
240
+ @uri.to_s.should == "//www.ietf.org/rfc/rfc2396.txt"
241
+ end
180
242
  end
181
243
 
182
244
  # Section 1.1.2 of RFC 3986
@@ -209,6 +271,16 @@ describe Addressable::URI, "when parsed from " +
209
271
  it "should be considered to be in normal form" do
210
272
  @uri.normalize.should be_eql(@uri)
211
273
  end
274
+
275
+ it "should correctly omit components" do
276
+ @uri.omit(:scheme, :authority).to_s.should == "/c=GB?objectClass?one"
277
+ @uri.omit(:path).to_s.should == "ldap://[2001:db8::7]?objectClass?one"
278
+ end
279
+
280
+ it "should correctly omit components destructively" do
281
+ @uri.omit!(:scheme, :authority)
282
+ @uri.to_s.should == "/c=GB?objectClass?one"
283
+ end
212
284
  end
213
285
 
214
286
  # Section 1.1.2 of RFC 3986
@@ -386,13 +458,13 @@ describe Addressable::URI, " when parsed from " +
386
458
  it "should have no password" do
387
459
  @uri.password.should == nil
388
460
  end
389
-
461
+
390
462
  it "should use port 80" do
391
- @uri.port.should == 80
463
+ @uri.inferred_port.should == 80
392
464
  end
393
-
465
+
394
466
  it "should not have a specified port" do
395
- @uri.specified_port.should == nil
467
+ @uri.port.should == nil
396
468
  end
397
469
 
398
470
  it "should have an empty path" do
@@ -401,6 +473,7 @@ describe Addressable::URI, " when parsed from " +
401
473
 
402
474
  it "should have no query string" do
403
475
  @uri.query.should == nil
476
+ @uri.query_values.should == nil
404
477
  end
405
478
 
406
479
  it "should have no fragment" do
@@ -422,7 +495,7 @@ describe Addressable::URI, " when parsed from " +
422
495
  it "should not be equal to 42" do
423
496
  (@uri == 42).should == false
424
497
  end
425
-
498
+
426
499
  it "should not be roughly equal to 42" do
427
500
  (@uri === 42).should == false
428
501
  end
@@ -446,9 +519,9 @@ describe Addressable::URI, " when parsed from " +
446
519
  end).should_not raise_error
447
520
  end
448
521
 
449
- it "should result in itself when merged with itself" do
450
- @uri.merge(@uri).to_s.should == "http://example.com"
451
- @uri.merge!(@uri).to_s.should == "http://example.com"
522
+ it "should result in itself when joined with itself" do
523
+ @uri.join(@uri).to_s.should == "http://example.com"
524
+ @uri.join!(@uri).to_s.should == "http://example.com"
452
525
  end
453
526
 
454
527
  # Section 6.2.3 of RFC 3986
@@ -470,22 +543,22 @@ describe Addressable::URI, " when parsed from " +
470
543
  it "should be equivalent to http://EXAMPLE.COM/" do
471
544
  @uri.should == Addressable::URI.parse("http://EXAMPLE.COM/")
472
545
  end
473
-
546
+
474
547
  it "should have a route of '/path/' to 'http://example.com/path/'" do
475
548
  @uri.route_to("http://example.com/path/").should ==
476
549
  Addressable::URI.parse("/path/")
477
550
  end
478
-
551
+
479
552
  it "should have a route of '/' from 'http://example.com/path/'" do
480
553
  @uri.route_from("http://example.com/path/").should ==
481
554
  Addressable::URI.parse("/")
482
555
  end
483
-
556
+
484
557
  it "should have a route of '#' to 'http://example.com/'" do
485
558
  @uri.route_to("http://example.com/").should ==
486
559
  Addressable::URI.parse("#")
487
560
  end
488
-
561
+
489
562
  it "should have a route of 'http://elsewhere.com/' to " +
490
563
  "'http://elsewhere.com/'" do
491
564
  @uri.route_to("http://elsewhere.com/").should ==
@@ -498,6 +571,12 @@ describe Addressable::URI, " when parsed from " +
498
571
  Addressable::URI.parse("http://example.com/relative/path")
499
572
  end
500
573
 
574
+ it "when joined with a bogus object a TypeError should be raised" do
575
+ (lambda do
576
+ @uri.join(42)
577
+ end).should raise_error(TypeError)
578
+ end
579
+
501
580
  it "should have the correct username after assignment" do
502
581
  @uri.user = "newuser"
503
582
  @uri.user.should == "newuser"
@@ -511,7 +590,7 @@ describe Addressable::URI, " when parsed from " +
511
590
  @uri.user.should == ""
512
591
  @uri.to_s.should == "http://:newpass@example.com"
513
592
  end
514
-
593
+
515
594
  it "should have the correct user/pass after repeated assignment" do
516
595
  @uri.user = nil
517
596
  @uri.user.should == nil
@@ -537,7 +616,7 @@ describe Addressable::URI, " when parsed from " +
537
616
  @uri.user.should == ""
538
617
  @uri.to_s.should == "http://:newpass@example.com"
539
618
  end
540
-
619
+
541
620
  it "should have the correct user/pass after userinfo assignment" do
542
621
  @uri.user = "newuser"
543
622
  @uri.user.should == "newuser"
@@ -548,7 +627,7 @@ describe Addressable::URI, " when parsed from " +
548
627
  @uri.user.should == nil
549
628
  @uri.password.should == nil
550
629
  end
551
-
630
+
552
631
  it "should correctly convert to a hash" do
553
632
  @uri.to_hash.should == {
554
633
  :scheme => "http",
@@ -572,7 +651,7 @@ describe Addressable::URI, " when parsed from " +
572
651
  before do
573
652
  @uri = Addressable::URI.parse("http://example.com/")
574
653
  end
575
-
654
+
576
655
  # Based on http://intertwingly.net/blog/2004/07/31/URI-Equivalence
577
656
  it "should be equivalent to http://example.com" do
578
657
  @uri.should == Addressable::URI.parse("http://example.com")
@@ -611,7 +690,7 @@ describe Addressable::URI, " when parsed from " +
611
690
  @uri.user.should == nil
612
691
  @uri.to_s.should == "http://example.com/"
613
692
  end
614
-
693
+
615
694
  it "should correctly convert to a hash" do
616
695
  @uri.to_hash.should == {
617
696
  :scheme => "http",
@@ -647,11 +726,11 @@ describe Addressable::URI, " when parsed from " +
647
726
  before do
648
727
  @uri = Addressable::URI.parse("http://@example.com/")
649
728
  end
650
-
729
+
651
730
  it "should be equivalent to http://example.com" do
652
731
  @uri.should == Addressable::URI.parse("http://example.com")
653
732
  end
654
-
733
+
655
734
  it "should correctly convert to a hash" do
656
735
  @uri.to_hash.should == {
657
736
  :scheme => "http",
@@ -675,7 +754,7 @@ describe Addressable::URI, " when parsed from " +
675
754
  before do
676
755
  @uri = Addressable::URI.parse("http://example.com./")
677
756
  end
678
-
757
+
679
758
  it "should be equivalent to http://example.com" do
680
759
  @uri.should == Addressable::URI.parse("http://example.com")
681
760
  end
@@ -694,11 +773,11 @@ describe Addressable::URI, " when parsed from " +
694
773
  before do
695
774
  @uri = Addressable::URI.parse("http://:@example.com/")
696
775
  end
697
-
776
+
698
777
  it "should be equivalent to http://example.com" do
699
778
  @uri.should == Addressable::URI.parse("http://example.com")
700
779
  end
701
-
780
+
702
781
  it "should correctly convert to a hash" do
703
782
  @uri.to_hash.should == {
704
783
  :scheme => "http",
@@ -746,23 +825,36 @@ describe Addressable::URI, " when parsed from " +
746
825
 
747
826
  # Based on http://intertwingly.net/blog/2004/07/31/URI-Equivalence
748
827
  it "should be equivalent to 'http://example.com/C%CC%A7'" do
749
- if Addressable::URI::IDNA.send(:use_libidn?)
750
- @uri.should == Addressable::URI.parse("http://example.com/C%CC%A7")
751
- else
752
- pending("Skipping IDN specification because GNU libidn is unavailable.")
753
- end
828
+ @uri.should == Addressable::URI.parse("http://example.com/C%CC%A7")
754
829
  end
755
-
830
+
756
831
  it "should not change if encoded with the normalizing algorithm" do
757
- Addressable::URI.normalized_encode(@uri).to_s.should ==
832
+ Addressable::URI.normalized_encode(@uri).to_s.should ==
758
833
  "http://example.com/%C3%87"
759
834
  end
760
-
835
+
836
+ it "should raise an error if encoding with an unexpected return type" do
837
+ (lambda do
838
+ Addressable::URI.normalized_encode(@uri, Integer)
839
+ end).should raise_error(TypeError)
840
+ end
841
+
761
842
  it "if percent encoded should be 'http://example.com/C%25CC%25A7'" do
762
843
  Addressable::URI.encode(@uri).to_s.should ==
763
844
  "http://example.com/%25C3%2587"
764
845
  end
765
846
 
847
+ it "if percent encoded should be 'http://example.com/C%25CC%25A7'" do
848
+ Addressable::URI.encode(@uri, Addressable::URI).should ==
849
+ Addressable::URI.parse("http://example.com/%25C3%2587")
850
+ end
851
+
852
+ it "should raise an error if encoding with an unexpected return type" do
853
+ (lambda do
854
+ Addressable::URI.encode(@uri, Integer)
855
+ end).should raise_error(TypeError)
856
+ end
857
+
766
858
  it "should be identical to its duplicate" do
767
859
  @uri.should == @uri.dup
768
860
  end
@@ -793,9 +885,9 @@ describe Addressable::URI, " when parsed from " +
793
885
  it "should have no password" do
794
886
  @uri.password.should == nil
795
887
  end
796
-
888
+
797
889
  it "should use port 80" do
798
- @uri.port.should == 80
890
+ @uri.inferred_port.should == 80
799
891
  end
800
892
 
801
893
  it "should have a path of '/'" do
@@ -817,7 +909,7 @@ describe Addressable::URI, " when parsed from " +
817
909
  it "should not be considered relative" do
818
910
  @uri.should_not be_relative
819
911
  end
820
-
912
+
821
913
  it "should be considered to be in normal form" do
822
914
  @uri.normalize.should be_eql(@uri)
823
915
  end
@@ -852,7 +944,7 @@ describe Addressable::URI, " when parsed from " +
852
944
  it "should have no password" do
853
945
  @uri.password.should == nil
854
946
  end
855
-
947
+
856
948
  it "should use port 80" do
857
949
  @uri.port.should == 80
858
950
  end
@@ -920,7 +1012,7 @@ describe Addressable::URI, " when parsed from " +
920
1012
  it "should be equal to http://EXAMPLE.COM/" do
921
1013
  @uri.should == Addressable::URI.parse("http://EXAMPLE.COM/")
922
1014
  end
923
-
1015
+
924
1016
  it "should correctly convert to a hash" do
925
1017
  @uri.to_hash.should == {
926
1018
  :scheme => "http",
@@ -964,7 +1056,7 @@ describe Addressable::URI, " when parsed from " +
964
1056
  it "should have no password" do
965
1057
  @uri.password.should == nil
966
1058
  end
967
-
1059
+
968
1060
  it "should use port 8080" do
969
1061
  @uri.port.should == 8080
970
1062
  end
@@ -993,25 +1085,25 @@ describe Addressable::URI, " when parsed from " +
993
1085
  @uri.eql?(Addressable::URI.parse(
994
1086
  "http://example.com:8080/")).should == true
995
1087
  end
996
-
1088
+
997
1089
  it "should have a route of 'http://example.com:8080/' from " +
998
1090
  "'http://example.com/path/to/'" do
999
1091
  @uri.route_from("http://example.com/path/to/").should ==
1000
1092
  Addressable::URI.parse("http://example.com:8080/")
1001
1093
  end
1002
-
1094
+
1003
1095
  it "should have a route of 'http://example.com:8080/' from " +
1004
1096
  "'http://example.com:80/path/to/'" do
1005
1097
  @uri.route_from("http://example.com:80/path/to/").should ==
1006
1098
  Addressable::URI.parse("http://example.com:8080/")
1007
1099
  end
1008
-
1100
+
1009
1101
  it "should have a route of '/' from " +
1010
1102
  "'http://example.com:8080/path/to/'" do
1011
1103
  @uri.route_from("http://example.com:8080/path/to/").should ==
1012
1104
  Addressable::URI.parse("/")
1013
1105
  end
1014
-
1106
+
1015
1107
  it "should have a route of 'http://example.com:8080/' from " +
1016
1108
  "'http://user:pass@example.com/path/to/'" do
1017
1109
  @uri.route_from("http://user:pass@example.com/path/to/").should ==
@@ -1061,9 +1153,9 @@ describe Addressable::URI, " when parsed from " +
1061
1153
  it "should have no password" do
1062
1154
  @uri.password.should == nil
1063
1155
  end
1064
-
1156
+
1065
1157
  it "should use port 80" do
1066
- @uri.port.should == 80
1158
+ @uri.inferred_port.should == 80
1067
1159
  end
1068
1160
 
1069
1161
  it "should have a path of '/path/to/resource/'" do
@@ -1090,31 +1182,31 @@ describe Addressable::URI, " when parsed from " +
1090
1182
  @uri.eql?(Addressable::URI.parse(
1091
1183
  "http://example.com/path/to/resource/")).should == true
1092
1184
  end
1093
-
1185
+
1094
1186
  it "should have a route of 'resource/' from " +
1095
1187
  "'http://example.com/path/to/'" do
1096
1188
  @uri.route_from("http://example.com/path/to/").should ==
1097
1189
  Addressable::URI.parse("resource/")
1098
1190
  end
1099
-
1191
+
1100
1192
  it "should have a route of 'resource/' from " +
1101
1193
  "'http://example.com:80/path/to/'" do
1102
1194
  @uri.route_from("http://example.com:80/path/to/").should ==
1103
1195
  Addressable::URI.parse("resource/")
1104
1196
  end
1105
-
1197
+
1106
1198
  it "should have a route of 'http://example.com/path/to/' from " +
1107
1199
  "'http://example.com:8080/path/to/'" do
1108
1200
  @uri.route_from("http://example.com:8080/path/to/").should ==
1109
1201
  Addressable::URI.parse("http://example.com/path/to/resource/")
1110
1202
  end
1111
-
1203
+
1112
1204
  it "should have a route of 'http://example.com/path/to/' from " +
1113
1205
  "'http://user:pass@example.com/path/to/'" do
1114
1206
  @uri.route_from("http://user:pass@example.com/path/to/").should ==
1115
1207
  Addressable::URI.parse("http://example.com/path/to/resource/")
1116
1208
  end
1117
-
1209
+
1118
1210
  it "should have a route of '/path/to/resource/' from " +
1119
1211
  "'http://example.com/to/resource/'" do
1120
1212
  @uri.route_from("http://example.com/to/resource/").should ==
@@ -1168,7 +1260,7 @@ describe Addressable::URI, "when parsed from " +
1168
1260
  it "should have no password" do
1169
1261
  @uri.password.should == nil
1170
1262
  end
1171
-
1263
+
1172
1264
  it "should not have a port" do
1173
1265
  @uri.port.should == nil
1174
1266
  end
@@ -1201,11 +1293,11 @@ describe Addressable::URI, "when parsed from " +
1201
1293
  @uri.route_from("http://example.com/")
1202
1294
  end).should raise_error(ArgumentError, /relative\/path\/to\/resource/)
1203
1295
  end
1204
-
1296
+
1205
1297
  it "when joined with 'another/relative/path' should be " +
1206
1298
  "'relative/path/to/another/relative/path'" do
1207
1299
  @uri.join('another/relative/path').should ==
1208
- Addressable::URI.parse("relative/path/to/another/relative/path")
1300
+ Addressable::URI.parse("relative/path/to/another/relative/path")
1209
1301
  end
1210
1302
 
1211
1303
  it "should be identical to its duplicate" do
@@ -1242,7 +1334,7 @@ describe Addressable::URI, "when parsed from " +
1242
1334
  it "should have no password" do
1243
1335
  @uri.password.should == nil
1244
1336
  end
1245
-
1337
+
1246
1338
  it "should not have a port" do
1247
1339
  @uri.port.should == nil
1248
1340
  end
@@ -1270,7 +1362,7 @@ describe Addressable::URI, "when parsed from " +
1270
1362
  it "when joined with 'another_relative_path' should be " +
1271
1363
  "'another_relative_path'" do
1272
1364
  @uri.join('another_relative_path').should ==
1273
- Addressable::URI.parse("another_relative_path")
1365
+ Addressable::URI.parse("another_relative_path")
1274
1366
  end
1275
1367
  end
1276
1368
 
@@ -1283,7 +1375,7 @@ describe Addressable::URI, " when parsed from " +
1283
1375
  it "should have a scheme of 'http'" do
1284
1376
  @uri.scheme.should == "http"
1285
1377
  end
1286
-
1378
+
1287
1379
  it "should have an authority segment of 'example.com'" do
1288
1380
  @uri.authority.should == "example.com"
1289
1381
  end
@@ -1299,9 +1391,9 @@ describe Addressable::URI, " when parsed from " +
1299
1391
  it "should have no password" do
1300
1392
  @uri.password.should == nil
1301
1393
  end
1302
-
1394
+
1303
1395
  it "should use port 80" do
1304
- @uri.port.should == 80
1396
+ @uri.inferred_port.should == 80
1305
1397
  end
1306
1398
 
1307
1399
  it "should have a path of '/file.txt'" do
@@ -1334,7 +1426,7 @@ describe Addressable::URI, " when parsed from " +
1334
1426
  it "should have a scheme of 'http'" do
1335
1427
  @uri.scheme.should == "http"
1336
1428
  end
1337
-
1429
+
1338
1430
  it "should have an authority segment of 'example.com'" do
1339
1431
  @uri.authority.should == "example.com"
1340
1432
  end
@@ -1350,9 +1442,9 @@ describe Addressable::URI, " when parsed from " +
1350
1442
  it "should have no password" do
1351
1443
  @uri.password.should == nil
1352
1444
  end
1353
-
1445
+
1354
1446
  it "should use port 80" do
1355
- @uri.port.should == 80
1447
+ @uri.inferred_port.should == 80
1356
1448
  end
1357
1449
 
1358
1450
  it "should have a path of '/file.txt;parameter'" do
@@ -1389,7 +1481,7 @@ describe Addressable::URI, " when parsed from " +
1389
1481
  it "should have a scheme of 'http'" do
1390
1482
  @uri.scheme.should == "http"
1391
1483
  end
1392
-
1484
+
1393
1485
  it "should have an authority segment of 'example.com'" do
1394
1486
  @uri.authority.should == "example.com"
1395
1487
  end
@@ -1405,9 +1497,9 @@ describe Addressable::URI, " when parsed from " +
1405
1497
  it "should have no password" do
1406
1498
  @uri.password.should == nil
1407
1499
  end
1408
-
1500
+
1409
1501
  it "should use port 80" do
1410
- @uri.port.should == 80
1502
+ @uri.inferred_port.should == 80
1411
1503
  end
1412
1504
 
1413
1505
  it "should have a path of '/file.txt;x=y'" do
@@ -1425,12 +1517,82 @@ describe Addressable::URI, " when parsed from " +
1425
1517
  it "should have no fragment" do
1426
1518
  @uri.fragment.should == nil
1427
1519
  end
1428
-
1520
+
1521
+ it "should be considered to be in normal form" do
1522
+ @uri.normalize.should be_eql(@uri)
1523
+ end
1524
+ end
1525
+
1526
+ describe Addressable::URI, " when parsed from " +
1527
+ "'svn+ssh://developername@rubyforge.org/var/svn/project'" do
1528
+ before do
1529
+ @uri = Addressable::URI.parse(
1530
+ "svn+ssh://developername@rubyforge.org/var/svn/project"
1531
+ )
1532
+ end
1533
+
1534
+ it "should have a scheme of 'svn+ssh'" do
1535
+ @uri.scheme.should == "svn+ssh"
1536
+ end
1537
+
1538
+ it "should be considered to be ip-based" do
1539
+ @uri.should be_ip_based
1540
+ end
1541
+
1542
+ it "should have a path of '/var/svn/project'" do
1543
+ @uri.path.should == "/var/svn/project"
1544
+ end
1545
+
1546
+ it "should have a username of 'developername'" do
1547
+ @uri.user.should == "developername"
1548
+ end
1549
+
1550
+ it "should have no password" do
1551
+ @uri.password.should == nil
1552
+ end
1553
+
1429
1554
  it "should be considered to be in normal form" do
1430
1555
  @uri.normalize.should be_eql(@uri)
1431
1556
  end
1432
1557
  end
1433
1558
 
1559
+ describe Addressable::URI, " when parsed from " +
1560
+ "'ssh+svn://developername@rubyforge.org/var/svn/project'" do
1561
+ before do
1562
+ @uri = Addressable::URI.parse(
1563
+ "ssh+svn://developername@rubyforge.org/var/svn/project"
1564
+ )
1565
+ end
1566
+
1567
+ it "should have a scheme of 'ssh+svn'" do
1568
+ @uri.scheme.should == "ssh+svn"
1569
+ end
1570
+
1571
+ it "should have a normalized scheme of 'svn+ssh'" do
1572
+ @uri.normalized_scheme.should == "svn+ssh"
1573
+ end
1574
+
1575
+ it "should not be considered to be ip-based" do
1576
+ @uri.should_not be_ip_based
1577
+ end
1578
+
1579
+ it "should have a path of '/var/svn/project'" do
1580
+ @uri.path.should == "/var/svn/project"
1581
+ end
1582
+
1583
+ it "should have a username of 'developername'" do
1584
+ @uri.user.should == "developername"
1585
+ end
1586
+
1587
+ it "should have no password" do
1588
+ @uri.password.should == nil
1589
+ end
1590
+
1591
+ it "should not be considered to be in normal form" do
1592
+ @uri.normalize.should_not be_eql(@uri)
1593
+ end
1594
+ end
1595
+
1434
1596
  describe Addressable::URI, " when parsed from " +
1435
1597
  "'mailto:user@example.com'" do
1436
1598
  before do
@@ -1452,7 +1614,7 @@ describe Addressable::URI, " when parsed from " +
1452
1614
  it "should have no user" do
1453
1615
  @uri.user.should == nil
1454
1616
  end
1455
-
1617
+
1456
1618
  it "should be considered to be in normal form" do
1457
1619
  @uri.normalize.should be_eql(@uri)
1458
1620
  end
@@ -1481,7 +1643,7 @@ describe Addressable::URI, " when parsed from " +
1481
1643
  it "should have no user" do
1482
1644
  @uri.user.should == nil
1483
1645
  end
1484
-
1646
+
1485
1647
  it "should be considered to be in normal form" do
1486
1648
  @uri.normalize.should be_eql(@uri)
1487
1649
  end
@@ -1492,7 +1654,7 @@ describe Addressable::URI, " when parsed from " +
1492
1654
  before do
1493
1655
  @uri = Addressable::URI.parse("http://example.com/x;y/")
1494
1656
  end
1495
-
1657
+
1496
1658
  it "should be considered to be in normal form" do
1497
1659
  @uri.normalize.should be_eql(@uri)
1498
1660
  end
@@ -1503,7 +1665,7 @@ describe Addressable::URI, " when parsed from " +
1503
1665
  before do
1504
1666
  @uri = Addressable::URI.parse("http://example.com/?x=1&y=2")
1505
1667
  end
1506
-
1668
+
1507
1669
  it "should be considered to be in normal form" do
1508
1670
  @uri.normalize.should be_eql(@uri)
1509
1671
  end
@@ -1522,7 +1684,7 @@ describe Addressable::URI, " when parsed from " +
1522
1684
  it "should have a path of 'http://example.com/'" do
1523
1685
  @uri.path.should == "http://example.com/"
1524
1686
  end
1525
-
1687
+
1526
1688
  it "should be considered to be in normal form" do
1527
1689
  @uri.normalize.should be_eql(@uri)
1528
1690
  end
@@ -1538,7 +1700,7 @@ describe Addressable::URI, " when parsed from " +
1538
1700
  it "should use the 'http' scheme" do
1539
1701
  @uri.scheme.should == "http"
1540
1702
  end
1541
-
1703
+
1542
1704
  it "should have an authority segment of 'user:pass@example.com'" do
1543
1705
  @uri.authority.should == "user:pass@example.com"
1544
1706
  end
@@ -1550,13 +1712,13 @@ describe Addressable::URI, " when parsed from " +
1550
1712
  it "should have a password of 'pass'" do
1551
1713
  @uri.password.should == "pass"
1552
1714
  end
1553
-
1715
+
1554
1716
  it "should have a host of 'example.com'" do
1555
1717
  @uri.host.should == "example.com"
1556
1718
  end
1557
1719
 
1558
1720
  it "should use port 80" do
1559
- @uri.port.should == 80
1721
+ @uri.inferred_port.should == 80
1560
1722
  end
1561
1723
 
1562
1724
  it "should have a path of '/path/to/resource'" do
@@ -1570,7 +1732,7 @@ describe Addressable::URI, " when parsed from " +
1570
1732
  it "should have a fragment of 'fragment'" do
1571
1733
  @uri.fragment.should == "fragment"
1572
1734
  end
1573
-
1735
+
1574
1736
  it "should be considered to be in normal form" do
1575
1737
  @uri.normalize.should be_eql(@uri)
1576
1738
  end
@@ -1580,33 +1742,33 @@ describe Addressable::URI, " when parsed from " +
1580
1742
  @uri.route_to("http://user:pass@example.com/path/").should ==
1581
1743
  Addressable::URI.parse("/path/")
1582
1744
  end
1583
-
1745
+
1584
1746
  it "should have a route of '/path/to/resource?query=x#fragment' " +
1585
1747
  "from 'http://user:pass@example.com/path/'" do
1586
1748
  @uri.route_from("http://user:pass@example.com/path/").should ==
1587
1749
  Addressable::URI.parse("to/resource?query=x#fragment")
1588
1750
  end
1589
-
1751
+
1590
1752
  it "should have a route of '?query=x#fragment' " +
1591
1753
  "from 'http://user:pass@example.com/path/to/resource'" do
1592
1754
  @uri.route_from("http://user:pass@example.com/path/to/resource").should ==
1593
1755
  Addressable::URI.parse("?query=x#fragment")
1594
1756
  end
1595
-
1757
+
1596
1758
  it "should have a route of '#fragment' " +
1597
1759
  "from 'http://user:pass@example.com/path/to/resource?query=x'" do
1598
1760
  @uri.route_from(
1599
1761
  "http://user:pass@example.com/path/to/resource?query=x").should ==
1600
1762
  Addressable::URI.parse("#fragment")
1601
1763
  end
1602
-
1764
+
1603
1765
  it "should have a route of '#fragment' from " +
1604
1766
  "'http://user:pass@example.com/path/to/resource?query=x#fragment'" do
1605
1767
  @uri.route_from(
1606
1768
  "http://user:pass@example.com/path/to/resource?query=x#fragment"
1607
1769
  ).should == Addressable::URI.parse("#fragment")
1608
1770
  end
1609
-
1771
+
1610
1772
  it "should have a route of 'http://elsewhere.com/' to " +
1611
1773
  "'http://elsewhere.com/'" do
1612
1774
  @uri.route_to("http://elsewhere.com/").should ==
@@ -1627,16 +1789,18 @@ describe Addressable::URI, " when parsed from " +
1627
1789
  @uri.to_s.should ==
1628
1790
  "ftp://user:pass@example.com/path/to/resource?query=x#fragment"
1629
1791
  end
1630
-
1792
+
1631
1793
  it "should have the correct authority segment after assignment" do
1632
1794
  @uri.authority = "newuser:newpass@example.com:80"
1633
1795
  @uri.authority.should == "newuser:newpass@example.com:80"
1634
1796
  @uri.user.should == "newuser"
1635
1797
  @uri.password.should == "newpass"
1798
+ @uri.userinfo.should == "newuser:newpass"
1799
+ @uri.normalized_userinfo.should == "newuser:newpass"
1636
1800
  @uri.host.should == "example.com"
1637
1801
  @uri.port.should == 80
1638
- @uri.specified_port.should == 80
1639
- @uri.to_s.should ==
1802
+ @uri.inferred_port.should == 80
1803
+ @uri.to_s.should ==
1640
1804
  "http://newuser:newpass@example.com:80" +
1641
1805
  "/path/to/resource?query=x#fragment"
1642
1806
  end
@@ -1648,8 +1812,8 @@ describe Addressable::URI, " when parsed from " +
1648
1812
  @uri.user.should == "newuser"
1649
1813
  @uri.password.should == "newpass"
1650
1814
  @uri.host.should == "example.com"
1651
- @uri.port.should == 80
1652
- @uri.specified_port.should == nil
1815
+ @uri.port.should == nil
1816
+ @uri.inferred_port.should == 80
1653
1817
  @uri.to_s.should ==
1654
1818
  "http://newuser:newpass@example.com" +
1655
1819
  "/path/to/resource?query=x#fragment"
@@ -1696,15 +1860,110 @@ describe Addressable::URI, " when parsed from " +
1696
1860
  it "should have the correct query string after assignment" do
1697
1861
  @uri.query = "newquery=x"
1698
1862
  @uri.query.should == "newquery=x"
1699
- @uri.to_s.should ==
1863
+ @uri.to_s.should ==
1700
1864
  "http://user:pass@example.com/path/to/resource?newquery=x#fragment"
1701
1865
  end
1702
1866
 
1867
+ it "should have the correct query string after hash assignment" do
1868
+ @uri.query_values = {"?uestion mark"=>"=sign", "hello"=>"günther"}
1869
+ @uri.query.split("&").should include("%3Fuestion%20mark=%3Dsign")
1870
+ @uri.query.split("&").should include("hello=g%C3%BCnther")
1871
+ @uri.query_values.should == {"?uestion mark"=>"=sign", "hello"=>"günther"}
1872
+ end
1873
+
1874
+ it "should have the correct query string after flag hash assignment" do
1875
+ @uri.query_values = {'flag?1' => true, 'fl=ag2' => true, 'flag3' => true}
1876
+ @uri.query.split("&").should include("flag%3F1")
1877
+ @uri.query.split("&").should include("fl%3Dag2")
1878
+ @uri.query.split("&").should include("flag3")
1879
+ @uri.query_values.should == {
1880
+ 'flag?1' => true, 'fl=ag2' => true, 'flag3' => true
1881
+ }
1882
+ end
1883
+
1703
1884
  it "should have the correct fragment after assignment" do
1704
1885
  @uri.fragment = "newfragment"
1705
1886
  @uri.fragment.should == "newfragment"
1706
1887
  @uri.to_s.should ==
1707
1888
  "http://user:pass@example.com/path/to/resource?query=x#newfragment"
1889
+
1890
+ @uri.fragment = nil
1891
+ @uri.fragment.should == nil
1892
+ @uri.to_s.should ==
1893
+ "http://user:pass@example.com/path/to/resource?query=x"
1894
+ end
1895
+
1896
+ it "should have the correct values after a merge" do
1897
+ @uri.merge(:fragment => "newfragment").to_s.should ==
1898
+ "http://user:pass@example.com/path/to/resource?query=x#newfragment"
1899
+ end
1900
+
1901
+ it "should have the correct values after a merge" do
1902
+ @uri.merge(:fragment => nil).to_s.should ==
1903
+ "http://user:pass@example.com/path/to/resource?query=x"
1904
+ end
1905
+
1906
+ it "should have the correct values after a merge" do
1907
+ @uri.merge(:userinfo => "newuser:newpass").to_s.should ==
1908
+ "http://newuser:newpass@example.com/path/to/resource?query=x#fragment"
1909
+ end
1910
+
1911
+ it "should have the correct values after a merge" do
1912
+ @uri.merge(:userinfo => nil).to_s.should ==
1913
+ "http://example.com/path/to/resource?query=x#fragment"
1914
+ end
1915
+
1916
+ it "should have the correct values after a merge" do
1917
+ @uri.merge(:path => "newpath").to_s.should ==
1918
+ "http://user:pass@example.com/newpath?query=x#fragment"
1919
+ end
1920
+
1921
+ it "should have the correct values after a merge" do
1922
+ @uri.merge(:port => "42", :path => "newpath", :query => "").to_s.should ==
1923
+ "http://user:pass@example.com:42/newpath?#fragment"
1924
+ end
1925
+
1926
+ it "should have the correct values after a merge" do
1927
+ @uri.merge(:authority => "foo:bar@baz:42").to_s.should ==
1928
+ "http://foo:bar@baz:42/path/to/resource?query=x#fragment"
1929
+ @uri.to_s.should ==
1930
+ "http://user:pass@example.com/path/to/resource?query=x#fragment"
1931
+ end
1932
+
1933
+ it "should have the correct values after a destructive merge" do
1934
+ @uri.merge!(:authority => "foo:bar@baz:42")
1935
+ @uri.to_s.should ==
1936
+ "http://foo:bar@baz:42/path/to/resource?query=x#fragment"
1937
+ end
1938
+
1939
+ it "should fail to merge with bogus values" do
1940
+ (lambda do
1941
+ @uri.merge(:port => "bogus")
1942
+ end).should raise_error(Addressable::URI::InvalidURIError)
1943
+ end
1944
+
1945
+ it "should fail to merge with bogus parameters" do
1946
+ (lambda do
1947
+ @uri.merge(42)
1948
+ end).should raise_error(TypeError)
1949
+ end
1950
+
1951
+ it "should fail to merge with bogus parameters" do
1952
+ (lambda do
1953
+ @uri.merge("http://example.com/")
1954
+ end).should raise_error(TypeError)
1955
+ end
1956
+
1957
+ it "should fail to merge with both authority and subcomponents" do
1958
+ (lambda do
1959
+ @uri.merge(:authority => "foo:bar@baz:42", :port => "42")
1960
+ end).should raise_error(ArgumentError)
1961
+ end
1962
+
1963
+ it "should fail to merge with both userinfo and subcomponents" do
1964
+ (lambda do
1965
+ @uri.merge(:userinfo => "foo:bar", :user => "foo")
1966
+ end).should raise_error(ArgumentError)
1708
1967
  end
1709
1968
 
1710
1969
  it "should be identical to its duplicate" do
@@ -1729,15 +1988,23 @@ describe Addressable::URI, " when parsed from " +
1729
1988
  it "should have no password" do
1730
1989
  @uri.password.should == nil
1731
1990
  end
1732
-
1991
+
1992
+ it "should have a userinfo of 'user'" do
1993
+ @uri.userinfo.should == "user"
1994
+ end
1995
+
1996
+ it "should have a normalized userinfo of 'user'" do
1997
+ @uri.normalized_userinfo.should == "user"
1998
+ end
1999
+
1733
2000
  it "should have a host of 'example.com'" do
1734
2001
  @uri.host.should == "example.com"
1735
2002
  end
1736
2003
 
1737
2004
  it "should use port 80" do
1738
- @uri.port.should == 80
2005
+ @uri.inferred_port.should == 80
1739
2006
  end
1740
-
2007
+
1741
2008
  it "should have the correct username after assignment" do
1742
2009
  @uri.user = "newuser"
1743
2010
  @uri.user.should == "newuser"
@@ -1757,8 +2024,8 @@ describe Addressable::URI, " when parsed from " +
1757
2024
  @uri.user.should == "newuser"
1758
2025
  @uri.password.should == "newpass"
1759
2026
  @uri.host.should == "example.com"
1760
- @uri.port.should == 80
1761
- @uri.specified_port.should == nil
2027
+ @uri.port.should == nil
2028
+ @uri.inferred_port.should == 80
1762
2029
  @uri.to_s.should == "http://newuser:newpass@example.com"
1763
2030
  end
1764
2031
 
@@ -1768,22 +2035,22 @@ describe Addressable::URI, " when parsed from " +
1768
2035
  @uri.user.should == nil
1769
2036
  @uri.password.should == nil
1770
2037
  @uri.host.should == "example.com"
1771
- @uri.port.should == 80
1772
- @uri.specified_port.should == nil
2038
+ @uri.port.should == nil
2039
+ @uri.inferred_port.should == 80
1773
2040
  @uri.to_s.should == "http://example.com"
1774
2041
  end
1775
-
2042
+
1776
2043
  it "should have the correct authority segment after assignment" do
1777
2044
  @uri.authority = "newuser@example.com"
1778
2045
  @uri.authority.should == "newuser@example.com"
1779
2046
  @uri.user.should == "newuser"
1780
2047
  @uri.password.should == nil
1781
2048
  @uri.host.should == "example.com"
1782
- @uri.port.should == 80
1783
- @uri.specified_port.should == nil
2049
+ @uri.port.should == nil
2050
+ @uri.inferred_port.should == 80
1784
2051
  @uri.to_s.should == "http://newuser@example.com"
1785
2052
  end
1786
-
2053
+
1787
2054
  it "should raise an error after nil assignment of authority segment" do
1788
2055
  (lambda do
1789
2056
  # This would create an invalid URI
@@ -1809,13 +2076,17 @@ describe Addressable::URI, " when parsed from " +
1809
2076
  it "should have a password of ''" do
1810
2077
  @uri.password.should == ""
1811
2078
  end
1812
-
2079
+
2080
+ it "should have a normalized userinfo of 'user:'" do
2081
+ @uri.normalized_userinfo.should == "user:"
2082
+ end
2083
+
1813
2084
  it "should have a host of 'example.com'" do
1814
2085
  @uri.host.should == "example.com"
1815
2086
  end
1816
2087
 
1817
2088
  it "should use port 80" do
1818
- @uri.port.should == 80
2089
+ @uri.inferred_port.should == 80
1819
2090
  end
1820
2091
 
1821
2092
  it "should have the correct username after assignment" do
@@ -1837,8 +2108,8 @@ describe Addressable::URI, " when parsed from " +
1837
2108
  @uri.user.should == "newuser"
1838
2109
  @uri.password.should == ""
1839
2110
  @uri.host.should == "example.com"
1840
- @uri.port.should == 80
1841
- @uri.specified_port.should == nil
2111
+ @uri.port.should == nil
2112
+ @uri.inferred_port.should == 80
1842
2113
  @uri.to_s.should == "http://newuser:@example.com"
1843
2114
  end
1844
2115
  end
@@ -1864,13 +2135,17 @@ describe Addressable::URI, " when parsed from " +
1864
2135
  it "should have a userinfo of ':pass'" do
1865
2136
  @uri.userinfo.should == ":pass"
1866
2137
  end
1867
-
2138
+
2139
+ it "should have a normalized userinfo of ':pass'" do
2140
+ @uri.normalized_userinfo.should == ":pass"
2141
+ end
2142
+
1868
2143
  it "should have a host of 'example.com'" do
1869
2144
  @uri.host.should == "example.com"
1870
2145
  end
1871
2146
 
1872
2147
  it "should use port 80" do
1873
- @uri.port.should == 80
2148
+ @uri.inferred_port.should == 80
1874
2149
  end
1875
2150
 
1876
2151
  it "should have the correct username after assignment" do
@@ -1893,8 +2168,8 @@ describe Addressable::URI, " when parsed from " +
1893
2168
  @uri.user.should == ""
1894
2169
  @uri.password.should == "newpass"
1895
2170
  @uri.host.should == "example.com"
1896
- @uri.port.should == 80
1897
- @uri.specified_port.should == nil
2171
+ @uri.port.should == nil
2172
+ @uri.inferred_port.should == 80
1898
2173
  @uri.to_s.should == "http://:newpass@example.com"
1899
2174
  end
1900
2175
  end
@@ -1916,13 +2191,17 @@ describe Addressable::URI, " when parsed from " +
1916
2191
  it "should have a password of ''" do
1917
2192
  @uri.password.should == ""
1918
2193
  end
1919
-
2194
+
2195
+ it "should have a normalized userinfo of nil" do
2196
+ @uri.normalized_userinfo.should == nil
2197
+ end
2198
+
1920
2199
  it "should have a host of 'example.com'" do
1921
2200
  @uri.host.should == "example.com"
1922
2201
  end
1923
2202
 
1924
2203
  it "should use port 80" do
1925
- @uri.port.should == 80
2204
+ @uri.inferred_port.should == 80
1926
2205
  end
1927
2206
 
1928
2207
  it "should have the correct username after assignment" do
@@ -1945,8 +2224,8 @@ describe Addressable::URI, " when parsed from " +
1945
2224
  @uri.user.should == ""
1946
2225
  @uri.password.should == ""
1947
2226
  @uri.host.should == "newexample.com"
1948
- @uri.port.should == 80
1949
- @uri.specified_port.should == nil
2227
+ @uri.port.should == nil
2228
+ @uri.inferred_port.should == 80
1950
2229
  @uri.to_s.should == "http://:@newexample.com"
1951
2230
  end
1952
2231
  end
@@ -1995,14 +2274,14 @@ describe Addressable::URI, " when parsed from " +
1995
2274
  it "should have a path of '/'" do
1996
2275
  @uri.path.should == "/"
1997
2276
  end
1998
-
2277
+
1999
2278
  it "should raise an error if routing is attempted" do
2000
2279
  (lambda do
2001
2280
  @uri.route_to("http://example.com/")
2002
2281
  end).should raise_error(ArgumentError, /\/\/example.com\//)
2003
2282
  (lambda do
2004
2283
  @uri.route_from("http://example.com/")
2005
- end).should raise_error(ArgumentError, /\/\/example.com\//)
2284
+ end).should raise_error(ArgumentError, /\/\/example.com\//)
2006
2285
  end
2007
2286
  end
2008
2287
 
@@ -2066,7 +2345,7 @@ describe Addressable::URI, " when parsed from " +
2066
2345
  end
2067
2346
 
2068
2347
  it "should use port 80" do
2069
- @uri.port.should == 80
2348
+ @uri.inferred_port.should == 80
2070
2349
  end
2071
2350
 
2072
2351
  it "should have a path of '/indirect/path/./to/../resource/'" do
@@ -2119,19 +2398,126 @@ describe Addressable::URI, "when parsed from " +
2119
2398
  end
2120
2399
  end
2121
2400
 
2122
- describe Addressable::URI, " when parsed from " +
2401
+ describe Addressable::URI, " when parsed from '?one=1&two=2&three=3'" do
2402
+ before do
2403
+ @uri = Addressable::URI.parse("?one=1&two=2&three=3")
2404
+ end
2405
+
2406
+ it "should have the correct query values" do
2407
+ @uri.query_values.should == {"one" => "1", "two" => "2", "three" => "3"}
2408
+ end
2409
+
2410
+ it "should raise an error for invalid query value notations" do
2411
+ (lambda do
2412
+ @uri.query_values(:notation => :bogus)
2413
+ end).should raise_error(ArgumentError)
2414
+ end
2415
+ end
2416
+
2417
+ describe Addressable::URI, " when parsed from '?one[two][three]=four'" do
2418
+ before do
2419
+ @uri = Addressable::URI.parse("?one[two][three]=four")
2420
+ end
2421
+
2422
+ it "should have the correct query values" do
2423
+ @uri.query_values.should == {"one" => {"two" => {"three" => "four"}}}
2424
+ end
2425
+
2426
+ it "should have the correct flat notation query values" do
2427
+ @uri.query_values(:notation => :flat).should == {
2428
+ "one[two][three]" => "four"
2429
+ }
2430
+ end
2431
+ end
2432
+
2433
+ describe Addressable::URI, " when parsed from '?one.two.three=four'" do
2434
+ before do
2435
+ @uri = Addressable::URI.parse("?one.two.three=four")
2436
+ end
2437
+
2438
+ it "should have the correct dot notation query values" do
2439
+ @uri.query_values(:notation => :dot).should == {
2440
+ "one" => {"two" => {"three" => "four"}}
2441
+ }
2442
+ end
2443
+
2444
+ it "should have the correct flat notation query values" do
2445
+ @uri.query_values(:notation => :flat).should == {
2446
+ "one.two.three" => "four"
2447
+ }
2448
+ end
2449
+ end
2450
+
2451
+ describe Addressable::URI, " when parsed from " +
2452
+ "'?one[two][three]=four&one[two][five]=six'" do
2453
+ before do
2454
+ @uri = Addressable::URI.parse("?one[two][three]=four&one[two][five]=six")
2455
+ end
2456
+
2457
+ it "should have the correct dot notation query values" do
2458
+ @uri.query_values(:notation => :subscript).should == {
2459
+ "one" => {"two" => {"three" => "four", "five" => "six"}}
2460
+ }
2461
+ end
2462
+
2463
+ it "should have the correct flat notation query values" do
2464
+ @uri.query_values(:notation => :flat).should == {
2465
+ "one[two][three]" => "four",
2466
+ "one[two][five]" => "six"
2467
+ }
2468
+ end
2469
+ end
2470
+
2471
+ describe Addressable::URI, " when parsed from " +
2472
+ "'?one.two.three=four&one.two.five=six'" do
2473
+ before do
2474
+ @uri = Addressable::URI.parse("?one.two.three=four&one.two.five=six")
2475
+ end
2476
+
2477
+ it "should have the correct dot notation query values" do
2478
+ @uri.query_values(:notation => :dot).should == {
2479
+ "one" => {"two" => {"three" => "four", "five" => "six"}}
2480
+ }
2481
+ end
2482
+
2483
+ it "should have the correct flat notation query values" do
2484
+ @uri.query_values(:notation => :flat).should == {
2485
+ "one.two.three" => "four",
2486
+ "one.two.five" => "six"
2487
+ }
2488
+ end
2489
+ end
2490
+
2491
+ describe Addressable::URI, " when parsed from " +
2492
+ "'?one[two][three][]=four&one[two][three][]=five'" do
2493
+ before do
2494
+ @uri = Addressable::URI.parse(
2495
+ "?one[two][three][]=four&one[two][three][]=five"
2496
+ )
2497
+ end
2498
+
2499
+ it "should have the correct dot notation query values" do
2500
+ @uri.query_values(:notation => :subscript).should == {
2501
+ "one" => {"two" => {"three" => ["four", "five"]}}
2502
+ }
2503
+ end
2504
+
2505
+ it "should raise an error if a key is repeated in the flat notation" do
2506
+ (lambda do
2507
+ @uri.query_values(:notation => :flat)
2508
+ end).should raise_error(ArgumentError)
2509
+ end
2510
+ end
2511
+
2512
+ describe Addressable::URI, " when parsed from " +
2123
2513
  "'http://www.詹姆斯.com/'" do
2124
2514
  before do
2125
2515
  @uri = Addressable::URI.parse("http://www.詹姆斯.com/")
2126
2516
  end
2127
2517
 
2128
2518
  it "should be equivalent to 'http://www.xn--8ws00zhy3a.com/'" do
2129
- if Addressable::URI::IDNA.send(:use_libidn?)
2130
- @uri.should ==
2131
- Addressable::URI.parse("http://www.xn--8ws00zhy3a.com/")
2132
- else
2133
- pending("Skipping IDN specification because GNU libidn is unavailable.")
2134
- end
2519
+ @uri.should ==
2520
+ Addressable::URI.parse("http://www.xn--8ws00zhy3a.com/")
2135
2521
  end
2136
2522
 
2137
2523
  it "should not have domain name encoded during normalization" do
@@ -2148,13 +2534,9 @@ describe Addressable::URI, " when parsed from " +
2148
2534
 
2149
2535
  it "should be equivalent to " +
2150
2536
  "'http://www.xn--8ws00zhy3a.com/%20some%20spaces%20/'" do
2151
- if Addressable::URI::IDNA.send(:use_libidn?)
2152
- @uri.should ==
2153
- Addressable::URI.parse(
2154
- "http://www.xn--8ws00zhy3a.com/%20some%20spaces%20/")
2155
- else
2156
- pending("Skipping IDN specification because GNU libidn is unavailable.")
2157
- end
2537
+ @uri.should ==
2538
+ Addressable::URI.parse(
2539
+ "http://www.xn--8ws00zhy3a.com/%20some%20spaces%20/")
2158
2540
  end
2159
2541
 
2160
2542
  it "should not have domain name encoded during normalization" do
@@ -2170,11 +2552,7 @@ describe Addressable::URI, " when parsed from " +
2170
2552
  end
2171
2553
 
2172
2554
  it "should be displayed as http://www.詹姆斯.com/" do
2173
- if Addressable::URI::IDNA.send(:use_libidn?)
2174
- @uri.display_uri.to_s.should == "http://www.詹姆斯.com/"
2175
- else
2176
- pending("Skipping IDN specification because GNU libidn is unavailable.")
2177
- end
2555
+ @uri.display_uri.to_s.should == "http://www.詹姆斯.com/"
2178
2556
  end
2179
2557
  end
2180
2558
 
@@ -2186,14 +2564,32 @@ describe Addressable::URI, " when parsed from " +
2186
2564
 
2187
2565
  it "should normalize to " +
2188
2566
  "http://www.xn--8ws00zhy3a.com/atomtests/iri/%E8%A9%B9.html" do
2189
- if Addressable::URI::IDNA.send(:use_libidn?)
2190
- @uri.normalize.to_s.should ==
2191
- "http://www.xn--8ws00zhy3a.com/atomtests/iri/%E8%A9%B9.html"
2192
- @uri.normalize!.to_s.should ==
2193
- "http://www.xn--8ws00zhy3a.com/atomtests/iri/%E8%A9%B9.html"
2194
- else
2195
- pending("Skipping IDN specification because GNU libidn is unavailable.")
2196
- end
2567
+ @uri.normalize.to_s.should ==
2568
+ "http://www.xn--8ws00zhy3a.com/atomtests/iri/%E8%A9%B9.html"
2569
+ @uri.normalize!.to_s.should ==
2570
+ "http://www.xn--8ws00zhy3a.com/atomtests/iri/%E8%A9%B9.html"
2571
+ end
2572
+ end
2573
+
2574
+ describe Addressable::URI, " when parsed from a percent-encoded IRI" do
2575
+ before do
2576
+ @uri = Addressable::URI.parse(
2577
+ "http://www.%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA" +
2578
+ "%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3" +
2579
+ "%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82" +
2580
+ "%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0" +
2581
+ "%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3" +
2582
+ "%81%9F%E3%82%8A%E3%81%AA%E3%81%84.w3.mag.keio.ac.jp"
2583
+ )
2584
+ end
2585
+
2586
+ it "should normalize to something sane" do
2587
+ @uri.normalize.to_s.should ==
2588
+ "http://www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3f" +
2589
+ "g11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp/"
2590
+ @uri.normalize!.to_s.should ==
2591
+ "http://www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3f" +
2592
+ "g11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp/"
2197
2593
  end
2198
2594
  end
2199
2595
 
@@ -2237,19 +2633,19 @@ describe Addressable::URI, "with a base uri of 'http://a/b/c/d;p?q'" do
2237
2633
  (@uri + "//g").to_s.should == "http://g"
2238
2634
  Addressable::URI.join(@uri.to_s, "//g").to_s.should == "http://g"
2239
2635
  end
2240
-
2636
+
2241
2637
  # Section 5.4.1 of RFC 3986
2242
2638
  it "when joined with '?y' should resolve to http://a/b/c/d;p?y" do
2243
2639
  (@uri + "?y").to_s.should == "http://a/b/c/d;p?y"
2244
2640
  Addressable::URI.join(@uri.to_s, "?y").to_s.should == "http://a/b/c/d;p?y"
2245
2641
  end
2246
-
2642
+
2247
2643
  # Section 5.4.1 of RFC 3986
2248
2644
  it "when joined with 'g?y' should resolve to http://a/b/c/g?y" do
2249
2645
  (@uri + "g?y").to_s.should == "http://a/b/c/g?y"
2250
2646
  Addressable::URI.join(@uri.to_s, "g?y").to_s.should == "http://a/b/c/g?y"
2251
2647
  end
2252
-
2648
+
2253
2649
  # Section 5.4.1 of RFC 3986
2254
2650
  it "when joined with '#s' should resolve to http://a/b/c/d;p?q#s" do
2255
2651
  (@uri + "#s").to_s.should == "http://a/b/c/d;p?q#s"
@@ -2480,88 +2876,11 @@ describe Addressable::URI, "with a base uri of 'http://a/b/c/d;p?q'" do
2480
2876
  Addressable::URI.join(
2481
2877
  @uri.to_s, "//example.com/").to_s.should == "http://example.com/"
2482
2878
  end
2483
- end
2484
-
2485
- describe Addressable::URI::IDNA, "without libidn bindings" do
2486
- before do
2487
- Addressable::URI::IDNA.instance_variable_set("@use_libidn", false)
2488
- end
2489
-
2490
- it "should raise an exception when an operation is attempted" do
2491
- (lambda do
2492
- Addressable::URI::IDNA.to_ascii("www.詹姆斯.com")
2493
- end).should raise_error
2494
- (lambda do
2495
- Addressable::URI::IDNA.to_unicode("www.xn--8ws00zhy3a.com")
2496
- end).should raise_error
2497
- end
2498
-
2499
- it "should not cause normalization routines to error out" do
2500
- (lambda do
2501
- uri = Addressable::URI.parse(
2502
- "http://www.詹姆斯.com/atomtests/iri/詹.html")
2503
- uri.normalize
2504
- end).should_not raise_error
2505
- end
2506
-
2507
- it "should not cause display uri routines to error out" do
2508
- (lambda do
2509
- uri = Addressable::URI.parse(
2510
- "http://www.xn--8ws00zhy3a.com/atomtests/iri/%E8%A9%B9.html")
2511
- uri.display_uri
2512
- end).should_not raise_error
2513
- end
2514
-
2515
- after do
2516
- Addressable::URI::IDNA.instance_variable_set("@use_libidn", nil)
2517
- Addressable::URI::IDNA.send(:use_libidn?)
2518
- end
2519
- end
2520
-
2521
- describe Addressable::URI::IDNA, "with rubygems and idn missing" do
2522
- before do
2523
- module Kernel
2524
- alias_method :saved_require, :require
2525
- def require(path)
2526
- raise LoadError,
2527
- "Libraries cannot be loaded during this test."
2528
- end
2529
- end
2530
- Addressable::URI::IDNA.instance_variable_set("@use_libidn", nil)
2531
- end
2532
-
2533
- it "should not raise an exception while checking " +
2534
- "if libidn is available" do
2535
- (lambda do
2536
- Addressable::URI::IDNA.send(:use_libidn?)
2537
- end).should_not raise_error
2538
- end
2539
-
2540
- it "should not cause normalization routines to error out" do
2541
- (lambda do
2542
- uri = Addressable::URI.parse(
2543
- "http://www.詹姆斯.com/atomtests/iri/詹.html")
2544
- uri.normalize
2545
- end).should_not raise_error
2546
- end
2547
2879
 
2548
- it "should not cause display uri routines to error out" do
2880
+ it "when joined with a bogus object a TypeError should be raised" do
2549
2881
  (lambda do
2550
- uri = Addressable::URI.parse(
2551
- "http://www.xn--8ws00zhy3a.com/atomtests/iri/%E8%A9%B9.html")
2552
- uri.display_uri
2553
- end).should_not raise_error
2554
- end
2555
-
2556
- after do
2557
- module Kernel
2558
- def require(path)
2559
- saved_require(path)
2560
- end
2561
- alias_method :require, :saved_require
2562
- end
2563
- Addressable::URI::IDNA.instance_variable_set("@use_libidn", nil)
2564
- Addressable::URI::IDNA.send(:use_libidn?)
2882
+ Addressable::URI.join(@uri, 42)
2883
+ end).should raise_error(TypeError)
2565
2884
  end
2566
2885
  end
2567
2886
 
@@ -2617,6 +2936,21 @@ describe Addressable::URI, "when converting the path " +
2617
2936
  @uri = Addressable::URI.convert_path(@path)
2618
2937
  @uri.to_s.should == "relative/path/to/something"
2619
2938
  end
2939
+
2940
+ it "should join with an absolute file path correctly" do
2941
+ @base = Addressable::URI.convert_path("/absolute/path/")
2942
+ @uri = Addressable::URI.convert_path(@path)
2943
+ (@base + @uri).to_s.should ==
2944
+ "file:///absolute/path/relative/path/to/something"
2945
+ end
2946
+ end
2947
+
2948
+ describe Addressable::URI, "when converting a bogus path" do
2949
+ it "should raise a TypeError" do
2950
+ (lambda do
2951
+ Addressable::URI.convert_path(42)
2952
+ end).should raise_error(TypeError)
2953
+ end
2620
2954
  end
2621
2955
 
2622
2956
  describe Addressable::URI, "when given the root directory" do
@@ -2679,6 +3013,32 @@ describe Addressable::URI, " when given the path " +
2679
3013
  end
2680
3014
  end
2681
3015
 
3016
+ describe Addressable::URI, " when given the path " +
3017
+ "'file:c:\\windows\\My Documents 100%20\\foo.txt'" do
3018
+ before do
3019
+ @path = "file:c:\\windows\\My Documents 100%20\\foo.txt"
3020
+ end
3021
+
3022
+ it "should convert to " +
3023
+ "\'file:///c:/windows/My%20Documents%20100%20/foo.txt\'" do
3024
+ @uri = Addressable::URI.convert_path(@path)
3025
+ @uri.to_s.should == "file:///c:/windows/My%20Documents%20100%20/foo.txt"
3026
+ end
3027
+ end
3028
+
3029
+ describe Addressable::URI, " when given the path " +
3030
+ "'file:/c:\\windows\\My Documents 100%20\\foo.txt'" do
3031
+ before do
3032
+ @path = "file:/c:\\windows\\My Documents 100%20\\foo.txt"
3033
+ end
3034
+
3035
+ it "should convert to " +
3036
+ "\'file:///c:/windows/My%20Documents%20100%20/foo.txt\'" do
3037
+ @uri = Addressable::URI.convert_path(@path)
3038
+ @uri.to_s.should == "file:///c:/windows/My%20Documents%20100%20/foo.txt"
3039
+ end
3040
+ end
3041
+
2682
3042
  describe Addressable::URI, " when given the path " +
2683
3043
  "'file:///c|/windows/My%20Documents%20100%20/foo.txt'" do
2684
3044
  before do
@@ -2731,9 +3091,9 @@ describe Addressable::URI, " when given the template pattern " +
2731
3091
  end
2732
3092
  end
2733
3093
 
2734
- # Section 3.3.1 of the URI Template draft
3094
+ # Section 3.3.1 of the URI Template draft v 01
2735
3095
  describe Addressable::URI, " when given the mapping supplied in " +
2736
- "Section 3.3.1 of the URI Template draft" do
3096
+ "Section 3.3.1 of the URI Template draft v 01" do
2737
3097
  before do
2738
3098
  @mapping = {
2739
3099
  "a" => "fred",
@@ -2748,80 +3108,206 @@ describe Addressable::URI, " when given the mapping supplied in " +
2748
3108
  "q" => "hullo#world"
2749
3109
  }
2750
3110
  end
2751
-
3111
+
2752
3112
  it "should result in 'http://example.org/page1#fred' " +
2753
3113
  "when used to expand 'http://example.org/page1\#{a}'" do
2754
3114
  Addressable::URI.expand_template(
2755
3115
  "http://example.org/page1\#{a}",
2756
- @mapping).to_s.should == "http://example.org/page1#fred"
3116
+ @mapping
3117
+ ).to_s.should == "http://example.org/page1#fred"
2757
3118
  end
2758
-
3119
+
2759
3120
  it "should result in 'http://example.org/fred/barney/' " +
2760
3121
  "when used to expand 'http://example.org/{a}/{b}/'" do
2761
3122
  Addressable::URI.expand_template(
2762
3123
  "http://example.org/{a}/{b}/",
2763
- @mapping).to_s.should == "http://example.org/fred/barney/"
3124
+ @mapping
3125
+ ).to_s.should == "http://example.org/fred/barney/"
2764
3126
  end
2765
-
3127
+
2766
3128
  it "should result in 'http://example.org/fredbarney/' " +
2767
3129
  "when used to expand 'http://example.org/{a}{b}/'" do
2768
3130
  Addressable::URI.expand_template(
2769
3131
  "http://example.org/{a}{b}/",
2770
- @mapping).to_s.should == "http://example.org/fredbarney/"
3132
+ @mapping
3133
+ ).to_s.should == "http://example.org/fredbarney/"
2771
3134
  end
2772
-
3135
+
2773
3136
  it "should result in " +
2774
3137
  "'http://example.com/order/cheeseburger/cheeseburger/cheeseburger/' " +
2775
3138
  "when used to expand 'http://example.com/order/{c}/{c}/{c}/'" do
2776
3139
  Addressable::URI.expand_template(
2777
3140
  "http://example.com/order/{c}/{c}/{c}/",
2778
- @mapping).to_s.should ==
3141
+ @mapping
3142
+ ).to_s.should ==
2779
3143
  "http://example.com/order/cheeseburger/cheeseburger/cheeseburger/"
2780
3144
  end
2781
-
3145
+
2782
3146
  it "should result in 'http://example.org/one%20two%20three' " +
2783
3147
  "when used to expand 'http://example.org/{d}'" do
2784
3148
  Addressable::URI.expand_template(
2785
3149
  "http://example.org/{d}",
2786
- @mapping).to_s.should == "http://example.org/one%20two%20three"
3150
+ @mapping
3151
+ ).to_s.should == "http://example.org/one%20two%20three"
2787
3152
  end
2788
-
3153
+
2789
3154
  it "should result in 'http://example.org/20%25%20tricky' " +
2790
3155
  "when used to expand 'http://example.org/{e}'" do
2791
3156
  Addressable::URI.expand_template(
2792
3157
  "http://example.org/{e}",
2793
- @mapping).to_s.should == "http://example.org/20%25%20tricky"
3158
+ @mapping
3159
+ ).to_s.should == "http://example.org/20%25%20tricky"
2794
3160
  end
2795
-
3161
+
2796
3162
  it "should result in 'http://example.com//' " +
2797
3163
  "when used to expand 'http://example.com/{f}/'" do
2798
3164
  Addressable::URI.expand_template(
2799
3165
  "http://example.com/{f}/",
2800
- @mapping).to_s.should == "http://example.com//"
3166
+ @mapping
3167
+ ).to_s.should == "http://example.com//"
2801
3168
  end
2802
-
3169
+
2803
3170
  it "should result in " +
2804
3171
  "'https://this-is-spinal-tap.example.org?date=&option=fred' " +
2805
3172
  "when used to expand " +
2806
3173
  "'{scheme}://{20}.example.org?date={wilma}&option={a}'" do
2807
3174
  Addressable::URI.expand_template(
2808
3175
  "{scheme}://{20}.example.org?date={wilma}&option={a}",
2809
- @mapping).to_s.should ==
3176
+ @mapping
3177
+ ).to_s.should ==
2810
3178
  "https://this-is-spinal-tap.example.org?date=&option=fred"
2811
3179
  end
2812
-
2813
- it "should result in 'http://example.org?quote=to+be+or+not+to+be' " +
3180
+
3181
+ # The v 01 draft conflicts with the v 03 draft here.
3182
+ # The Addressable implementation uses v 03.
3183
+ it "should result in " +
3184
+ "'http://example.org?quote%3Dto%2Bbe%2Bor%2Bnot%2Bto%2Bbe' " +
2814
3185
  "when used to expand 'http://example.org?{p}'" do
2815
3186
  Addressable::URI.expand_template(
2816
3187
  "http://example.org?{p}",
2817
- @mapping).to_s.should == "http://example.org?quote=to+be+or+not+to+be"
3188
+ @mapping
3189
+ ).to_s.should == "http://example.org?quote%3Dto%2Bbe%2Bor%2Bnot%2Bto%2Bbe"
2818
3190
  end
2819
-
2820
- it "should result in 'http://example.com/hullo#world' " +
3191
+
3192
+ # The v 01 draft conflicts with the v 03 draft here.
3193
+ # The Addressable implementation uses v 03.
3194
+ it "should result in 'http://example.com/hullo%23world' " +
2821
3195
  "when used to expand 'http://example.com/{q}'" do
2822
3196
  Addressable::URI.expand_template(
2823
3197
  "http://example.com/{q}",
2824
- @mapping).to_s.should == "http://example.com/hullo#world"
3198
+ @mapping
3199
+ ).to_s.should == "http://example.com/hullo%23world"
3200
+ end
3201
+ end
3202
+
3203
+ # Section 4.5 of the URI Template draft v 03
3204
+ describe Addressable::URI, " when given the mapping supplied in " +
3205
+ "Section 4.5 of the URI Template draft v 03" do
3206
+ before do
3207
+ @mapping = {
3208
+ "foo" => "ϓ",
3209
+ "bar" => "fred",
3210
+ "baz" => "10,20,30",
3211
+ "qux" => ["10","20","30"],
3212
+ "corge" => [],
3213
+ "grault" => "",
3214
+ "garply" => "a/b/c",
3215
+ "waldo" => "ben & jerrys",
3216
+ "fred" => ["fred", "", "wilma"],
3217
+ "plugh" => ["ẛ", "ṡ"],
3218
+ "1-a_b.c" => "200"
3219
+ }
3220
+ end
3221
+
3222
+ it "should result in 'http://example.org/?q=fred' " +
3223
+ "when used to expand 'http://example.org/?q={bar}'" do
3224
+ Addressable::URI.expand_template(
3225
+ "http://example.org/?q={bar}",
3226
+ @mapping
3227
+ ).to_s.should == "http://example.org/?q=fred"
3228
+ end
3229
+
3230
+ it "should result in '/' " +
3231
+ "when used to expand '/{xyzzy}'" do
3232
+ Addressable::URI.expand_template(
3233
+ "/{xyzzy}",
3234
+ @mapping
3235
+ ).to_s.should == "/"
3236
+ end
3237
+
3238
+ it "should result in " +
3239
+ "'http://example.org/?foo=%CE%8E&bar=fred&baz=10%2C20%2C30' " +
3240
+ "when used to expand " +
3241
+ "'http://example.org/?{-join|&|foo,bar,xyzzy,baz}'" do
3242
+ Addressable::URI.expand_template(
3243
+ "http://example.org/?{-join|&|foo,bar,xyzzy,baz}",
3244
+ @mapping
3245
+ ).to_s.should ==
3246
+ "http://example.org/?foo=%CE%8E&bar=fred&baz=10%2C20%2C30"
3247
+ end
3248
+
3249
+ it "should result in 'http://example.org/?d=10,20,30' " +
3250
+ "when used to expand 'http://example.org/?d={-list|,|qux}'" do
3251
+ Addressable::URI.expand_template(
3252
+ "http://example.org/?d={-list|,|qux}",
3253
+ @mapping
3254
+ ).to_s.should == "http://example.org/?d=10,20,30"
3255
+ end
3256
+
3257
+ it "should result in 'http://example.org/?d=10&d=20&d=30' " +
3258
+ "when used to expand 'http://example.org/?d={-list|&d=|qux}'" do
3259
+ Addressable::URI.expand_template(
3260
+ "http://example.org/?d={-list|&d=|qux}",
3261
+ @mapping
3262
+ ).to_s.should == "http://example.org/?d=10&d=20&d=30"
3263
+ end
3264
+
3265
+ it "should result in 'http://example.org/fredfred/a%2Fb%2Fc' " +
3266
+ "when used to expand 'http://example.org/{bar}{bar}/{garply}'" do
3267
+ Addressable::URI.expand_template(
3268
+ "http://example.org/{bar}{bar}/{garply}",
3269
+ @mapping
3270
+ ).to_s.should == "http://example.org/fredfred/a%2Fb%2Fc"
3271
+ end
3272
+
3273
+ it "should result in 'http://example.org/fred/fred//wilma' " +
3274
+ "when used to expand 'http://example.org/{bar}{-prefix|/|fred}'" do
3275
+ Addressable::URI.expand_template(
3276
+ "http://example.org/{bar}{-prefix|/|fred}",
3277
+ @mapping
3278
+ ).to_s.should == "http://example.org/fred/fred//wilma"
3279
+ end
3280
+
3281
+ it "should result in ':%E1%B9%A1:%E1%B9%A1:' " +
3282
+ "when used to expand '{-neg|:|corge}{-suffix|:|plugh}'" do
3283
+ Addressable::URI.expand_template(
3284
+ "{-neg|:|corge}{-suffix|:|plugh}",
3285
+ @mapping
3286
+ ).to_s.should == ":%E1%B9%A1:%E1%B9%A1:"
3287
+ end
3288
+
3289
+ it "should result in '../ben%20%26%20jerrys/' " +
3290
+ "when used to expand '../{waldo}/'" do
3291
+ Addressable::URI.expand_template(
3292
+ "../{waldo}/",
3293
+ @mapping
3294
+ ).to_s.should == "../ben%20%26%20jerrys/"
3295
+ end
3296
+
3297
+ it "should result in 'telnet:192.0.2.16:80' " +
3298
+ "when used to expand 'telnet:192.0.2.16{-opt|:80|grault}'" do
3299
+ Addressable::URI.expand_template(
3300
+ "telnet:192.0.2.16{-opt|:80|grault}",
3301
+ @mapping
3302
+ ).to_s.should == "telnet:192.0.2.16:80"
3303
+ end
3304
+
3305
+ it "should result in ':200:' " +
3306
+ "when used to expand ':{1-a_b.c}:'" do
3307
+ Addressable::URI.expand_template(
3308
+ ":{1-a_b.c}:",
3309
+ @mapping
3310
+ ).to_s.should == ":200:"
2825
3311
  end
2826
3312
  end
2827
3313
 
@@ -2833,75 +3319,356 @@ describe Addressable::URI, "when given a mapping that contains a " +
2833
3319
  "b" => "barney",
2834
3320
  }
2835
3321
  end
2836
-
3322
+
2837
3323
  it "should result in 'http://example.com/%7Bb%7D/barney/' " +
2838
3324
  "when used to expand 'http://example.com/{a}/{b}/'" do
2839
3325
  Addressable::URI.expand_template(
2840
3326
  "http://example.com/{a}/{b}/",
2841
3327
  @mapping).to_s.should == "http://example.com/%7Bb%7D/barney/"
2842
3328
  end
3329
+
3330
+ it "should result in 'http://example.com//%7Bb%7D/' " +
3331
+ "when used to expand 'http://example.com/{-opt|foo|foo}/{a}/'" do
3332
+ Addressable::URI.expand_template(
3333
+ "http://example.com/{-opt|foo|foo}/{a}/",
3334
+ @mapping).to_s.should == "http://example.com//%7Bb%7D/"
3335
+ end
3336
+
3337
+ it "should result in 'http://example.com//%7Bb%7D/' " +
3338
+ "when used to expand 'http://example.com/{-neg|foo|b}/{a}/'" do
3339
+ Addressable::URI.expand_template(
3340
+ "http://example.com/{-neg|foo|b}/{a}/",
3341
+ @mapping).to_s.should == "http://example.com//%7Bb%7D/"
3342
+ end
3343
+
3344
+ it "should result in 'http://example.com//barney/%7Bb%7D/' " +
3345
+ "when used to expand 'http://example.com/{-prefix|/|b}/{a}/'" do
3346
+ Addressable::URI.expand_template(
3347
+ "http://example.com/{-prefix|/|b}/{a}/",
3348
+ @mapping).to_s.should == "http://example.com//barney/%7Bb%7D/"
3349
+ end
3350
+
3351
+ it "should result in 'http://example.com/barney//%7Bb%7D/' " +
3352
+ "when used to expand 'http://example.com/{-suffix|/|b}/{a}/'" do
3353
+ Addressable::URI.expand_template(
3354
+ "http://example.com/{-suffix|/|b}/{a}/",
3355
+ @mapping).to_s.should == "http://example.com/barney//%7Bb%7D/"
3356
+ end
3357
+
3358
+ it "should result in 'http://example.com/%7Bb%7D/?b=barney&c=42' " +
3359
+ "when used to expand 'http://example.com/{a}/?{-join|&|b,c=42}'" do
3360
+ Addressable::URI.expand_template(
3361
+ "http://example.com/{a}/?{-join|&|b,c=42}",
3362
+ @mapping).to_s.should == "http://example.com/%7Bb%7D/?b=barney&c=42"
3363
+ end
3364
+
3365
+ it "should result in 'http://example.com/42/?b=barney' " +
3366
+ "when used to expand 'http://example.com/{c=42}/?{-join|&|b}'" do
3367
+ Addressable::URI.expand_template(
3368
+ "http://example.com/{c=42}/?{-join|&|b}",
3369
+ @mapping).to_s.should == "http://example.com/42/?b=barney"
3370
+ end
2843
3371
  end
2844
3372
 
2845
- describe Addressable::URI, "when given a mapping that contains values " +
2846
- "that are already percent-encoded" do
3373
+ describe Addressable::URI, "when given a single variable mapping" do
2847
3374
  before do
2848
3375
  @mapping = {
2849
- "a" => "%7Bb%7D"
3376
+ "foo" => "fred"
2850
3377
  }
2851
3378
  end
2852
-
2853
- it "should result in 'http://example.com/%257Bb%257D/' " +
2854
- "when used to expand 'http://example.com/{a}/'" do
3379
+
3380
+ it "should result in 'fred' when used to expand '{foo}'" do
2855
3381
  Addressable::URI.expand_template(
2856
- "http://example.com/{a}/",
2857
- @mapping).to_s.should == "http://example.com/%257Bb%257D/"
3382
+ "{foo}",
3383
+ @mapping
3384
+ ).to_s.should == "fred"
2858
3385
  end
2859
- end
2860
3386
 
2861
- describe Addressable::URI, " when parsed from " +
2862
- "'/'" do
2863
- before do
2864
- @uri = Addressable::URI.parse("/")
3387
+ it "should result in 'wilma' when used to expand '{bar=wilma}'" do
3388
+ Addressable::URI.expand_template(
3389
+ "{bar=wilma}",
3390
+ @mapping
3391
+ ).to_s.should == "wilma"
2865
3392
  end
2866
-
2867
- it "should have the correct mapping when extracting values " +
2868
- "using the pattern '/'" do
2869
- @uri.extract_mapping("/").should == {}
3393
+
3394
+ it "should result in '' when used to expand '{baz}'" do
3395
+ Addressable::URI.expand_template(
3396
+ "{baz}",
3397
+ @mapping
3398
+ ).to_s.should == ""
2870
3399
  end
2871
3400
  end
2872
3401
 
2873
- describe Addressable::URI, " when parsed from '/one/'" do
3402
+ describe Addressable::URI, "when given a simple mapping" do
2874
3403
  before do
2875
- @uri = Addressable::URI.parse("/one/")
3404
+ @mapping = {
3405
+ "foo" => "fred",
3406
+ "bar" => "barney",
3407
+ "baz" => ""
3408
+ }
2876
3409
  end
2877
-
2878
- it "should not match the pattern '/two/'" do
2879
- @uri.extract_mapping("/two/").should == nil
3410
+
3411
+ it "should result in 'foo=fred&bar=barney&baz=' when used to expand " +
3412
+ "'{-join|&|foo,bar,baz,qux}'" do
3413
+ Addressable::URI.expand_template(
3414
+ "{-join|&|foo,bar,baz,qux}",
3415
+ @mapping
3416
+ ).to_s.should == "foo=fred&bar=barney&baz="
2880
3417
  end
2881
-
2882
- it "should have the correct mapping when extracting values " +
2883
- "using the pattern '/{number}/'" do
2884
- @uri.extract_mapping("/{number}/").should == {"number" => "one"}
3418
+
3419
+ it "should result in 'bar=barney' when used to expand " +
3420
+ "'{-join|&|bar}'" do
3421
+ Addressable::URI.expand_template(
3422
+ "{-join|&|bar}",
3423
+ @mapping
3424
+ ).to_s.should == "bar=barney"
3425
+ end
3426
+
3427
+ it "should result in '' when used to expand " +
3428
+ "'{-join|&|qux}'" do
3429
+ Addressable::URI.expand_template(
3430
+ "{-join|&|qux}",
3431
+ @mapping
3432
+ ).to_s.should == ""
2885
3433
  end
2886
3434
  end
2887
3435
 
2888
- describe Addressable::URI, " when parsed from '/one/two/'" do
3436
+ describe Addressable::URI, "when given a mapping containing values " +
3437
+ "that are already percent-encoded" do
2889
3438
  before do
2890
- @uri = Addressable::URI.parse("/one/two/")
2891
- end
2892
-
3439
+ @mapping = {
3440
+ "a" => "%7Bb%7D"
3441
+ }
3442
+ end
3443
+
3444
+ it "should result in 'http://example.com/%257Bb%257D/' " +
3445
+ "when used to expand 'http://example.com/{a}/'" do
3446
+ Addressable::URI.expand_template(
3447
+ "http://example.com/{a}/",
3448
+ @mapping).to_s.should == "http://example.com/%257Bb%257D/"
3449
+ end
3450
+ end
3451
+
3452
+ describe Addressable::URI, "when given a mapping containing bogus values" do
3453
+ it "should raise a TypeError" do
3454
+ (lambda do
3455
+ Addressable::URI.expand_template(
3456
+ "http://example.com/{bogus}/", {
3457
+ "bogus" => 42
3458
+ }
3459
+ )
3460
+ end).should raise_error(TypeError)
3461
+ end
3462
+ end
3463
+
3464
+ describe Addressable::URI, "when given a pattern with bogus operators" do
3465
+ it "should raise an InvalidTemplateOperatorError" do
3466
+ (lambda do
3467
+ Addressable::URI.expand_template(
3468
+ "http://example.com/{-bogus|/|a,b,c}/", {
3469
+ "a" => "a", "b" => "b", "c" => "c"
3470
+ }
3471
+ )
3472
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
3473
+ end
3474
+
3475
+ it "should raise an InvalidTemplateOperatorError" do
3476
+ (lambda do
3477
+ Addressable::URI.expand_template(
3478
+ "http://example.com/{-prefix|/|a,b,c}/", {
3479
+ "a" => "a", "b" => "b", "c" => "c"
3480
+ }
3481
+ )
3482
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
3483
+ end
3484
+
3485
+ it "should raise an InvalidTemplateOperatorError" do
3486
+ (lambda do
3487
+ Addressable::URI.expand_template(
3488
+ "http://example.com/{-suffix|/|a,b,c}/", {
3489
+ "a" => "a", "b" => "b", "c" => "c"
3490
+ }
3491
+ )
3492
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
3493
+ end
3494
+
3495
+ it "should raise an InvalidTemplateOperatorError" do
3496
+ (lambda do
3497
+ Addressable::URI.expand_template(
3498
+ "http://example.com/{-join|/|a,b,c}/", {
3499
+ "a" => ["a"], "b" => ["b"], "c" => "c"
3500
+ }
3501
+ )
3502
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
3503
+ end
3504
+
3505
+ it "should raise an InvalidTemplateOperatorError" do
3506
+ (lambda do
3507
+ Addressable::URI.expand_template(
3508
+ "http://example.com/{-list|/|a,b,c}/", {
3509
+ "a" => ["a"], "b" => ["b"], "c" => "c"
3510
+ }
3511
+ )
3512
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
3513
+ end
3514
+ end
3515
+
3516
+ describe Addressable::URI, "when given a mapping that contains an Array" do
3517
+ before do
3518
+ @mapping = {"query" => "an example search query".split(" ")}
3519
+ end
3520
+
3521
+ it "should result in 'http://example.com/search/an+example+search+query/'" +
3522
+ " when used to expand 'http://example.com/search/{-list|+|query}/'" do
3523
+ Addressable::URI.expand_template(
3524
+ "http://example.com/search/{-list|+|query}/",
3525
+ @mapping).to_s.should ==
3526
+ "http://example.com/search/an+example+search+query/"
3527
+ end
3528
+ end
3529
+
3530
+ class SuperString
3531
+ def initialize(string)
3532
+ @string = string.to_s
3533
+ end
3534
+
3535
+ def to_str
3536
+ return @string
3537
+ end
3538
+ end
3539
+
3540
+ describe Addressable::URI, " when parsing a non-String object" do
3541
+ it "should correctly parse anything with a 'to_str' method" do
3542
+ Addressable::URI.parse(SuperString.new(42))
3543
+ end
3544
+
3545
+ it "should raise a TypeError for objects than cannot be converted" do
3546
+ (lambda do
3547
+ Addressable::URI.parse(42)
3548
+ end).should raise_error(TypeError)
3549
+ end
3550
+
3551
+ it "should correctly parse heuristically anything with a 'to_str' method" do
3552
+ Addressable::URI.heuristic_parse(SuperString.new(42))
3553
+ end
3554
+
3555
+ it "should raise a TypeError for objects than cannot be converted" do
3556
+ (lambda do
3557
+ Addressable::URI.heuristic_parse(42)
3558
+ end).should raise_error(TypeError)
3559
+ end
3560
+ end
3561
+
3562
+ describe Addressable::URI, "when encoding a multibyte string" do
3563
+ it "should result in correct percent encoded sequence" do
3564
+ Addressable::URI.encode_component("günther").should == "g%C3%BCnther"
3565
+ end
3566
+
3567
+ it "should result in correct percent encoded sequence" do
3568
+ Addressable::URI.encode_component(
3569
+ "günther", /[^a-zA-Z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\-\.\_\~]/
3570
+ ).should == "g%C3%BCnther"
3571
+ end
3572
+ end
3573
+
3574
+ describe Addressable::URI, "when unencoding a multibyte string" do
3575
+ it "should result in correct percent encoded sequence" do
3576
+ Addressable::URI.unencode_component("g%C3%BCnther").should == "günther"
3577
+ end
3578
+
3579
+ it "should result in correct percent encoded sequence as a URI" do
3580
+ Addressable::URI.unencode(
3581
+ "/path?g%C3%BCnther", ::Addressable::URI
3582
+ ).should == Addressable::URI.new(
3583
+ :path => "/path", :query => "günther"
3584
+ )
3585
+ end
3586
+ end
3587
+
3588
+ describe Addressable::URI, "when unencoding a bogus object" do
3589
+ it "should raise a TypeError" do
3590
+ (lambda do
3591
+ Addressable::URI.unencode_component(42)
3592
+ end).should raise_error(TypeError)
3593
+ end
3594
+
3595
+ it "should raise a TypeError" do
3596
+ (lambda do
3597
+ Addressable::URI.unencode("/path?g%C3%BCnther", Integer)
3598
+ end).should raise_error(TypeError)
3599
+ end
3600
+ end
3601
+
3602
+ describe Addressable::URI, "when encoding a bogus object" do
3603
+ it "should raise a TypeError" do
3604
+ (lambda do
3605
+ Addressable::URI.encode(42)
3606
+ end).should raise_error(TypeError)
3607
+ end
3608
+
3609
+ it "should raise a TypeError" do
3610
+ (lambda do
3611
+ Addressable::URI.normalized_encode(42)
3612
+ end).should raise_error(TypeError)
3613
+ end
3614
+
3615
+ it "should raise a TypeError" do
3616
+ (lambda do
3617
+ Addressable::URI.encode_component("günther", 42)
3618
+ end).should raise_error(TypeError)
3619
+ end
3620
+
3621
+ it "should raise a TypeError" do
3622
+ (lambda do
3623
+ Addressable::URI.encode_component(42)
3624
+ end).should raise_error(TypeError)
3625
+ end
3626
+ end
3627
+
3628
+ describe Addressable::URI, " when parsed from " +
3629
+ "'/'" do
3630
+ before do
3631
+ @uri = Addressable::URI.parse("/")
3632
+ end
3633
+
3634
+ it "should have the correct mapping when extracting values " +
3635
+ "using the pattern '/'" do
3636
+ @uri.extract_mapping("/").should == {}
3637
+ end
3638
+ end
3639
+
3640
+ describe Addressable::URI, " when parsed from '/one/'" do
3641
+ before do
3642
+ @uri = Addressable::URI.parse("/one/")
3643
+ end
3644
+
3645
+ it "should not match the pattern '/two/'" do
3646
+ @uri.extract_mapping("/two/").should == nil
3647
+ end
3648
+
3649
+ it "should have the correct mapping when extracting values " +
3650
+ "using the pattern '/{number}/'" do
3651
+ @uri.extract_mapping("/{number}/").should == {"number" => "one"}
3652
+ end
3653
+ end
3654
+
3655
+ describe Addressable::URI, " when parsed from '/one/two/'" do
3656
+ before do
3657
+ @uri = Addressable::URI.parse("/one/two/")
3658
+ end
3659
+
2893
3660
  it "should not match the pattern '/{number}/' " +
2894
3661
  "with the SlashlessProcessor" do
2895
3662
  @uri.extract_mapping("/{number}/", SlashlessProcessor).should == nil
2896
3663
  end
2897
-
3664
+
2898
3665
  it "should have the correct mapping when extracting values " +
2899
3666
  "using the pattern '/{number}/' without a processor" do
2900
3667
  @uri.extract_mapping("/{number}/").should == {
2901
3668
  "number" => "one/two"
2902
3669
  }
2903
3670
  end
2904
-
3671
+
2905
3672
  it "should have the correct mapping when extracting values " +
2906
3673
  "using the pattern '/{first}/{second}/' with the SlashlessProcessor" do
2907
3674
  @uri.extract_mapping("/{first}/{second}/", SlashlessProcessor).should == {
@@ -2917,7 +3684,7 @@ describe Addressable::URI, " when parsed from " +
2917
3684
  @uri = Addressable::URI.parse(
2918
3685
  "http://example.com/search/an+example+search+query/")
2919
3686
  end
2920
-
3687
+
2921
3688
  it "should have the correct mapping when extracting values using " +
2922
3689
  "the pattern 'http://example.com/search/{query}/' with the " +
2923
3690
  "ExampleProcessor" do
@@ -2927,7 +3694,17 @@ describe Addressable::URI, " when parsed from " +
2927
3694
  "query" => "an example search query"
2928
3695
  }
2929
3696
  end
2930
-
3697
+
3698
+ it "should have the correct mapping when extracting values " +
3699
+ "using the pattern " +
3700
+ "'http://example.com/search/{-list|+|query}/'" do
3701
+ @uri.extract_mapping(
3702
+ "http://example.com/search/{-list|+|query}/"
3703
+ ).should == {
3704
+ "query" => ["an", "example", "search", "query"]
3705
+ }
3706
+ end
3707
+
2931
3708
  it "should return nil when extracting values using " +
2932
3709
  "a non-matching pattern" do
2933
3710
  @uri.extract_mapping(
@@ -2942,7 +3719,7 @@ describe Addressable::URI, " when parsed from " +
2942
3719
  @uri = Addressable::URI.parse(
2943
3720
  "http://example.com/a/b/c/")
2944
3721
  end
2945
-
3722
+
2946
3723
  it "should have the correct mapping when extracting values " +
2947
3724
  "using the pattern " +
2948
3725
  "'http://example.com/{first}/{second}/' with the ExampleProcessor" do
@@ -2953,6 +3730,85 @@ describe Addressable::URI, " when parsed from " +
2953
3730
  "second" => "b/c"
2954
3731
  }
2955
3732
  end
3733
+
3734
+ it "should have the correct mapping when extracting values " +
3735
+ "using the pattern " +
3736
+ "'http://example.com/{first}/{-list|/|second}/'" do
3737
+ @uri.extract_mapping(
3738
+ "http://example.com/{first}/{-list|/|second}/"
3739
+ ).should == {
3740
+ "first" => "a",
3741
+ "second" => ["b", "c"]
3742
+ }
3743
+ end
3744
+
3745
+ it "should have the correct mapping when extracting values " +
3746
+ "using the pattern " +
3747
+ "'http://example.com/{first}/{-list|/|rot13}/' " +
3748
+ "with the ExampleProcessor" do
3749
+ @uri.extract_mapping(
3750
+ "http://example.com/{first}/{-list|/|rot13}/",
3751
+ ExampleProcessor
3752
+ ).should == {
3753
+ "first" => "a",
3754
+ "rot13" => ["o", "p"]
3755
+ }
3756
+ end
3757
+
3758
+ it "should have the correct mapping when extracting values " +
3759
+ "using the pattern " +
3760
+ "'http://example.com/{-list|/|rot13}/' " +
3761
+ "with the ExampleProcessor" do
3762
+ @uri.extract_mapping(
3763
+ "http://example.com/{-list|/|rot13}/",
3764
+ ExampleProcessor
3765
+ ).should == {
3766
+ "rot13" => ["n", "o", "p"]
3767
+ }
3768
+ end
3769
+
3770
+ it "should not map to anything when extracting values " +
3771
+ "using the pattern " +
3772
+ "'http://example.com/{-list|/|rot13}/'" do
3773
+ @uri.extract_mapping("http://example.com/{-join|/|a,b,c}/").should == nil
3774
+ end
3775
+ end
3776
+
3777
+ describe Addressable::URI, " when parsed from " +
3778
+ "'http://example.com/?a=one&b=two&c=three'" do
3779
+ before do
3780
+ @uri = Addressable::URI.parse("http://example.com/?a=one&b=two&c=three")
3781
+ end
3782
+
3783
+ it "should have the correct mapping when extracting values " +
3784
+ "using the pattern " +
3785
+ "'http://example.com/?{-join|&|a,b,c}'" do
3786
+ @uri.extract_mapping(
3787
+ "http://example.com/?{-join|&|a,b,c}"
3788
+ ).should == {
3789
+ "a" => "one",
3790
+ "b" => "two",
3791
+ "c" => "three"
3792
+ }
3793
+ end
3794
+ end
3795
+
3796
+ describe Addressable::URI, " when parsed from " +
3797
+ "'http://example.com/?rot13=frperg'" do
3798
+ before do
3799
+ @uri = Addressable::URI.parse("http://example.com/?rot13=frperg")
3800
+ end
3801
+
3802
+ it "should have the correct mapping when extracting values " +
3803
+ "using the pattern " +
3804
+ "'http://example.com/?{-join|&|rot13}' with the ExampleProcessor" do
3805
+ @uri.extract_mapping(
3806
+ "http://example.com/?{-join|&|rot13}",
3807
+ ExampleProcessor
3808
+ ).should == {
3809
+ "rot13" => "secret"
3810
+ }
3811
+ end
2956
3812
  end
2957
3813
 
2958
3814
  describe Addressable::URI, " when parsed from " +
@@ -2960,15 +3816,319 @@ describe Addressable::URI, " when parsed from " +
2960
3816
  before do
2961
3817
  @uri = Addressable::URI.parse("http://example.com/one/spacer/two/")
2962
3818
  end
2963
-
3819
+
2964
3820
  it "should have the correct mapping when extracting values " +
2965
3821
  "using the pattern " +
2966
3822
  "'http://example.com/{first}/spacer/{second}/'" do
2967
3823
  @uri.extract_mapping(
2968
- "http://example.com/{first}/spacer/{second}/").should == {
2969
- "first" => "one",
2970
- "second" => "two"
2971
- }
3824
+ "http://example.com/{first}/spacer/{second}/"
3825
+ ).should == {
3826
+ "first" => "one",
3827
+ "second" => "two"
3828
+ }
3829
+ end
3830
+
3831
+ it "should have the correct mapping when extracting values " +
3832
+ "using the pattern " +
3833
+ "'http://example.com{-prefix|/|stuff}/'" do
3834
+ @uri.extract_mapping(
3835
+ "http://example.com{-prefix|/|stuff}/"
3836
+ ).should == {
3837
+ "stuff" => ["one", "spacer", "two"]
3838
+ }
3839
+ end
3840
+
3841
+ it "should have the correct mapping when extracting values " +
3842
+ "using the pattern " +
3843
+ "'http://example.com/o{-prefix|/|stuff}/'" do
3844
+ @uri.extract_mapping(
3845
+ "http://example.com/o{-prefix|/|stuff}/"
3846
+ ).should == nil
3847
+ end
3848
+
3849
+ it "should have the correct mapping when extracting values " +
3850
+ "using the pattern " +
3851
+ "'http://example.com/{first}/spacer{-prefix|/|stuff}/'" do
3852
+ @uri.extract_mapping(
3853
+ "http://example.com/{first}/spacer{-prefix|/|stuff}/"
3854
+ ).should == {
3855
+ "first" => "one",
3856
+ "stuff" => ["two"]
3857
+ }
3858
+ end
3859
+
3860
+ it "should not match anything when extracting values " +
3861
+ "using the incorrect suffix pattern " +
3862
+ "'http://example.com/{-prefix|/|stuff}/'" do
3863
+ @uri.extract_mapping(
3864
+ "http://example.com/{-prefix|/|stuff}/"
3865
+ ).should == nil
3866
+ end
3867
+
3868
+ it "should have the correct mapping when extracting values " +
3869
+ "using the pattern " +
3870
+ "'http://example.com{-prefix|/|rot13}/' with the ExampleProcessor" do
3871
+ @uri.extract_mapping(
3872
+ "http://example.com{-prefix|/|rot13}/",
3873
+ ExampleProcessor
3874
+ ).should == {
3875
+ "rot13" => ["bar", "fcnpre", "gjb"]
3876
+ }
3877
+ end
3878
+
3879
+ it "should have the correct mapping when extracting values " +
3880
+ "using the pattern " +
3881
+ "'http://example.com{-prefix|/|rot13}' with the ExampleProcessor" do
3882
+ @uri.extract_mapping(
3883
+ "http://example.com{-prefix|/|rot13}",
3884
+ ExampleProcessor
3885
+ ).should == {
3886
+ "rot13" => ["bar", "fcnpre", "gjb", ""]
3887
+ }
3888
+ end
3889
+
3890
+ it "should not match anything when extracting values " +
3891
+ "using the incorrect suffix pattern " +
3892
+ "'http://example.com/{-prefix|/|rot13}' with the ExampleProcessor" do
3893
+ @uri.extract_mapping(
3894
+ "http://example.com/{-prefix|/|rot13}",
3895
+ ExampleProcessor
3896
+ ).should == nil
3897
+ end
3898
+
3899
+ it "should have the correct mapping when extracting values " +
3900
+ "using the pattern " +
3901
+ "'http://example.com/{-suffix|/|stuff}'" do
3902
+ @uri.extract_mapping(
3903
+ "http://example.com/{-suffix|/|stuff}"
3904
+ ).should == {
3905
+ "stuff" => ["one", "spacer", "two"]
3906
+ }
3907
+ end
3908
+
3909
+ it "should have the correct mapping when extracting values " +
3910
+ "using the pattern " +
3911
+ "'http://example.com/{-suffix|/|stuff}o'" do
3912
+ @uri.extract_mapping(
3913
+ "http://example.com/{-suffix|/|stuff}o"
3914
+ ).should == nil
3915
+ end
3916
+
3917
+ it "should have the correct mapping when extracting values " +
3918
+ "using the pattern " +
3919
+ "'http://example.com/o{-suffix|/|stuff}'" do
3920
+ @uri.extract_mapping(
3921
+ "http://example.com/o{-suffix|/|stuff}"
3922
+ ).should == {"stuff"=>["ne", "spacer", "two"]}
3923
+ end
3924
+
3925
+ it "should have the correct mapping when extracting values " +
3926
+ "using the pattern " +
3927
+ "'http://example.com/{first}/spacer/{-suffix|/|stuff}'" do
3928
+ @uri.extract_mapping(
3929
+ "http://example.com/{first}/spacer/{-suffix|/|stuff}"
3930
+ ).should == {
3931
+ "first" => "one",
3932
+ "stuff" => ["two"]
3933
+ }
3934
+ end
3935
+
3936
+ it "should not match anything when extracting values " +
3937
+ "using the incorrect suffix pattern " +
3938
+ "'http://example.com/{-suffix|/|stuff}/'" do
3939
+ @uri.extract_mapping(
3940
+ "http://example.com/{-suffix|/|stuff}/"
3941
+ ).should == nil
3942
+ end
3943
+
3944
+ it "should have the correct mapping when extracting values " +
3945
+ "using the pattern " +
3946
+ "'http://example.com/{-suffix|/|rot13}' with the ExampleProcessor" do
3947
+ @uri.extract_mapping(
3948
+ "http://example.com/{-suffix|/|rot13}",
3949
+ ExampleProcessor
3950
+ ).should == {
3951
+ "rot13" => ["bar", "fcnpre", "gjb"]
3952
+ }
3953
+ end
3954
+
3955
+ it "should have the correct mapping when extracting values " +
3956
+ "using the pattern " +
3957
+ "'http://example.com{-suffix|/|rot13}' with the ExampleProcessor" do
3958
+ @uri.extract_mapping(
3959
+ "http://example.com{-suffix|/|rot13}",
3960
+ ExampleProcessor
3961
+ ).should == {
3962
+ "rot13" => ["", "bar", "fcnpre", "gjb"]
3963
+ }
3964
+ end
3965
+
3966
+ it "should not match anything when extracting values " +
3967
+ "using the incorrect suffix pattern " +
3968
+ "'http://example.com/{-suffix|/|rot13}/' with the ExampleProcessor" do
3969
+ @uri.extract_mapping(
3970
+ "http://example.com/{-suffix|/|rot13}/",
3971
+ ExampleProcessor
3972
+ ).should == nil
3973
+ end
3974
+ end
3975
+
3976
+ describe Addressable::URI, " when parsed from " +
3977
+ "'http://example.com/?email=bob@sporkmonger.com'" do
3978
+ before do
3979
+ @uri = Addressable::URI.parse(
3980
+ "http://example.com/?email=bob@sporkmonger.com"
3981
+ )
3982
+ end
3983
+
3984
+ it "should not match anything when extracting values " +
3985
+ "using the incorrect opt pattern " +
3986
+ "'http://example.com/?email={-opt|bogus@bogus.com|test}'" do
3987
+ @uri.extract_mapping(
3988
+ "http://example.com/?email={-opt|bogus@bogus.com|test}"
3989
+ ).should == nil
3990
+ end
3991
+
3992
+ it "should not match anything when extracting values " +
3993
+ "using the incorrect neg pattern " +
3994
+ "'http://example.com/?email={-neg|bogus@bogus.com|test}'" do
3995
+ @uri.extract_mapping(
3996
+ "http://example.com/?email={-neg|bogus@bogus.com|test}"
3997
+ ).should == nil
3998
+ end
3999
+
4000
+ it "should indicate a match when extracting values " +
4001
+ "using the opt pattern " +
4002
+ "'http://example.com/?email={-opt|bob@sporkmonger.com|test}'" do
4003
+ @uri.extract_mapping(
4004
+ "http://example.com/?email={-opt|bob@sporkmonger.com|test}"
4005
+ ).should == {}
4006
+ end
4007
+
4008
+ it "should indicate a match when extracting values " +
4009
+ "using the neg pattern " +
4010
+ "'http://example.com/?email={-neg|bob@sporkmonger.com|test}'" do
4011
+ @uri.extract_mapping(
4012
+ "http://example.com/?email={-neg|bob@sporkmonger.com|test}"
4013
+ ).should == {}
4014
+ end
4015
+ end
4016
+
4017
+ describe Addressable::URI, " when parsed from " +
4018
+ "'http://example.com/?email='" do
4019
+ before do
4020
+ @uri = Addressable::URI.parse(
4021
+ "http://example.com/?email="
4022
+ )
4023
+ end
4024
+
4025
+ it "should indicate a match when extracting values " +
4026
+ "using the opt pattern " +
4027
+ "'http://example.com/?email={-opt|bob@sporkmonger.com|test}'" do
4028
+ @uri.extract_mapping(
4029
+ "http://example.com/?email={-opt|bob@sporkmonger.com|test}"
4030
+ ).should == {}
4031
+ end
4032
+
4033
+ it "should indicate a match when extracting values " +
4034
+ "using the neg pattern " +
4035
+ "'http://example.com/?email={-neg|bob@sporkmonger.com|test}'" do
4036
+ @uri.extract_mapping(
4037
+ "http://example.com/?email={-neg|bob@sporkmonger.com|test}"
4038
+ ).should == {}
4039
+ end
4040
+ end
4041
+
4042
+ describe Addressable::URI, " when parsed from " +
4043
+ "'http://example.com/a/b/c/?one=1&two=2#foo'" do
4044
+ before do
4045
+ @uri = Addressable::URI.parse(
4046
+ "http://example.com/a/b/c/?one=1&two=2#foo"
4047
+ )
4048
+ end
4049
+
4050
+ it "should have the correct mapping when extracting values " +
4051
+ "using the pattern " +
4052
+ "'http://{host}/{-suffix|/|segments}?{-join|&|one,two}\#{fragment}'" do
4053
+ @uri.extract_mapping(
4054
+ "http://{host}/{-suffix|/|segments}?{-join|&|one,two}\#{fragment}"
4055
+ ).should == {
4056
+ "host" => "example.com",
4057
+ "segments" => ["a", "b", "c"],
4058
+ "one" => "1",
4059
+ "two" => "2",
4060
+ "fragment" => "foo"
4061
+ }
4062
+ end
4063
+
4064
+ it "should not match when extracting values " +
4065
+ "using the pattern " +
4066
+ "'http://{host}/{-suffix|/|segments}?{-join|&|one}\#{fragment}'" do
4067
+ @uri.extract_mapping(
4068
+ "http://{host}/{-suffix|/|segments}?{-join|&|one}\#{fragment}"
4069
+ ).should == nil
4070
+ end
4071
+
4072
+ it "should not match when extracting values " +
4073
+ "using the pattern " +
4074
+ "'http://{host}/{-suffix|/|segments}?{-join|&|bogus}\#{fragment}'" do
4075
+ @uri.extract_mapping(
4076
+ "http://{host}/{-suffix|/|segments}?{-join|&|bogus}\#{fragment}"
4077
+ ).should == nil
4078
+ end
4079
+
4080
+ it "should not match when extracting values " +
4081
+ "using the pattern " +
4082
+ "'http://{host}/{-suffix|/|segments}?" +
4083
+ "{-join|&|one,bogus}\#{fragment}'" do
4084
+ @uri.extract_mapping(
4085
+ "http://{host}/{-suffix|/|segments}?{-join|&|one,bogus}\#{fragment}"
4086
+ ).should == nil
4087
+ end
4088
+
4089
+ it "should not match when extracting values " +
4090
+ "using the pattern " +
4091
+ "'http://{host}/{-suffix|/|segments}?" +
4092
+ "{-join|&|one,two,bogus}\#{fragment}'" do
4093
+ @uri.extract_mapping(
4094
+ "http://{host}/{-suffix|/|segments}?{-join|&|one,two,bogus}\#{fragment}"
4095
+ ).should == {
4096
+ "host" => "example.com",
4097
+ "segments" => ["a", "b", "c"],
4098
+ "one" => "1",
4099
+ "two" => "2",
4100
+ "fragment" => "foo"
4101
+ }
4102
+ end
4103
+ end
4104
+
4105
+ describe Addressable::URI, "when given a pattern with bogus operators" do
4106
+ before do
4107
+ @uri = Addressable::URI.parse("http://example.com/a/b/c/")
4108
+ end
4109
+
4110
+ it "should raise an InvalidTemplateOperatorError" do
4111
+ (lambda do
4112
+ @uri.extract_mapping("http://example.com/{-bogus|/|a,b,c}/")
4113
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
4114
+ end
4115
+
4116
+ it "should raise an InvalidTemplateOperatorError" do
4117
+ (lambda do
4118
+ @uri.extract_mapping("http://example.com/{-prefix|/|a,b,c}/")
4119
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
4120
+ end
4121
+
4122
+ it "should raise an InvalidTemplateOperatorError" do
4123
+ (lambda do
4124
+ @uri.extract_mapping("http://example.com/{-suffix|/|a,b,c}/")
4125
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
4126
+ end
4127
+
4128
+ it "should raise an InvalidTemplateOperatorError" do
4129
+ (lambda do
4130
+ @uri.extract_mapping("http://example.com/{-list|/|a,b,c}/")
4131
+ end).should raise_error(Addressable::URI::InvalidTemplateOperatorError)
2972
4132
  end
2973
4133
  end
2974
4134