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
@@ -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
|