mustermann 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +429 -672
- data/lib/mustermann.rb +95 -20
- data/lib/mustermann/ast/boundaries.rb +44 -0
- data/lib/mustermann/ast/compiler.rb +13 -7
- data/lib/mustermann/ast/expander.rb +22 -12
- data/lib/mustermann/ast/node.rb +69 -5
- data/lib/mustermann/ast/param_scanner.rb +20 -0
- data/lib/mustermann/ast/parser.rb +138 -19
- data/lib/mustermann/ast/pattern.rb +59 -7
- data/lib/mustermann/ast/template_generator.rb +28 -0
- data/lib/mustermann/ast/transformer.rb +2 -2
- data/lib/mustermann/ast/translator.rb +20 -0
- data/lib/mustermann/ast/validation.rb +4 -3
- data/lib/mustermann/composite.rb +101 -0
- data/lib/mustermann/expander.rb +2 -2
- data/lib/mustermann/identity.rb +56 -0
- data/lib/mustermann/pattern.rb +185 -10
- data/lib/mustermann/pattern_cache.rb +49 -0
- data/lib/mustermann/regexp.rb +1 -0
- data/lib/mustermann/regexp_based.rb +18 -1
- data/lib/mustermann/regular.rb +4 -1
- data/lib/mustermann/simple_match.rb +5 -0
- data/lib/mustermann/sinatra.rb +22 -5
- data/lib/mustermann/to_pattern.rb +11 -6
- data/lib/mustermann/version.rb +1 -1
- data/mustermann.gemspec +1 -14
- data/spec/ast_spec.rb +14 -0
- data/spec/composite_spec.rb +147 -0
- data/spec/expander_spec.rb +15 -0
- data/spec/identity_spec.rb +44 -0
- data/spec/mustermann_spec.rb +17 -2
- data/spec/pattern_spec.rb +7 -3
- data/spec/regular_spec.rb +25 -0
- data/spec/sinatra_spec.rb +184 -9
- data/spec/to_pattern_spec.rb +49 -0
- metadata +15 -180
- data/.gitignore +0 -18
- data/.rspec +0 -2
- data/.travis.yml +0 -4
- data/.yardopts +0 -1
- data/Gemfile +0 -2
- data/LICENSE +0 -22
- data/Rakefile +0 -6
- data/internals.md +0 -64
- data/lib/mustermann/ast/tree_renderer.rb +0 -29
- data/lib/mustermann/rails.rb +0 -17
- data/lib/mustermann/shell.rb +0 -29
- data/lib/mustermann/simple.rb +0 -35
- data/lib/mustermann/template.rb +0 -47
- data/spec/rails_spec.rb +0 -521
- data/spec/shell_spec.rb +0 -108
- data/spec/simple_spec.rb +0 -236
- data/spec/support.rb +0 -5
- data/spec/support/coverage.rb +0 -16
- data/spec/support/env.rb +0 -16
- data/spec/support/expand_matcher.rb +0 -27
- data/spec/support/match_matcher.rb +0 -39
- data/spec/support/pattern.rb +0 -39
- data/spec/template_spec.rb +0 -814
data/spec/mustermann_spec.rb
CHANGED
@@ -15,7 +15,7 @@ describe Mustermann do
|
|
15
15
|
example { Mustermann.new('', type: :template) .should be_a(Mustermann::Template) }
|
16
16
|
|
17
17
|
example { expect { Mustermann.new('', foo: :bar) }.to raise_error(ArgumentError, "unsupported option :foo for Mustermann::Sinatra") }
|
18
|
-
example { expect { Mustermann.new('', type: :ast) }.to raise_error(ArgumentError, "unsupported type :ast") }
|
18
|
+
example { expect { Mustermann.new('', type: :ast) }.to raise_error(ArgumentError, "unsupported type :ast (cannot load such file -- mustermann/ast)") }
|
19
19
|
end
|
20
20
|
|
21
21
|
context "pattern argument" do
|
@@ -35,6 +35,20 @@ describe Mustermann do
|
|
35
35
|
example { Mustermann.new(pattern, type: :rails) .should be_a(Mustermann::Rails) }
|
36
36
|
example { Mustermann.new(pattern).to_s.should be == 'foo' }
|
37
37
|
end
|
38
|
+
|
39
|
+
context "multiple arguments" do
|
40
|
+
example { Mustermann.new('', '') .should be_a(Mustermann::Composite) }
|
41
|
+
example { Mustermann.new('', '').patterns.first .should be_a(Mustermann::Sinatra) }
|
42
|
+
example { Mustermann.new('', '').operator .should be == :| }
|
43
|
+
example { Mustermann.new('', '', operator: :&).operator .should be == :& }
|
44
|
+
example { Mustermann.new('', '', greedy: true) .should be_a(Mustermann::Composite) }
|
45
|
+
end
|
46
|
+
|
47
|
+
context "invalid arguments" do
|
48
|
+
it "raise a TypeError for unsupported types" do
|
49
|
+
expect { Mustermann.new(10) }.to raise_error(TypeError, "Fixnum can't be coerced into Mustermann::Pattern")
|
50
|
+
end
|
51
|
+
end
|
38
52
|
end
|
39
53
|
|
40
54
|
describe :[] do
|
@@ -45,7 +59,8 @@ describe Mustermann do
|
|
45
59
|
example { Mustermann[:simple] .should be == Mustermann::Simple }
|
46
60
|
example { Mustermann[:template] .should be == Mustermann::Template }
|
47
61
|
|
48
|
-
example { expect { Mustermann[:ast]
|
62
|
+
example { expect { Mustermann[:ast] }.to raise_error(ArgumentError, "unsupported type :ast (cannot load such file -- mustermann/ast)") }
|
63
|
+
example { expect { Mustermann[:expander] }.to raise_error(ArgumentError, "unsupported type :expander") }
|
49
64
|
end
|
50
65
|
|
51
66
|
describe :extend_object do
|
data/spec/pattern_spec.rb
CHANGED
@@ -20,10 +20,14 @@ describe Mustermann::Pattern do
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
describe :
|
23
|
+
describe :respond_to? do
|
24
24
|
subject(:pattern) { Mustermann::Pattern.new("") }
|
25
|
-
|
26
|
-
it {
|
25
|
+
|
26
|
+
it { should_not respond_to(:expand) }
|
27
|
+
it { should_not respond_to(:to_templates) }
|
28
|
+
|
29
|
+
it { expect { pattern.expand } .to raise_error(NotImplementedError) }
|
30
|
+
it { expect { pattern.to_templates } .to raise_error(NotImplementedError) }
|
27
31
|
end
|
28
32
|
|
29
33
|
describe :== do
|
data/spec/regular_spec.rb
CHANGED
@@ -7,6 +7,9 @@ describe Mustermann::Regular do
|
|
7
7
|
pattern '' do
|
8
8
|
it { should match('') }
|
9
9
|
it { should_not match('/') }
|
10
|
+
|
11
|
+
it { should_not respond_to(:expand) }
|
12
|
+
it { should_not respond_to(:to_templates) }
|
10
13
|
end
|
11
14
|
|
12
15
|
pattern '/' do
|
@@ -33,4 +36,26 @@ describe Mustermann::Regular do
|
|
33
36
|
it { should match('/%0Afoo') .capturing foo: '%0Afoo' }
|
34
37
|
it { should match('/foo%2Fbar') .capturing foo: 'foo%2Fbar' }
|
35
38
|
end
|
39
|
+
|
40
|
+
context "peeking" do
|
41
|
+
subject(:pattern) { Mustermann::Regular.new("(?<name>[^/]+)") }
|
42
|
+
|
43
|
+
describe :peek_size do
|
44
|
+
example { pattern.peek_size("foo bar/blah") .should be == "foo bar".size }
|
45
|
+
example { pattern.peek_size("foo%20bar/blah") .should be == "foo%20bar".size }
|
46
|
+
example { pattern.peek_size("/foo bar") .should be_nil }
|
47
|
+
end
|
48
|
+
|
49
|
+
describe :peek_match do
|
50
|
+
example { pattern.peek_match("foo bar/blah") .to_s .should be == "foo bar" }
|
51
|
+
example { pattern.peek_match("foo%20bar/blah") .to_s .should be == "foo%20bar" }
|
52
|
+
example { pattern.peek_match("/foo bar") .should be_nil }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe :peek_params do
|
56
|
+
example { pattern.peek_params("foo bar/blah") .should be == [{"name" => "foo bar"}, "foo bar".size] }
|
57
|
+
example { pattern.peek_params("foo%20bar/blah") .should be == [{"name" => "foo bar"}, "foo%20bar".size] }
|
58
|
+
example { pattern.peek_params("/foo bar") .should be_nil }
|
59
|
+
end
|
60
|
+
end
|
36
61
|
end
|
data/spec/sinatra_spec.rb
CHANGED
@@ -7,6 +7,11 @@ describe Mustermann::Sinatra do
|
|
7
7
|
pattern '' do
|
8
8
|
it { should match('') }
|
9
9
|
it { should_not match('/') }
|
10
|
+
|
11
|
+
it { should generate_template('') }
|
12
|
+
|
13
|
+
it { should respond_to(:expand) }
|
14
|
+
it { should respond_to(:to_templates) }
|
10
15
|
end
|
11
16
|
|
12
17
|
pattern '/' do
|
@@ -43,6 +48,8 @@ describe Mustermann::Sinatra do
|
|
43
48
|
it { should_not match('/foo/bar') }
|
44
49
|
it { should_not match('/') }
|
45
50
|
it { should_not match('/foo/') }
|
51
|
+
|
52
|
+
it { should generate_template('/{foo}') }
|
46
53
|
end
|
47
54
|
|
48
55
|
pattern '/föö' do
|
@@ -61,10 +68,34 @@ describe Mustermann::Sinatra do
|
|
61
68
|
|
62
69
|
example { pattern.params('/bar/foo').should be == {"foo" => "bar", "bar" => "foo"} }
|
63
70
|
example { pattern.params('').should be_nil }
|
71
|
+
|
72
|
+
it { should generate_template('/{foo}/{bar}') }
|
73
|
+
end
|
74
|
+
|
75
|
+
pattern "/{foo}/{bar}" do
|
76
|
+
it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
|
77
|
+
it { should match('/foo.bar/bar.foo') .capturing foo: 'foo.bar', bar: 'bar.foo' }
|
78
|
+
it { should match('/user@example.com/name') .capturing foo: 'user@example.com', bar: 'name' }
|
79
|
+
it { should match('/10.1/te.st') .capturing foo: '10.1', bar: 'te.st' }
|
80
|
+
it { should match('/10.1.2/te.st') .capturing foo: '10.1.2', bar: 'te.st' }
|
81
|
+
|
82
|
+
it { should_not match('/foo%2Fbar') }
|
83
|
+
it { should_not match('/foo%2fbar') }
|
84
|
+
|
85
|
+
example { pattern.params('/bar/foo').should be == {"foo" => "bar", "bar" => "foo"} }
|
86
|
+
example { pattern.params('').should be_nil }
|
87
|
+
|
88
|
+
it { should generate_template('/{foo}/{bar}') }
|
64
89
|
end
|
65
90
|
|
66
91
|
pattern '/hello/:person' do
|
67
92
|
it { should match('/hello/Frank').capturing person: 'Frank' }
|
93
|
+
it { should generate_template('/hello/{person}') }
|
94
|
+
end
|
95
|
+
|
96
|
+
pattern '/hello/{person}' do
|
97
|
+
it { should match('/hello/Frank').capturing person: 'Frank' }
|
98
|
+
it { should generate_template('/hello/{person}') }
|
68
99
|
end
|
69
100
|
|
70
101
|
pattern '/?:foo?/?:bar?' do
|
@@ -73,23 +104,40 @@ describe Mustermann::Sinatra do
|
|
73
104
|
it { should match('/') .capturing foo: nil, bar: nil }
|
74
105
|
it { should match('') .capturing foo: nil, bar: nil }
|
75
106
|
|
76
|
-
it {
|
107
|
+
it { should expand(foo: 'hello') .to('/hello/') }
|
108
|
+
it { should expand(foo: 'hello', bar: 'world') .to('/hello/world') }
|
109
|
+
it { should expand(bar: 'world') .to('//world') }
|
110
|
+
it { should expand .to('//') }
|
111
|
+
it { should_not expand(baz: '') }
|
77
112
|
|
78
|
-
|
79
|
-
|
80
|
-
# it { should expand(bar: 'world') .to('//world') }
|
81
|
-
# it { should expand .to('') }
|
82
|
-
# it { should_not expand(baz: '') }
|
113
|
+
it { should_not match('/hello/world/') }
|
114
|
+
it { should generate_templates("", "/", "//", "//{bar}", "/{bar}", "/{foo}", "/{foo}/", "/{foo}/{bar}", "/{foo}{bar}", "{bar}", "{foo}", "{foo}/", "{foo}/{bar}", "{foo}{bar}") }
|
83
115
|
end
|
84
116
|
|
85
117
|
pattern '/:foo_bar' do
|
86
118
|
it { should match('/hello').capturing foo_bar: 'hello' }
|
119
|
+
it { should generate_template('/{foo_bar}') }
|
120
|
+
end
|
121
|
+
|
122
|
+
pattern '/{foo.bar}' do
|
123
|
+
it { should match('/hello').capturing :"foo.bar" => 'hello' }
|
124
|
+
it { should generate_template('/{foo.bar}') }
|
87
125
|
end
|
88
126
|
|
89
127
|
pattern '/*' do
|
90
128
|
it { should match('/') .capturing splat: '' }
|
91
129
|
it { should match('/foo') .capturing splat: 'foo' }
|
92
130
|
it { should match('/foo/bar') .capturing splat: 'foo/bar' }
|
131
|
+
it { should generate_template('/{+splat}') }
|
132
|
+
|
133
|
+
example { pattern.params('/foo').should be == {"splat" => ["foo"]} }
|
134
|
+
end
|
135
|
+
|
136
|
+
pattern '/{+splat}' do
|
137
|
+
it { should match('/') .capturing splat: '' }
|
138
|
+
it { should match('/foo') .capturing splat: 'foo' }
|
139
|
+
it { should match('/foo/bar') .capturing splat: 'foo/bar' }
|
140
|
+
it { should generate_template('/{+splat}') }
|
93
141
|
|
94
142
|
example { pattern.params('/foo').should be == {"splat" => ["foo"]} }
|
95
143
|
end
|
@@ -98,6 +146,17 @@ describe Mustermann::Sinatra do
|
|
98
146
|
it { should match('/') .capturing foo: '' }
|
99
147
|
it { should match('/foo') .capturing foo: 'foo' }
|
100
148
|
it { should match('/foo/bar') .capturing foo: 'foo/bar' }
|
149
|
+
it { should generate_template('/{+foo}') }
|
150
|
+
|
151
|
+
example { pattern.params('/foo') .should be == {"foo" => "foo" } }
|
152
|
+
example { pattern.params('/foo/bar') .should be == {"foo" => "foo/bar" } }
|
153
|
+
end
|
154
|
+
|
155
|
+
pattern '/{+foo}' do
|
156
|
+
it { should match('/') .capturing foo: '' }
|
157
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
158
|
+
it { should match('/foo/bar') .capturing foo: 'foo/bar' }
|
159
|
+
it { should generate_template('/{+foo}') }
|
101
160
|
|
102
161
|
example { pattern.params('/foo') .should be == {"foo" => "foo" } }
|
103
162
|
example { pattern.params('/foo/bar') .should be == {"foo" => "foo/bar" } }
|
@@ -105,6 +164,12 @@ describe Mustermann::Sinatra do
|
|
105
164
|
|
106
165
|
pattern '/*foo/*bar' do
|
107
166
|
it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
|
167
|
+
it { should generate_template('/{+foo}/{+bar}') }
|
168
|
+
end
|
169
|
+
|
170
|
+
pattern '/{+foo}/{+bar}' do
|
171
|
+
it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
|
172
|
+
it { should generate_template('/{+foo}/{+bar}') }
|
108
173
|
end
|
109
174
|
|
110
175
|
pattern '/:foo/*' do
|
@@ -112,6 +177,18 @@ describe Mustermann::Sinatra do
|
|
112
177
|
it { should match("/foo/") .capturing foo: 'foo', splat: '' }
|
113
178
|
it { should match('/h%20w/h%20a%20y') .capturing foo: 'h%20w', splat: 'h%20a%20y' }
|
114
179
|
it { should_not match('/foo') }
|
180
|
+
it { should generate_template('/{foo}/{+splat}') }
|
181
|
+
|
182
|
+
example { pattern.params('/bar/foo').should be == {"splat" => ["foo"], "foo" => "bar"} }
|
183
|
+
example { pattern.params('/bar/foo/f%20o').should be == {"splat" => ["foo/f o"], "foo" => "bar"} }
|
184
|
+
end
|
185
|
+
|
186
|
+
pattern '/{foo}/*' do
|
187
|
+
it { should match("/foo/bar/baz") .capturing foo: 'foo', splat: 'bar/baz' }
|
188
|
+
it { should match("/foo/") .capturing foo: 'foo', splat: '' }
|
189
|
+
it { should match('/h%20w/h%20a%20y') .capturing foo: 'h%20w', splat: 'h%20a%20y' }
|
190
|
+
it { should_not match('/foo') }
|
191
|
+
it { should generate_template('/{foo}/{+splat}') }
|
115
192
|
|
116
193
|
example { pattern.params('/bar/foo').should be == {"splat" => ["foo"], "foo" => "bar"} }
|
117
194
|
example { pattern.params('/bar/foo/f%20o').should be == {"splat" => ["foo/f o"], "foo" => "bar"} }
|
@@ -131,12 +208,18 @@ describe Mustermann::Sinatra do
|
|
131
208
|
it { should match('/path%20with%20spaces') }
|
132
209
|
it { should match('/path%2Bwith%2Bspaces') }
|
133
210
|
it { should match('/path+with+spaces') }
|
211
|
+
|
212
|
+
it { should generate_template('/path%20with%20spaces') }
|
134
213
|
end
|
135
214
|
|
136
215
|
pattern '/foo&bar' do
|
137
216
|
it { should match('/foo&bar') }
|
138
217
|
end
|
139
218
|
|
219
|
+
pattern '/foo\{bar' do
|
220
|
+
it { should match('/foo%7Bbar') }
|
221
|
+
end
|
222
|
+
|
140
223
|
pattern '/*/:foo/*/*' do
|
141
224
|
it { should match('/bar/foo/bling/baz/boom') }
|
142
225
|
|
@@ -153,13 +236,29 @@ describe Mustermann::Sinatra do
|
|
153
236
|
end
|
154
237
|
end
|
155
238
|
|
239
|
+
pattern '/{+splat}/{foo}/{+splat}/{+splat}' do
|
240
|
+
it { should match('/bar/foo/bling/baz/boom') }
|
241
|
+
|
242
|
+
it "should capture all splat parts" do
|
243
|
+
match = pattern.match('/bar/foo/bling/baz/boom')
|
244
|
+
match.captures.should be == ['bar', 'foo', 'bling', 'baz/boom']
|
245
|
+
match.names.should be == ['splat', 'foo']
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'should map to proper params' do
|
249
|
+
pattern.params('/bar/foo/bling/baz/boom').should be == {
|
250
|
+
"foo" => "foo", "splat" => ['bar', 'bling', 'baz/boom']
|
251
|
+
}
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
156
255
|
pattern '/test.bar' do
|
157
256
|
it { should match('/test.bar') }
|
158
257
|
it { should_not match('/test0bar') }
|
159
258
|
end
|
160
259
|
|
161
260
|
pattern '/:file.:ext' do
|
162
|
-
it { should match('/pony.jpg')
|
261
|
+
it { should match('/pony.jpg') .capturing file: 'pony', ext: 'jpg' }
|
163
262
|
it { should match('/pony%2Ejpg') .capturing file: 'pony', ext: 'jpg' }
|
164
263
|
it { should match('/pony%2ejpg') .capturing file: 'pony', ext: 'jpg' }
|
165
264
|
|
@@ -179,12 +278,18 @@ describe Mustermann::Sinatra do
|
|
179
278
|
it { should match('/ax') .capturing a: 'a' }
|
180
279
|
it { should match('/axax') .capturing a: 'axa' }
|
181
280
|
it { should match('/axaxx') .capturing a: 'axax' }
|
281
|
+
|
282
|
+
it { should generate_template('/{a}x') }
|
283
|
+
it { should generate_template('/{a}') }
|
182
284
|
end
|
183
285
|
|
184
286
|
pattern '/:user(@:host)?' do
|
185
287
|
it { should match('/foo@bar') .capturing user: 'foo', host: 'bar' }
|
186
288
|
it { should match('/foo.foo@bar') .capturing user: 'foo.foo', host: 'bar' }
|
187
289
|
it { should match('/foo@bar.bar') .capturing user: 'foo', host: 'bar.bar' }
|
290
|
+
|
291
|
+
it { should generate_template('/{user}') }
|
292
|
+
it { should generate_template('/{user}@{host}') }
|
188
293
|
end
|
189
294
|
|
190
295
|
pattern '/:file(.:ext)?' do
|
@@ -195,6 +300,10 @@ describe Mustermann::Sinatra do
|
|
195
300
|
it { should match('/pony.png.jpg') .capturing file: 'pony.png', ext: 'jpg' }
|
196
301
|
it { should match('/pony.') .capturing file: 'pony.' }
|
197
302
|
it { should_not match('/.jpg') }
|
303
|
+
|
304
|
+
it { should generate_template('/{file}') }
|
305
|
+
it { should generate_template('/{file}.{ext}') }
|
306
|
+
it { should_not generate_template('/{file}.') }
|
198
307
|
end
|
199
308
|
|
200
309
|
pattern '/:id/test.bar' do
|
@@ -323,6 +432,37 @@ describe Mustermann::Sinatra do
|
|
323
432
|
it { should match('/foo/bar/baz').capturing foo: 'foo', bar: 'bar', baz: 'baz' }
|
324
433
|
end
|
325
434
|
|
435
|
+
pattern "/(foo|bar)" do
|
436
|
+
it { should match("/foo") }
|
437
|
+
it { should match("/bar") }
|
438
|
+
|
439
|
+
it { should generate_template('/foo') }
|
440
|
+
it { should generate_template('/bar') }
|
441
|
+
end
|
442
|
+
|
443
|
+
pattern "/(foo\\|bar)" do
|
444
|
+
it { should match "/foo%7Cbar" }
|
445
|
+
it { should generate_template "/foo%7Cbar" }
|
446
|
+
|
447
|
+
it { should_not match("/foo") }
|
448
|
+
it { should_not match("/bar") }
|
449
|
+
|
450
|
+
it { should_not generate_template('/foo') }
|
451
|
+
it { should_not generate_template('/bar') }
|
452
|
+
end
|
453
|
+
|
454
|
+
pattern "/(:a/:b|:c)" do
|
455
|
+
it { should match("/foo") .capturing c: 'foo' }
|
456
|
+
it { should match("/foo/bar") .capturing a: 'foo', b: 'bar' }
|
457
|
+
|
458
|
+
it { should generate_template('/{a}/{b}') }
|
459
|
+
it { should generate_template('/{c}') }
|
460
|
+
|
461
|
+
it { should expand(a: 'foo', b: 'bar') .to('/foo/bar') }
|
462
|
+
it { should expand(c: 'foo') .to('/foo') }
|
463
|
+
it { should_not expand(a: 'foo', b: 'bar', c: 'baz') }
|
464
|
+
end
|
465
|
+
|
326
466
|
pattern '/:foo', capture: /\d+/ do
|
327
467
|
it { should match('/1') .capturing foo: '1' }
|
328
468
|
it { should match('/123') .capturing foo: '123' }
|
@@ -508,6 +648,11 @@ describe Mustermann::Sinatra do
|
|
508
648
|
to raise_error(Mustermann::ParseError, 'unexpected ? while parsing "foo??bar"')
|
509
649
|
end
|
510
650
|
|
651
|
+
example '| outside of group' do
|
652
|
+
expect { Mustermann::Sinatra.new('foo|bar') }.
|
653
|
+
to raise_error(Mustermann::ParseError, 'unexpected | while parsing "foo|bar"')
|
654
|
+
end
|
655
|
+
|
511
656
|
example 'dangling escape' do
|
512
657
|
expect { Mustermann::Sinatra.new('foo\\') }.
|
513
658
|
to raise_error(Mustermann::ParseError, 'unexpected end of string while parsing "foo\\\\"')
|
@@ -563,11 +708,41 @@ describe Mustermann::Sinatra do
|
|
563
708
|
end
|
564
709
|
|
565
710
|
describe :to_regexp do
|
566
|
-
example('empty pattern') { Mustermann::Sinatra.new('').to_regexp.should be == /\A\Z/ }
|
711
|
+
example('empty pattern') { Mustermann::Sinatra.new('').to_regexp.should be == /\A(?-mix:)\Z/ }
|
567
712
|
|
568
713
|
context 'Regexp.try_convert' do
|
569
|
-
example('empty pattern') { Regexp.try_convert(Mustermann::Sinatra.new('')).should be == /\A\Z/ }
|
714
|
+
example('empty pattern') { Regexp.try_convert(Mustermann::Sinatra.new('')).should be == /\A(?-mix:)\Z/ }
|
570
715
|
end
|
571
716
|
end
|
572
717
|
end
|
718
|
+
|
719
|
+
context 'Proc compatibility' do
|
720
|
+
describe :to_proc do
|
721
|
+
example { Mustermann::Sinatra.new("/").to_proc.should be_a(Proc) }
|
722
|
+
example('non-matching') { Mustermann::Sinatra.new("/") .to_proc.call('/foo').should be == false }
|
723
|
+
example('matching') { Mustermann::Sinatra.new("/:foo") .to_proc.call('/foo').should be == true }
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
context "peeking" do
|
728
|
+
subject(:pattern) { Mustermann::Sinatra.new(":name") }
|
729
|
+
|
730
|
+
describe :peek_size do
|
731
|
+
example { pattern.peek_size("foo bar/blah") .should be == "foo bar".size }
|
732
|
+
example { pattern.peek_size("foo%20bar/blah") .should be == "foo%20bar".size }
|
733
|
+
example { pattern.peek_size("/foo bar") .should be_nil }
|
734
|
+
end
|
735
|
+
|
736
|
+
describe :peek_match do
|
737
|
+
example { pattern.peek_match("foo bar/blah") .to_s .should be == "foo bar" }
|
738
|
+
example { pattern.peek_match("foo%20bar/blah") .to_s .should be == "foo%20bar" }
|
739
|
+
example { pattern.peek_match("/foo bar") .should be_nil }
|
740
|
+
end
|
741
|
+
|
742
|
+
describe :peek_params do
|
743
|
+
example { pattern.peek_params("foo bar/blah") .should be == [{"name" => "foo bar"}, "foo bar".size] }
|
744
|
+
example { pattern.peek_params("foo%20bar/blah") .should be == [{"name" => "foo bar"}, "foo%20bar".size] }
|
745
|
+
example { pattern.peek_params("/foo bar") .should be_nil }
|
746
|
+
end
|
747
|
+
end
|
573
748
|
end
|
data/spec/to_pattern_spec.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'support'
|
2
2
|
require 'mustermann/to_pattern'
|
3
|
+
require 'delegate'
|
3
4
|
|
4
5
|
describe Mustermann::ToPattern do
|
5
6
|
context String do
|
@@ -12,9 +13,57 @@ describe Mustermann::ToPattern do
|
|
12
13
|
example { //.to_pattern(type: :rails) .should be_a(Mustermann::Regular) }
|
13
14
|
end
|
14
15
|
|
16
|
+
context Symbol do
|
17
|
+
example { :foo.to_pattern .should be_a(Mustermann::Sinatra) }
|
18
|
+
example { :foo.to_pattern(type: :rails) .should be_a(Mustermann::Sinatra) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context Array do
|
22
|
+
example { [:foo, :bar].to_pattern .should be_a(Mustermann::Composite) }
|
23
|
+
example { [:foo, :bar].to_pattern(type: :rails) .should be_a(Mustermann::Composite) }
|
24
|
+
end
|
25
|
+
|
15
26
|
context Mustermann::Pattern do
|
16
27
|
subject(:pattern) { Mustermann.new('') }
|
17
28
|
example { pattern.to_pattern.should be == pattern }
|
18
29
|
example { pattern.to_pattern(type: :rails).should be_a(Mustermann::Sinatra) }
|
19
30
|
end
|
31
|
+
|
32
|
+
context 'custom class' do
|
33
|
+
let(:example_class) do
|
34
|
+
Class.new do
|
35
|
+
include Mustermann::ToPattern
|
36
|
+
def to_s
|
37
|
+
":foo/:bar"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
example { example_class.new.to_pattern .should be_a(Mustermann::Sinatra) }
|
43
|
+
example { example_class.new.to_pattern(type: :rails) .should be_a(Mustermann::Rails) }
|
44
|
+
example { Mustermann.new(example_class.new) .should be_a(Mustermann::Sinatra) }
|
45
|
+
example { Mustermann.new(example_class.new, type: :rails) .should be_a(Mustermann::Rails) }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'primitive delegate' do
|
49
|
+
let(:example_class) do
|
50
|
+
Class.new(DelegateClass(Array)) do
|
51
|
+
include Mustermann::ToPattern
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
example { example_class.new([:foo, :bar]).to_pattern .should be_a(Mustermann::Composite) }
|
56
|
+
example { example_class.new([:foo, :bar]).to_pattern(type: :rails) .should be_a(Mustermann::Composite) }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'primitive subclass' do
|
60
|
+
let(:example_class) do
|
61
|
+
Class.new(Array) do
|
62
|
+
include Mustermann::ToPattern
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
example { example_class.new([:foo, :bar]).to_pattern .should be_a(Mustermann::Composite) }
|
67
|
+
example { example_class.new([:foo, :bar]).to_pattern(type: :rails) .should be_a(Mustermann::Composite) }
|
68
|
+
end
|
20
69
|
end
|