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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +429 -672
  3. data/lib/mustermann.rb +95 -20
  4. data/lib/mustermann/ast/boundaries.rb +44 -0
  5. data/lib/mustermann/ast/compiler.rb +13 -7
  6. data/lib/mustermann/ast/expander.rb +22 -12
  7. data/lib/mustermann/ast/node.rb +69 -5
  8. data/lib/mustermann/ast/param_scanner.rb +20 -0
  9. data/lib/mustermann/ast/parser.rb +138 -19
  10. data/lib/mustermann/ast/pattern.rb +59 -7
  11. data/lib/mustermann/ast/template_generator.rb +28 -0
  12. data/lib/mustermann/ast/transformer.rb +2 -2
  13. data/lib/mustermann/ast/translator.rb +20 -0
  14. data/lib/mustermann/ast/validation.rb +4 -3
  15. data/lib/mustermann/composite.rb +101 -0
  16. data/lib/mustermann/expander.rb +2 -2
  17. data/lib/mustermann/identity.rb +56 -0
  18. data/lib/mustermann/pattern.rb +185 -10
  19. data/lib/mustermann/pattern_cache.rb +49 -0
  20. data/lib/mustermann/regexp.rb +1 -0
  21. data/lib/mustermann/regexp_based.rb +18 -1
  22. data/lib/mustermann/regular.rb +4 -1
  23. data/lib/mustermann/simple_match.rb +5 -0
  24. data/lib/mustermann/sinatra.rb +22 -5
  25. data/lib/mustermann/to_pattern.rb +11 -6
  26. data/lib/mustermann/version.rb +1 -1
  27. data/mustermann.gemspec +1 -14
  28. data/spec/ast_spec.rb +14 -0
  29. data/spec/composite_spec.rb +147 -0
  30. data/spec/expander_spec.rb +15 -0
  31. data/spec/identity_spec.rb +44 -0
  32. data/spec/mustermann_spec.rb +17 -2
  33. data/spec/pattern_spec.rb +7 -3
  34. data/spec/regular_spec.rb +25 -0
  35. data/spec/sinatra_spec.rb +184 -9
  36. data/spec/to_pattern_spec.rb +49 -0
  37. metadata +15 -180
  38. data/.gitignore +0 -18
  39. data/.rspec +0 -2
  40. data/.travis.yml +0 -4
  41. data/.yardopts +0 -1
  42. data/Gemfile +0 -2
  43. data/LICENSE +0 -22
  44. data/Rakefile +0 -6
  45. data/internals.md +0 -64
  46. data/lib/mustermann/ast/tree_renderer.rb +0 -29
  47. data/lib/mustermann/rails.rb +0 -17
  48. data/lib/mustermann/shell.rb +0 -29
  49. data/lib/mustermann/simple.rb +0 -35
  50. data/lib/mustermann/template.rb +0 -47
  51. data/spec/rails_spec.rb +0 -521
  52. data/spec/shell_spec.rb +0 -108
  53. data/spec/simple_spec.rb +0 -236
  54. data/spec/support.rb +0 -5
  55. data/spec/support/coverage.rb +0 -16
  56. data/spec/support/env.rb +0 -16
  57. data/spec/support/expand_matcher.rb +0 -27
  58. data/spec/support/match_matcher.rb +0 -39
  59. data/spec/support/pattern.rb +0 -39
  60. data/spec/template_spec.rb +0 -814
@@ -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] }.to raise_error(ArgumentError, "unsupported type :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
@@ -20,10 +20,14 @@ describe Mustermann::Pattern do
20
20
  end
21
21
  end
22
22
 
23
- describe :expand do
23
+ describe :respond_to? do
24
24
  subject(:pattern) { Mustermann::Pattern.new("") }
25
- it { should_not respond_to(:expand) }
26
- it { expect { pattern.expand }.to raise_error(NotImplementedError) }
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
@@ -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
@@ -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 { should_not match('/hello/world/') }
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
- # it { should expand(foo: 'hello') .to('/hello') }
79
- # it { should expand(foo: 'hello', bar: 'world') .to('/hello/world') }
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') .capturing file: 'pony', ext: '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
@@ -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