mustermann 3.0.3 → 3.1.1

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.
data/spec/sinatra_spec.rb DELETED
@@ -1,836 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'support'
3
- require 'mustermann/sinatra'
4
-
5
- describe Mustermann::Sinatra do
6
- extend Support::Pattern
7
-
8
- pattern '' do
9
- it { should match('') }
10
- it { should_not match('/') }
11
-
12
- it { should generate_template('') }
13
-
14
- it { should respond_to(:expand) }
15
- it { should respond_to(:to_templates) }
16
- end
17
-
18
- pattern '/' do
19
- it { should match('/') }
20
- it { should_not match('/foo') }
21
- end
22
-
23
- pattern '/foo' do
24
- it { should match('/foo') }
25
- it { should_not match('/bar') }
26
- it { should_not match('/foo.bar') }
27
- end
28
-
29
- pattern '/foo/bar' do
30
- it { should match('/foo/bar') }
31
- it { should_not match('/foo%2Fbar') }
32
- it { should_not match('/foo%2fbar') }
33
- end
34
-
35
- pattern '/foo\/bar' do
36
- it { should match('/foo/bar') }
37
- it { should match('/foo%2Fbar') }
38
- it { should match('/foo%2fbar') }
39
- end
40
-
41
- pattern '/:foo' do
42
- it { should match('/foo') .capturing foo: 'foo' }
43
- it { should match('/bar') .capturing foo: 'bar' }
44
- it { should match('/foo.bar') .capturing foo: 'foo.bar' }
45
- it { should match('/%0Afoo') .capturing foo: '%0Afoo' }
46
- it { should match('/foo%2Fbar') .capturing foo: 'foo%2Fbar' }
47
-
48
- it { should_not match('/foo?') }
49
- it { should_not match('/foo/bar') }
50
- it { should_not match('/') }
51
- it { should_not match('/foo/') }
52
-
53
- it { should generate_template('/{foo}') }
54
- end
55
-
56
- pattern '/föö' do
57
- it { should match("/f%C3%B6%C3%B6") }
58
- end
59
-
60
- pattern "/:foo/:bar" do
61
- it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
62
- it { should match('/foo.bar/bar.foo') .capturing foo: 'foo.bar', bar: 'bar.foo' }
63
- it { should match('/user@example.com/name') .capturing foo: 'user@example.com', bar: 'name' }
64
- it { should match('/10.1/te.st') .capturing foo: '10.1', bar: 'te.st' }
65
- it { should match('/10.1.2/te.st') .capturing foo: '10.1.2', bar: 'te.st' }
66
-
67
- it { should_not match('/foo%2Fbar') }
68
- it { should_not match('/foo%2fbar') }
69
-
70
- example { pattern.params('/bar/foo').should be == {"foo" => "bar", "bar" => "foo"} }
71
- example { pattern.params('').should be_nil }
72
-
73
- it { should generate_template('/{foo}/{bar}') }
74
- end
75
-
76
- pattern "/{foo}/{bar}" do
77
- it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
78
- it { should match('/foo.bar/bar.foo') .capturing foo: 'foo.bar', bar: 'bar.foo' }
79
- it { should match('/user@example.com/name') .capturing foo: 'user@example.com', bar: 'name' }
80
- it { should match('/10.1/te.st') .capturing foo: '10.1', bar: 'te.st' }
81
- it { should match('/10.1.2/te.st') .capturing foo: '10.1.2', bar: 'te.st' }
82
-
83
- it { should_not match('/foo%2Fbar') }
84
- it { should_not match('/foo%2fbar') }
85
-
86
- example { pattern.params('/bar/foo').should be == {"foo" => "bar", "bar" => "foo"} }
87
- example { pattern.params('').should be_nil }
88
-
89
- it { should generate_template('/{foo}/{bar}') }
90
- end
91
-
92
- pattern '/hello/:person' do
93
- it { should match('/hello/Frank').capturing person: 'Frank' }
94
- it { should generate_template('/hello/{person}') }
95
- end
96
-
97
- pattern '/hello/{person}' do
98
- it { should match('/hello/Frank').capturing person: 'Frank' }
99
- it { should generate_template('/hello/{person}') }
100
- end
101
-
102
- pattern '/?:foo?/?:bar?' do
103
- it { should match('/hello/world') .capturing foo: 'hello', bar: 'world' }
104
- it { should match('/hello') .capturing foo: 'hello', bar: nil }
105
- it { should match('/') .capturing foo: nil, bar: nil }
106
- it { should match('') .capturing foo: nil, bar: nil }
107
-
108
- it { should expand(foo: 'hello') .to('/hello/') }
109
- it { should expand(foo: 'hello', bar: 'world') .to('/hello/world') }
110
- it { should expand(bar: 'world') .to('//world') }
111
- it { should expand .to('//') }
112
- it { should_not expand(baz: '') }
113
-
114
- it { should_not match('/hello/world/') }
115
- it { should generate_templates("", "/", "//", "//{bar}", "/{bar}", "/{foo}", "/{foo}/", "/{foo}/{bar}", "/{foo}{bar}", "{bar}", "{foo}", "{foo}/", "{foo}/{bar}", "{foo}{bar}") }
116
- end
117
-
118
- pattern '/:foo_bar' do
119
- it { should match('/hello').capturing foo_bar: 'hello' }
120
- it { should generate_template('/{foo_bar}') }
121
- end
122
-
123
- pattern '/{foo.bar}' do
124
- it { should match('/hello').capturing :"foo.bar" => 'hello' }
125
- it { should generate_template('/{foo.bar}') }
126
- end
127
-
128
- pattern '/*' do
129
- it { should match('/') .capturing splat: '' }
130
- it { should match('/foo') .capturing splat: 'foo' }
131
- it { should match('/foo/bar') .capturing splat: 'foo/bar' }
132
- it { should generate_template('/{+splat}') }
133
-
134
- example { pattern.params('/foo').should be == {"splat" => ["foo"]} }
135
- end
136
-
137
- pattern '/{+splat}' do
138
- it { should match('/') .capturing splat: '' }
139
- it { should match('/foo') .capturing splat: 'foo' }
140
- it { should match('/foo/bar') .capturing splat: 'foo/bar' }
141
- it { should generate_template('/{+splat}') }
142
-
143
- example { pattern.params('/foo').should be == {"splat" => ["foo"]} }
144
- end
145
-
146
- pattern '/*foo' do
147
- it { should match('/') .capturing foo: '' }
148
- it { should match('/foo') .capturing foo: 'foo' }
149
- it { should match('/foo/bar') .capturing foo: 'foo/bar' }
150
- it { should generate_template('/{+foo}') }
151
-
152
- example { pattern.params('/foo') .should be == {"foo" => "foo" } }
153
- example { pattern.params('/foo/bar') .should be == {"foo" => "foo/bar" } }
154
- end
155
-
156
- pattern '/{+foo}' do
157
- it { should match('/') .capturing foo: '' }
158
- it { should match('/foo') .capturing foo: 'foo' }
159
- it { should match('/foo/bar') .capturing foo: 'foo/bar' }
160
- it { should generate_template('/{+foo}') }
161
-
162
- example { pattern.params('/foo') .should be == {"foo" => "foo" } }
163
- example { pattern.params('/foo/bar') .should be == {"foo" => "foo/bar" } }
164
- end
165
-
166
- pattern '/*foo/*bar' do
167
- it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
168
- it { should generate_template('/{+foo}/{+bar}') }
169
- end
170
-
171
- pattern '/{+foo}/{+bar}' do
172
- it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
173
- it { should generate_template('/{+foo}/{+bar}') }
174
- end
175
-
176
- pattern '/:foo/*' do
177
- it { should match("/foo/bar/baz") .capturing foo: 'foo', splat: 'bar/baz' }
178
- it { should match("/foo/") .capturing foo: 'foo', splat: '' }
179
- it { should match('/h%20w/h%20a%20y') .capturing foo: 'h%20w', splat: 'h%20a%20y' }
180
- it { should_not match('/foo') }
181
- it { should generate_template('/{foo}/{+splat}') }
182
-
183
- example { pattern.params('/bar/foo').should be == {"splat" => ["foo"], "foo" => "bar"} }
184
- example { pattern.params('/bar/foo/f%20o').should be == {"splat" => ["foo/f o"], "foo" => "bar"} }
185
- end
186
-
187
- pattern '/{foo}/*' do
188
- it { should match("/foo/bar/baz") .capturing foo: 'foo', splat: 'bar/baz' }
189
- it { should match("/foo/") .capturing foo: 'foo', splat: '' }
190
- it { should match('/h%20w/h%20a%20y') .capturing foo: 'h%20w', splat: 'h%20a%20y' }
191
- it { should_not match('/foo') }
192
- it { should generate_template('/{foo}/{+splat}') }
193
-
194
- example { pattern.params('/bar/foo').should be == {"splat" => ["foo"], "foo" => "bar"} }
195
- example { pattern.params('/bar/foo/f%20o').should be == {"splat" => ["foo/f o"], "foo" => "bar"} }
196
- end
197
-
198
- pattern '/test$/' do
199
- it { should match('/test$/') }
200
- end
201
-
202
- pattern '/te+st/' do
203
- it { should match('/te+st/') }
204
- it { should_not match('/test/') }
205
- it { should_not match('/teest/') }
206
- end
207
-
208
- pattern "/path with spaces" do
209
- it { should match('/path%20with%20spaces') }
210
- it { should match('/path%2Bwith%2Bspaces') }
211
- it { should match('/path+with+spaces') }
212
-
213
- it { should generate_template('/path%20with%20spaces') }
214
- end
215
-
216
- pattern '/foo&bar' do
217
- it { should match('/foo&bar') }
218
- end
219
-
220
- pattern '/foo\{bar' do
221
- it { should match('/foo%7Bbar') }
222
- end
223
-
224
- pattern '/*/:foo/*/*' do
225
- it { should match('/bar/foo/bling/baz/boom') }
226
-
227
- it "should capture all splat parts" do
228
- match = pattern.match('/bar/foo/bling/baz/boom')
229
- match.captures.should be == ['bar', 'foo', 'bling', 'baz/boom']
230
- match.names.should be == ['splat', 'foo']
231
- end
232
-
233
- it 'should map to proper params' do
234
- pattern.params('/bar/foo/bling/baz/boom').should be == {
235
- "foo" => "foo", "splat" => ['bar', 'bling', 'baz/boom']
236
- }
237
- end
238
- end
239
-
240
- pattern '/{+splat}/{foo}/{+splat}/{+splat}' do
241
- it { should match('/bar/foo/bling/baz/boom') }
242
-
243
- it "should capture all splat parts" do
244
- match = pattern.match('/bar/foo/bling/baz/boom')
245
- match.captures.should be == ['bar', 'foo', 'bling', 'baz/boom']
246
- match.names.should be == ['splat', 'foo']
247
- end
248
-
249
- it 'should map to proper params' do
250
- pattern.params('/bar/foo/bling/baz/boom').should be == {
251
- "foo" => "foo", "splat" => ['bar', 'bling', 'baz/boom']
252
- }
253
- end
254
- end
255
-
256
- pattern '/test.bar' do
257
- it { should match('/test.bar') }
258
- it { should_not match('/test0bar') }
259
- end
260
-
261
- pattern '/:file.:ext' do
262
- it { should match('/pony.jpg') .capturing file: 'pony', ext: 'jpg' }
263
- it { should match('/pony%2Ejpg') .capturing file: 'pony', ext: 'jpg' }
264
- it { should match('/pony%2ejpg') .capturing file: 'pony', ext: 'jpg' }
265
-
266
- it { should match('/pony%E6%AD%A3%2Ejpg') .capturing file: 'pony%E6%AD%A3', ext: 'jpg' }
267
- it { should match('/pony%e6%ad%a3%2ejpg') .capturing file: 'pony%e6%ad%a3', ext: 'jpg' }
268
- it { should match('/pony正%2Ejpg') .capturing file: 'pony正', ext: 'jpg' }
269
- it { should match('/pony正%2ejpg') .capturing file: 'pony正', ext: 'jpg' }
270
- it { should match('/pony正..jpg') .capturing file: 'pony正.', ext: 'jpg' }
271
-
272
- it { should_not match('/.jpg') }
273
- end
274
-
275
- pattern '/(:a)x?' do
276
- it { should match('/a') .capturing a: 'a' }
277
- it { should match('/xa') .capturing a: 'xa' }
278
- it { should match('/axa') .capturing a: 'axa' }
279
- it { should match('/ax') .capturing a: 'a' }
280
- it { should match('/axax') .capturing a: 'axa' }
281
- it { should match('/axaxx') .capturing a: 'axax' }
282
-
283
- it { should generate_template('/{a}x') }
284
- it { should generate_template('/{a}') }
285
- end
286
-
287
- pattern '/:user(@:host)?' do
288
- it { should match('/foo@bar') .capturing user: 'foo', host: 'bar' }
289
- it { should match('/foo.foo@bar') .capturing user: 'foo.foo', host: 'bar' }
290
- it { should match('/foo@bar.bar') .capturing user: 'foo', host: 'bar.bar' }
291
-
292
- it { should generate_template('/{user}') }
293
- it { should generate_template('/{user}@{host}') }
294
- end
295
-
296
- pattern '/:file(.:ext)?' do
297
- it { should match('/pony') .capturing file: 'pony', ext: nil }
298
- it { should match('/pony.jpg') .capturing file: 'pony', ext: 'jpg' }
299
- it { should match('/pony%2Ejpg') .capturing file: 'pony', ext: 'jpg' }
300
- it { should match('/pony%2ejpg') .capturing file: 'pony', ext: 'jpg' }
301
- it { should match('/pony.png.jpg') .capturing file: 'pony.png', ext: 'jpg' }
302
- it { should match('/pony.') .capturing file: 'pony.' }
303
- it { should_not match('/.jpg') }
304
-
305
- it { should generate_template('/{file}') }
306
- it { should generate_template('/{file}.{ext}') }
307
- it { should_not generate_template('/{file}.') }
308
- end
309
-
310
- pattern '/:id/test.bar' do
311
- it { should match('/3/test.bar') .capturing id: '3' }
312
- it { should match('/2/test.bar') .capturing id: '2' }
313
- it { should match('/2E/test.bar') .capturing id: '2E' }
314
- it { should match('/2e/test.bar') .capturing id: '2e' }
315
- it { should match('/%2E/test.bar') .capturing id: '%2E' }
316
- end
317
-
318
- pattern '/10/:id' do
319
- it { should match('/10/test') .capturing id: 'test' }
320
- it { should match('/10/te.st') .capturing id: 'te.st' }
321
- end
322
-
323
- pattern '/10.1/:id' do
324
- it { should match('/10.1/test') .capturing id: 'test' }
325
- it { should match('/10.1/te.st') .capturing id: 'te.st' }
326
- end
327
-
328
- pattern '/:foo.:bar/:id' do
329
- it { should match('/10.1/te.st') .capturing foo: "10", bar: "1", id: "te.st" }
330
- it { should match('/10.1.2/te.st') .capturing foo: "10.1", bar: "2", id: "te.st" }
331
- end
332
-
333
- pattern '/:a/:b.?:c?' do
334
- it { should match('/a/b') .capturing a: 'a', b: 'b', c: nil }
335
- it { should match('/a/b.c') .capturing a: 'a', b: 'b', c: 'c' }
336
- it { should match('/a.b/c') .capturing a: 'a.b', b: 'c', c: nil }
337
- it { should match('/a.b/c.d') .capturing a: 'a.b', b: 'c', c: 'd' }
338
- it { should_not match('/a.b/c.d/e') }
339
- end
340
-
341
- pattern '/:a(foo:b)?' do
342
- it { should match('/barfoobar') .capturing a: 'bar', b: 'bar' }
343
- it { should match('/barfoobarfoobar') .capturing a: 'barfoobar', b: 'bar' }
344
- it { should match('/bar') .capturing a: 'bar', b: nil }
345
- it { should_not match('/') }
346
- end
347
-
348
- pattern '/foo?' do
349
- it { should match('/fo') }
350
- it { should match('/foo') }
351
- it { should_not match('') }
352
- it { should_not match('/') }
353
- it { should_not match('/f') }
354
- it { should_not match('/fooo') }
355
- end
356
-
357
- pattern '/foo\?' do
358
- it { should match('/foo?') }
359
- it { should_not match('/foo\?') }
360
- it { should_not match('/fo') }
361
- it { should_not match('/foo') }
362
- it { should_not match('') }
363
- it { should_not match('/') }
364
- it { should_not match('/f') }
365
- it { should_not match('/fooo') }
366
- end
367
-
368
- pattern '/foo\\\?' do
369
- it { should match('/foo%5c') }
370
- it { should match('/foo') }
371
- it { should_not match('/foo\?') }
372
- it { should_not match('/fo') }
373
- it { should_not match('') }
374
- it { should_not match('/') }
375
- it { should_not match('/f') }
376
- it { should_not match('/fooo') }
377
- end
378
-
379
- pattern '/\(' do
380
- it { should match('/(') }
381
- end
382
-
383
- pattern '/\(?' do
384
- it { should match('/(') }
385
- it { should match('/') }
386
- end
387
-
388
- pattern '/(\()?' do
389
- it { should match('/(') }
390
- it { should match('/') }
391
- end
392
-
393
- pattern '/(\(\))?' do
394
- it { should match('/') }
395
- it { should match('/()') }
396
- it { should_not match('/(') }
397
- end
398
-
399
- pattern '/\(\)?' do
400
- it { should match('/(') }
401
- it { should match('/()') }
402
- it { should_not match('/') }
403
- end
404
-
405
- pattern '/\*' do
406
- it { should match('/*') }
407
- it { should_not match('/a') }
408
- end
409
-
410
- pattern '/\*/*' do
411
- it { should match('/*/b/c') }
412
- it { should_not match('/a/b/c') }
413
- end
414
-
415
- pattern '/\:foo' do
416
- it { should match('/:foo') }
417
- it { should_not match('/foo') }
418
- end
419
-
420
- pattern '/:fOO' do
421
- it { should match('/a').capturing fOO: 'a' }
422
- end
423
-
424
- pattern '/:_X' do
425
- it { should match('/a').capturing _X: 'a' }
426
- end
427
-
428
- pattern '/:f00' do
429
- it { should match('/a').capturing f00: 'a' }
430
- end
431
-
432
- pattern '/:foo(/:bar)?/:baz?' do
433
- it { should match('/foo/bar/baz').capturing foo: 'foo', bar: 'bar', baz: 'baz' }
434
- end
435
-
436
- pattern "/(foo|bar)" do
437
- it { should match("/foo") }
438
- it { should match("/bar") }
439
-
440
- it { should generate_template('/foo') }
441
- it { should generate_template('/bar') }
442
- end
443
-
444
- pattern "/(foo\\|bar)" do
445
- it { should match "/foo%7Cbar" }
446
- it { should generate_template "/foo%7Cbar" }
447
-
448
- it { should_not match("/foo") }
449
- it { should_not match("/bar") }
450
-
451
- it { should_not generate_template('/foo') }
452
- it { should_not generate_template('/bar') }
453
- end
454
-
455
- pattern "/(:a/:b|:c)" do
456
- it { should match("/foo") .capturing c: 'foo' }
457
- it { should match("/foo/bar") .capturing a: 'foo', b: 'bar' }
458
-
459
- it { should generate_template('/{a}/{b}') }
460
- it { should generate_template('/{c}') }
461
-
462
- it { should expand(a: 'foo', b: 'bar') .to('/foo/bar') }
463
- it { should expand(c: 'foo') .to('/foo') }
464
- it { should_not expand(a: 'foo', b: 'bar', c: 'baz') }
465
- end
466
-
467
- pattern "/:a/:b|:c" do
468
- it { should match("foo") .capturing c: 'foo' }
469
- it { should match("/foo/bar") .capturing a: 'foo', b: 'bar' }
470
-
471
- it { should generate_template('/{a}/{b}') }
472
- it { should generate_template('{c}') }
473
-
474
- it { should expand(a: 'foo', b: 'bar') .to('/foo/bar') }
475
- it { should expand(c: 'foo') .to('foo') }
476
- it { should_not expand(a: 'foo', b: 'bar', c: 'baz') }
477
- end
478
-
479
- pattern "/({foo}|{bar})", capture: { foo: /\d+/, bar: /\w+/ } do
480
- it { should match("/a") .capturing foo: nil, bar: 'a' }
481
- it { should match("/1234") .capturing foo: "1234", bar: nil }
482
-
483
- it { should_not match("/a/b") }
484
- end
485
-
486
- pattern "/{foo|bar}", capture: { foo: /\d+/, bar: /\w+/ } do
487
- it { should match("/a") .capturing foo: nil, bar: 'a' }
488
- it { should match("/1234") .capturing foo: "1234", bar: nil }
489
-
490
- it { should_not match("/a/b") }
491
- end
492
-
493
- pattern "/{foo|bar|baz}", capture: { foo: /\d+/, bar: /[ab]+/, baz: /[cde]+/ } do
494
- it { should match("/ab") .capturing foo: nil, bar: 'ab', baz: nil }
495
- it { should match("/1234") .capturing foo: "1234", bar: nil, baz: nil }
496
- it { should match("/ccddee") .capturing foo: nil, bar: nil, baz: "ccddee" }
497
-
498
- it { should_not match("/a/b") }
499
- end
500
-
501
- pattern '/:foo', capture: /\d+/ do
502
- it { should match('/1') .capturing foo: '1' }
503
- it { should match('/123') .capturing foo: '123' }
504
-
505
- it { should_not match('/') }
506
- it { should_not match('/foo') }
507
- end
508
-
509
- pattern '/:foo', capture: /\d+/ do
510
- it { should match('/1') .capturing foo: '1' }
511
- it { should match('/123') .capturing foo: '123' }
512
-
513
- it { should_not match('/') }
514
- it { should_not match('/foo') }
515
- end
516
-
517
- pattern '/:foo', capture: '1' do
518
- it { should match('/1').capturing foo: '1' }
519
-
520
- it { should_not match('/') }
521
- it { should_not match('/foo') }
522
- it { should_not match('/123') }
523
- end
524
-
525
- pattern '/:foo', capture: 'a.b' do
526
- it { should match('/a.b') .capturing foo: 'a.b' }
527
- it { should match('/a%2Eb') .capturing foo: 'a%2Eb' }
528
- it { should match('/a%2eb') .capturing foo: 'a%2eb' }
529
-
530
- it { should_not match('/ab') }
531
- it { should_not match('/afb') }
532
- it { should_not match('/a1b') }
533
- it { should_not match('/a.bc') }
534
- end
535
-
536
- pattern '/:foo(/:bar)?', capture: :alpha do
537
- it { should match('/abc') .capturing foo: 'abc', bar: nil }
538
- it { should match('/a/b') .capturing foo: 'a', bar: 'b' }
539
- it { should match('/a') .capturing foo: 'a', bar: nil }
540
-
541
- it { should_not match('/1/2') }
542
- it { should_not match('/a/2') }
543
- it { should_not match('/1/b') }
544
- it { should_not match('/1') }
545
- it { should_not match('/1/') }
546
- it { should_not match('/a/') }
547
- it { should_not match('//a') }
548
- end
549
-
550
- pattern '/:foo', capture: ['foo', 'bar', /\d+/] do
551
- it { should match('/1') .capturing foo: '1' }
552
- it { should match('/123') .capturing foo: '123' }
553
- it { should match('/foo') .capturing foo: 'foo' }
554
- it { should match('/bar') .capturing foo: 'bar' }
555
-
556
- it { should_not match('/') }
557
- it { should_not match('/baz') }
558
- it { should_not match('/foo1') }
559
- end
560
-
561
- pattern '/:foo:bar:baz', capture: { foo: :alpha, bar: /\d+/ } do
562
- it { should match('/ab123xy-1') .capturing foo: 'ab', bar: '123', baz: 'xy-1' }
563
- it { should match('/ab123') .capturing foo: 'ab', bar: '12', baz: '3' }
564
- it { should_not match('/123abcxy-1') }
565
- it { should_not match('/abcxy-1') }
566
- it { should_not match('/abc1') }
567
- end
568
-
569
- pattern '/:foo', capture: { foo: ['foo', 'bar', /\d+/] } do
570
- it { should match('/1') .capturing foo: '1' }
571
- it { should match('/123') .capturing foo: '123' }
572
- it { should match('/foo') .capturing foo: 'foo' }
573
- it { should match('/bar') .capturing foo: 'bar' }
574
-
575
- it { should_not match('/') }
576
- it { should_not match('/baz') }
577
- it { should_not match('/foo1') }
578
- end
579
-
580
- pattern '/:file(.:ext)?', capture: { ext: ['jpg', 'png'] } do
581
- it { should match('/pony') .capturing file: 'pony', ext: nil }
582
- it { should match('/pony.jpg') .capturing file: 'pony', ext: 'jpg' }
583
- it { should match('/pony%2Ejpg') .capturing file: 'pony', ext: 'jpg' }
584
- it { should match('/pony%2ejpg') .capturing file: 'pony', ext: 'jpg' }
585
- it { should match('/pony.png') .capturing file: 'pony', ext: 'png' }
586
- it { should match('/pony%2Epng') .capturing file: 'pony', ext: 'png' }
587
- it { should match('/pony%2epng') .capturing file: 'pony', ext: 'png' }
588
- it { should match('/pony.png.jpg') .capturing file: 'pony.png', ext: 'jpg' }
589
- it { should match('/pony.jpg.png') .capturing file: 'pony.jpg', ext: 'png' }
590
- it { should match('/pony.gif') .capturing file: 'pony.gif', ext: nil }
591
- it { should match('/pony.') .capturing file: 'pony.', ext: nil }
592
- it { should_not match('.jpg') }
593
- end
594
-
595
- pattern '/:file:ext?', capture: { ext: ['.jpg', '.png', '.tar.gz'] } do
596
- it { should match('/pony') .capturing file: 'pony', ext: nil }
597
- it { should match('/pony.jpg') .capturing file: 'pony', ext: '.jpg' }
598
- it { should match('/pony.png') .capturing file: 'pony', ext: '.png' }
599
- it { should match('/pony.png.jpg') .capturing file: 'pony.png', ext: '.jpg' }
600
- it { should match('/pony.jpg.png') .capturing file: 'pony.jpg', ext: '.png' }
601
- it { should match('/pony.tar.gz') .capturing file: 'pony', ext: '.tar.gz' }
602
- it { should match('/pony.gif') .capturing file: 'pony.gif', ext: nil }
603
- it { should match('/pony.') .capturing file: 'pony.', ext: nil }
604
- it { should_not match('/.jpg') }
605
- end
606
-
607
- pattern '/:a(@:b)?', capture: { b: /\d+/ } do
608
- it { should match('/a') .capturing a: 'a', b: nil }
609
- it { should match('/a@1') .capturing a: 'a', b: '1' }
610
- it { should match('/a@b') .capturing a: 'a@b', b: nil }
611
- it { should match('/a@1@2') .capturing a: 'a@1', b: '2' }
612
- end
613
-
614
- pattern '/(:a)b?', greedy: false do
615
- it { should match('/ab').capturing a: 'a' }
616
- end
617
-
618
- pattern '/:file(.:ext)?', greedy: false do
619
- it { should match('/pony') .capturing file: 'pony', ext: nil }
620
- it { should match('/pony.jpg') .capturing file: 'pony', ext: 'jpg' }
621
- it { should match('/pony.png.jpg') .capturing file: 'pony', ext: 'png.jpg' }
622
- end
623
-
624
- pattern '/auth/*', except: '/auth/login' do
625
- it { should match('/auth/admin') }
626
- it { should match('/auth/foobar') }
627
- it { should_not match('/auth/login') }
628
- end
629
-
630
- pattern '/:foo/:bar', except: '/:bar/20' do
631
- it { should match('/foo/bar').capturing foo: 'foo', bar: 'bar' }
632
- it { should_not match('/20/20') }
633
- end
634
-
635
- pattern '/foo?', uri_decode: false do
636
- it { should match('/foo') }
637
- it { should match('/fo') }
638
- it { should_not match('/foo?') }
639
- end
640
-
641
- pattern '/foo/bar', uri_decode: false do
642
- it { should match('/foo/bar') }
643
- it { should_not match('/foo%2Fbar') }
644
- it { should_not match('/foo%2fbar') }
645
- end
646
-
647
- pattern "/path with spaces", uri_decode: false do
648
- it { should match('/path with spaces') }
649
- it { should_not match('/path%20with%20spaces') }
650
- it { should_not match('/path%2Bwith%2Bspaces') }
651
- it { should_not match('/path+with+spaces') }
652
- end
653
-
654
- pattern "/path with spaces", space_matches_plus: false do
655
- it { should match('/path%20with%20spaces') }
656
- it { should_not match('/path%2Bwith%2Bspaces') }
657
- it { should_not match('/path+with+spaces') }
658
- end
659
-
660
- context 'invalid syntax' do
661
- example 'unexpected closing parenthesis' do
662
- expect { Mustermann::Sinatra.new('foo)bar') }.
663
- to raise_error(Mustermann::ParseError, 'unexpected ) while parsing "foo)bar"')
664
- end
665
-
666
- example 'missing closing parenthesis' do
667
- expect { Mustermann::Sinatra.new('foo(bar') }.
668
- to raise_error(Mustermann::ParseError, 'unexpected end of string while parsing "foo(bar"')
669
- end
670
-
671
- example 'missing unescaped closing parenthesis' do
672
- expect { Mustermann::Sinatra.new('foo(bar\)') }.
673
- to raise_error(Mustermann::ParseError, 'unexpected end of string while parsing "foo(bar\\\\)"')
674
- end
675
-
676
- example '? at beginning of route' do
677
- expect { Mustermann::Sinatra.new('?foobar') }.
678
- to raise_error(Mustermann::ParseError, 'unexpected ? while parsing "?foobar"')
679
- end
680
-
681
- example 'double ?' do
682
- expect { Mustermann::Sinatra.new('foo??bar') }.
683
- to raise_error(Mustermann::ParseError, 'unexpected ? while parsing "foo??bar"')
684
- end
685
-
686
- example 'dangling escape' do
687
- expect { Mustermann::Sinatra.new('foo\\') }.
688
- to raise_error(Mustermann::ParseError, 'unexpected end of string while parsing "foo\\\\"')
689
- end
690
- end
691
-
692
- context 'invalid capture names' do
693
- example 'empty name' do
694
- expect { Mustermann::Sinatra.new('/:/') }.
695
- to raise_error(Mustermann::CompileError, "capture name can't be empty: \"/:/\"")
696
- end
697
-
698
- example 'named splat' do
699
- expect { Mustermann::Sinatra.new('/:splat/') }.
700
- to raise_error(Mustermann::CompileError, "capture name can't be splat: \"/:splat/\"")
701
- end
702
-
703
- example 'named captures' do
704
- expect { Mustermann::Sinatra.new('/:captures/') }.
705
- to raise_error(Mustermann::CompileError, "capture name can't be captures: \"/:captures/\"")
706
- end
707
-
708
- example 'with capital letter' do
709
- expect { Mustermann::Sinatra.new('/:Foo/') }.
710
- to raise_error(Mustermann::CompileError, "capture name must start with underscore or lower case letter: \"/:Foo/\"")
711
- end
712
-
713
- example 'with integer' do
714
- expect { Mustermann::Sinatra.new('/:1a/') }.
715
- to raise_error(Mustermann::CompileError, "capture name must start with underscore or lower case letter: \"/:1a/\"")
716
- end
717
-
718
- example 'same name twice' do
719
- expect { Mustermann::Sinatra.new('/:foo(/:bar)?/:bar?') }.
720
- to raise_error(Mustermann::CompileError, "can't use the same capture name twice: \"/:foo(/:bar)?/:bar?\"")
721
- end
722
- end
723
-
724
- context 'Regexp compatibility' do
725
- describe :=== do
726
- example('non-matching') { Mustermann::Sinatra.new("/") .should_not be === '/foo' }
727
- example('matching') { Mustermann::Sinatra.new("/:foo") .should be === '/foo' }
728
- end
729
-
730
- describe :=~ do
731
- example('non-matching') { Mustermann::Sinatra.new("/") .should_not be =~ '/foo' }
732
- example('matching') { Mustermann::Sinatra.new("/:foo") .should be =~ '/foo' }
733
-
734
- context 'String#=~' do
735
- example('non-matching') { "/foo".should_not be =~ Mustermann::Sinatra.new("/") }
736
- example('matching') { "/foo".should be =~ Mustermann::Sinatra.new("/:foo") }
737
- end
738
- end
739
-
740
- describe :to_regexp do
741
- example('empty pattern') { Mustermann::Sinatra.new('').to_regexp.should be == /\A(?-mix:)\Z/ }
742
-
743
- context 'Regexp.try_convert' do
744
- example('empty pattern') { Regexp.try_convert(Mustermann::Sinatra.new('')).should be == /\A(?-mix:)\Z/ }
745
- end
746
- end
747
- end
748
-
749
- context 'Proc compatibility' do
750
- describe :to_proc do
751
- example { Mustermann::Sinatra.new("/").to_proc.should be_a(Proc) }
752
- example('non-matching') { Mustermann::Sinatra.new("/") .to_proc.call('/foo').should be == false }
753
- example('matching') { Mustermann::Sinatra.new("/:foo") .to_proc.call('/foo').should be == true }
754
- end
755
- end
756
-
757
- context "peeking" do
758
- subject(:pattern) { Mustermann::Sinatra.new(":name") }
759
-
760
- describe :peek_size do
761
- example { pattern.peek_size("foo bar/blah") .should be == "foo bar".size }
762
- example { pattern.peek_size("foo%20bar/blah") .should be == "foo%20bar".size }
763
- example { pattern.peek_size("/foo bar") .should be_nil }
764
- end
765
-
766
- describe :peek_match do
767
- example { pattern.peek_match("foo bar/blah") .to_s .should be == "foo bar" }
768
- example { pattern.peek_match("foo%20bar/blah") .to_s .should be == "foo%20bar" }
769
- example { pattern.peek_match("/foo bar") .should be_nil }
770
- end
771
-
772
- describe :peek_params do
773
- example { pattern.peek_params("foo bar/blah") .should be == [{"name" => "foo bar"}, "foo bar".size] }
774
- example { pattern.peek_params("foo%20bar/blah") .should be == [{"name" => "foo bar"}, "foo%20bar".size] }
775
- example { pattern.peek_params("/foo bar") .should be_nil }
776
- end
777
- end
778
-
779
- describe :| do
780
- let(:first) { Mustermann.new("a") }
781
- let(:second) { Mustermann.new("b") }
782
- subject(:composite) { first | second }
783
-
784
- context "with no capture names" do
785
- its(:class) { should be == Mustermann::Sinatra }
786
- its(:to_s) { should be == "a|b" }
787
- end
788
-
789
- context "only first has captures" do
790
- let(:first) { Mustermann.new(":a") }
791
- its(:class) { should be == Mustermann::Sinatra }
792
- its(:to_s) { should be == "{a}|b" }
793
- end
794
-
795
- context "only second has captures" do
796
- let(:second) { Mustermann.new(":b") }
797
- its(:class) { should be == Mustermann::Sinatra }
798
- its(:to_s) { should be == "a|{b}" }
799
- end
800
-
801
- context "both have captures" do
802
- let(:first) { Mustermann.new(":a") }
803
- let(:second) { Mustermann.new(":b") }
804
- its(:class) { should be == Mustermann::Composite }
805
- end
806
-
807
- context "options mismatch" do
808
- let(:second) { Mustermann.new(":b", greedy: false) }
809
- its(:class) { should be == Mustermann::Composite }
810
- end
811
-
812
- context "argument is a string" do
813
- let(:second) { ":b" }
814
- its(:class) { should be == Mustermann::Sinatra }
815
- its(:to_s) { should be == "a|\\:b" }
816
- end
817
-
818
- context "argument is an identity pattern" do
819
- let(:second) { Mustermann::Identity.new(":b") }
820
- its(:class) { should be == Mustermann::Sinatra }
821
- its(:to_s) { should be == "a|\\:b" }
822
- end
823
-
824
- context "argument is an identity pattern, but options mismatch" do
825
- let(:second) { Mustermann::Identity.new(":b", uri_decode: false) }
826
- its(:class) { should be == Mustermann::Composite }
827
- end
828
- end
829
-
830
- describe "native concatination" do
831
- subject { Mustermann.new(prefix) + Mustermann.new(pattern) }
832
- let(:prefix) { "/a" }
833
- let(:pattern) { "/:b(.:c)?" }
834
- it { should match("/a/b.json") }
835
- end
836
- end