addressable 2.2.8 → 2.3.2
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.
- data/CHANGELOG.md +14 -0
- data/README.md +7 -3
- data/Rakefile +2 -2
- data/data/unicode.data +0 -0
- data/lib/addressable/idna/pure.rb +7 -4235
- data/lib/addressable/template.rb +334 -543
- data/lib/addressable/uri.rb +117 -160
- data/lib/addressable/version.rb +2 -2
- data/spec/addressable/idna_spec.rb +15 -0
- data/spec/addressable/template_spec.rb +920 -2063
- data/spec/addressable/uri_spec.rb +265 -129
- metadata +5 -27
- data/Gemfile.lock +0 -35
@@ -1,2144 +1,1001 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
# Copyright (C) 2006-2011 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
1
|
require "addressable/template"
|
18
2
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
class Encoding
|
31
|
-
def initialize(name)
|
32
|
-
@name = name
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_s
|
36
|
-
return @name
|
3
|
+
shared_examples_for 'expands' do |tests|
|
4
|
+
tests.each do |template, expansion|
|
5
|
+
exp = expansion.is_a?(Array) ? expansion.first : expansion
|
6
|
+
it "#{template} to #{exp}" do
|
7
|
+
tmpl = Addressable::Template.new(template).expand(subject)
|
8
|
+
if expansion.is_a?(Array)
|
9
|
+
expansion.any?{|i| i == tmpl.to_str}.should be_true
|
10
|
+
else
|
11
|
+
tmpl.to_str.should == expansion
|
12
|
+
end
|
37
13
|
end
|
38
|
-
|
39
|
-
UTF_8 = Encoding.new("UTF-8")
|
40
|
-
ASCII_8BIT = Encoding.new("US-ASCII")
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class ExampleProcessor
|
45
|
-
def self.validate(name, value)
|
46
|
-
return !!(value =~ /^[\w ]+$/) if name == "query"
|
47
|
-
return true
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.transform(name, value)
|
51
|
-
return value.gsub(/ /, "+") if name == "query"
|
52
|
-
return value
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.restore(name, value)
|
56
|
-
return value.gsub(/\+/, " ") if name == "query"
|
57
|
-
return value.tr("A-Za-z", "N-ZA-Mn-za-m") if name == "rot13"
|
58
|
-
return value
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.match(name)
|
62
|
-
return ".*?" if name == "first"
|
63
|
-
return ".*"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
class SlashlessProcessor
|
68
|
-
def self.match(name)
|
69
|
-
return "[^/\\n]*"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class NoOpProcessor
|
74
|
-
def self.transform(name, value)
|
75
|
-
value
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe Addressable::Template do
|
80
|
-
it "should raise a TypeError for invalid patterns" do
|
81
|
-
(lambda do
|
82
|
-
Addressable::Template.new(42)
|
83
|
-
end).should raise_error(TypeError, "Can't convert Fixnum into String.")
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
describe Addressable::Template, "created with the pattern '/'" do
|
88
|
-
before do
|
89
|
-
@template = Addressable::Template.new("/")
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should have no variables" do
|
93
|
-
@template.variables.should be_empty
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should have the correct mapping when extracting from '/'" do
|
97
|
-
@template.extract("/").should == {}
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
describe Addressable::URI, "when parsed from '/one/'" do
|
102
|
-
before do
|
103
|
-
@uri = Addressable::URI.parse("/one/")
|
104
|
-
end
|
105
|
-
|
106
|
-
it "should not match the pattern '/two/'" do
|
107
|
-
Addressable::Template.new("/two/").extract(@uri).should == nil
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should have the correct mapping when extracting values " +
|
111
|
-
"using the pattern '/{number}/'" do
|
112
|
-
Addressable::Template.new(
|
113
|
-
"/{number}/"
|
114
|
-
).extract(@uri).should == {"number" => "one"}
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
describe Addressable::Template, "created with the pattern '/{number}/'" do
|
119
|
-
before do
|
120
|
-
@template = Addressable::Template.new("/{number}/")
|
121
|
-
end
|
122
|
-
|
123
|
-
it "should have the variables ['number']" do
|
124
|
-
@template.variables.should == ["number"]
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should not match the pattern '/'" do
|
128
|
-
@template.match("/").should == nil
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should match the pattern '/two/'" do
|
132
|
-
@template.match("/two/").mapping.should == {"number" => "two"}
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
describe Addressable::Template,
|
137
|
-
"created with the pattern '/{number}/{number}/'" do
|
138
|
-
before do
|
139
|
-
@template = Addressable::Template.new("/{number}/{number}/")
|
140
|
-
end
|
141
|
-
|
142
|
-
it "should have one variable" do
|
143
|
-
@template.variables.should == ["number"]
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should have the correct mapping when extracting from '/1/1/'" do
|
147
|
-
@template.extract("/1/1/").should == {"number" => "1"}
|
148
|
-
end
|
149
|
-
|
150
|
-
it "should not match '/1/2/'" do
|
151
|
-
@template.match("/1/2/").should == nil
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should not match '/2/1/'" do
|
155
|
-
@template.match("/2/1/").should == nil
|
156
|
-
end
|
157
|
-
|
158
|
-
it "should not match '/1/'" do
|
159
|
-
@template.match("/1/").should == nil
|
160
|
-
end
|
161
|
-
|
162
|
-
it "should not match '/1/1/1/'" do
|
163
|
-
@template.match("/1/1/1/").should == nil
|
164
|
-
end
|
165
|
-
|
166
|
-
it "should not match '/1/2/3/'" do
|
167
|
-
@template.match("/1/2/3/").should == nil
|
168
14
|
end
|
169
15
|
end
|
170
16
|
|
171
|
-
describe
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
end
|
180
|
-
|
181
|
-
it "should have the correct mapping when extracting from '/1.1'" do
|
182
|
-
@template.extract("/1.1").should == {"number" => "1"}
|
183
|
-
end
|
184
|
-
|
185
|
-
it "should have the correct mapping when extracting from '/99.99'" do
|
186
|
-
@template.extract("/99.99").should == {"number" => "99"}
|
187
|
-
end
|
188
|
-
|
189
|
-
it "should not match '/1.2'" do
|
190
|
-
@template.match("/1.2").should == nil
|
191
|
-
end
|
192
|
-
|
193
|
-
it "should not match '/2.1'" do
|
194
|
-
@template.match("/2.1").should == nil
|
195
|
-
end
|
196
|
-
|
197
|
-
it "should not match '/1'" do
|
198
|
-
@template.match("/1").should == nil
|
199
|
-
end
|
200
|
-
|
201
|
-
it "should not match '/1.1.1'" do
|
202
|
-
@template.match("/1.1.1").should == nil
|
203
|
-
end
|
204
|
-
|
205
|
-
it "should not match '/1.23'" do
|
206
|
-
@template.match("/1.23").should == nil
|
207
|
-
end
|
17
|
+
describe "Level 1:" do
|
18
|
+
subject{
|
19
|
+
{:var => "value", :hello => "Hello World!"}
|
20
|
+
}
|
21
|
+
it_behaves_like 'expands', {
|
22
|
+
'{var}' => 'value',
|
23
|
+
'{hello}' => 'Hello%20World%21'
|
24
|
+
}
|
208
25
|
end
|
209
26
|
|
210
|
-
describe
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
@template.extract("/99/99/").should == {"number" => "99"}
|
226
|
-
end
|
227
|
-
|
228
|
-
it "should not match '/1/1'" do
|
229
|
-
@template.match("/1/1").should == nil
|
230
|
-
end
|
231
|
-
|
232
|
-
it "should not match '/11/'" do
|
233
|
-
@template.match("/11/").should == nil
|
234
|
-
end
|
235
|
-
|
236
|
-
it "should not match '/1/2/'" do
|
237
|
-
@template.match("/1/2/").should == nil
|
238
|
-
end
|
239
|
-
|
240
|
-
it "should not match '/2/1/'" do
|
241
|
-
@template.match("/2/1/").should == nil
|
242
|
-
end
|
243
|
-
|
244
|
-
it "should not match '/1/'" do
|
245
|
-
@template.match("/1/").should == nil
|
246
|
-
end
|
247
|
-
|
248
|
-
it "should not match '/1/1/1/'" do
|
249
|
-
@template.match("/1/1/1/").should == nil
|
27
|
+
describe "Level 2" do
|
28
|
+
subject{
|
29
|
+
{
|
30
|
+
:var => "value",
|
31
|
+
:hello => "Hello World!",
|
32
|
+
:path => "/foo/bar"
|
33
|
+
}
|
34
|
+
}
|
35
|
+
context "Operator +:" do
|
36
|
+
it_behaves_like 'expands', {
|
37
|
+
'{+var}' => 'value',
|
38
|
+
'{+hello}' => 'Hello%20World!',
|
39
|
+
'{+path}/here' => '/foo/bar/here',
|
40
|
+
'here?ref={+path}' => 'here?ref=/foo/bar'
|
41
|
+
}
|
250
42
|
end
|
251
|
-
|
252
|
-
|
253
|
-
|
43
|
+
context "Operator #:" do
|
44
|
+
it_behaves_like 'expands', {
|
45
|
+
'X{#var}' => 'X#value',
|
46
|
+
'X{#hello}' => 'X#Hello%20World!'
|
47
|
+
}
|
254
48
|
end
|
255
49
|
end
|
256
50
|
|
257
|
-
describe
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
"
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
it "should have the correct mapping when extracting " +
|
274
|
-
"from '/99/?number=99'" do
|
275
|
-
@template.extract("/99/?number=99").should == {"number" => "99"}
|
276
|
-
end
|
277
|
-
|
278
|
-
it "should have the correct mapping when extracting " +
|
279
|
-
"from '/1/?number=1&letter=a'" do
|
280
|
-
@template.extract("/1/?number=1&letter=a").should == {
|
281
|
-
"number" => "1", "letter" => "a"
|
51
|
+
describe "Level 3" do
|
52
|
+
subject{
|
53
|
+
{
|
54
|
+
:var => "value",
|
55
|
+
:hello => "Hello World!",
|
56
|
+
:empty => "",
|
57
|
+
:path => "/foo/bar",
|
58
|
+
:x => "1024",
|
59
|
+
:y => "768"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
context "Operator nil (multiple vars):" do
|
63
|
+
it_behaves_like 'expands', {
|
64
|
+
'map?{x,y}' => 'map?1024,768',
|
65
|
+
'{x,hello,y}' => '1024,Hello%20World%21,768'
|
282
66
|
}
|
283
67
|
end
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
it "should not match '/1/?number=2'" do
|
290
|
-
@template.match("/1/?number=2").should == nil
|
291
|
-
end
|
292
|
-
|
293
|
-
it "should not match '/2/?number=1'" do
|
294
|
-
@template.match("/2/?number=1").should == nil
|
295
|
-
end
|
296
|
-
|
297
|
-
it "should not match '/1/?'" do
|
298
|
-
@template.match("/1/?").should == nil
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
|
-
describe Addressable::Template,
|
303
|
-
"created with the pattern '/{number}/{-list|/|number}/'" do
|
304
|
-
before do
|
305
|
-
@template = Addressable::Template.new("/{number}/{-list|/|number}/")
|
68
|
+
context "Operator + (multiple vars):" do
|
69
|
+
it_behaves_like 'expands', {
|
70
|
+
'{+x,hello,y}' => '1024,Hello%20World!,768',
|
71
|
+
'{+path,x}/here' => '/foo/bar,1024/here'
|
72
|
+
}
|
306
73
|
end
|
307
|
-
|
308
|
-
|
309
|
-
|
74
|
+
context "Operator # (multiple vars):" do
|
75
|
+
it_behaves_like 'expands', {
|
76
|
+
'{#x,hello,y}' => '#1024,Hello%20World!,768',
|
77
|
+
'{#path,x}/here' => '#/foo/bar,1024/here'
|
78
|
+
}
|
310
79
|
end
|
311
|
-
|
312
|
-
|
313
|
-
|
80
|
+
context "Operator ." do
|
81
|
+
it_behaves_like 'expands', {
|
82
|
+
'X{.var}' => 'X.value',
|
83
|
+
'X{.x,y}' => 'X.1024.768'
|
84
|
+
}
|
314
85
|
end
|
315
|
-
|
316
|
-
|
317
|
-
|
86
|
+
context "Operator /" do
|
87
|
+
it_behaves_like 'expands', {
|
88
|
+
'{/var}' => '/value',
|
89
|
+
'{/var,x}/here' => '/value/1024/here'
|
90
|
+
}
|
318
91
|
end
|
319
|
-
|
320
|
-
|
321
|
-
|
92
|
+
context "Operator ;" do
|
93
|
+
it_behaves_like 'expands', {
|
94
|
+
'{;x,y}' => ';x=1024;y=768',
|
95
|
+
'{;x,y,empty}' => ';x=1024;y=768;empty'
|
96
|
+
}
|
322
97
|
end
|
323
|
-
|
324
|
-
|
325
|
-
|
98
|
+
context "Operator ?" do
|
99
|
+
it_behaves_like 'expands', {
|
100
|
+
'{?x,y}' => '?x=1024&y=768',
|
101
|
+
'{?x,y,empty}' => '?x=1024&y=768&empty='
|
102
|
+
}
|
326
103
|
end
|
327
|
-
|
328
|
-
|
329
|
-
|
104
|
+
context "Operator &" do
|
105
|
+
it_behaves_like 'expands', {
|
106
|
+
'?fixed=yes{&x}' => '?fixed=yes&x=1024',
|
107
|
+
'{&x,y,empty}' => '&x=1024&y=768&empty='
|
108
|
+
}
|
330
109
|
end
|
331
110
|
end
|
332
111
|
|
333
|
-
describe
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
"
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
112
|
+
describe "Level 4" do
|
113
|
+
subject{
|
114
|
+
{
|
115
|
+
:var => "value",
|
116
|
+
:hello => "Hello World!",
|
117
|
+
:path => "/foo/bar",
|
118
|
+
:semi => ";",
|
119
|
+
:list => %w(red green blue),
|
120
|
+
:keys => {"semi" => ';', "dot" => '.', "comma" => ','}
|
121
|
+
}
|
122
|
+
}
|
123
|
+
context "Expansion with value modifiers" do
|
124
|
+
it_behaves_like 'expands', {
|
125
|
+
'{var:3}' => 'val',
|
126
|
+
'{var:30}' => 'value',
|
127
|
+
'{list}' => 'red,green,blue',
|
128
|
+
'{list*}' => 'red,green,blue',
|
129
|
+
'{keys}' => [
|
130
|
+
'semi,%3B,dot,.,comma,%2C',
|
131
|
+
'dot,.,semi,%3B,comma,%2C',
|
132
|
+
'comma,%2C,semi,%3B,dot,.',
|
133
|
+
'semi,%3B,comma,%2C,dot,.',
|
134
|
+
'dot,.,comma,%2C,semi,%3B',
|
135
|
+
'comma,%2C,dot,.,semi,%3B'
|
136
|
+
],
|
137
|
+
'{keys*}' => [
|
138
|
+
'semi=%3B,dot=.,comma=%2C',
|
139
|
+
'dot=.,semi=%3B,comma=%2C',
|
140
|
+
'comma=%2C,semi=%3B,dot=.',
|
141
|
+
'semi=%3B,comma=%2C,dot=.',
|
142
|
+
'dot=.,comma=%2C,semi=%3B',
|
143
|
+
'comma=%2C,dot=.,semi=%3B'
|
144
|
+
]
|
145
|
+
}
|
355
146
|
end
|
356
|
-
|
357
|
-
|
358
|
-
|
147
|
+
context "Operator + with value modifiers" do
|
148
|
+
it_behaves_like 'expands', {
|
149
|
+
'{+path:6}/here' => '/foo/b/here',
|
150
|
+
'{+list}' => 'red,green,blue',
|
151
|
+
'{+list*}' => 'red,green,blue',
|
152
|
+
'{+keys}' => [
|
153
|
+
'semi,;,dot,.,comma,,',
|
154
|
+
'dot,.,semi,;,comma,,',
|
155
|
+
'comma,,,semi,;,dot,.',
|
156
|
+
'semi,;,comma,,,dot,.',
|
157
|
+
'dot,.,comma,,,semi,;',
|
158
|
+
'comma,,,dot,.,semi,;'
|
159
|
+
],
|
160
|
+
'{+keys*}' => [
|
161
|
+
'semi=;,dot=.,comma=,',
|
162
|
+
'dot=.,semi=;,comma=,',
|
163
|
+
'comma=,,semi=;,dot=.',
|
164
|
+
'semi=;,comma=,,dot=.',
|
165
|
+
'dot=.,comma=,,semi=;',
|
166
|
+
'comma=,,dot=.,semi=;'
|
167
|
+
]
|
168
|
+
}
|
359
169
|
end
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
170
|
+
context "Operator # with value modifiers" do
|
171
|
+
it_behaves_like 'expands', {
|
172
|
+
'{#path:6}/here' => '#/foo/b/here',
|
173
|
+
'{#list}' => '#red,green,blue',
|
174
|
+
'{#list*}' => '#red,green,blue',
|
175
|
+
'{#keys}' => [
|
176
|
+
'#semi,;,dot,.,comma,,',
|
177
|
+
'#dot,.,semi,;,comma,,',
|
178
|
+
'#comma,,,semi,;,dot,.',
|
179
|
+
'#semi,;,comma,,,dot,.',
|
180
|
+
'#dot,.,comma,,,semi,;',
|
181
|
+
'#comma,,,dot,.,semi,;'
|
182
|
+
],
|
183
|
+
'{#keys*}' => [
|
184
|
+
'#semi=;,dot=.,comma=,',
|
185
|
+
'#dot=.,semi=;,comma=,',
|
186
|
+
'#comma=,,semi=;,dot=.',
|
187
|
+
'#semi=;,comma=,,dot=.',
|
188
|
+
'#dot=.,comma=,,semi=;',
|
189
|
+
'#comma=,,dot=.,semi=;'
|
190
|
+
]
|
191
|
+
}
|
370
192
|
end
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
193
|
+
context "Operator . with value modifiers" do
|
194
|
+
it_behaves_like 'expands', {
|
195
|
+
'X{.var:3}' => 'X.val',
|
196
|
+
'X{.list}' => 'X.red,green,blue',
|
197
|
+
'X{.list*}' => 'X.red.green.blue',
|
198
|
+
'X{.keys}' => [
|
199
|
+
'X.semi,%3B,dot,.,comma,%2C',
|
200
|
+
'X.dot,.,semi,%3B,comma,%2C',
|
201
|
+
'X.comma,%2C,semi,%3B,dot,.',
|
202
|
+
'X.semi,%3B,comma,%2C,dot,.',
|
203
|
+
'X.dot,.,comma,%2C,semi,%3B',
|
204
|
+
'X.comma,%2C,dot,.,semi,%3B'
|
205
|
+
],
|
206
|
+
'X{.keys*}' => [
|
207
|
+
'X.semi=%3B.dot=..comma=%2C',
|
208
|
+
'X.dot=..semi=%3B.comma=%2C',
|
209
|
+
'X.comma=%2C.semi=%3B.dot=.',
|
210
|
+
'X.semi=%3B.comma=%2C.dot=.',
|
211
|
+
'X.dot=..comma=%2C.semi=%3B',
|
212
|
+
'X.comma=%2C.dot=..semi=%3B'
|
213
|
+
]
|
214
|
+
}
|
377
215
|
end
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
216
|
+
context "Operator / with value modifiers" do
|
217
|
+
it_behaves_like 'expands', {
|
218
|
+
'{/var:1,var}' => '/v/value',
|
219
|
+
'{/list}' => '/red,green,blue',
|
220
|
+
'{/list*}' => '/red/green/blue',
|
221
|
+
'{/list*,path:4}' => '/red/green/blue/%2Ffoo',
|
222
|
+
'{/keys}' => [
|
223
|
+
'/semi,%3B,dot,.,comma,%2C',
|
224
|
+
'/dot,.,semi,%3B,comma,%2C',
|
225
|
+
'/comma,%2C,semi,%3B,dot,.',
|
226
|
+
'/semi,%3B,comma,%2C,dot,.',
|
227
|
+
'/dot,.,comma,%2C,semi,%3B',
|
228
|
+
'/comma,%2C,dot,.,semi,%3B'
|
229
|
+
],
|
230
|
+
'{/keys*}' => [
|
231
|
+
'/semi=%3B/dot=./comma=%2C',
|
232
|
+
'/dot=./semi=%3B/comma=%2C',
|
233
|
+
'/comma=%2C/semi=%3B/dot=.',
|
234
|
+
'/semi=%3B/comma=%2C/dot=.',
|
235
|
+
'/dot=./comma=%2C/semi=%3B',
|
236
|
+
'/comma=%2C/dot=./semi=%3B'
|
237
|
+
]
|
238
|
+
}
|
383
239
|
end
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
240
|
+
context "Operator ; with value modifiers" do
|
241
|
+
it_behaves_like 'expands', {
|
242
|
+
'{;hello:5}' => ';hello=Hello',
|
243
|
+
'{;list}' => ';list=red,green,blue',
|
244
|
+
'{;list*}' => ';list=red;list=green;list=blue',
|
245
|
+
'{;keys}' => [
|
246
|
+
';keys=semi,%3B,dot,.,comma,%2C',
|
247
|
+
';keys=dot,.,semi,%3B,comma,%2C',
|
248
|
+
';keys=comma,%2C,semi,%3B,dot,.',
|
249
|
+
';keys=semi,%3B,comma,%2C,dot,.',
|
250
|
+
';keys=dot,.,comma,%2C,semi,%3B',
|
251
|
+
';keys=comma,%2C,dot,.,semi,%3B'
|
252
|
+
],
|
253
|
+
'{;keys*}' => [
|
254
|
+
';semi=%3B;dot=.;comma=%2C',
|
255
|
+
';dot=.;semi=%3B;comma=%2C',
|
256
|
+
';comma=%2C;semi=%3B;dot=.',
|
257
|
+
';semi=%3B;comma=%2C;dot=.',
|
258
|
+
';dot=.;comma=%2C;semi=%3B',
|
259
|
+
';comma=%2C;dot=.;semi=%3B'
|
260
|
+
]
|
261
|
+
}
|
390
262
|
end
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
263
|
+
context "Operator ? with value modifiers" do
|
264
|
+
it_behaves_like 'expands', {
|
265
|
+
'{?var:3}' => '?var=val',
|
266
|
+
'{?list}' => '?list=red,green,blue',
|
267
|
+
'{?list*}' => '?list=red&list=green&list=blue',
|
268
|
+
'{?keys}' => [
|
269
|
+
'?keys=semi,%3B,dot,.,comma,%2C',
|
270
|
+
'?keys=dot,.,semi,%3B,comma,%2C',
|
271
|
+
'?keys=comma,%2C,semi,%3B,dot,.',
|
272
|
+
'?keys=semi,%3B,comma,%2C,dot,.',
|
273
|
+
'?keys=dot,.,comma,%2C,semi,%3B',
|
274
|
+
'?keys=comma,%2C,dot,.,semi,%3B'
|
275
|
+
],
|
276
|
+
'{?keys*}' => [
|
277
|
+
'?semi=%3B&dot=.&comma=%2C',
|
278
|
+
'?dot=.&semi=%3B&comma=%2C',
|
279
|
+
'?comma=%2C&semi=%3B&dot=.',
|
280
|
+
'?semi=%3B&comma=%2C&dot=.',
|
281
|
+
'?dot=.&comma=%2C&semi=%3B',
|
282
|
+
'?comma=%2C&dot=.&semi=%3B'
|
283
|
+
]
|
396
284
|
}
|
397
285
|
end
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
286
|
+
context "Operator & with value modifiers" do
|
287
|
+
it_behaves_like 'expands', {
|
288
|
+
'{&var:3}' => '&var=val',
|
289
|
+
'{&list}' => '&list=red,green,blue',
|
290
|
+
'{&list*}' => '&list=red&list=green&list=blue',
|
291
|
+
'{&keys}' => [
|
292
|
+
'&keys=semi,%3B,dot,.,comma,%2C',
|
293
|
+
'&keys=dot,.,semi,%3B,comma,%2C',
|
294
|
+
'&keys=comma,%2C,semi,%3B,dot,.',
|
295
|
+
'&keys=semi,%3B,comma,%2C,dot,.',
|
296
|
+
'&keys=dot,.,comma,%2C,semi,%3B',
|
297
|
+
'&keys=comma,%2C,dot,.,semi,%3B'
|
298
|
+
],
|
299
|
+
'{&keys*}' => [
|
300
|
+
'&semi=%3B&dot=.&comma=%2C',
|
301
|
+
'&dot=.&semi=%3B&comma=%2C',
|
302
|
+
'&comma=%2C&semi=%3B&dot=.',
|
303
|
+
'&semi=%3B&comma=%2C&dot=.',
|
304
|
+
'&dot=.&comma=%2C&semi=%3B',
|
305
|
+
'&comma=%2C&dot=.&semi=%3B'
|
306
|
+
]
|
406
307
|
}
|
407
308
|
end
|
408
309
|
end
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
it "should have the correct mapping when extracting values using " +
|
418
|
-
"the pattern 'http://example.com/search/{query}/' with the " +
|
419
|
-
"ExampleProcessor" do
|
420
|
-
Addressable::Template.new(
|
421
|
-
"http://example.com/search/{query}/"
|
422
|
-
).extract(@uri, ExampleProcessor).should == {
|
423
|
-
"query" => "an example search query"
|
310
|
+
describe "Modifiers" do
|
311
|
+
subject{
|
312
|
+
{
|
313
|
+
:var => "value",
|
314
|
+
:semi => ";",
|
315
|
+
:year => %w(1965 2000 2012),
|
316
|
+
:dom => %w(example com)
|
424
317
|
}
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
"query" => ["an", "example", "search", "query"]
|
318
|
+
}
|
319
|
+
context "length" do
|
320
|
+
it_behaves_like 'expands', {
|
321
|
+
'{var:3}' => 'val',
|
322
|
+
'{var:30}' => 'value',
|
323
|
+
'{var}' => 'value',
|
324
|
+
'{semi}' => '%3B',
|
325
|
+
'{semi:2}' => '%3B'
|
434
326
|
}
|
435
327
|
end
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
).extract(@uri).should == nil
|
328
|
+
context "explode" do
|
329
|
+
it_behaves_like 'expands', {
|
330
|
+
'find{?year*}' => 'find?year=1965&year=2000&year=2012',
|
331
|
+
'www{.dom*}' => 'www.example.com',
|
332
|
+
}
|
442
333
|
end
|
443
334
|
end
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
"
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
"
|
455
|
-
|
456
|
-
"
|
457
|
-
|
458
|
-
|
459
|
-
|
335
|
+
describe "Expansion" do
|
336
|
+
subject{
|
337
|
+
{
|
338
|
+
:count => ["one", "two", "three"],
|
339
|
+
:dom => ["example", "com"],
|
340
|
+
:dub => "me/too",
|
341
|
+
:hello => "Hello World!",
|
342
|
+
:half => "50%",
|
343
|
+
:var => "value",
|
344
|
+
:who => "fred",
|
345
|
+
:base => "http://example.com/home/",
|
346
|
+
:path => "/foo/bar",
|
347
|
+
:list => ["red", "green", "blue"],
|
348
|
+
:keys => {"semi" => ";","dot" => ".","comma" => ","},
|
349
|
+
:v => "6",
|
350
|
+
:x => "1024",
|
351
|
+
:y => "768",
|
352
|
+
:empty => "",
|
353
|
+
:empty_keys => {},
|
354
|
+
:undef => nil
|
460
355
|
}
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
356
|
+
}
|
357
|
+
context "concatenation" do
|
358
|
+
it_behaves_like 'expands', {
|
359
|
+
'{count}' => 'one,two,three',
|
360
|
+
'{count*}' => 'one,two,three',
|
361
|
+
'{/count}' => '/one,two,three',
|
362
|
+
'{/count*}' => '/one/two/three',
|
363
|
+
'{;count}' => ';count=one,two,three',
|
364
|
+
'{;count*}' => ';count=one;count=two;count=three',
|
365
|
+
'{?count}' => '?count=one,two,three',
|
366
|
+
'{?count*}' => '?count=one&count=two&count=three',
|
367
|
+
'{&count*}' => '&count=one&count=two&count=three'
|
471
368
|
}
|
472
369
|
end
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
370
|
+
context "simple expansion" do
|
371
|
+
it_behaves_like 'expands', {
|
372
|
+
'{var}' => 'value',
|
373
|
+
'{hello}' => 'Hello%20World%21',
|
374
|
+
'{half}' => '50%25',
|
375
|
+
'O{empty}X' => 'OX',
|
376
|
+
'O{undef}X' => 'OX',
|
377
|
+
'{x,y}' => '1024,768',
|
378
|
+
'{x,hello,y}' => '1024,Hello%20World%21,768',
|
379
|
+
'?{x,empty}' => '?1024,',
|
380
|
+
'?{x,undef}' => '?1024',
|
381
|
+
'?{undef,y}' => '?768',
|
382
|
+
'{var:3}' => 'val',
|
383
|
+
'{var:30}' => 'value',
|
384
|
+
'{list}' => 'red,green,blue',
|
385
|
+
'{list*}' => 'red,green,blue',
|
386
|
+
'{keys}' => [
|
387
|
+
'semi,%3B,dot,.,comma,%2C',
|
388
|
+
'dot,.,semi,%3B,comma,%2C',
|
389
|
+
'comma,%2C,semi,%3B,dot,.',
|
390
|
+
'semi,%3B,comma,%2C,dot,.',
|
391
|
+
'dot,.,comma,%2C,semi,%3B',
|
392
|
+
'comma,%2C,dot,.,semi,%3B'
|
393
|
+
],
|
394
|
+
'{keys*}' => [
|
395
|
+
'semi=%3B,dot=.,comma=%2C',
|
396
|
+
'dot=.,semi=%3B,comma=%2C',
|
397
|
+
'comma=%2C,semi=%3B,dot=.',
|
398
|
+
'semi=%3B,comma=%2C,dot=.',
|
399
|
+
'dot=.,comma=%2C,semi=%3B',
|
400
|
+
'comma=%2C,dot=.,semi=%3B'
|
401
|
+
]
|
483
402
|
}
|
484
403
|
end
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
404
|
+
context "reserved expansion (+)" do
|
405
|
+
it_behaves_like 'expands', {
|
406
|
+
'{+var}' => 'value',
|
407
|
+
'{+hello}' => 'Hello%20World!',
|
408
|
+
'{+half}' => '50%25',
|
409
|
+
'{base}index' => 'http%3A%2F%2Fexample.com%2Fhome%2Findex',
|
410
|
+
'{+base}index' => 'http://example.com/home/index',
|
411
|
+
'O{+empty}X' => 'OX',
|
412
|
+
'O{+undef}X' => 'OX',
|
413
|
+
'{+path}/here' => '/foo/bar/here',
|
414
|
+
'here?ref={+path}' => 'here?ref=/foo/bar',
|
415
|
+
'up{+path}{var}/here' => 'up/foo/barvalue/here',
|
416
|
+
'{+x,hello,y}' => '1024,Hello%20World!,768',
|
417
|
+
'{+path,x}/here' => '/foo/bar,1024/here',
|
418
|
+
'{+path:6}/here' => '/foo/b/here',
|
419
|
+
'{+list}' => 'red,green,blue',
|
420
|
+
'{+list*}' => 'red,green,blue',
|
421
|
+
'{+keys}' => [
|
422
|
+
'semi,;,dot,.,comma,,',
|
423
|
+
'dot,.,semi,;,comma,,',
|
424
|
+
'comma,,,semi,;,dot,.',
|
425
|
+
'semi,;,comma,,,dot,.',
|
426
|
+
'dot,.,comma,,,semi,;',
|
427
|
+
'comma,,,dot,.,semi,;'
|
428
|
+
],
|
429
|
+
'{+keys*}' => [
|
430
|
+
'semi=;,dot=.,comma=,',
|
431
|
+
'dot=.,semi=;,comma=,',
|
432
|
+
'comma=,,semi=;,dot=.',
|
433
|
+
'semi=;,comma=,,dot=.',
|
434
|
+
'dot=.,comma=,,semi=;',
|
435
|
+
'comma=,,dot=.,semi=;'
|
436
|
+
]
|
494
437
|
}
|
495
438
|
end
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
439
|
+
context "fragment expansion (#)" do
|
440
|
+
it_behaves_like 'expands', {
|
441
|
+
'{#var}' => '#value',
|
442
|
+
'{#hello}' => '#Hello%20World!',
|
443
|
+
'{#half}' => '#50%25',
|
444
|
+
'foo{#empty}' => 'foo#',
|
445
|
+
'foo{#undef}' => 'foo',
|
446
|
+
'{#x,hello,y}' => '#1024,Hello%20World!,768',
|
447
|
+
'{#path,x}/here' => '#/foo/bar,1024/here',
|
448
|
+
'{#path:6}/here' => '#/foo/b/here',
|
449
|
+
'{#list}' => '#red,green,blue',
|
450
|
+
'{#list*}' => '#red,green,blue',
|
451
|
+
'{#keys}' => [
|
452
|
+
'#semi,;,dot,.,comma,,',
|
453
|
+
'#dot,.,semi,;,comma,,',
|
454
|
+
'#comma,,,semi,;,dot,.',
|
455
|
+
'#semi,;,comma,,,dot,.',
|
456
|
+
'#dot,.,comma,,,semi,;',
|
457
|
+
'#comma,,,dot,.,semi,;'
|
458
|
+
],
|
459
|
+
'{#keys*}' => [
|
460
|
+
'#semi=;,dot=.,comma=,',
|
461
|
+
'#dot=.,semi=;,comma=,',
|
462
|
+
'#comma=,,semi=;,dot=.',
|
463
|
+
'#semi=;,comma=,,dot=.',
|
464
|
+
'#dot=.,comma=,,semi=;',
|
465
|
+
'#comma=,,dot=.,semi=;'
|
466
|
+
]
|
521
467
|
}
|
522
468
|
end
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
469
|
+
context "label expansion (.)" do
|
470
|
+
it_behaves_like 'expands', {
|
471
|
+
'{.who}' => '.fred',
|
472
|
+
'{.who,who}' => '.fred.fred',
|
473
|
+
'{.half,who}' => '.50%25.fred',
|
474
|
+
'www{.dom*}' => 'www.example.com',
|
475
|
+
'X{.var}' => 'X.value',
|
476
|
+
'X{.empty}' => 'X.',
|
477
|
+
'X{.undef}' => 'X',
|
478
|
+
'X{.var:3}' => 'X.val',
|
479
|
+
'X{.list}' => 'X.red,green,blue',
|
480
|
+
'X{.list*}' => 'X.red.green.blue',
|
481
|
+
'X{.keys}' => [
|
482
|
+
'X.semi,%3B,dot,.,comma,%2C',
|
483
|
+
'X.dot,.,semi,%3B,comma,%2C',
|
484
|
+
'X.comma,%2C,semi,%3B,dot,.',
|
485
|
+
'X.semi,%3B,comma,%2C,dot,.',
|
486
|
+
'X.dot,.,comma,%2C,semi,%3B',
|
487
|
+
'X.comma,%2C,dot,.,semi,%3B'
|
488
|
+
],
|
489
|
+
'X{.keys*}' => [
|
490
|
+
'X.semi=%3B.dot=..comma=%2C',
|
491
|
+
'X.dot=..semi=%3B.comma=%2C',
|
492
|
+
'X.comma=%2C.semi=%3B.dot=.',
|
493
|
+
'X.semi=%3B.comma=%2C.dot=.',
|
494
|
+
'X.dot=..comma=%2C.semi=%3B',
|
495
|
+
'X.comma=%2C.dot=..semi=%3B'
|
496
|
+
],
|
497
|
+
'X{.empty_keys}' => 'X',
|
498
|
+
'X{.empty_keys*}' => 'X'
|
538
499
|
}
|
539
500
|
end
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
501
|
+
context "path expansion (/)" do
|
502
|
+
it_behaves_like 'expands', {
|
503
|
+
'{/who}' => '/fred',
|
504
|
+
'{/who,who}' => '/fred/fred',
|
505
|
+
'{/half,who}' => '/50%25/fred',
|
506
|
+
'{/who,dub}' => '/fred/me%2Ftoo',
|
507
|
+
'{/var}' => '/value',
|
508
|
+
'{/var,empty}' => '/value/',
|
509
|
+
'{/var,undef}' => '/value',
|
510
|
+
'{/var,x}/here' => '/value/1024/here',
|
511
|
+
'{/var:1,var}' => '/v/value',
|
512
|
+
'{/list}' => '/red,green,blue',
|
513
|
+
'{/list*}' => '/red/green/blue',
|
514
|
+
'{/list*,path:4}' => '/red/green/blue/%2Ffoo',
|
515
|
+
'{/keys}' => [
|
516
|
+
'/semi,%3B,dot,.,comma,%2C',
|
517
|
+
'/dot,.,semi,%3B,comma,%2C',
|
518
|
+
'/comma,%2C,semi,%3B,dot,.',
|
519
|
+
'/semi,%3B,comma,%2C,dot,.',
|
520
|
+
'/dot,.,comma,%2C,semi,%3B',
|
521
|
+
'/comma,%2C,dot,.,semi,%3B'
|
522
|
+
],
|
523
|
+
'{/keys*}' => [
|
524
|
+
'/semi=%3B/dot=./comma=%2C',
|
525
|
+
'/dot=./semi=%3B/comma=%2C',
|
526
|
+
'/comma=%2C/semi=%3B/dot=.',
|
527
|
+
'/semi=%3B/comma=%2C/dot=.',
|
528
|
+
'/dot=./comma=%2C/semi=%3B',
|
529
|
+
'/comma=%2C/dot=./semi=%3B'
|
530
|
+
]
|
531
|
+
}
|
546
532
|
end
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
533
|
+
context "path-style expansion (;)" do
|
534
|
+
it_behaves_like 'expands', {
|
535
|
+
'{;who}' => ';who=fred',
|
536
|
+
'{;half}' => ';half=50%25',
|
537
|
+
'{;empty}' => ';empty',
|
538
|
+
'{;v,empty,who}' => ';v=6;empty;who=fred',
|
539
|
+
'{;v,bar,who}' => ';v=6;who=fred',
|
540
|
+
'{;x,y}' => ';x=1024;y=768',
|
541
|
+
'{;x,y,empty}' => ';x=1024;y=768;empty',
|
542
|
+
'{;x,y,undef}' => ';x=1024;y=768',
|
543
|
+
'{;hello:5}' => ';hello=Hello',
|
544
|
+
'{;list}' => ';list=red,green,blue',
|
545
|
+
'{;list*}' => ';list=red;list=green;list=blue',
|
546
|
+
'{;keys}' => [
|
547
|
+
';keys=semi,%3B,dot,.,comma,%2C',
|
548
|
+
';keys=dot,.,semi,%3B,comma,%2C',
|
549
|
+
';keys=comma,%2C,semi,%3B,dot,.',
|
550
|
+
';keys=semi,%3B,comma,%2C,dot,.',
|
551
|
+
';keys=dot,.,comma,%2C,semi,%3B',
|
552
|
+
';keys=comma,%2C,dot,.,semi,%3B'
|
553
|
+
],
|
554
|
+
'{;keys*}' => [
|
555
|
+
';semi=%3B;dot=.;comma=%2C',
|
556
|
+
';dot=.;semi=%3B;comma=%2C',
|
557
|
+
';comma=%2C;semi=%3B;dot=.',
|
558
|
+
';semi=%3B;comma=%2C;dot=.',
|
559
|
+
';dot=.;comma=%2C;semi=%3B',
|
560
|
+
';comma=%2C;dot=.;semi=%3B'
|
561
|
+
]
|
554
562
|
}
|
555
563
|
end
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
564
|
+
context "form query expansion (?)" do
|
565
|
+
it_behaves_like 'expands', {
|
566
|
+
'{?who}' => '?who=fred',
|
567
|
+
'{?half}' => '?half=50%25',
|
568
|
+
'{?x,y}' => '?x=1024&y=768',
|
569
|
+
'{?x,y,empty}' => '?x=1024&y=768&empty=',
|
570
|
+
'{?x,y,undef}' => '?x=1024&y=768',
|
571
|
+
'{?var:3}' => '?var=val',
|
572
|
+
'{?list}' => '?list=red,green,blue',
|
573
|
+
'{?list*}' => '?list=red&list=green&list=blue',
|
574
|
+
'{?keys}' => [
|
575
|
+
'?keys=semi,%3B,dot,.,comma,%2C',
|
576
|
+
'?keys=dot,.,semi,%3B,comma,%2C',
|
577
|
+
'?keys=comma,%2C,semi,%3B,dot,.',
|
578
|
+
'?keys=semi,%3B,comma,%2C,dot,.',
|
579
|
+
'?keys=dot,.,comma,%2C,semi,%3B',
|
580
|
+
'?keys=comma,%2C,dot,.,semi,%3B'
|
581
|
+
],
|
582
|
+
'{?keys*}' => [
|
583
|
+
'?semi=%3B&dot=.&comma=%2C',
|
584
|
+
'?dot=.&semi=%3B&comma=%2C',
|
585
|
+
'?comma=%2C&semi=%3B&dot=.',
|
586
|
+
'?semi=%3B&comma=%2C&dot=.',
|
587
|
+
'?dot=.&comma=%2C&semi=%3B',
|
588
|
+
'?comma=%2C&dot=.&semi=%3B'
|
589
|
+
]
|
563
590
|
}
|
564
591
|
end
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
592
|
+
context "form query expansion (&)" do
|
593
|
+
it_behaves_like 'expands', {
|
594
|
+
'{&who}' => '&who=fred',
|
595
|
+
'{&half}' => '&half=50%25',
|
596
|
+
'?fixed=yes{&x}' => '?fixed=yes&x=1024',
|
597
|
+
'{&x,y,empty}' => '&x=1024&y=768&empty=',
|
598
|
+
'{&x,y,undef}' => '&x=1024&y=768',
|
599
|
+
'{&var:3}' => '&var=val',
|
600
|
+
'{&list}' => '&list=red,green,blue',
|
601
|
+
'{&list*}' => '&list=red&list=green&list=blue',
|
602
|
+
'{&keys}' => [
|
603
|
+
'&keys=semi,%3B,dot,.,comma,%2C',
|
604
|
+
'&keys=dot,.,semi,%3B,comma,%2C',
|
605
|
+
'&keys=comma,%2C,semi,%3B,dot,.',
|
606
|
+
'&keys=semi,%3B,comma,%2C,dot,.',
|
607
|
+
'&keys=dot,.,comma,%2C,semi,%3B',
|
608
|
+
'&keys=comma,%2C,dot,.,semi,%3B'
|
609
|
+
],
|
610
|
+
'{&keys*}' => [
|
611
|
+
'&semi=%3B&dot=.&comma=%2C',
|
612
|
+
'&dot=.&semi=%3B&comma=%2C',
|
613
|
+
'&comma=%2C&semi=%3B&dot=.',
|
614
|
+
'&semi=%3B&comma=%2C&dot=.',
|
615
|
+
'&dot=.&comma=%2C&semi=%3B',
|
616
|
+
'&comma=%2C&dot=.&semi=%3B'
|
617
|
+
]
|
572
618
|
}
|
573
619
|
end
|
574
620
|
end
|
575
621
|
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
end
|
581
|
-
|
582
|
-
it "should have the correct mapping when extracting values " +
|
583
|
-
"using the pattern " +
|
584
|
-
"'http://example.com/{first}/spacer/{second}/'" do
|
585
|
-
Addressable::Template.new(
|
586
|
-
"http://example.com/{first}/spacer/{second}/"
|
587
|
-
).extract(@uri).should == {
|
588
|
-
"first" => "one",
|
589
|
-
"second" => "two"
|
590
|
-
}
|
622
|
+
class ExampleTwoProcessor
|
623
|
+
def self.restore(name, value)
|
624
|
+
return value.gsub(/-/, " ") if name == "query"
|
625
|
+
return value
|
591
626
|
end
|
592
627
|
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
Addressable::Template.new(
|
597
|
-
"http://example.com{-prefix|/|stuff}/"
|
598
|
-
).extract(@uri).should == {
|
599
|
-
"stuff" => ["one", "spacer", "two"]
|
600
|
-
}
|
628
|
+
def self.match(name)
|
629
|
+
return ".*?" if name == "first"
|
630
|
+
return ".*"
|
601
631
|
end
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
"'http://example.com/o{-prefix|/|stuff}/'" do
|
606
|
-
Addressable::Template.new(
|
607
|
-
"http://example.com/o{-prefix|/|stuff}/"
|
608
|
-
).extract(@uri).should == nil
|
632
|
+
def self.validate(name, value)
|
633
|
+
return !!(value =~ /^[\w ]+$/) if name == "query"
|
634
|
+
return true
|
609
635
|
end
|
610
636
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
Addressable::Template.new(
|
615
|
-
"http://example.com/{first}/spacer{-prefix|/|stuff}/"
|
616
|
-
).extract(@uri).should == {
|
617
|
-
"first" => "one",
|
618
|
-
"stuff" => "two"
|
619
|
-
}
|
637
|
+
def self.transform(name, value)
|
638
|
+
return value.gsub(/ /, "+") if name == "query"
|
639
|
+
return value
|
620
640
|
end
|
641
|
+
end
|
621
642
|
|
622
|
-
it "should not match anything when extracting values " +
|
623
|
-
"using the incorrect suffix pattern " +
|
624
|
-
"'http://example.com/{-prefix|/|stuff}/'" do
|
625
|
-
Addressable::Template.new(
|
626
|
-
"http://example.com/{-prefix|/|stuff}/"
|
627
|
-
).extract(@uri).should == nil
|
628
|
-
end
|
629
643
|
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
"rot13" => ["bar", "fcnpre", "gjb"]
|
644
|
+
describe Addressable::Template do
|
645
|
+
describe "Matching" do
|
646
|
+
let(:uri){
|
647
|
+
Addressable::URI.parse(
|
648
|
+
"http://example.com/search/an-example-search-query/"
|
649
|
+
)
|
637
650
|
}
|
638
|
-
|
639
|
-
|
640
|
-
it "should have the correct mapping when extracting values " +
|
641
|
-
"using the pattern " +
|
642
|
-
"'http://example.com{-prefix|/|rot13}' with the ExampleProcessor" do
|
643
|
-
Addressable::Template.new(
|
644
|
-
"http://example.com{-prefix|/|rot13}"
|
645
|
-
).extract(@uri, ExampleProcessor).should == {
|
646
|
-
"rot13" => ["bar", "fcnpre", "gjb", ""]
|
651
|
+
let(:uri2){
|
652
|
+
Addressable::URI.parse("http://example.com/a/b/c/")
|
647
653
|
}
|
648
|
-
|
654
|
+
let(:uri3){
|
655
|
+
Addressable::URI.parse("http://example.com/;a=1;b=2;c=3;first=foo")
|
656
|
+
}
|
657
|
+
let(:uri4){
|
658
|
+
Addressable::URI.parse("http://example.com/?a=1&b=2&c=3&first=foo")
|
659
|
+
}
|
660
|
+
context "first uri with ExampleTwoProcessor" do
|
661
|
+
subject{
|
662
|
+
match = Addressable::Template.new(
|
663
|
+
"http://example.com/search/{query}/"
|
664
|
+
).match(uri, ExampleTwoProcessor)
|
665
|
+
}
|
666
|
+
its(:variables){ should == ["query"]}
|
667
|
+
its(:captures){ should == ["an example search query"]}
|
668
|
+
end
|
649
669
|
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
670
|
+
context "second uri with ExampleTwoProcessor" do
|
671
|
+
subject{
|
672
|
+
match = Addressable::Template.new(
|
673
|
+
"http://example.com/{first}/{+second}/"
|
674
|
+
).match(uri2, ExampleTwoProcessor)
|
675
|
+
}
|
676
|
+
its(:variables){ should == ["first", "second"]}
|
677
|
+
its(:captures){ should == ["a", "b/c"] }
|
678
|
+
end
|
679
|
+
context "second uri" do
|
680
|
+
subject{
|
681
|
+
match = Addressable::Template.new(
|
682
|
+
"http://example.com/{first}{/second*}/"
|
683
|
+
).match(uri2)
|
684
|
+
}
|
685
|
+
its(:variables){ should == ["first", "second"]}
|
686
|
+
its(:captures){ should == ["a", ["b","c"]] }
|
687
|
+
end
|
688
|
+
context "third uri" do
|
689
|
+
subject{
|
690
|
+
match = Addressable::Template.new(
|
691
|
+
"http://example.com/{;hash*,first}"
|
692
|
+
).match(uri3)
|
693
|
+
}
|
694
|
+
its(:variables){ should == ["hash", "first"]}
|
695
|
+
its(:captures){ should == [
|
696
|
+
{"a" => "1", "b" => "2", "c" => "3", "first" => "foo"}, nil] }
|
697
|
+
end
|
698
|
+
context "fourth uri" do
|
699
|
+
subject{
|
700
|
+
match = Addressable::Template.new(
|
701
|
+
"http://example.com/{?hash*,first}"
|
702
|
+
).match(uri4)
|
703
|
+
}
|
704
|
+
its(:variables){ should == ["hash", "first"]}
|
705
|
+
its(:captures){ should == [
|
706
|
+
{"a" => "1", "b" => "2", "c" => "3", "first"=> "foo"}, nil] }
|
707
|
+
end
|
656
708
|
end
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
"http://example.com/{-suffix|/|stuff}"
|
663
|
-
).extract(@uri).should == {
|
664
|
-
"stuff" => ["one", "spacer", "two"]
|
709
|
+
describe "extract" do
|
710
|
+
let(:template) {
|
711
|
+
Addressable::Template.new(
|
712
|
+
"http://{host}{/segments*}/{?one,two,bogus}{#fragment}"
|
713
|
+
)
|
665
714
|
}
|
715
|
+
let(:uri){ "http://example.com/a/b/c/?one=1&two=2#foo" }
|
716
|
+
it "should be able to extract" do
|
717
|
+
template.extract(uri).should == {
|
718
|
+
"host" => "example.com",
|
719
|
+
"segments" => %w(a b c),
|
720
|
+
"one" => "1",
|
721
|
+
"bogus" => nil,
|
722
|
+
"two" => "2",
|
723
|
+
"fragment" => "foo"
|
724
|
+
}
|
725
|
+
end
|
666
726
|
end
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
"
|
673
|
-
|
727
|
+
describe "Partial expand" do
|
728
|
+
context "partial_expand with two simple values" do
|
729
|
+
subject{
|
730
|
+
Addressable::Template.new("http://example.com/{one}/{two}/")
|
731
|
+
}
|
732
|
+
it "builds a new pattern" do
|
733
|
+
subject.partial_expand("one" => "1").pattern.should ==
|
734
|
+
"http://example.com/1/{two}/"
|
735
|
+
end
|
736
|
+
end
|
737
|
+
context "partial_expand query with missing param in middle" do
|
738
|
+
subject{
|
739
|
+
Addressable::Template.new("http://example.com/{?one,two,three}/")
|
740
|
+
}
|
741
|
+
it "builds a new pattern" do
|
742
|
+
subject.partial_expand("one" => "1", "three" => "3").pattern.should ==
|
743
|
+
"http://example.com/?one=1{&two}&three=3/"
|
744
|
+
end
|
745
|
+
end
|
746
|
+
context "partial_expand with query string" do
|
747
|
+
subject{
|
748
|
+
Addressable::Template.new("http://example.com/{?two,one}/")
|
749
|
+
}
|
750
|
+
it "builds a new pattern" do
|
751
|
+
subject.partial_expand("one" => "1").pattern.should ==
|
752
|
+
"http://example.com/{?two}&one=1/"
|
753
|
+
end
|
754
|
+
end
|
755
|
+
context "partial_expand with path operator" do
|
756
|
+
subject{
|
757
|
+
Addressable::Template.new("http://example.com{/one,two}/")
|
758
|
+
}
|
759
|
+
it "builds a new pattern" do
|
760
|
+
subject.partial_expand("one" => "1").pattern.should ==
|
761
|
+
"http://example.com/1{/two}/"
|
762
|
+
end
|
763
|
+
end
|
674
764
|
end
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
"
|
681
|
-
|
765
|
+
describe "Expand" do
|
766
|
+
context "expand with a processor" do
|
767
|
+
subject{
|
768
|
+
Addressable::Template.new("http://example.com/search/{query}/")
|
769
|
+
}
|
770
|
+
it "processes spaces" do
|
771
|
+
subject.expand({"query" => "an example search query"},
|
772
|
+
ExampleTwoProcessor).to_str.should ==
|
773
|
+
"http://example.com/search/an+example+search+query/"
|
774
|
+
end
|
775
|
+
it "validates" do
|
776
|
+
lambda{
|
777
|
+
subject.expand({"query" => "Bogus!"},
|
778
|
+
ExampleTwoProcessor).to_str
|
779
|
+
}.should raise_error(Addressable::Template::InvalidTemplateValueError)
|
780
|
+
end
|
781
|
+
end
|
782
|
+
context "partial_expand query with missing param in middle" do
|
783
|
+
subject{
|
784
|
+
Addressable::Template.new("http://example.com/{?one,two,three}/")
|
785
|
+
}
|
786
|
+
it "builds a new pattern" do
|
787
|
+
subject.partial_expand("one" => "1", "three" => "3").pattern.should ==
|
788
|
+
"http://example.com/?one=1{&two}&three=3/"
|
789
|
+
end
|
790
|
+
end
|
791
|
+
context "partial_expand with query string" do
|
792
|
+
subject{
|
793
|
+
Addressable::Template.new("http://example.com/{?two,one}/")
|
794
|
+
}
|
795
|
+
it "builds a new pattern" do
|
796
|
+
subject.partial_expand("one" => "1").pattern.should ==
|
797
|
+
"http://example.com/{?two}&one=1/"
|
798
|
+
end
|
799
|
+
end
|
800
|
+
context "partial_expand with path operator" do
|
801
|
+
subject{
|
802
|
+
Addressable::Template.new("http://example.com{/one,two}/")
|
803
|
+
}
|
804
|
+
it "builds a new pattern" do
|
805
|
+
subject.partial_expand("one" => "1").pattern.should ==
|
806
|
+
"http://example.com/1{/two}/"
|
807
|
+
end
|
808
|
+
end
|
682
809
|
end
|
810
|
+
context "Matching with operators" do
|
811
|
+
describe "Level 1:" do
|
812
|
+
subject { Addressable::Template.new("foo{foo}/{bar}baz") }
|
813
|
+
it "can match" do
|
814
|
+
data = subject.match("foofoo/bananabaz")
|
815
|
+
data.mapping["foo"].should == "foo"
|
816
|
+
data.mapping["bar"].should == "banana"
|
817
|
+
end
|
818
|
+
it "lists vars" do
|
819
|
+
subject.variables.should == ["foo", "bar"]
|
820
|
+
end
|
821
|
+
end
|
683
822
|
|
684
|
-
|
685
|
-
|
686
|
-
"
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
"
|
692
|
-
|
693
|
-
|
823
|
+
describe "Level 2:" do
|
824
|
+
subject { Addressable::Template.new("foo{+foo}{#bar}baz") }
|
825
|
+
it "can match" do
|
826
|
+
data = subject.match("foo/test/banana#bazbaz")
|
827
|
+
data.mapping["foo"].should == "/test/banana"
|
828
|
+
data.mapping["bar"].should == "baz"
|
829
|
+
end
|
830
|
+
it "lists vars" do
|
831
|
+
subject.variables.should == ["foo", "bar"]
|
832
|
+
end
|
833
|
+
end
|
694
834
|
|
695
|
-
|
696
|
-
"
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
835
|
+
describe "Level 3:" do
|
836
|
+
context "no operator" do
|
837
|
+
subject { Addressable::Template.new("foo{foo,bar}baz") }
|
838
|
+
it "can match" do
|
839
|
+
data = subject.match("foofoo,barbaz")
|
840
|
+
data.mapping["foo"].should == "foo"
|
841
|
+
data.mapping["bar"].should == "bar"
|
842
|
+
end
|
843
|
+
it "lists vars" do
|
844
|
+
subject.variables.should == ["foo", "bar"]
|
845
|
+
end
|
846
|
+
end
|
847
|
+
context "+ operator" do
|
848
|
+
subject { Addressable::Template.new("foo{+foo,bar}baz") }
|
849
|
+
it "can match" do
|
850
|
+
data = subject.match("foofoo/bar,barbaz")
|
851
|
+
data.mapping["bar"].should == "foo/bar,bar"
|
852
|
+
data.mapping["foo"].should == ""
|
853
|
+
end
|
854
|
+
it "lists vars" do
|
855
|
+
subject.variables.should == ["foo", "bar"]
|
856
|
+
end
|
857
|
+
end
|
858
|
+
context ". operator" do
|
859
|
+
subject { Addressable::Template.new("foo{.foo,bar}baz") }
|
860
|
+
it "can match" do
|
861
|
+
data = subject.match("foo.foo.barbaz")
|
862
|
+
data.mapping["foo"].should == "foo"
|
863
|
+
data.mapping["bar"].should == "bar"
|
864
|
+
end
|
865
|
+
it "lists vars" do
|
866
|
+
subject.variables.should == ["foo", "bar"]
|
867
|
+
end
|
868
|
+
end
|
869
|
+
context "/ operator" do
|
870
|
+
subject { Addressable::Template.new("foo{/foo,bar}baz") }
|
871
|
+
it "can match" do
|
872
|
+
data = subject.match("foo/foo/barbaz")
|
873
|
+
data.mapping["foo"].should == "foo"
|
874
|
+
data.mapping["bar"].should == "bar"
|
875
|
+
end
|
876
|
+
it "lists vars" do
|
877
|
+
subject.variables.should == ["foo", "bar"]
|
878
|
+
end
|
879
|
+
end
|
880
|
+
context "; operator" do
|
881
|
+
subject { Addressable::Template.new("foo{;foo,bar,baz}baz") }
|
882
|
+
it "can match" do
|
883
|
+
data = subject.match("foo;foo=bar%20baz;bar=foo;bazbaz")
|
884
|
+
data.mapping["foo"].should == "bar baz"
|
885
|
+
data.mapping["bar"].should == "foo"
|
886
|
+
data.mapping["baz"].should == ""
|
887
|
+
end
|
888
|
+
it "lists vars" do
|
889
|
+
subject.variables.should == %w(foo bar baz)
|
890
|
+
end
|
891
|
+
end
|
892
|
+
context "? operator" do
|
893
|
+
context "test" do
|
894
|
+
subject { Addressable::Template.new("foo{?foo,bar}baz") }
|
895
|
+
it "can match" do
|
896
|
+
data = subject.match("foo?foo=bar%20baz&bar=foobaz")
|
897
|
+
data.mapping["foo"].should == "bar baz"
|
898
|
+
data.mapping["bar"].should == "foo"
|
899
|
+
end
|
900
|
+
it "lists vars" do
|
901
|
+
subject.variables.should == %w(foo bar)
|
902
|
+
end
|
903
|
+
end
|
904
|
+
context "issue #71" do
|
905
|
+
subject { Addressable::Template.new("http://cyberscore.dev/api/users{?username}") }
|
906
|
+
it "can match" do
|
907
|
+
data = subject.match("http://cyberscore.dev/api/users?username=foobaz")
|
908
|
+
data.mapping["username"].should == "foobaz"
|
909
|
+
end
|
910
|
+
it "lists vars" do
|
911
|
+
subject.variables.should == %w(username)
|
912
|
+
subject.keys.should == %w(username)
|
913
|
+
end
|
914
|
+
end
|
915
|
+
end
|
916
|
+
context "& operator" do
|
917
|
+
subject { Addressable::Template.new("foo{&foo,bar}baz") }
|
918
|
+
it "can match" do
|
919
|
+
data = subject.match("foo&foo=bar%20baz&bar=foobaz")
|
920
|
+
data.mapping["foo"].should == "bar baz"
|
921
|
+
data.mapping["bar"].should == "foo"
|
922
|
+
end
|
923
|
+
it "lists vars" do
|
924
|
+
subject.variables.should == %w(foo bar)
|
925
|
+
end
|
926
|
+
end
|
927
|
+
end
|
701
928
|
end
|
702
929
|
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
"
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
"
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
"
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
"
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
end
|
772
|
-
|
773
|
-
describe Addressable::URI, "when parsed from " +
|
774
|
-
"'http://example.com/?email='" do
|
775
|
-
before do
|
776
|
-
@uri = Addressable::URI.parse(
|
777
|
-
"http://example.com/?email="
|
778
|
-
)
|
779
|
-
end
|
780
|
-
|
781
|
-
it "should indicate a match when extracting values " +
|
782
|
-
"using the opt pattern " +
|
783
|
-
"'http://example.com/?email={-opt|bob@sporkmonger.com|test}'" do
|
784
|
-
Addressable::Template.new(
|
785
|
-
"http://example.com/?email={-opt|bob@sporkmonger.com|test}"
|
786
|
-
).extract(@uri).should == {}
|
787
|
-
end
|
788
|
-
|
789
|
-
it "should indicate a match when extracting values " +
|
790
|
-
"using the neg pattern " +
|
791
|
-
"'http://example.com/?email={-neg|bob@sporkmonger.com|test}'" do
|
792
|
-
Addressable::Template.new(
|
793
|
-
"http://example.com/?email={-neg|bob@sporkmonger.com|test}"
|
794
|
-
).extract(@uri).should == {}
|
795
|
-
end
|
796
|
-
end
|
797
|
-
|
798
|
-
describe Addressable::URI, "when parsed from " +
|
799
|
-
"'http://example.com/a/b/c/?one=1&two=2#foo'" do
|
800
|
-
before do
|
801
|
-
@uri = Addressable::URI.parse(
|
802
|
-
"http://example.com/a/b/c/?one=1&two=2#foo"
|
803
|
-
)
|
804
|
-
end
|
805
|
-
|
806
|
-
it "should have the correct mapping when extracting values " +
|
807
|
-
"using the pattern " +
|
808
|
-
"'http://{host}/{-suffix|/|segments}?{-join|&|one,two}\#{fragment}'" do
|
809
|
-
Addressable::Template.new(
|
810
|
-
"http://{host}/{-suffix|/|segments}?{-join|&|one,two}\#{fragment}"
|
811
|
-
).extract(@uri).should == {
|
812
|
-
"host" => "example.com",
|
813
|
-
"segments" => ["a", "b", "c"],
|
814
|
-
"one" => "1",
|
815
|
-
"two" => "2",
|
816
|
-
"fragment" => "foo"
|
817
|
-
}
|
818
|
-
end
|
819
|
-
|
820
|
-
it "should not match when extracting values " +
|
821
|
-
"using the pattern " +
|
822
|
-
"'http://{host}/{-suffix|/|segments}?{-join|&|one}\#{fragment}'" do
|
823
|
-
Addressable::Template.new(
|
824
|
-
"http://{host}/{-suffix|/|segments}?{-join|&|one}\#{fragment}"
|
825
|
-
).extract(@uri).should == nil
|
826
|
-
end
|
827
|
-
|
828
|
-
it "should not match when extracting values " +
|
829
|
-
"using the pattern " +
|
830
|
-
"'http://{host}/{-suffix|/|segments}?{-join|&|bogus}\#{fragment}'" do
|
831
|
-
Addressable::Template.new(
|
832
|
-
"http://{host}/{-suffix|/|segments}?{-join|&|bogus}\#{fragment}"
|
833
|
-
).extract(@uri).should == nil
|
834
|
-
end
|
835
|
-
|
836
|
-
it "should not match when extracting values " +
|
837
|
-
"using the pattern " +
|
838
|
-
"'http://{host}/{-suffix|/|segments}?" +
|
839
|
-
"{-join|&|one,bogus}\#{fragment}'" do
|
840
|
-
Addressable::Template.new(
|
841
|
-
"http://{host}/{-suffix|/|segments}?{-join|&|one,bogus}\#{fragment}"
|
842
|
-
).extract(@uri).should == nil
|
843
|
-
end
|
844
|
-
|
845
|
-
it "should not match when extracting values " +
|
846
|
-
"using the pattern " +
|
847
|
-
"'http://{host}/{-suffix|/|segments}?" +
|
848
|
-
"{-join|&|one,two,bogus}\#{fragment}'" do
|
849
|
-
Addressable::Template.new(
|
850
|
-
"http://{host}/{-suffix|/|segments}?{-join|&|one,two,bogus}\#{fragment}"
|
851
|
-
).extract(@uri).should == {
|
852
|
-
"host" => "example.com",
|
853
|
-
"segments" => ["a", "b", "c"],
|
854
|
-
"one" => "1",
|
855
|
-
"two" => "2",
|
856
|
-
"fragment" => "foo"
|
857
|
-
}
|
858
|
-
end
|
859
|
-
end
|
860
|
-
|
861
|
-
describe Addressable::URI, "when given a pattern with bogus operators" do
|
862
|
-
before do
|
863
|
-
@uri = Addressable::URI.parse("http://example.com/a/b/c/")
|
864
|
-
end
|
865
|
-
|
866
|
-
it "should raise an InvalidTemplateOperatorError" do
|
867
|
-
(lambda do
|
868
|
-
Addressable::Template.new(
|
869
|
-
"http://example.com/{-bogus|/|a,b,c}/"
|
870
|
-
).extract(@uri)
|
871
|
-
end).should raise_error(
|
872
|
-
Addressable::Template::InvalidTemplateOperatorError
|
873
|
-
)
|
874
|
-
end
|
875
|
-
|
876
|
-
it "should raise an InvalidTemplateOperatorError" do
|
877
|
-
(lambda do
|
878
|
-
Addressable::Template.new(
|
879
|
-
"http://example.com{-prefix|/|a,b,c}/"
|
880
|
-
).extract(@uri)
|
881
|
-
end).should raise_error(
|
882
|
-
Addressable::Template::InvalidTemplateOperatorError
|
883
|
-
)
|
884
|
-
end
|
885
|
-
|
886
|
-
it "should raise an InvalidTemplateOperatorError" do
|
887
|
-
(lambda do
|
888
|
-
Addressable::Template.new(
|
889
|
-
"http://example.com/{-suffix|/|a,b,c}"
|
890
|
-
).extract(@uri)
|
891
|
-
end).should raise_error(
|
892
|
-
Addressable::Template::InvalidTemplateOperatorError
|
893
|
-
)
|
894
|
-
end
|
895
|
-
|
896
|
-
it "should raise an InvalidTemplateOperatorError" do
|
897
|
-
(lambda do
|
898
|
-
Addressable::Template.new(
|
899
|
-
"http://example.com/{-list|/|a,b,c}/"
|
900
|
-
).extract(@uri)
|
901
|
-
end).should raise_error(
|
902
|
-
Addressable::Template::InvalidTemplateOperatorError
|
903
|
-
)
|
904
|
-
end
|
905
|
-
end
|
906
|
-
|
907
|
-
describe Addressable::URI, "when given a mapping that contains an Array" do
|
908
|
-
before do
|
909
|
-
@mapping = {"query" => "an example search query".split(" ")}
|
910
|
-
end
|
911
|
-
|
912
|
-
it "should result in 'http://example.com/search/an+example+search+query/'" +
|
913
|
-
" when used to expand 'http://example.com/search/{-list|+|query}/'" do
|
914
|
-
Addressable::Template.new(
|
915
|
-
"http://example.com/search/{-list|+|query}/"
|
916
|
-
).expand(@mapping).to_str.should ==
|
917
|
-
"http://example.com/search/an+example+search+query/"
|
918
|
-
end
|
919
|
-
|
920
|
-
it "should result in 'http://example.com/search/an+example+search+query/'" +
|
921
|
-
" when used to expand 'http://example.com/search/{-list|+|query}/'" +
|
922
|
-
" with a NoOpProcessor" do
|
923
|
-
Addressable::Template.new(
|
924
|
-
"http://example.com/search/{-list|+|query}/"
|
925
|
-
).expand(@mapping, NoOpProcessor).to_str.should ==
|
926
|
-
"http://example.com/search/an+example+search+query/"
|
927
|
-
end
|
928
|
-
end
|
929
|
-
|
930
|
-
describe Addressable::URI, "when given an empty mapping" do
|
931
|
-
before do
|
932
|
-
@mapping = {}
|
933
|
-
end
|
934
|
-
|
935
|
-
it "should result in 'http://example.com/search/'" +
|
936
|
-
" when used to expand 'http://example.com/search/{-list|+|query}'" do
|
937
|
-
Addressable::Template.new(
|
938
|
-
"http://example.com/search/{-list|+|query}"
|
939
|
-
).expand(@mapping).to_str.should == "http://example.com/search/"
|
940
|
-
end
|
941
|
-
|
942
|
-
it "should result in 'http://example.com'" +
|
943
|
-
" when used to expand 'http://example.com{-prefix|/|foo}'" do
|
944
|
-
Addressable::Template.new(
|
945
|
-
"http://example.com{-prefix|/|foo}"
|
946
|
-
).expand(@mapping).to_str.should == "http://example.com"
|
947
|
-
end
|
948
|
-
|
949
|
-
it "should result in 'http://example.com'" +
|
950
|
-
" when used to expand 'http://example.com{-suffix|/|foo}'" do
|
951
|
-
Addressable::Template.new(
|
952
|
-
"http://example.com{-suffix|/|foo}"
|
953
|
-
).expand(@mapping).to_str.should == "http://example.com"
|
954
|
-
end
|
955
|
-
end
|
956
|
-
|
957
|
-
describe Addressable::URI, "when given the template pattern " +
|
958
|
-
"'http://example.com/search/{query}/' " +
|
959
|
-
"to be processed with the ExampleProcessor" do
|
960
|
-
before do
|
961
|
-
@pattern = "http://example.com/search/{query}/"
|
962
|
-
end
|
963
|
-
|
964
|
-
it "should expand to " +
|
965
|
-
"'http://example.com/search/an+example+search+query/' " +
|
966
|
-
"with a mapping of {\"query\" => \"an example search query\"} " do
|
967
|
-
Addressable::Template.new(
|
968
|
-
"http://example.com/search/{query}/"
|
969
|
-
).expand({
|
970
|
-
"query" => "an example search query"
|
971
|
-
}, ExampleProcessor).to_s.should ==
|
972
|
-
"http://example.com/search/an+example+search+query/"
|
973
|
-
end
|
974
|
-
|
975
|
-
it "should raise an error " +
|
976
|
-
"with a mapping of {\"query\" => \"invalid!\"}" do
|
977
|
-
(lambda do
|
978
|
-
Addressable::Template.new(
|
979
|
-
"http://example.com/search/{query}/"
|
980
|
-
).expand({"query" => "invalid!"}, ExampleProcessor).to_s
|
981
|
-
end).should raise_error(Addressable::Template::InvalidTemplateValueError)
|
982
|
-
end
|
983
|
-
end
|
984
|
-
|
985
|
-
# Section 3.3.1 of the URI Template draft v 01
|
986
|
-
describe Addressable::URI, "when given the mapping supplied in " +
|
987
|
-
"Section 3.3.1 of the URI Template draft v 01" do
|
988
|
-
before do
|
989
|
-
@mapping = {
|
990
|
-
"a" => "fred",
|
991
|
-
"b" => "barney",
|
992
|
-
"c" => "cheeseburger",
|
993
|
-
"d" => "one two three",
|
994
|
-
"e" => "20% tricky",
|
995
|
-
"f" => "",
|
996
|
-
"20" => "this-is-spinal-tap",
|
997
|
-
"scheme" => "https",
|
998
|
-
"p" => "quote=to+be+or+not+to+be",
|
999
|
-
"q" => "hullo#world"
|
1000
|
-
}
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
it "should result in 'http://example.org/page1#fred' " +
|
1004
|
-
"when used to expand 'http://example.org/page1\#{a}'" do
|
1005
|
-
Addressable::Template.new(
|
1006
|
-
"http://example.org/page1\#{a}"
|
1007
|
-
).expand(@mapping).to_s.should == "http://example.org/page1#fred"
|
1008
|
-
end
|
1009
|
-
|
1010
|
-
it "should result in 'http://example.org/fred/barney/' " +
|
1011
|
-
"when used to expand 'http://example.org/{a}/{b}/'" do
|
1012
|
-
Addressable::Template.new(
|
1013
|
-
"http://example.org/{a}/{b}/"
|
1014
|
-
).expand(@mapping).to_s.should == "http://example.org/fred/barney/"
|
1015
|
-
end
|
1016
|
-
|
1017
|
-
it "should result in 'http://example.org/fredbarney/' " +
|
1018
|
-
"when used to expand 'http://example.org/{a}{b}/'" do
|
1019
|
-
Addressable::Template.new(
|
1020
|
-
"http://example.org/{a}{b}/"
|
1021
|
-
).expand(@mapping).to_s.should == "http://example.org/fredbarney/"
|
1022
|
-
end
|
1023
|
-
|
1024
|
-
it "should result in " +
|
1025
|
-
"'http://example.com/order/cheeseburger/cheeseburger/cheeseburger/' " +
|
1026
|
-
"when used to expand 'http://example.com/order/{c}/{c}/{c}/'" do
|
1027
|
-
Addressable::Template.new(
|
1028
|
-
"http://example.com/order/{c}/{c}/{c}/"
|
1029
|
-
).expand(@mapping).to_s.should ==
|
1030
|
-
"http://example.com/order/cheeseburger/cheeseburger/cheeseburger/"
|
1031
|
-
end
|
1032
|
-
|
1033
|
-
it "should result in 'http://example.org/one%20two%20three' " +
|
1034
|
-
"when used to expand 'http://example.org/{d}'" do
|
1035
|
-
Addressable::Template.new(
|
1036
|
-
"http://example.org/{d}"
|
1037
|
-
).expand(@mapping).to_s.should ==
|
1038
|
-
"http://example.org/one%20two%20three"
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
it "should result in 'http://example.org/20%25%20tricky' " +
|
1042
|
-
"when used to expand 'http://example.org/{e}'" do
|
1043
|
-
Addressable::Template.new(
|
1044
|
-
"http://example.org/{e}"
|
1045
|
-
).expand(@mapping).to_s.should ==
|
1046
|
-
"http://example.org/20%25%20tricky"
|
1047
|
-
end
|
1048
|
-
|
1049
|
-
it "should result in 'http://example.com//' " +
|
1050
|
-
"when used to expand 'http://example.com/{f}/'" do
|
1051
|
-
Addressable::Template.new(
|
1052
|
-
"http://example.com/{f}/"
|
1053
|
-
).expand(@mapping).to_s.should ==
|
1054
|
-
"http://example.com//"
|
1055
|
-
end
|
1056
|
-
|
1057
|
-
it "should result in " +
|
1058
|
-
"'https://this-is-spinal-tap.example.org?date=&option=fred' " +
|
1059
|
-
"when used to expand " +
|
1060
|
-
"'{scheme}://{20}.example.org?date={wilma}&option={a}'" do
|
1061
|
-
Addressable::Template.new(
|
1062
|
-
"{scheme}://{20}.example.org?date={wilma}&option={a}"
|
1063
|
-
).expand(@mapping).to_s.should ==
|
1064
|
-
"https://this-is-spinal-tap.example.org?date=&option=fred"
|
1065
|
-
end
|
1066
|
-
|
1067
|
-
# The v 01 draft conflicts with the v 03 draft here.
|
1068
|
-
# The Addressable implementation uses v 03.
|
1069
|
-
it "should result in " +
|
1070
|
-
"'http://example.org?quote%3Dto%2Bbe%2Bor%2Bnot%2Bto%2Bbe' " +
|
1071
|
-
"when used to expand 'http://example.org?{p}'" do
|
1072
|
-
Addressable::Template.new(
|
1073
|
-
"http://example.org?{p}"
|
1074
|
-
).expand(@mapping).to_s.should ==
|
1075
|
-
"http://example.org?quote%3Dto%2Bbe%2Bor%2Bnot%2Bto%2Bbe"
|
1076
|
-
end
|
1077
|
-
|
1078
|
-
# The v 01 draft conflicts with the v 03 draft here.
|
1079
|
-
# The Addressable implementation uses v 03.
|
1080
|
-
it "should result in 'http://example.com/hullo%23world' " +
|
1081
|
-
"when used to expand 'http://example.com/{q}'" do
|
1082
|
-
Addressable::Template.new(
|
1083
|
-
"http://example.com/{q}"
|
1084
|
-
).expand(@mapping).to_s.should == "http://example.com/hullo%23world"
|
1085
|
-
end
|
1086
|
-
end
|
1087
|
-
|
1088
|
-
# Section 4.5 of the URI Template draft v 03
|
1089
|
-
describe Addressable::URI, "when given the mapping supplied in " +
|
1090
|
-
"Section 4.5 of the URI Template draft v 03" do
|
1091
|
-
before do
|
1092
|
-
@mapping = {
|
1093
|
-
"foo" => "ϓ",
|
1094
|
-
"bar" => "fred",
|
1095
|
-
"baz" => "10,20,30",
|
1096
|
-
"qux" => ["10","20","30"],
|
1097
|
-
"corge" => [],
|
1098
|
-
"grault" => "",
|
1099
|
-
"garply" => "a/b/c",
|
1100
|
-
"waldo" => "ben & jerrys",
|
1101
|
-
"fred" => ["fred", "", "wilma"],
|
1102
|
-
"plugh" => ["ẛ", "ṡ"],
|
1103
|
-
"1-a_b.c" => "200"
|
1104
|
-
}
|
1105
|
-
end
|
1106
|
-
|
1107
|
-
it "should result in 'http://example.org/?q=fred' " +
|
1108
|
-
"when used to expand 'http://example.org/?q={bar}'" do
|
1109
|
-
Addressable::Template.new(
|
1110
|
-
"http://example.org/?q={bar}"
|
1111
|
-
).expand(@mapping).to_s.should == "http://example.org/?q=fred"
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
it "should result in '/' " +
|
1115
|
-
"when used to expand '/{xyzzy}'" do
|
1116
|
-
Addressable::Template.new(
|
1117
|
-
"/{xyzzy}"
|
1118
|
-
).expand(@mapping).to_s.should == "/"
|
1119
|
-
end
|
1120
|
-
|
1121
|
-
it "should result in " +
|
1122
|
-
"'http://example.org/?foo=%CE%8E&bar=fred&baz=10%2C20%2C30' " +
|
1123
|
-
"when used to expand " +
|
1124
|
-
"'http://example.org/?{-join|&|foo,bar,xyzzy,baz}'" do
|
1125
|
-
Addressable::Template.new(
|
1126
|
-
"http://example.org/?{-join|&|foo,bar,xyzzy,baz}"
|
1127
|
-
).expand(@mapping).to_s.should ==
|
1128
|
-
"http://example.org/?foo=%CE%8E&bar=fred&baz=10%2C20%2C30"
|
1129
|
-
end
|
1130
|
-
|
1131
|
-
it "should result in 'http://example.org/?d=10,20,30' " +
|
1132
|
-
"when used to expand 'http://example.org/?d={-list|,|qux}'" do
|
1133
|
-
Addressable::Template.new(
|
1134
|
-
"http://example.org/?d={-list|,|qux}"
|
1135
|
-
).expand(
|
1136
|
-
@mapping
|
1137
|
-
).to_s.should == "http://example.org/?d=10,20,30"
|
1138
|
-
end
|
1139
|
-
|
1140
|
-
it "should result in 'http://example.org/?d=10&d=20&d=30' " +
|
1141
|
-
"when used to expand 'http://example.org/?d={-list|&d=|qux}'" do
|
1142
|
-
Addressable::Template.new(
|
1143
|
-
"http://example.org/?d={-list|&d=|qux}"
|
1144
|
-
).expand(
|
1145
|
-
@mapping
|
1146
|
-
).to_s.should == "http://example.org/?d=10&d=20&d=30"
|
1147
|
-
end
|
1148
|
-
|
1149
|
-
it "should result in 'http://example.org/fredfred/a%2Fb%2Fc' " +
|
1150
|
-
"when used to expand 'http://example.org/{bar}{bar}/{garply}'" do
|
1151
|
-
Addressable::Template.new(
|
1152
|
-
"http://example.org/{bar}{bar}/{garply}"
|
1153
|
-
).expand(
|
1154
|
-
@mapping
|
1155
|
-
).to_s.should == "http://example.org/fredfred/a%2Fb%2Fc"
|
1156
|
-
end
|
1157
|
-
|
1158
|
-
it "should result in 'http://example.org/fred/fred//wilma' " +
|
1159
|
-
"when used to expand 'http://example.org/{bar}{-prefix|/|fred}'" do
|
1160
|
-
Addressable::Template.new(
|
1161
|
-
"http://example.org/{bar}{-prefix|/|fred}"
|
1162
|
-
).expand(
|
1163
|
-
@mapping
|
1164
|
-
).to_s.should == "http://example.org/fred/fred//wilma"
|
1165
|
-
end
|
1166
|
-
|
1167
|
-
it "should result in ':%E1%B9%A1:%E1%B9%A1:' " +
|
1168
|
-
"when used to expand '{-neg|:|corge}{-suffix|:|plugh}'" do
|
1169
|
-
# Note: We need to check the path, because technically, this is an
|
1170
|
-
# invalid URI.
|
1171
|
-
Addressable::Template.new(
|
1172
|
-
"{-neg|:|corge}{-suffix|:|plugh}"
|
1173
|
-
).expand(@mapping).path.should == ":%E1%B9%A1:%E1%B9%A1:"
|
1174
|
-
end
|
1175
|
-
|
1176
|
-
it "should result in '../ben%20%26%20jerrys/' " +
|
1177
|
-
"when used to expand '../{waldo}/'" do
|
1178
|
-
Addressable::Template.new(
|
1179
|
-
"../{waldo}/"
|
1180
|
-
).expand(
|
1181
|
-
@mapping
|
1182
|
-
).to_s.should == "../ben%20%26%20jerrys/"
|
1183
|
-
end
|
1184
|
-
|
1185
|
-
it "should result in 'telnet:192.0.2.16:80' " +
|
1186
|
-
"when used to expand 'telnet:192.0.2.16{-opt|:80|grault}'" do
|
1187
|
-
Addressable::Template.new(
|
1188
|
-
"telnet:192.0.2.16{-opt|:80|grault}"
|
1189
|
-
).expand(
|
1190
|
-
@mapping
|
1191
|
-
).to_s.should == "telnet:192.0.2.16:80"
|
1192
|
-
end
|
1193
|
-
|
1194
|
-
it "should result in ':200:' " +
|
1195
|
-
"when used to expand ':{1-a_b.c}:'" do
|
1196
|
-
# Note: We need to check the path, because technically, this is an
|
1197
|
-
# invalid URI.
|
1198
|
-
Addressable::Template.new(
|
1199
|
-
":{1-a_b.c}:"
|
1200
|
-
).expand(@mapping).path.should == ":200:"
|
1201
|
-
end
|
1202
|
-
end
|
1203
|
-
|
1204
|
-
describe Addressable::URI, "when given a mapping that contains a " +
|
1205
|
-
"template-var within a value" do
|
1206
|
-
before do
|
1207
|
-
@mapping = {
|
1208
|
-
"a" => "{b}",
|
1209
|
-
"b" => "barney",
|
1210
|
-
}
|
1211
|
-
end
|
1212
|
-
|
1213
|
-
it "should result in 'http://example.com/%7Bb%7D/barney/' " +
|
1214
|
-
"when used to expand 'http://example.com/{a}/{b}/'" do
|
1215
|
-
Addressable::Template.new(
|
1216
|
-
"http://example.com/{a}/{b}/"
|
1217
|
-
).expand(
|
1218
|
-
@mapping
|
1219
|
-
).to_s.should == "http://example.com/%7Bb%7D/barney/"
|
1220
|
-
end
|
1221
|
-
|
1222
|
-
it "should result in 'http://example.com//%7Bb%7D/' " +
|
1223
|
-
"when used to expand 'http://example.com/{-opt|foo|foo}/{a}/'" do
|
1224
|
-
Addressable::Template.new(
|
1225
|
-
"http://example.com/{-opt|foo|foo}/{a}/"
|
1226
|
-
).expand(
|
1227
|
-
@mapping
|
1228
|
-
).to_s.should == "http://example.com//%7Bb%7D/"
|
1229
|
-
end
|
1230
|
-
|
1231
|
-
it "should result in 'http://example.com//%7Bb%7D/' " +
|
1232
|
-
"when used to expand 'http://example.com/{-neg|foo|b}/{a}/'" do
|
1233
|
-
Addressable::Template.new(
|
1234
|
-
"http://example.com/{-neg|foo|b}/{a}/"
|
1235
|
-
).expand(
|
1236
|
-
@mapping
|
1237
|
-
).to_s.should == "http://example.com//%7Bb%7D/"
|
1238
|
-
end
|
1239
|
-
|
1240
|
-
it "should result in 'http://example.com//barney/%7Bb%7D/' " +
|
1241
|
-
"when used to expand 'http://example.com/{-prefix|/|b}/{a}/'" do
|
1242
|
-
Addressable::Template.new(
|
1243
|
-
"http://example.com/{-prefix|/|b}/{a}/"
|
1244
|
-
).expand(
|
1245
|
-
@mapping
|
1246
|
-
).to_s.should == "http://example.com//barney/%7Bb%7D/"
|
1247
|
-
end
|
1248
|
-
|
1249
|
-
it "should result in 'http://example.com/barney//%7Bb%7D/' " +
|
1250
|
-
"when used to expand 'http://example.com/{-suffix|/|b}/{a}/'" do
|
1251
|
-
Addressable::Template.new(
|
1252
|
-
"http://example.com/{-suffix|/|b}/{a}/"
|
1253
|
-
).expand(
|
1254
|
-
@mapping
|
1255
|
-
).to_s.should == "http://example.com/barney//%7Bb%7D/"
|
1256
|
-
end
|
1257
|
-
|
1258
|
-
it "should result in 'http://example.com/%7Bb%7D/?b=barney&c=42' " +
|
1259
|
-
"when used to expand 'http://example.com/{a}/?{-join|&|b,c=42}'" do
|
1260
|
-
Addressable::Template.new(
|
1261
|
-
"http://example.com/{a}/?{-join|&|b,c=42}"
|
1262
|
-
).expand(
|
1263
|
-
@mapping
|
1264
|
-
).to_s.should == "http://example.com/%7Bb%7D/?b=barney&c=42"
|
1265
|
-
end
|
1266
|
-
|
1267
|
-
it "should result in 'http://example.com/42/?b=barney' " +
|
1268
|
-
"when used to expand 'http://example.com/{c=42}/?{-join|&|b}'" do
|
1269
|
-
Addressable::Template.new(
|
1270
|
-
"http://example.com/{c=42}/?{-join|&|b}"
|
1271
|
-
).expand(@mapping).to_s.should == "http://example.com/42/?b=barney"
|
1272
|
-
end
|
1273
|
-
end
|
1274
|
-
|
1275
|
-
describe Addressable::URI, "when given a single variable mapping" do
|
1276
|
-
before do
|
1277
|
-
@mapping = {
|
1278
|
-
"foo" => "fred"
|
1279
|
-
}
|
1280
|
-
end
|
1281
|
-
|
1282
|
-
it "should result in 'fred' when used to expand '{foo}'" do
|
1283
|
-
Addressable::Template.new(
|
1284
|
-
"{foo}"
|
1285
|
-
).expand(@mapping).to_s.should == "fred"
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
it "should result in 'wilma' when used to expand '{bar=wilma}'" do
|
1289
|
-
Addressable::Template.new(
|
1290
|
-
"{bar=wilma}"
|
1291
|
-
).expand(@mapping).to_s.should == "wilma"
|
1292
|
-
end
|
1293
|
-
|
1294
|
-
it "should result in '' when used to expand '{baz}'" do
|
1295
|
-
Addressable::Template.new(
|
1296
|
-
"{baz}"
|
1297
|
-
).expand(@mapping).to_s.should == ""
|
1298
|
-
end
|
1299
|
-
end
|
1300
|
-
|
1301
|
-
describe Addressable::URI, "when given a simple mapping" do
|
1302
|
-
before do
|
1303
|
-
@mapping = {
|
1304
|
-
"foo" => "fred",
|
1305
|
-
"bar" => "barney",
|
1306
|
-
"baz" => ""
|
1307
|
-
}
|
1308
|
-
end
|
1309
|
-
|
1310
|
-
it "should result in 'foo=fred&bar=barney&baz=' when used to expand " +
|
1311
|
-
"'{-join|&|foo,bar,baz,qux}'" do
|
1312
|
-
Addressable::Template.new(
|
1313
|
-
"{-join|&|foo,bar,baz,qux}"
|
1314
|
-
).expand(@mapping).to_s.should == "foo=fred&bar=barney&baz="
|
1315
|
-
end
|
1316
|
-
|
1317
|
-
it "should result in 'bar=barney' when used to expand " +
|
1318
|
-
"'{-join|&|bar}'" do
|
1319
|
-
Addressable::Template.new(
|
1320
|
-
"{-join|&|bar}"
|
1321
|
-
).expand(@mapping).to_s.should == "bar=barney"
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
it "should result in '' when used to expand " +
|
1325
|
-
"'{-join|&|qux}'" do
|
1326
|
-
Addressable::Template.new(
|
1327
|
-
"{-join|&|qux}"
|
1328
|
-
).expand(@mapping).to_s.should == ""
|
1329
|
-
end
|
1330
|
-
end
|
1331
|
-
|
1332
|
-
describe Addressable::URI, "extracting defaults from a pattern" do
|
1333
|
-
before do
|
1334
|
-
@template = Addressable::Template.new("{foo}{bar=baz}{-opt|found|cond}")
|
1335
|
-
end
|
1336
|
-
|
1337
|
-
it "should extract default value" do
|
1338
|
-
@template.variable_defaults.should == {"bar" => "baz"}
|
1339
|
-
end
|
1340
|
-
end
|
1341
|
-
|
1342
|
-
describe Addressable::URI, "when given a mapping with symbol keys" do
|
1343
|
-
before do
|
1344
|
-
@mapping = { :name => "fred" }
|
1345
|
-
end
|
1346
|
-
|
1347
|
-
it "should result in 'fred' when used to expand '{foo}'" do
|
1348
|
-
Addressable::Template.new(
|
1349
|
-
"{name}"
|
1350
|
-
).expand(@mapping).to_s.should == "fred"
|
1351
|
-
end
|
1352
|
-
end
|
1353
|
-
|
1354
|
-
describe Addressable::URI, "when given a mapping with bogus keys" do
|
1355
|
-
before do
|
1356
|
-
@mapping = { Object.new => "fred" }
|
1357
|
-
end
|
1358
|
-
|
1359
|
-
it "should raise an error" do
|
1360
|
-
(lambda do
|
1361
|
-
Addressable::Template.new(
|
1362
|
-
"{name}"
|
1363
|
-
).expand(@mapping)
|
1364
|
-
end).should raise_error(TypeError)
|
1365
|
-
end
|
1366
|
-
end
|
1367
|
-
|
1368
|
-
describe Addressable::URI, "when given a mapping with numeric values" do
|
1369
|
-
before do
|
1370
|
-
@mapping = { :id => 123 }
|
1371
|
-
end
|
1372
|
-
|
1373
|
-
it "should result in 'fred' when used to expand '{foo}'" do
|
1374
|
-
Addressable::Template.new(
|
1375
|
-
"{id}"
|
1376
|
-
).expand(@mapping).to_s.should == "123"
|
1377
|
-
end
|
1378
|
-
end
|
1379
|
-
|
1380
|
-
describe Addressable::URI, "when given a mapping containing values " +
|
1381
|
-
"that are already percent-encoded" do
|
1382
|
-
before do
|
1383
|
-
@mapping = {
|
1384
|
-
"a" => "%7Bb%7D"
|
1385
|
-
}
|
1386
|
-
end
|
1387
|
-
|
1388
|
-
it "should result in 'http://example.com/%257Bb%257D/' " +
|
1389
|
-
"when used to expand 'http://example.com/{a}/'" do
|
1390
|
-
Addressable::Template.new(
|
1391
|
-
"http://example.com/{a}/"
|
1392
|
-
).expand(@mapping).to_s.should == "http://example.com/%257Bb%257D/"
|
1393
|
-
end
|
1394
|
-
end
|
1395
|
-
|
1396
|
-
describe Addressable::URI, "when given a pattern with bogus operators" do
|
1397
|
-
it "should raise an InvalidTemplateOperatorError" do
|
1398
|
-
(lambda do
|
1399
|
-
Addressable::Template.new(
|
1400
|
-
"http://example.com/{-bogus|/|a,b,c}/"
|
1401
|
-
).expand({
|
1402
|
-
"a" => "a", "b" => "b", "c" => "c"
|
1403
|
-
})
|
1404
|
-
end).should raise_error(
|
1405
|
-
Addressable::Template::InvalidTemplateOperatorError
|
1406
|
-
)
|
1407
|
-
end
|
1408
|
-
|
1409
|
-
it "should raise an InvalidTemplateOperatorError" do
|
1410
|
-
(lambda do
|
1411
|
-
Addressable::Template.new(
|
1412
|
-
"http://example.com/{-prefix|/|a,b,c}/"
|
1413
|
-
).expand({
|
1414
|
-
"a" => "a", "b" => "b", "c" => "c"
|
1415
|
-
})
|
1416
|
-
end).should raise_error(
|
1417
|
-
Addressable::Template::InvalidTemplateOperatorError
|
1418
|
-
)
|
1419
|
-
end
|
1420
|
-
|
1421
|
-
it "should raise an InvalidTemplateOperatorError" do
|
1422
|
-
(lambda do
|
1423
|
-
Addressable::Template.new(
|
1424
|
-
"http://example.com/{-suffix|/|a,b,c}/"
|
1425
|
-
).expand({
|
1426
|
-
"a" => "a", "b" => "b", "c" => "c"
|
1427
|
-
})
|
1428
|
-
end).should raise_error(
|
1429
|
-
Addressable::Template::InvalidTemplateOperatorError
|
1430
|
-
)
|
1431
|
-
end
|
1432
|
-
|
1433
|
-
it "should raise an InvalidTemplateOperatorError" do
|
1434
|
-
(lambda do
|
1435
|
-
Addressable::Template.new(
|
1436
|
-
"http://example.com/{-join|/|a,b,c}/"
|
1437
|
-
).expand({
|
1438
|
-
"a" => ["a"], "b" => ["b"], "c" => "c"
|
1439
|
-
})
|
1440
|
-
end).should raise_error(
|
1441
|
-
Addressable::Template::InvalidTemplateOperatorError
|
1442
|
-
)
|
1443
|
-
end
|
1444
|
-
|
1445
|
-
it "should raise an InvalidTemplateOperatorError" do
|
1446
|
-
(lambda do
|
1447
|
-
Addressable::Template.new(
|
1448
|
-
"http://example.com/{-list|/|a,b,c}/"
|
1449
|
-
).expand({
|
1450
|
-
"a" => ["a"], "b" => ["b"], "c" => "c"
|
1451
|
-
})
|
1452
|
-
end).should raise_error(
|
1453
|
-
Addressable::Template::InvalidTemplateOperatorError
|
1454
|
-
)
|
1455
|
-
end
|
1456
|
-
end
|
1457
|
-
|
1458
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1459
|
-
before do
|
1460
|
-
@initial_template = Addressable::Template.new(
|
1461
|
-
"http://example.com/{one}/{two}/"
|
1462
|
-
)
|
1463
|
-
@partial_template = @initial_template.partial_expand({"one" => "1"})
|
1464
|
-
end
|
1465
|
-
|
1466
|
-
it "should produce the same result when fully expanded" do
|
1467
|
-
@initial_template.expand({"one" => "1", "two" => "2"}).should ==
|
1468
|
-
@partial_template.expand({"two" => "2"})
|
1469
|
-
end
|
1470
|
-
|
1471
|
-
it "should raise an error if the template is expanded with bogus values" do
|
1472
|
-
(lambda do
|
1473
|
-
@initial_template.expand({"one" => Object.new, "two" => Object.new})
|
1474
|
-
end).should raise_error(TypeError)
|
1475
|
-
(lambda do
|
1476
|
-
@partial_template.expand({"two" => Object.new})
|
1477
|
-
end).should raise_error(TypeError)
|
1478
|
-
end
|
1479
|
-
end
|
1480
|
-
|
1481
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1482
|
-
before do
|
1483
|
-
@initial_template = Addressable::Template.new(
|
1484
|
-
"http://example.com/{one}/{two}/"
|
1485
|
-
)
|
1486
|
-
@partial_template = @initial_template.partial_expand({"two" => "2"})
|
1487
|
-
end
|
1488
|
-
|
1489
|
-
it "should produce the same result when fully expanded" do
|
1490
|
-
@initial_template.expand({"one" => "1", "two" => "2"}).should ==
|
1491
|
-
@partial_template.expand({"one" => "1"})
|
1492
|
-
end
|
1493
|
-
end
|
1494
|
-
|
1495
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1496
|
-
before do
|
1497
|
-
@initial_template = Addressable::Template.new(
|
1498
|
-
"http://example.com/{one}/{two}/"
|
1499
|
-
)
|
1500
|
-
@partial_template = @initial_template.partial_expand({"two" => "2"})
|
1501
|
-
end
|
1502
|
-
|
1503
|
-
it "should produce the same result when fully expanded" do
|
1504
|
-
@initial_template.expand({"one" => "1", "two" => "2"}).should ==
|
1505
|
-
@partial_template.expand({"one" => "1"})
|
1506
|
-
end
|
1507
|
-
end
|
1508
|
-
|
1509
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1510
|
-
before do
|
1511
|
-
@initial_template = Addressable::Template.new(
|
1512
|
-
"http://example.com/{one=1}/{two=2}/"
|
1513
|
-
)
|
1514
|
-
@partial_template = @initial_template.partial_expand({"one" => "3"})
|
1515
|
-
end
|
1516
|
-
|
1517
|
-
it "should produce the same result when fully expanded" do
|
1518
|
-
@initial_template.expand({"one" => "3", "two" => "4"}).should ==
|
1519
|
-
@partial_template.expand({"two" => "4"})
|
1520
|
-
end
|
1521
|
-
|
1522
|
-
it "should produce the correct result when fully expanded" do
|
1523
|
-
@partial_template.expand({}).should === "http://example.com/3/2/"
|
1524
|
-
end
|
1525
|
-
end
|
1526
|
-
|
1527
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1528
|
-
before do
|
1529
|
-
@initial_template = Addressable::Template.new(
|
1530
|
-
"http://example.com/{one=1}/{two=2}/"
|
1531
|
-
)
|
1532
|
-
@partial_template = @initial_template.partial_expand({"two" => "4"})
|
1533
|
-
end
|
1534
|
-
|
1535
|
-
it "should produce the same result when fully expanded" do
|
1536
|
-
@initial_template.expand({"one" => "3", "two" => "4"}).should ==
|
1537
|
-
@partial_template.expand({"one" => "3"})
|
1538
|
-
end
|
1539
|
-
|
1540
|
-
it "should produce the correct result when fully expanded" do
|
1541
|
-
@partial_template.expand({}).should === "http://example.com/1/4/"
|
1542
|
-
end
|
1543
|
-
end
|
1544
|
-
|
1545
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1546
|
-
before do
|
1547
|
-
@initial_template = Addressable::Template.new(
|
1548
|
-
"http://example.com/{-opt|found|one,two,three}"
|
1549
|
-
)
|
1550
|
-
@partial_template = @initial_template.partial_expand({})
|
1551
|
-
end
|
1552
|
-
|
1553
|
-
it "should produce the same result when fully expanded" do
|
1554
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1555
|
-
@partial_template.expand({"two" => "2"}).to_str
|
1556
|
-
end
|
1557
|
-
|
1558
|
-
it "should produce the correct result when fully expanded" do
|
1559
|
-
@partial_template.expand({}).to_str.should == "http://example.com/"
|
1560
|
-
end
|
1561
|
-
|
1562
|
-
it "should produce the correct result when fully expanded" do
|
1563
|
-
@partial_template.expand({"one" => "1"}).to_str.should ==
|
1564
|
-
"http://example.com/found"
|
1565
|
-
end
|
1566
|
-
|
1567
|
-
it "should produce the correct result when fully expanded" do
|
1568
|
-
@partial_template.expand({"two" => "2"}).to_str.should ==
|
1569
|
-
"http://example.com/found"
|
1570
|
-
end
|
1571
|
-
|
1572
|
-
it "should produce the correct result when fully expanded" do
|
1573
|
-
@partial_template.expand({"three" => "3"}).to_str.should ==
|
1574
|
-
"http://example.com/found"
|
1575
|
-
end
|
1576
|
-
|
1577
|
-
it "should produce the correct result when fully expanded" do
|
1578
|
-
@partial_template.expand({"four" => "4"}).to_str.should ==
|
1579
|
-
"http://example.com/"
|
1580
|
-
end
|
1581
|
-
|
1582
|
-
it "should produce the correct result when fully expanded" do
|
1583
|
-
@partial_template.expand({"one" => "1", "two" => "2"}).to_str.should ==
|
1584
|
-
"http://example.com/found"
|
1585
|
-
end
|
1586
|
-
end
|
1587
|
-
|
1588
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1589
|
-
before do
|
1590
|
-
@initial_template = Addressable::Template.new(
|
1591
|
-
"http://example.com/{-opt|found|one,two,three}"
|
1592
|
-
)
|
1593
|
-
@partial_template = @initial_template.partial_expand({"one" => "1"})
|
1594
|
-
end
|
1595
|
-
|
1596
|
-
it "should produce the same result when fully expanded" do
|
1597
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1598
|
-
@partial_template.expand({"two" => "2"}).to_str
|
1599
|
-
end
|
1600
|
-
|
1601
|
-
it "should produce the correct result when fully expanded" do
|
1602
|
-
@partial_template.expand({}).to_str.should == "http://example.com/found"
|
1603
|
-
end
|
1604
|
-
|
1605
|
-
it "should produce the correct pattern" do
|
1606
|
-
@partial_template.pattern.should == "http://example.com/found"
|
1607
|
-
end
|
1608
|
-
end
|
1609
|
-
|
1610
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1611
|
-
before do
|
1612
|
-
@initial_template = Addressable::Template.new(
|
1613
|
-
"http://example.com/{-neg|notfound|one,two,three}"
|
1614
|
-
)
|
1615
|
-
@partial_template = @initial_template.partial_expand({})
|
1616
|
-
end
|
1617
|
-
|
1618
|
-
it "should produce the same result when fully expanded" do
|
1619
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1620
|
-
@partial_template.expand({"two" => "2"}).to_str
|
1621
|
-
end
|
1622
|
-
|
1623
|
-
it "should produce the correct result when fully expanded" do
|
1624
|
-
@partial_template.expand({}).to_str.should == "http://example.com/notfound"
|
1625
|
-
end
|
1626
|
-
|
1627
|
-
it "should produce the correct result when fully expanded" do
|
1628
|
-
@partial_template.expand({"one" => "1"}).to_str.should ==
|
1629
|
-
"http://example.com/"
|
1630
|
-
end
|
1631
|
-
|
1632
|
-
it "should produce the correct result when fully expanded" do
|
1633
|
-
@partial_template.expand({"two" => "2"}).to_str.should ==
|
1634
|
-
"http://example.com/"
|
1635
|
-
end
|
1636
|
-
|
1637
|
-
it "should produce the correct result when fully expanded" do
|
1638
|
-
@partial_template.expand({"three" => "3"}).to_str.should ==
|
1639
|
-
"http://example.com/"
|
1640
|
-
end
|
1641
|
-
|
1642
|
-
it "should produce the correct result when fully expanded" do
|
1643
|
-
@partial_template.expand({"four" => "4"}).to_str.should ==
|
1644
|
-
"http://example.com/notfound"
|
1645
|
-
end
|
1646
|
-
|
1647
|
-
it "should produce the correct result when fully expanded" do
|
1648
|
-
@partial_template.expand({"one" => "1", "two" => "2"}).to_str.should ==
|
1649
|
-
"http://example.com/"
|
1650
|
-
end
|
1651
|
-
end
|
1652
|
-
|
1653
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1654
|
-
before do
|
1655
|
-
@initial_template = Addressable::Template.new(
|
1656
|
-
"http://example.com/{-neg|notfound|one,two,three}"
|
1657
|
-
)
|
1658
|
-
@partial_template = @initial_template.partial_expand({"one" => "1"})
|
1659
|
-
end
|
1660
|
-
|
1661
|
-
it "should produce the same result when fully expanded" do
|
1662
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1663
|
-
@partial_template.expand({"two" => "2"}).to_str
|
1664
|
-
end
|
1665
|
-
|
1666
|
-
it "should produce the correct result when fully expanded" do
|
1667
|
-
@partial_template.expand({}).to_str.should == "http://example.com/"
|
1668
|
-
end
|
1669
|
-
|
1670
|
-
it "should produce the correct pattern" do
|
1671
|
-
@partial_template.pattern.should == "http://example.com/"
|
1672
|
-
end
|
1673
|
-
end
|
1674
|
-
|
1675
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1676
|
-
before do
|
1677
|
-
@initial_template = Addressable::Template.new(
|
1678
|
-
"http://example.com/?{-prefix|x=|one}"
|
1679
|
-
)
|
1680
|
-
@partial_template = @initial_template.partial_expand({})
|
1681
|
-
end
|
1682
|
-
|
1683
|
-
it "should produce the same result when fully expanded" do
|
1684
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1685
|
-
@partial_template.expand({"one" => "1"}).to_str
|
1686
|
-
end
|
1687
|
-
|
1688
|
-
it "should produce the correct result when fully expanded" do
|
1689
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?"
|
1690
|
-
end
|
1691
|
-
|
1692
|
-
it "should produce the correct result when fully expanded" do
|
1693
|
-
@partial_template.expand({"one" => "1"}).to_str.should ==
|
1694
|
-
"http://example.com/?x=1"
|
1695
|
-
end
|
1696
|
-
|
1697
|
-
it "should produce the correct result when fully expanded" do
|
1698
|
-
@partial_template.expand({"two" => "2"}).to_str.should ==
|
1699
|
-
"http://example.com/?"
|
1700
|
-
end
|
1701
|
-
|
1702
|
-
it "should produce the correct result when fully expanded" do
|
1703
|
-
@partial_template.expand({"one" => "1", "two" => "2"}).to_str.should ==
|
1704
|
-
"http://example.com/?x=1"
|
1705
|
-
end
|
1706
|
-
end
|
1707
|
-
|
1708
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1709
|
-
before do
|
1710
|
-
@initial_template = Addressable::Template.new(
|
1711
|
-
"http://example.com/?{-prefix|x=|one}"
|
1712
|
-
)
|
1713
|
-
@partial_template = @initial_template.partial_expand({"one" => "1"})
|
1714
|
-
end
|
1715
|
-
|
1716
|
-
it "should produce the same result when fully expanded" do
|
1717
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1718
|
-
@partial_template.expand({}).to_str
|
1719
|
-
end
|
1720
|
-
|
1721
|
-
it "should produce the correct result when fully expanded" do
|
1722
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?x=1"
|
1723
|
-
end
|
1724
|
-
|
1725
|
-
it "should produce the correct pattern" do
|
1726
|
-
@partial_template.pattern.should == "http://example.com/?x=1"
|
1727
|
-
end
|
1728
|
-
end
|
1729
|
-
|
1730
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1731
|
-
before do
|
1732
|
-
@initial_template = Addressable::Template.new(
|
1733
|
-
"http://example.com/?{-suffix|=x|one}"
|
1734
|
-
)
|
1735
|
-
@partial_template = @initial_template.partial_expand({})
|
1736
|
-
end
|
1737
|
-
|
1738
|
-
it "should produce the same result when fully expanded" do
|
1739
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1740
|
-
@partial_template.expand({"one" => "1"}).to_str
|
1741
|
-
end
|
1742
|
-
|
1743
|
-
it "should produce the correct result when fully expanded" do
|
1744
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?"
|
1745
|
-
end
|
1746
|
-
|
1747
|
-
it "should produce the correct result when fully expanded" do
|
1748
|
-
@partial_template.expand({"one" => "1"}).to_str.should ==
|
1749
|
-
"http://example.com/?1=x"
|
1750
|
-
end
|
1751
|
-
|
1752
|
-
it "should produce the correct result when fully expanded" do
|
1753
|
-
@partial_template.expand({"two" => "2"}).to_str.should ==
|
1754
|
-
"http://example.com/?"
|
1755
|
-
end
|
1756
|
-
|
1757
|
-
it "should produce the correct result when fully expanded" do
|
1758
|
-
@partial_template.expand({"one" => "1", "two" => "2"}).to_str.should ==
|
1759
|
-
"http://example.com/?1=x"
|
1760
|
-
end
|
1761
|
-
end
|
1762
|
-
|
1763
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1764
|
-
before do
|
1765
|
-
@initial_template = Addressable::Template.new(
|
1766
|
-
"http://example.com/?{-suffix|=x|one}"
|
1767
|
-
)
|
1768
|
-
@partial_template = @initial_template.partial_expand({"one" => "1"})
|
1769
|
-
end
|
1770
|
-
|
1771
|
-
it "should produce the same result when fully expanded" do
|
1772
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1773
|
-
@partial_template.expand({}).to_str
|
1774
|
-
end
|
1775
|
-
|
1776
|
-
it "should produce the correct result when fully expanded" do
|
1777
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?1=x"
|
1778
|
-
end
|
1779
|
-
|
1780
|
-
it "should produce the correct pattern" do
|
1781
|
-
@partial_template.pattern.should == "http://example.com/?1=x"
|
1782
|
-
end
|
1783
|
-
end
|
1784
|
-
|
1785
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1786
|
-
before do
|
1787
|
-
@initial_template = Addressable::Template.new(
|
1788
|
-
"http://example.com/?{-join|&|one}"
|
1789
|
-
)
|
1790
|
-
@partial_template = @initial_template.partial_expand({})
|
1791
|
-
end
|
1792
|
-
|
1793
|
-
it "should produce the same result when fully expanded" do
|
1794
|
-
@initial_template.expand({"one" => "1"}).to_str.should ==
|
1795
|
-
@partial_template.expand({"one" => "1"}).to_str
|
1796
|
-
end
|
1797
|
-
|
1798
|
-
it "should produce the correct result when fully expanded" do
|
1799
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?"
|
1800
|
-
end
|
1801
|
-
|
1802
|
-
it "should produce the correct result when fully expanded" do
|
1803
|
-
@partial_template.pattern.should == @initial_template.pattern
|
1804
|
-
end
|
1805
|
-
end
|
1806
|
-
|
1807
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1808
|
-
before do
|
1809
|
-
@initial_template = Addressable::Template.new(
|
1810
|
-
"http://example.com/?{-join|&|one,two}"
|
1811
|
-
)
|
1812
|
-
@partial_template = @initial_template.partial_expand({"one" => "1"})
|
1813
|
-
end
|
1814
|
-
|
1815
|
-
it "should produce the same result when fully expanded" do
|
1816
|
-
@initial_template.expand({"one" => "1", "two" => "2"}).to_str.should ==
|
1817
|
-
@partial_template.expand({"two" => "2"}).to_str
|
1818
|
-
end
|
1819
|
-
|
1820
|
-
it "should produce the correct result when fully expanded" do
|
1821
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?one=1"
|
1822
|
-
end
|
1823
|
-
end
|
1824
|
-
|
1825
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1826
|
-
before do
|
1827
|
-
@initial_template = Addressable::Template.new(
|
1828
|
-
"http://example.com/?{-join|&|one,two}"
|
1829
|
-
)
|
1830
|
-
@partial_template = @initial_template.partial_expand({"two" => "2"})
|
1831
|
-
end
|
1832
|
-
|
1833
|
-
it "should produce the same result when fully expanded" do
|
1834
|
-
@initial_template.expand({"one" => "1", "two" => "2"}).to_str.should ==
|
1835
|
-
@partial_template.expand({"one" => "1"}).to_str
|
1836
|
-
end
|
1837
|
-
|
1838
|
-
it "should produce the correct result when fully expanded" do
|
1839
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?two=2"
|
1840
|
-
end
|
1841
|
-
end
|
1842
|
-
|
1843
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1844
|
-
before do
|
1845
|
-
@initial_template = Addressable::Template.new(
|
1846
|
-
"http://example.com/?{-join|&|one,two,three}"
|
1847
|
-
)
|
1848
|
-
@partial_template = @initial_template.partial_expand({"one" => "1"})
|
1849
|
-
end
|
1850
|
-
|
1851
|
-
it "should produce the same result when fully expanded" do
|
1852
|
-
@initial_template.expand({
|
1853
|
-
"one" => "1", "two" => "2", "three" => "3"
|
1854
|
-
}).to_str.should ==
|
1855
|
-
@partial_template.expand({"two" => "2", "three" => "3"}).to_str
|
1856
|
-
end
|
1857
|
-
|
1858
|
-
it "should produce the correct result when fully expanded" do
|
1859
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?one=1"
|
1860
|
-
end
|
1861
|
-
|
1862
|
-
it "should produce the correct result when fully expanded" do
|
1863
|
-
@partial_template.expand({"two" => "2"}).to_str.should ==
|
1864
|
-
"http://example.com/?one=1&two=2"
|
1865
|
-
end
|
1866
|
-
|
1867
|
-
it "should produce the correct result when fully expanded" do
|
1868
|
-
@partial_template.expand({"three" => "3"}).to_str.should ==
|
1869
|
-
"http://example.com/?one=1&three=3"
|
1870
|
-
end
|
1871
|
-
end
|
1872
|
-
|
1873
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1874
|
-
before do
|
1875
|
-
@initial_template = Addressable::Template.new(
|
1876
|
-
"http://example.com/?{-join|&|one,two,three}"
|
1877
|
-
)
|
1878
|
-
@partial_template = @initial_template.partial_expand({"two" => "2"})
|
1879
|
-
end
|
1880
|
-
|
1881
|
-
it "should produce the same result when fully expanded" do
|
1882
|
-
@initial_template.expand({
|
1883
|
-
"one" => "1", "two" => "2", "three" => "3"
|
1884
|
-
}).to_str.should ==
|
1885
|
-
@partial_template.expand({"one" => "1", "three" => "3"}).to_str
|
1886
|
-
end
|
1887
|
-
|
1888
|
-
it "should produce the correct result when fully expanded" do
|
1889
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?two=2"
|
1890
|
-
end
|
1891
|
-
|
1892
|
-
it "should produce the correct result when fully expanded" do
|
1893
|
-
@partial_template.expand({"one" => "1"}).to_str.should ==
|
1894
|
-
"http://example.com/?one=1&two=2"
|
1895
|
-
end
|
1896
|
-
|
1897
|
-
it "should produce the correct result when fully expanded" do
|
1898
|
-
@partial_template.expand({"three" => "3"}).to_str.should ==
|
1899
|
-
"http://example.com/?two=2&three=3"
|
1900
|
-
end
|
1901
|
-
end
|
1902
|
-
|
1903
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1904
|
-
before do
|
1905
|
-
@initial_template = Addressable::Template.new(
|
1906
|
-
"http://example.com/?{-join|&|one,two,three}"
|
1907
|
-
)
|
1908
|
-
@partial_template = @initial_template.partial_expand({"three" => "3"})
|
1909
|
-
end
|
1910
|
-
|
1911
|
-
it "should produce the same result when fully expanded" do
|
1912
|
-
@initial_template.expand({
|
1913
|
-
"one" => "1", "two" => "2", "three" => "3"
|
1914
|
-
}).to_str.should ==
|
1915
|
-
@partial_template.expand({"one" => "1", "two" => "2"}).to_str
|
1916
|
-
end
|
1917
|
-
|
1918
|
-
it "should produce the correct result when fully expanded" do
|
1919
|
-
@partial_template.expand({}).to_str.should == "http://example.com/?three=3"
|
1920
|
-
end
|
1921
|
-
|
1922
|
-
it "should produce the correct result when fully expanded" do
|
1923
|
-
@partial_template.expand({"one" => "1"}).to_str.should ==
|
1924
|
-
"http://example.com/?one=1&three=3"
|
1925
|
-
end
|
1926
|
-
|
1927
|
-
it "should produce the correct result when fully expanded" do
|
1928
|
-
@partial_template.expand({"two" => "2"}).to_str.should ==
|
1929
|
-
"http://example.com/?two=2&three=3"
|
1930
|
-
end
|
1931
|
-
end
|
1932
|
-
|
1933
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1934
|
-
before do
|
1935
|
-
@initial_template = Addressable::Template.new(
|
1936
|
-
"http://example.com/?{-join|&|one,two,three}"
|
1937
|
-
)
|
1938
|
-
@partial_template = @initial_template.partial_expand({
|
1939
|
-
"one" => "1", "two" => "2"
|
1940
|
-
})
|
1941
|
-
end
|
1942
|
-
|
1943
|
-
it "should produce the same result when fully expanded" do
|
1944
|
-
@initial_template.expand({
|
1945
|
-
"one" => "1", "two" => "2", "three" => "3"
|
1946
|
-
}).to_str.should ==
|
1947
|
-
@partial_template.expand({"three" => "3"}).to_str
|
1948
|
-
end
|
1949
|
-
|
1950
|
-
it "should produce the correct result when fully expanded" do
|
1951
|
-
@partial_template.expand({}).to_str.should ==
|
1952
|
-
"http://example.com/?one=1&two=2"
|
1953
|
-
end
|
1954
|
-
|
1955
|
-
it "should produce the correct result when fully expanded" do
|
1956
|
-
@partial_template.expand({"three" => "3"}).to_str.should ==
|
1957
|
-
"http://example.com/?one=1&two=2&three=3"
|
1958
|
-
end
|
1959
|
-
end
|
1960
|
-
|
1961
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1962
|
-
before do
|
1963
|
-
@initial_template = Addressable::Template.new(
|
1964
|
-
"http://example.com/?{-join|&|one,two,three}"
|
1965
|
-
)
|
1966
|
-
@partial_template = @initial_template.partial_expand({
|
1967
|
-
"one" => "1", "three" => "3"
|
1968
|
-
})
|
1969
|
-
end
|
1970
|
-
|
1971
|
-
it "should produce the same result when fully expanded" do
|
1972
|
-
@initial_template.expand({
|
1973
|
-
"one" => "1", "two" => "2", "three" => "3"
|
1974
|
-
}).to_str.should ==
|
1975
|
-
@partial_template.expand({"two" => "2"}).to_str
|
1976
|
-
end
|
1977
|
-
|
1978
|
-
it "should produce the correct result when fully expanded" do
|
1979
|
-
@partial_template.expand({}).to_str.should ==
|
1980
|
-
"http://example.com/?one=1&three=3"
|
1981
|
-
end
|
1982
|
-
|
1983
|
-
it "should produce the correct result when fully expanded" do
|
1984
|
-
@partial_template.expand({"two" => "2"}).to_str.should ==
|
1985
|
-
"http://example.com/?one=1&two=2&three=3"
|
1986
|
-
end
|
1987
|
-
end
|
1988
|
-
|
1989
|
-
describe Addressable::Template, "with a partially expanded template" do
|
1990
|
-
before do
|
1991
|
-
@initial_template = Addressable::Template.new(
|
1992
|
-
"http://example.com/?{-join|&|one,two,three}"
|
1993
|
-
)
|
1994
|
-
@partial_template = @initial_template.partial_expand({
|
1995
|
-
"two" => "2", "three" => "3"
|
1996
|
-
})
|
1997
|
-
end
|
1998
|
-
|
1999
|
-
it "should produce the same result when fully expanded" do
|
2000
|
-
@initial_template.expand({
|
2001
|
-
"one" => "1", "two" => "2", "three" => "3"
|
2002
|
-
}).to_str.should ==
|
2003
|
-
@partial_template.expand({"one" => "1"}).to_str
|
2004
|
-
end
|
2005
|
-
|
2006
|
-
it "should produce the correct result when fully expanded" do
|
2007
|
-
@partial_template.expand({}).to_str.should ==
|
2008
|
-
"http://example.com/?two=2&three=3"
|
2009
|
-
end
|
2010
|
-
|
2011
|
-
it "should produce the correct result when fully expanded" do
|
2012
|
-
@partial_template.expand({"one" => "1"}).to_str.should ==
|
2013
|
-
"http://example.com/?one=1&two=2&three=3"
|
2014
|
-
end
|
2015
|
-
end
|
2016
|
-
|
2017
|
-
describe Addressable::Template, "with a partially expanded template" do
|
2018
|
-
before do
|
2019
|
-
@initial_template = Addressable::Template.new(
|
2020
|
-
"http://example.com/?{-join|&|one,two,three}"
|
2021
|
-
)
|
2022
|
-
end
|
2023
|
-
|
2024
|
-
it "should raise an error when partially expanding a bogus operator" do
|
2025
|
-
(lambda do
|
2026
|
-
@initial_template.partial_expand({"one" => ["1"]})
|
2027
|
-
end).should raise_error(
|
2028
|
-
Addressable::Template::InvalidTemplateOperatorError
|
2029
|
-
)
|
2030
|
-
(lambda do
|
2031
|
-
@initial_template.partial_expand({"two" => "2", "three" => ["3"]})
|
2032
|
-
end).should raise_error(
|
2033
|
-
Addressable::Template::InvalidTemplateOperatorError
|
2034
|
-
)
|
2035
|
-
end
|
2036
|
-
end
|
2037
|
-
|
2038
|
-
describe Addressable::Template, "with a partially expanded template" do
|
2039
|
-
before do
|
2040
|
-
@initial_template = Addressable::Template.new(
|
2041
|
-
"http://example.com/{-list|/|numbers}/{-list|/|letters}/"
|
2042
|
-
)
|
2043
|
-
@partial_template = @initial_template.partial_expand({})
|
2044
|
-
end
|
2045
|
-
|
2046
|
-
it "should produce the same result when fully expanded" do
|
2047
|
-
@initial_template.expand({
|
2048
|
-
"numbers" => ["1", "2", "3"], "letters" => ["a", "b", "c"]
|
2049
|
-
}).to_str.should == @partial_template.expand({
|
2050
|
-
"numbers" => ["1", "2", "3"], "letters" => ["a", "b", "c"]
|
2051
|
-
}).to_str
|
2052
|
-
end
|
2053
|
-
|
2054
|
-
it "should produce the correct result when fully expanded" do
|
2055
|
-
@partial_template.expand({}).to_str.should == "http://example.com///"
|
2056
|
-
end
|
2057
|
-
|
2058
|
-
it "should produce the correct result when fully expanded" do
|
2059
|
-
@partial_template.pattern.should == @initial_template.pattern
|
2060
|
-
end
|
2061
|
-
end
|
2062
|
-
|
2063
|
-
describe Addressable::Template, "with a partially expanded template" do
|
2064
|
-
before do
|
2065
|
-
@initial_template = Addressable::Template.new(
|
2066
|
-
"http://example.com/{-list|/|numbers}/{-list|/|letters}/"
|
2067
|
-
)
|
2068
|
-
@partial_template = @initial_template.partial_expand({
|
2069
|
-
"numbers" => ["1", "2", "3"]
|
2070
|
-
})
|
2071
|
-
end
|
2072
|
-
|
2073
|
-
it "should produce the same result when fully expanded" do
|
2074
|
-
@initial_template.expand({
|
2075
|
-
"numbers" => ["1", "2", "3"], "letters" => ["a", "b", "c"]
|
2076
|
-
}).to_str.should == @partial_template.expand({
|
2077
|
-
"letters" => ["a", "b", "c"]
|
2078
|
-
}).to_str
|
2079
|
-
end
|
2080
|
-
|
2081
|
-
it "should produce the correct result when fully expanded" do
|
2082
|
-
@partial_template.expand({}).to_str.should == "http://example.com/1/2/3//"
|
2083
|
-
end
|
2084
|
-
end
|
2085
|
-
|
2086
|
-
describe Addressable::Template, "with a partially expanded template" do
|
2087
|
-
before do
|
2088
|
-
@initial_template = Addressable::Template.new(
|
2089
|
-
"http://example.com/{-list|/|numbers}/{-list|/|letters}/"
|
2090
|
-
)
|
2091
|
-
@partial_template = @initial_template.partial_expand({
|
2092
|
-
"letters" => ["a", "b", "c"]
|
2093
|
-
})
|
2094
|
-
end
|
2095
|
-
|
2096
|
-
it "should produce the same result when fully expanded" do
|
2097
|
-
@initial_template.expand({
|
2098
|
-
"numbers" => ["1", "2", "3"], "letters" => ["a", "b", "c"]
|
2099
|
-
}).to_str.should == @partial_template.expand({
|
2100
|
-
"numbers" => ["1", "2", "3"]
|
2101
|
-
}).to_str
|
2102
|
-
end
|
2103
|
-
|
2104
|
-
it "should produce the correct result when fully expanded" do
|
2105
|
-
@partial_template.expand({}).to_str.should == "http://example.com//a/b/c/"
|
2106
|
-
end
|
2107
|
-
end
|
2108
|
-
|
2109
|
-
describe Addressable::Template, "with a partially expanded template" do
|
2110
|
-
before do
|
2111
|
-
@initial_template = Addressable::Template.new(
|
2112
|
-
"http://example.com/{-list|/|numbers}/{-list|/|letters}/"
|
2113
|
-
)
|
2114
|
-
end
|
2115
|
-
|
2116
|
-
it "should raise an error when partially expanding a bogus operator" do
|
2117
|
-
(lambda do
|
2118
|
-
@initial_template.partial_expand({"numbers" => "1"})
|
2119
|
-
end).should raise_error(
|
2120
|
-
Addressable::Template::InvalidTemplateOperatorError
|
2121
|
-
)
|
2122
|
-
(lambda do
|
2123
|
-
@initial_template.partial_expand({"letters" => "a"})
|
2124
|
-
end).should raise_error(
|
2125
|
-
Addressable::Template::InvalidTemplateOperatorError
|
2126
|
-
)
|
2127
|
-
end
|
2128
|
-
end
|
2129
|
-
|
2130
|
-
describe Addressable::Template, "with a partially expanded template" do
|
2131
|
-
before do
|
2132
|
-
@initial_template = Addressable::Template.new(
|
2133
|
-
"http://example.com/{-bogus|/|one,two}/"
|
2134
|
-
)
|
2135
|
-
end
|
2136
|
-
|
2137
|
-
it "should raise an error when partially expanding a bogus operator" do
|
2138
|
-
(lambda do
|
2139
|
-
@initial_template.partial_expand({"one" => "1"})
|
2140
|
-
end).should raise_error(
|
2141
|
-
Addressable::Template::InvalidTemplateOperatorError
|
2142
|
-
)
|
930
|
+
context "support regexes:" do
|
931
|
+
context "EXPRESSION" do
|
932
|
+
subject { Addressable::Template::EXPRESSION }
|
933
|
+
it "should be able to match an expression" do
|
934
|
+
subject.should match("{foo}")
|
935
|
+
subject.should match("{foo,9}")
|
936
|
+
subject.should match("{foo.bar,baz}")
|
937
|
+
subject.should match("{+foo.bar,baz}")
|
938
|
+
subject.should match("{foo,foo%20bar}")
|
939
|
+
subject.should match("{#foo:20,baz*}")
|
940
|
+
subject.should match("stuff{#foo:20,baz*}things")
|
941
|
+
end
|
942
|
+
it "should fail on non vars" do
|
943
|
+
subject.should_not match("!{foo")
|
944
|
+
subject.should_not match("{foo.bar.}")
|
945
|
+
subject.should_not match("!{}")
|
946
|
+
end
|
947
|
+
end
|
948
|
+
context "VARNAME" do
|
949
|
+
subject { Addressable::Template::VARNAME }
|
950
|
+
it "should be able to match a variable" do
|
951
|
+
subject.should match("foo")
|
952
|
+
subject.should match("9")
|
953
|
+
subject.should match("foo.bar")
|
954
|
+
subject.should match("foo_bar")
|
955
|
+
subject.should match("foo_bar.baz")
|
956
|
+
subject.should match("foo%20bar")
|
957
|
+
subject.should match("foo%20bar.baz")
|
958
|
+
end
|
959
|
+
it "should fail on non vars" do
|
960
|
+
subject.should_not match("!foo")
|
961
|
+
subject.should_not match("foo.bar.")
|
962
|
+
subject.should_not match("foo%2%00bar")
|
963
|
+
subject.should_not match("foo_ba%r")
|
964
|
+
subject.should_not match("foo_bar*")
|
965
|
+
subject.should_not match("foo_bar:20")
|
966
|
+
end
|
967
|
+
end
|
968
|
+
context "VARIABLE_LIST" do
|
969
|
+
subject { Addressable::Template::VARIABLE_LIST }
|
970
|
+
it "should be able to match a variable list" do
|
971
|
+
subject.should match("foo,bar")
|
972
|
+
subject.should match("foo")
|
973
|
+
subject.should match("foo,bar*,baz")
|
974
|
+
subject.should match("foo.bar,bar_baz*,baz:12")
|
975
|
+
end
|
976
|
+
it "should fail on non vars" do
|
977
|
+
subject.should_not match(",foo,bar*,baz")
|
978
|
+
subject.should_not match("foo,*bar,baz")
|
979
|
+
subject.should_not match("foo,,bar*,baz")
|
980
|
+
end
|
981
|
+
end
|
982
|
+
context "VARSPEC" do
|
983
|
+
subject { Addressable::Template::VARSPEC }
|
984
|
+
it "should be able to match a variable with modifier" do
|
985
|
+
subject.should match("9:8")
|
986
|
+
subject.should match("foo.bar*")
|
987
|
+
subject.should match("foo_bar:12")
|
988
|
+
subject.should match("foo_bar.baz*")
|
989
|
+
subject.should match("foo%20bar:12")
|
990
|
+
subject.should match("foo%20bar.baz*")
|
991
|
+
end
|
992
|
+
it "should fail on non vars" do
|
993
|
+
subject.should_not match("!foo")
|
994
|
+
subject.should_not match("*foo")
|
995
|
+
subject.should_not match("fo*o")
|
996
|
+
subject.should_not match("fo:o")
|
997
|
+
subject.should_not match("foo:")
|
998
|
+
end
|
999
|
+
end
|
2143
1000
|
end
|
2144
1001
|
end
|