addressable 2.3.8 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of addressable might be problematic. Click here for more details.

@@ -21,8 +21,8 @@ if !defined?(Addressable::VERSION)
21
21
  module Addressable
22
22
  module VERSION
23
23
  MAJOR = 2
24
- MINOR = 3
25
- TINY = 8
24
+ MINOR = 4
25
+ TINY = 0
26
26
 
27
27
  STRING = [MAJOR, MINOR, TINY].join('.')
28
28
  end
@@ -137,6 +137,10 @@ shared_examples_for "converting from unicode to ASCII" do
137
137
  end
138
138
 
139
139
  shared_examples_for "converting from ASCII to unicode" do
140
+ it "should return the identity conversion when the ACE prefix has no suffix" do
141
+ expect(Addressable::IDNA.to_unicode("xn--...-")).to eq("xn--...-")
142
+ end
143
+
140
144
  it "should convert 'www.google.com' correctly" do
141
145
  expect(Addressable::IDNA.to_unicode("www.google.com")).to eq("www.google.com")
142
146
  end
@@ -147,12 +151,24 @@ shared_examples_for "converting from ASCII to unicode" do
147
151
  )).to eq("www.詹姆斯.com")
148
152
  end
149
153
 
154
+ it "should convert '詹姆斯.com' correctly" do
155
+ expect(Addressable::IDNA.to_unicode(
156
+ "xn--8ws00zhy3a.com"
157
+ )).to eq("詹姆斯.com")
158
+ end
159
+
150
160
  it "should convert 'www.iñtërnâtiônàlizætiøn.com' correctly" do
151
161
  expect(Addressable::IDNA.to_unicode(
152
162
  "www.xn--itrntinliztin-vdb0a5exd8ewcye.com"
153
163
  )).to eq("www.iñtërnâtiônàlizætiøn.com")
154
164
  end
155
165
 
166
+ it "should convert 'iñtërnâtiônàlizætiøn.com' correctly" do
167
+ expect(Addressable::IDNA.to_unicode(
168
+ "xn--itrntinliztin-vdb0a5exd8ewcye.com"
169
+ )).to eq("iñtërnâtiônàlizætiøn.com")
170
+ end
171
+
156
172
  it "should convert " +
157
173
  "'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
158
174
  "correctly" do
@@ -0,0 +1,104 @@
1
+ # coding: utf-8
2
+ # Copyright (C) 2006-2015 Bob Aman
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+
17
+ require "spec_helper"
18
+
19
+ require "addressable/uri"
20
+ require "addressable/template"
21
+ require "rack/mount"
22
+
23
+ describe Rack::Mount do
24
+ let(:app_one) do
25
+ proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 1'] }
26
+ end
27
+ let(:app_two) do
28
+ proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 2'] }
29
+ end
30
+ let(:app_three) do
31
+ proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 3'] }
32
+ end
33
+ let(:routes) do
34
+ s = Rack::Mount::RouteSet.new do |set|
35
+ set.add_route(app_one, {
36
+ :request_method => 'GET',
37
+ :path_info => Addressable::Template.new('/one/{id}/')
38
+ }, {:id => 'unidentified'}, :one)
39
+ set.add_route(app_two, {
40
+ :request_method => 'GET',
41
+ :path_info => Addressable::Template.new('/two/')
42
+ }, {:id => 'unidentified'}, :two)
43
+ set.add_route(app_three, {
44
+ :request_method => 'GET',
45
+ :path_info => Addressable::Template.new('/three/{id}/').to_regexp
46
+ }, {:id => 'unidentified'}, :three)
47
+ end
48
+ s.rehash
49
+ s
50
+ end
51
+
52
+ it "should generate from routes with Addressable::Template" do
53
+ path, _ = routes.generate(:path_info, :one, {:id => '123'})
54
+ expect(path).to eq '/one/123/'
55
+ end
56
+
57
+ it "should generate from routes with Addressable::Template using defaults" do
58
+ path, _ = routes.generate(:path_info, :one, {})
59
+ expect(path).to eq '/one/unidentified/'
60
+ end
61
+
62
+ it "should recognize routes with Addressable::Template" do
63
+ request = Rack::Request.new(
64
+ 'REQUEST_METHOD' => 'GET',
65
+ 'PATH_INFO' => '/one/123/'
66
+ )
67
+ route, _, params = routes.recognize(request)
68
+ expect(route).not_to be_nil
69
+ expect(route.app).to eq app_one
70
+ expect(params).to eq({id: '123'})
71
+ end
72
+
73
+ it "should generate from routes with Addressable::Template" do
74
+ path, _ = routes.generate(:path_info, :two, {:id => '654'})
75
+ expect(path).to eq '/two/'
76
+ end
77
+
78
+ it "should generate from routes with Addressable::Template using defaults" do
79
+ path, _ = routes.generate(:path_info, :two, {})
80
+ expect(path).to eq '/two/'
81
+ end
82
+
83
+ it "should recognize routes with Addressable::Template" do
84
+ request = Rack::Request.new(
85
+ 'REQUEST_METHOD' => 'GET',
86
+ 'PATH_INFO' => '/two/'
87
+ )
88
+ route, _, params = routes.recognize(request)
89
+ expect(route).not_to be_nil
90
+ expect(route.app).to eq app_two
91
+ expect(params).to eq({id: 'unidentified'})
92
+ end
93
+
94
+ it "should recognize routes with derived Regexp" do
95
+ request = Rack::Request.new(
96
+ 'REQUEST_METHOD' => 'GET',
97
+ 'PATH_INFO' => '/three/789/'
98
+ )
99
+ route, _, params = routes.recognize(request)
100
+ expect(route).not_to be_nil
101
+ expect(route.app).to eq app_three
102
+ expect(params).to eq({id: '789'})
103
+ end
104
+ end
@@ -0,0 +1,57 @@
1
+ # coding: utf-8
2
+ # Copyright (C) 2006-2015 Bob Aman
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+
17
+ require "spec_helper"
18
+
19
+ require "addressable/uri"
20
+
21
+ describe Addressable::URI, "when created with a URI known to cause crashes " +
22
+ "in certain browsers" do
23
+ it "should parse correctly" do
24
+ uri = Addressable::URI.parse('%%30%30')
25
+ expect(uri.path).to eq('%%30%30')
26
+ expect(uri.normalize.path).to eq('%2500')
27
+ end
28
+
29
+ it "should parse correctly as a full URI" do
30
+ uri = Addressable::URI.parse('http://www.example.com/%%30%30')
31
+ expect(uri.path).to eq('/%%30%30')
32
+ expect(uri.normalize.path).to eq('/%2500')
33
+ end
34
+ end
35
+
36
+ describe Addressable::URI, "when created with a URI known to cause crashes " +
37
+ "in certain browsers" do
38
+ it "should parse correctly" do
39
+ uri = Addressable::URI.parse('لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
40
+ expect(uri.path).to eq('لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
41
+ expect(uri.normalize.path).to eq(
42
+ '%D9%84%D9%8F%D8%B5%D9%91%D8%A8%D9%8F%D9%84%D9%8F%D9%84%D8%B5%D9%91' +
43
+ '%D8%A8%D9%8F%D8%B1%D8%B1%D9%8B%20%E0%A5%A3%20%E0%A5%A3h%20%E0%A5' +
44
+ '%A3%20%E0%A5%A3%20%E5%86%97'
45
+ )
46
+ end
47
+
48
+ it "should parse correctly as a full URI" do
49
+ uri = Addressable::URI.parse('http://www.example.com/لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
50
+ expect(uri.path).to eq('/لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
51
+ expect(uri.normalize.path).to eq(
52
+ '/%D9%84%D9%8F%D8%B5%D9%91%D8%A8%D9%8F%D9%84%D9%8F%D9%84%D8%B5%D9%91' +
53
+ '%D8%A8%D9%8F%D8%B1%D8%B1%D9%8B%20%E0%A5%A3%20%E0%A5%A3h%20%E0%A5' +
54
+ '%A3%20%E0%A5%A3%20%E5%86%97'
55
+ )
56
+ end
57
+ end
@@ -698,6 +698,13 @@ describe "Expansion" do
698
698
  ]
699
699
  }
700
700
  end
701
+ context "non-string key in match data" do
702
+ subject {Addressable::Template.new("http://example.com/{one}")}
703
+
704
+ it "raises TypeError" do
705
+ expect { subject.expand(Object.new => "1") }.to raise_error TypeError
706
+ end
707
+ end
701
708
  end
702
709
 
703
710
  class ExampleTwoProcessor
@@ -728,6 +735,21 @@ class DumbProcessor
728
735
  end
729
736
 
730
737
  describe Addressable::Template do
738
+ describe 'initialize' do
739
+ context 'with a non-string' do
740
+ it 'raises a TypeError' do
741
+ expect { Addressable::Template.new(nil) }.to raise_error(TypeError)
742
+ end
743
+ end
744
+ end
745
+
746
+ describe 'freeze' do
747
+ subject { Addressable::Template.new("http://example.com/{first}/{+second}/") }
748
+ it 'freezes the template' do
749
+ expect(subject.freeze).to be_frozen
750
+ end
751
+ end
752
+
731
753
  describe "Matching" do
732
754
  let(:uri){
733
755
  Addressable::URI.parse(
@@ -818,6 +840,21 @@ describe Addressable::Template do
818
840
  its(:captures){ should == ["foo", nil, nil] }
819
841
  end
820
842
  end
843
+
844
+ describe 'match' do
845
+ subject { Addressable::Template.new('http://example.com/first/second/') }
846
+ context 'when the URI is the same as the template' do
847
+ it 'returns the match data itself with an empty mapping' do
848
+ uri = Addressable::URI.parse('http://example.com/first/second/')
849
+ match_data = subject.match(uri)
850
+ expect(match_data).to be_an Addressable::Template::MatchData
851
+ expect(match_data.uri).to eq(uri)
852
+ expect(match_data.template).to eq(subject)
853
+ expect(match_data.mapping).to be_empty
854
+ end
855
+ end
856
+ end
857
+
821
858
  describe "extract" do
822
859
  let(:template) {
823
860
  Addressable::Template.new(
@@ -901,13 +938,23 @@ describe Addressable::Template do
901
938
  )
902
939
  end
903
940
  end
941
+ context "partial_expand form style query with missing param at beginning" do
942
+ subject {
943
+ Addressable::Template.new("http://example.com/{?one,two}/")
944
+ }
945
+ it "builds a new pattern" do
946
+ expect(subject.partial_expand(:two => "2").pattern).to eq(
947
+ "http://example.com/?two=2{&one}/"
948
+ )
949
+ end
950
+ end
904
951
  context "partial_expand with query string" do
905
952
  subject {
906
953
  Addressable::Template.new("http://example.com/{?two,one}/")
907
954
  }
908
955
  it "builds a new pattern" do
909
956
  expect(subject.partial_expand(:one => "1").pattern).to eq(
910
- "http://example.com/{?two}&one=1/"
957
+ "http://example.com/?one=1{&two}/"
911
958
  )
912
959
  end
913
960
  end
@@ -949,7 +996,7 @@ describe Addressable::Template do
949
996
  }
950
997
  it "builds a new pattern" do
951
998
  expect(subject.partial_expand("one" => "1").pattern).to eq(
952
- "http://example.com/{?two}&one=1/"
999
+ "http://example.com/?one=1{&two}/"
953
1000
  )
954
1001
  end
955
1002
  end
@@ -998,7 +1045,7 @@ describe Addressable::Template do
998
1045
  }
999
1046
  it "builds a new pattern" do
1000
1047
  expect(subject.partial_expand("one" => "1").pattern).to eq(
1001
- "http://example.com/{?two}&one=1/"
1048
+ "http://example.com/?one=1{&two}/"
1002
1049
  )
1003
1050
  end
1004
1051
  end
@@ -18,6 +18,7 @@ require "spec_helper"
18
18
 
19
19
  require "addressable/uri"
20
20
  require "uri"
21
+ require "ipaddr"
21
22
 
22
23
  if !"".respond_to?("force_encoding")
23
24
  class String
@@ -68,6 +69,14 @@ describe Addressable::URI, "when created with a non-numeric port number" do
68
69
  end
69
70
  end
70
71
 
72
+ describe Addressable::URI, "when created with a invalid encoded port number" do
73
+ it "should raise an error" do
74
+ expect(lambda do
75
+ Addressable::URI.new(:port => "%eb")
76
+ end).to raise_error(Addressable::URI::InvalidURIError)
77
+ end
78
+ end
79
+
71
80
  describe Addressable::URI, "when created with a non-string scheme" do
72
81
  it "should raise an error" do
73
82
  expect(lambda do
@@ -157,6 +166,51 @@ describe Addressable::URI, "when created with a scheme but no hierarchical " +
157
166
  end
158
167
  end
159
168
 
169
+ describe Addressable::URI, "quote handling" do
170
+ describe 'in host name' do
171
+ it "should raise an error for single quote" do
172
+ expect(lambda do
173
+ Addressable::URI.parse("http://local\"host/")
174
+ end).to raise_error(Addressable::URI::InvalidURIError)
175
+ end
176
+ end
177
+ end
178
+
179
+ describe Addressable::URI, "newline normalization" do
180
+ it "should not accept newlines in scheme" do
181
+ expect(lambda do
182
+ Addressable::URI.parse("ht%0atp://localhost/")
183
+ end).to raise_error(Addressable::URI::InvalidURIError)
184
+ end
185
+
186
+ it "should not unescape newline in path" do
187
+ uri = Addressable::URI.parse("http://localhost/%0a").normalize
188
+ expect(uri.to_s).to eq("http://localhost/%0A")
189
+ end
190
+
191
+ it "should not unescape newline in hostname" do
192
+ uri = Addressable::URI.parse("http://local%0ahost/").normalize
193
+ expect(uri.to_s).to eq("http://local%0Ahost/")
194
+ end
195
+
196
+ it "should not unescape newline in username" do
197
+ uri = Addressable::URI.parse("http://foo%0abar@localhost/").normalize
198
+ expect(uri.to_s).to eq("http://foo%0Abar@localhost/")
199
+ end
200
+
201
+ it "should not unescape newline in username" do
202
+ uri = Addressable::URI.parse("http://example:foo%0abar@example/").normalize
203
+ expect(uri.to_s).to eq("http://example:foo%0Abar@example/")
204
+ end
205
+
206
+ it "should not accept newline in hostname" do
207
+ uri = Addressable::URI.parse("http://localhost/")
208
+ expect(lambda do
209
+ uri.host = "local\nhost"
210
+ end).to raise_error(Addressable::URI::InvalidURIError)
211
+ end
212
+ end
213
+
160
214
  describe Addressable::URI, "when created with ambiguous path" do
161
215
  it "should raise an error" do
162
216
  expect(lambda do
@@ -232,6 +286,48 @@ describe Addressable::URI, "when created from nil components" do
232
286
  end).to raise_error(Addressable::URI::InvalidURIError)
233
287
  end
234
288
 
289
+ it "should raise an error if the scheme begins with a digit" do
290
+ expect(lambda do
291
+ @uri.scheme = "1scheme"
292
+ end).to raise_error(Addressable::URI::InvalidURIError)
293
+ end
294
+
295
+ it "should raise an error if the scheme begins with a plus" do
296
+ expect(lambda do
297
+ @uri.scheme = "+scheme"
298
+ end).to raise_error(Addressable::URI::InvalidURIError)
299
+ end
300
+
301
+ it "should raise an error if the scheme begins with a dot" do
302
+ expect(lambda do
303
+ @uri.scheme = ".scheme"
304
+ end).to raise_error(Addressable::URI::InvalidURIError)
305
+ end
306
+
307
+ it "should raise an error if the scheme begins with a dash" do
308
+ expect(lambda do
309
+ @uri.scheme = "-scheme"
310
+ end).to raise_error(Addressable::URI::InvalidURIError)
311
+ end
312
+
313
+ it "should raise an error if the scheme contains an illegal character" do
314
+ expect(lambda do
315
+ @uri.scheme = "scheme!"
316
+ end).to raise_error(Addressable::URI::InvalidURIError)
317
+ end
318
+
319
+ it "should raise an error if the scheme contains whitespace" do
320
+ expect(lambda do
321
+ @uri.scheme = "sch eme"
322
+ end).to raise_error(Addressable::URI::InvalidURIError)
323
+ end
324
+
325
+ it "should raise an error if the scheme contains a newline" do
326
+ expect(lambda do
327
+ @uri.scheme = "sch\neme"
328
+ end).to raise_error(Addressable::URI::InvalidURIError)
329
+ end
330
+
235
331
  it "should raise an error if set into an invalid state" do
236
332
  expect(lambda do
237
333
  @uri.user = "user"
@@ -1047,6 +1143,26 @@ describe Addressable::URI, "when parsed from an Addressable::URI object" do
1047
1143
  expect(original_uri.host).to eq('example.com')
1048
1144
  expect(original_uri.to_s).to eq('http://example.com/')
1049
1145
  end
1146
+
1147
+ it "should not have unexpected side-effects" do
1148
+ original_uri = Addressable::URI.parse("http://example.com/")
1149
+ new_uri = Addressable::URI.parse(original_uri)
1150
+ new_uri.origin = 'https://www.example.com:8080'
1151
+ expect(new_uri.host).to eq('www.example.com')
1152
+ expect(new_uri.to_s).to eq('https://www.example.com:8080/')
1153
+ expect(original_uri.host).to eq('example.com')
1154
+ expect(original_uri.to_s).to eq('http://example.com/')
1155
+ end
1156
+
1157
+ it "should not have unexpected side-effects" do
1158
+ original_uri = Addressable::URI.parse("http://example.com/")
1159
+ new_uri = Addressable::URI.heuristic_parse(original_uri)
1160
+ new_uri.origin = 'https://www.example.com:8080'
1161
+ expect(new_uri.host).to eq('www.example.com')
1162
+ expect(new_uri.to_s).to eq('https://www.example.com:8080/')
1163
+ expect(original_uri.host).to eq('example.com')
1164
+ expect(original_uri.to_s).to eq('http://example.com/')
1165
+ end
1050
1166
  end
1051
1167
 
1052
1168
  describe Addressable::URI, "when parsed from something that looks " +
@@ -1059,6 +1175,15 @@ describe Addressable::URI, "when parsed from something that looks " +
1059
1175
  end
1060
1176
  end
1061
1177
 
1178
+ describe Addressable::URI, "when parsed from a standard library URI object" do
1179
+ it "should parse without error" do
1180
+ uri = Addressable::URI.parse(URI.parse("http://example.com/"))
1181
+ expect(lambda do
1182
+ Addressable::URI.parse(uri)
1183
+ end).not_to raise_error
1184
+ end
1185
+ end
1186
+
1062
1187
  describe Addressable::URI, "when parsed from ''" do
1063
1188
  before do
1064
1189
  @uri = Addressable::URI.parse("")
@@ -1908,6 +2033,12 @@ describe Addressable::URI, "when assigning IPv6 address" do
1908
2033
  expect(uri.to_s).to eq('http://[3ffe:1900:4545:3:200:f8ff:fe21:67cf]/')
1909
2034
  end
1910
2035
 
2036
+ it "should allow to set bare IPv6 address as hostname with IPAddr object" do
2037
+ uri = Addressable::URI.parse("http://[::1]/")
2038
+ uri.hostname = IPAddr.new('3ffe:1900:4545:3:200:f8ff:fe21:67cf')
2039
+ expect(uri.to_s).to eq('http://[3ffe:1900:4545:3:200:f8ff:fe21:67cf]/')
2040
+ end
2041
+
1911
2042
  it "should not allow to set bare IPv6 address as host" do
1912
2043
  uri = Addressable::URI.parse("http://[::1]/")
1913
2044
  skip "not checked"
@@ -3586,15 +3717,6 @@ describe Addressable::URI, "when parsed from " +
3586
3717
  expect(@uri.to_str).to eq(
3587
3718
  "ftp://user:pass@example.com/path/to/resource?query=x#fragment"
3588
3719
  )
3589
- @uri.scheme = "bogus!"
3590
- expect(@uri.scheme).to eq("bogus!")
3591
- expect(@uri.normalized_scheme).to eq("bogus%21")
3592
- expect(@uri.normalize.to_s).to eq(
3593
- "bogus%21://user:pass@example.com/path/to/resource?query=x#fragment"
3594
- )
3595
- expect(@uri.normalize.to_str).to eq(
3596
- "bogus%21://user:pass@example.com/path/to/resource?query=x#fragment"
3597
- )
3598
3720
  end
3599
3721
 
3600
3722
  it "should have the correct site segment after assignment" do
@@ -3663,12 +3785,31 @@ describe Addressable::URI, "when parsed from " +
3663
3785
  expect(@uri.authority).to eq("user:pass@newexample.com")
3664
3786
  end
3665
3787
 
3788
+ it "should have the correct host after assignment" do
3789
+ @uri.hostname = "newexample.com"
3790
+ expect(@uri.host).to eq("newexample.com")
3791
+ expect(@uri.hostname).to eq("newexample.com")
3792
+ expect(@uri.authority).to eq("user:pass@newexample.com")
3793
+ end
3794
+
3795
+ it "should raise an error if assigning a bogus object to the hostname" do
3796
+ expect(lambda do
3797
+ @uri.hostname = Object.new
3798
+ end).to raise_error
3799
+ end
3800
+
3666
3801
  it "should have the correct port after assignment" do
3667
3802
  @uri.port = 8080
3668
3803
  expect(@uri.port).to eq(8080)
3669
3804
  expect(@uri.authority).to eq("user:pass@example.com:8080")
3670
3805
  end
3671
3806
 
3807
+ it "should have the correct origin after assignment" do
3808
+ @uri.origin = "http://newexample.com"
3809
+ expect(@uri.host).to eq("newexample.com")
3810
+ expect(@uri.authority).to eq("newexample.com")
3811
+ end
3812
+
3672
3813
  it "should have the correct path after assignment" do
3673
3814
  @uri.path = "/newpath/to/resource"
3674
3815
  expect(@uri.path).to eq("/newpath/to/resource")
@@ -5395,6 +5536,24 @@ describe Addressable::URI, "when form encoding a non-Array object" do
5395
5536
  end
5396
5537
  end
5397
5538
 
5539
+ # See https://tools.ietf.org/html/rfc6749#appendix-B
5540
+ describe Addressable::URI, "when form encoding the example value from OAuth 2" do
5541
+ it "should result in correct values" do
5542
+ expect(Addressable::URI.form_encode(
5543
+ {"value" => " %&+£€"}
5544
+ )).to eq("value=+%25%26%2B%C2%A3%E2%82%AC")
5545
+ end
5546
+ end
5547
+
5548
+ # See https://tools.ietf.org/html/rfc6749#appendix-B
5549
+ describe Addressable::URI, "when form unencoding the example value from OAuth 2" do
5550
+ it "should result in correct values" do
5551
+ expect(Addressable::URI.form_unencode(
5552
+ "value=+%25%26%2B%C2%A3%E2%82%AC"
5553
+ )).to eq([["value", " %&+£€"]])
5554
+ end
5555
+ end
5556
+
5398
5557
  describe Addressable::URI, "when form unencoding a string" do
5399
5558
  it "should result in correct values" do
5400
5559
  expect(Addressable::URI.form_unencode(