mustermann 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'thread'
|
3
|
+
require 'mustermann'
|
4
|
+
|
5
|
+
module Mustermann
|
6
|
+
# A simple, persistent cache for creating repositories.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# require 'mustermann/pattern_cache'
|
10
|
+
# cache = Mustermann::PatternCache.new
|
11
|
+
#
|
12
|
+
# # use this instead of Mustermann.new
|
13
|
+
# pattern = cache.create_pattern("/:name", type: :rails)
|
14
|
+
#
|
15
|
+
# @note
|
16
|
+
# {Mustermann::Pattern.new} (which is used by {Mustermann.new}) will reuse instances that have
|
17
|
+
# not yet been garbage collected. You only need an extra cache if you do not keep a reference to
|
18
|
+
# the patterns around.
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
class PatternCache
|
22
|
+
# @param [Hash] pattern_options default options used for {#create_pattern}
|
23
|
+
def initialize(**pattern_options)
|
24
|
+
@cached = Set.new
|
25
|
+
@mutex = Mutex.new
|
26
|
+
@pattern_options = pattern_options
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param (see Mustermann.new)
|
30
|
+
# @return (see Mustermann.new)
|
31
|
+
# @raise (see Mustermann.new)
|
32
|
+
# @see Mustermann.new
|
33
|
+
def create_pattern(string, **pattern_options)
|
34
|
+
pattern = Mustermann.new(string, **pattern_options, **@pattern_options)
|
35
|
+
@mutex.synchronize { @cached.add(pattern) } unless @cached.include? pattern
|
36
|
+
pattern
|
37
|
+
end
|
38
|
+
|
39
|
+
# Removes all pattern instances from the cache.
|
40
|
+
def clear
|
41
|
+
@mutex.synchronize { @cached.clear }
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Integer] number of currently cached patterns
|
45
|
+
def size
|
46
|
+
@mutex.synchronize { @cached.size }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'mustermann/regular'
|
@@ -15,7 +15,24 @@ module Mustermann
|
|
15
15
|
# @see (see Mustermann::Pattern#initialize)
|
16
16
|
def initialize(string, **options)
|
17
17
|
super
|
18
|
-
|
18
|
+
regexp = compile(**options)
|
19
|
+
@peek_regexp = /\A(#{regexp})/
|
20
|
+
@regexp = /\A#{regexp}\Z/
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param (see Mustermann::Pattern#peek_size)
|
24
|
+
# @return (see Mustermann::Pattern#peek_size)
|
25
|
+
# @see (see Mustermann::Pattern#peek_size)
|
26
|
+
def peek_size(string)
|
27
|
+
return unless match = peek_match(string)
|
28
|
+
match.to_s.size
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param (see Mustermann::Pattern#peek_match)
|
32
|
+
# @return (see Mustermann::Pattern#peek_match)
|
33
|
+
# @see (see Mustermann::Pattern#peek_match)
|
34
|
+
def peek_match(string)
|
35
|
+
@peek_regexp.match(string)
|
19
36
|
end
|
20
37
|
|
21
38
|
extend Forwardable
|
data/lib/mustermann/regular.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'mustermann'
|
1
2
|
require 'mustermann/regexp_based'
|
2
3
|
|
3
4
|
module Mustermann
|
@@ -9,6 +10,8 @@ module Mustermann
|
|
9
10
|
# @see Mustermann::Pattern
|
10
11
|
# @see file:README.md#simple Syntax description in the README
|
11
12
|
class Regular < RegexpBased
|
13
|
+
register :regexp, :regular
|
14
|
+
|
12
15
|
# @param (see Mustermann::Pattern#initialize)
|
13
16
|
# @return (see Mustermann::Pattern#initialize)
|
14
17
|
# @see (see Mustermann::Pattern#initialize)
|
@@ -18,7 +21,7 @@ module Mustermann
|
|
18
21
|
end
|
19
22
|
|
20
23
|
def compile(**options)
|
21
|
-
|
24
|
+
/#{@string}/
|
22
25
|
end
|
23
26
|
|
24
27
|
private :compile
|
data/lib/mustermann/sinatra.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'mustermann'
|
1
2
|
require 'mustermann/ast/pattern'
|
2
3
|
|
3
4
|
module Mustermann
|
@@ -9,11 +10,27 @@ module Mustermann
|
|
9
10
|
# @see Mustermann::Pattern
|
10
11
|
# @see file:README.md#sinatra Syntax description in the README
|
11
12
|
class Sinatra < AST::Pattern
|
12
|
-
|
13
|
-
|
14
|
-
on(?
|
15
|
-
|
16
|
-
on(
|
13
|
+
register :sinatra
|
14
|
+
|
15
|
+
on(nil, ??, ?), ?|) { |c| unexpected(c) }
|
16
|
+
|
17
|
+
on(?*) { |c| scan(/\w+/) ? node(:named_splat, buffer.matched) : node(:splat) }
|
18
|
+
on(?:) { |c| node(:capture) { scan(/\w+/) } }
|
19
|
+
on(?\\) { |c| node(:char, expect(/./)) }
|
20
|
+
|
21
|
+
on ?( do |char|
|
22
|
+
groups = []
|
23
|
+
groups << node(:group) { read unless check(?)) or scan(?|) } until scan(?))
|
24
|
+
groups.size == 1 ? groups.first : node(:union, groups)
|
25
|
+
end
|
26
|
+
|
27
|
+
on ?{ do |char|
|
28
|
+
type = scan(?+) ? :named_splat : :capture
|
29
|
+
name = expect(/[\w\.]+/)
|
30
|
+
type = :splat if type == :named_splat and name == 'splat'
|
31
|
+
expect(?})
|
32
|
+
node(type, name)
|
33
|
+
end
|
17
34
|
|
18
35
|
suffix ?? do |char, element|
|
19
36
|
node(:optional, element)
|
@@ -16,8 +16,11 @@ module Mustermann
|
|
16
16
|
#
|
17
17
|
# Foo.new.to_pattern # => #<Mustermann::Sinatra:":foo/:bar">
|
18
18
|
#
|
19
|
-
# By default included into
|
19
|
+
# By default included into String, Symbol, Regexp, Array and {Mustermann::Pattern}.
|
20
20
|
module ToPattern
|
21
|
+
PRIMITIVES = [String, Symbol, Array, Regexp, Mustermann::Pattern]
|
22
|
+
private_constant :PRIMITIVES
|
23
|
+
|
21
24
|
# Converts the object into a {Mustermann::Pattern}.
|
22
25
|
#
|
23
26
|
# @example converting a string
|
@@ -30,16 +33,18 @@ module Mustermann
|
|
30
33
|
# /.*/.to_pattern # => #<Mustermann::Regular:".*">
|
31
34
|
#
|
32
35
|
# @example converting a pattern
|
33
|
-
#
|
36
|
+
# Mustermann.new("foo").to_pattern # => #<Mustermann::Sinatra:"foo">
|
34
37
|
#
|
35
38
|
# @param [Hash] options The options hash.
|
36
39
|
# @return [Mustermann::Pattern] pattern corresponding to object.
|
37
40
|
def to_pattern(**options)
|
38
|
-
|
41
|
+
input = self if PRIMITIVES.any? { |p| self.is_a? p }
|
42
|
+
input ||= __getobj__ if respond_to?(:__getobj__)
|
43
|
+
Mustermann.new(input || to_s, **options)
|
39
44
|
end
|
40
45
|
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
PRIMITIVES.each do |klass|
|
47
|
+
append_features(klass)
|
48
|
+
end
|
44
49
|
end
|
45
50
|
end
|
data/lib/mustermann/version.rb
CHANGED
data/mustermann.gemspec
CHANGED
@@ -10,22 +10,9 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.summary = %q{use patterns like regular expressions}
|
11
11
|
s.description = %q{library implementing patterns that behave like regular expressions}
|
12
12
|
s.license = 'MIT'
|
13
|
+
s.required_ruby_version = '>= 2.1.0'
|
13
14
|
s.files = `git ls-files`.split("\n")
|
14
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
-
s.extra_rdoc_files = %w[README.md internals.md]
|
17
|
-
s.require_path = 'lib'
|
18
|
-
s.required_ruby_version = '>= 2.0.0'
|
19
|
-
|
20
17
|
s.add_dependency 'tool', '~> 0.2'
|
21
|
-
s.add_development_dependency 'rspec' #, '~> 2.14'
|
22
|
-
s.add_development_dependency 'rspec-its'
|
23
|
-
s.add_development_dependency 'addressable'
|
24
|
-
s.add_development_dependency 'sinatra', '~> 1.4'
|
25
|
-
s.add_development_dependency 'rack-test'
|
26
|
-
s.add_development_dependency 'rake'
|
27
|
-
s.add_development_dependency 'yard'
|
28
|
-
s.add_development_dependency 'redcarpet'
|
29
|
-
s.add_development_dependency 'simplecov'
|
30
|
-
s.add_development_dependency 'coveralls'
|
31
18
|
end
|
data/spec/ast_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'support'
|
2
|
+
require 'mustermann/ast/node'
|
3
|
+
|
4
|
+
describe Mustermann::AST do
|
5
|
+
describe :type do
|
6
|
+
example { Mustermann::AST::Node[:char].type .should be == :char }
|
7
|
+
example { Mustermann::AST::Node[:char].new.type .should be == :char }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe :min_size do
|
11
|
+
example { Mustermann::AST::Node[:char].new.min_size.should be == 1 }
|
12
|
+
example { Mustermann::AST::Node[:node].new.min_size.should be == 0 }
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'support'
|
2
|
+
require 'mustermann'
|
3
|
+
|
4
|
+
describe Mustermann::Composite do
|
5
|
+
describe :new do
|
6
|
+
example 'with no argument' do
|
7
|
+
expect { Mustermann::Composite.new }.
|
8
|
+
to raise_error(ArgumentError, 'cannot create empty composite pattern')
|
9
|
+
end
|
10
|
+
|
11
|
+
example 'with one argument' do
|
12
|
+
pattern = Mustermann.new('/foo')
|
13
|
+
Mustermann::Composite.new(pattern).should be == pattern
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context :| do
|
18
|
+
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second') }
|
19
|
+
|
20
|
+
describe :== do
|
21
|
+
example { subject.should be == subject }
|
22
|
+
example { subject.should be == Mustermann.new('/foo/:name', '/:first/:second') }
|
23
|
+
example { subject.should_not be == Mustermann.new('/foo/:name') }
|
24
|
+
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe :=== do
|
28
|
+
example { subject.should be === "/foo/bar" }
|
29
|
+
example { subject.should be === "/fox/bar" }
|
30
|
+
example { subject.should_not be === "/foo" }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe :params do
|
34
|
+
example { subject.params("/foo/bar") .should be == { "name" => "bar" } }
|
35
|
+
example { subject.params("/fox/bar") .should be == { "first" => "fox", "second" => "bar" } }
|
36
|
+
example { subject.params("/foo") .should be_nil }
|
37
|
+
end
|
38
|
+
|
39
|
+
describe :=== do
|
40
|
+
example { subject.should match("/foo/bar") }
|
41
|
+
example { subject.should match("/fox/bar") }
|
42
|
+
example { subject.should_not match("/foo") }
|
43
|
+
end
|
44
|
+
|
45
|
+
describe :expand do
|
46
|
+
example { subject.should respond_to(:expand) }
|
47
|
+
example { subject.expand(name: 'bar') .should be == '/foo/bar' }
|
48
|
+
example { subject.expand(first: 'fox', second: 'bar') .should be == '/fox/bar' }
|
49
|
+
|
50
|
+
context "without expandable patterns" do
|
51
|
+
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', type: :simple) }
|
52
|
+
example { subject.should_not respond_to(:expand) }
|
53
|
+
example { expect { subject.expand(name: 'bar') }.to raise_error(NotImplementedError) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe :to_templates do
|
58
|
+
example { should respond_to(:to_templates) }
|
59
|
+
example { should generate_templates('/foo/{name}', '/{first}/{second}') }
|
60
|
+
|
61
|
+
context "without patterns implementing to_templates" do
|
62
|
+
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', type: :simple) }
|
63
|
+
example { should_not respond_to(:to_templates) }
|
64
|
+
example { expect { subject.to_templates }.to raise_error(NotImplementedError) }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context :& do
|
70
|
+
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
71
|
+
|
72
|
+
describe :== do
|
73
|
+
example { subject.should be == subject }
|
74
|
+
example { subject.should be == Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
75
|
+
example { subject.should_not be == Mustermann.new('/foo/:name') }
|
76
|
+
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second') }
|
77
|
+
end
|
78
|
+
|
79
|
+
describe :=== do
|
80
|
+
example { subject.should be === "/foo/bar" }
|
81
|
+
example { subject.should_not be === "/fox/bar" }
|
82
|
+
example { subject.should_not be === "/foo" }
|
83
|
+
end
|
84
|
+
|
85
|
+
describe :params do
|
86
|
+
example { subject.params("/foo/bar") .should be == { "name" => "bar" } }
|
87
|
+
example { subject.params("/fox/bar") .should be_nil }
|
88
|
+
example { subject.params("/foo") .should be_nil }
|
89
|
+
end
|
90
|
+
|
91
|
+
describe :match do
|
92
|
+
example { subject.should match("/foo/bar") }
|
93
|
+
example { subject.should_not match("/fox/bar") }
|
94
|
+
example { subject.should_not match("/foo") }
|
95
|
+
end
|
96
|
+
|
97
|
+
describe :expand do
|
98
|
+
example { subject.should_not respond_to(:expand) }
|
99
|
+
example { expect { subject.expand(name: 'bar') }.to raise_error(NotImplementedError) }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context :^ do
|
104
|
+
subject(:pattern) { Mustermann.new('/foo/:name', '/:first/:second', operator: :^) }
|
105
|
+
|
106
|
+
describe :== do
|
107
|
+
example { subject.should be == subject }
|
108
|
+
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second') }
|
109
|
+
example { subject.should_not be == Mustermann.new('/foo/:name') }
|
110
|
+
example { subject.should_not be == Mustermann.new('/foo/:name', '/:first/:second', operator: :&) }
|
111
|
+
end
|
112
|
+
|
113
|
+
describe :=== do
|
114
|
+
example { subject.should_not be === "/foo/bar" }
|
115
|
+
example { subject.should be === "/fox/bar" }
|
116
|
+
example { subject.should_not be === "/foo" }
|
117
|
+
end
|
118
|
+
|
119
|
+
describe :params do
|
120
|
+
example { subject.params("/foo/bar") .should be_nil }
|
121
|
+
example { subject.params("/fox/bar") .should be == { "first" => "fox", "second" => "bar" } }
|
122
|
+
example { subject.params("/foo") .should be_nil }
|
123
|
+
end
|
124
|
+
|
125
|
+
describe :match do
|
126
|
+
example { subject.should_not match("/foo/bar") }
|
127
|
+
example { subject.should match("/fox/bar") }
|
128
|
+
example { subject.should_not match("/foo") }
|
129
|
+
end
|
130
|
+
|
131
|
+
describe :expand do
|
132
|
+
example { subject.should_not respond_to(:expand) }
|
133
|
+
example { expect { subject.expand(name: 'bar') }.to raise_error(NotImplementedError) }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe :inspect do
|
138
|
+
let(:sinatra) { Mustermann.new('x') }
|
139
|
+
let(:rails) { Mustermann.new('x', type: :rails) }
|
140
|
+
let(:identity) { Mustermann.new('x', type: :identity) }
|
141
|
+
|
142
|
+
example { (sinatra | rails) .inspect.should include('(sinatra:"x" | rails:"x")') }
|
143
|
+
example { (sinatra ^ rails) .inspect.should include('(sinatra:"x" ^ rails:"x")') }
|
144
|
+
example { (sinatra | rails | identity) .inspect.should include('(sinatra:"x" | rails:"x" | identity:"x")') }
|
145
|
+
example { (sinatra | rails & identity) .inspect.should include('(sinatra:"x" | (rails:"x" & identity:"x"))') }
|
146
|
+
end
|
147
|
+
end
|
data/spec/expander_spec.rb
CHANGED
@@ -30,6 +30,21 @@ describe Mustermann::Expander do
|
|
30
30
|
expander.expand(foo: 'pony', ext: nil).should be == '/pony'
|
31
31
|
end
|
32
32
|
|
33
|
+
it 'supports splat' do
|
34
|
+
expander = Mustermann::Expander.new << Mustermann.new("/foo/*/baz")
|
35
|
+
expander.expand(splat: 'bar').should be == '/foo/bar/baz'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'supports multiple splats' do
|
39
|
+
expander = Mustermann::Expander.new << Mustermann.new("/foo/*/bar/*")
|
40
|
+
expander.expand(splat: [123, 456]).should be == '/foo/123/bar/456'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'supports identity patterns' do
|
44
|
+
expander = Mustermann::Expander.new('/:foo', type: :identity)
|
45
|
+
expander.expand.should be == '/:foo'
|
46
|
+
end
|
47
|
+
|
33
48
|
describe :additional_values do
|
34
49
|
context "illegal value" do
|
35
50
|
example { expect { Mustermann::Expander.new(additional_values: :foo) }.to raise_error(ArgumentError) }
|
data/spec/identity_spec.rb
CHANGED
@@ -7,6 +7,21 @@ describe Mustermann::Identity do
|
|
7
7
|
pattern '' do
|
8
8
|
it { should match('') }
|
9
9
|
it { should_not match('/') }
|
10
|
+
|
11
|
+
it { should respond_to(:expand) }
|
12
|
+
it { should respond_to(:to_templates) }
|
13
|
+
|
14
|
+
|
15
|
+
it { should generate_template('') }
|
16
|
+
it { should expand.to('') }
|
17
|
+
it { should expand(:ignore, a: 10).to('') }
|
18
|
+
it { should expand(:append, a: 10).to('?a=10') }
|
19
|
+
it { should_not expand(:raise, a: 10) }
|
20
|
+
it { should_not expand(a: 10) }
|
21
|
+
|
22
|
+
example do
|
23
|
+
pattern.match('').inspect.should be == '#<Mustermann::SimpleMatch "">'
|
24
|
+
end
|
10
25
|
end
|
11
26
|
|
12
27
|
pattern '/' do
|
@@ -15,6 +30,9 @@ describe Mustermann::Identity do
|
|
15
30
|
|
16
31
|
example { pattern.params('/').should be == {} }
|
17
32
|
example { pattern.params('').should be_nil }
|
33
|
+
|
34
|
+
it { should generate_template('/') }
|
35
|
+
it { should expand.to('/') }
|
18
36
|
end
|
19
37
|
|
20
38
|
pattern '/foo' do
|
@@ -37,6 +55,9 @@ describe Mustermann::Identity do
|
|
37
55
|
it { should_not match('/foo/bar') }
|
38
56
|
it { should_not match('/') }
|
39
57
|
it { should_not match('/foo/') }
|
58
|
+
|
59
|
+
it { should generate_template('/:foo') }
|
60
|
+
it { should expand.to('/:foo') }
|
40
61
|
end
|
41
62
|
|
42
63
|
pattern '/föö' do
|
@@ -57,6 +78,7 @@ describe Mustermann::Identity do
|
|
57
78
|
it { should match('/path%20with%20spaces') }
|
58
79
|
it { should_not match('/path%2Bwith%2Bspaces') }
|
59
80
|
it { should_not match('/path+with+spaces') }
|
81
|
+
it { should generate_template('/path%20with%20spaces') }
|
60
82
|
end
|
61
83
|
|
62
84
|
pattern '/foo&bar' do
|
@@ -79,4 +101,26 @@ describe Mustermann::Identity do
|
|
79
101
|
it { should_not match('/path%2Bwith%2Bspaces') }
|
80
102
|
it { should_not match('/path+with+spaces') }
|
81
103
|
end
|
104
|
+
|
105
|
+
context "peeking" do
|
106
|
+
subject(:pattern) { Mustermann::Identity.new("foo bar") }
|
107
|
+
|
108
|
+
describe :peek_size do
|
109
|
+
example { pattern.peek_size("foo bar blah") .should be == "foo bar".size }
|
110
|
+
example { pattern.peek_size("foo%20bar blah") .should be == "foo%20bar".size }
|
111
|
+
example { pattern.peek_size("foobar") .should be_nil }
|
112
|
+
end
|
113
|
+
|
114
|
+
describe :peek_match do
|
115
|
+
example { pattern.peek_match("foo bar blah").to_s .should be == "foo bar" }
|
116
|
+
example { pattern.peek_match("foo%20bar blah").to_s .should be == "foo%20bar" }
|
117
|
+
example { pattern.peek_match("foobar") .should be_nil }
|
118
|
+
end
|
119
|
+
|
120
|
+
describe :peek_params do
|
121
|
+
example { pattern.peek_params("foo bar blah") .should be == [{}, "foo bar".size] }
|
122
|
+
example { pattern.peek_params("foo%20bar blah") .should be == [{}, "foo%20bar".size] }
|
123
|
+
example { pattern.peek_params("foobar") .should be_nil }
|
124
|
+
end
|
125
|
+
end
|
82
126
|
end
|