usher 0.4.8 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +12 -1
- data/Rakefile +5 -29
- data/VERSION.yml +2 -2
- data/lib/usher.rb +126 -37
- data/lib/usher/grapher.rb +5 -4
- data/lib/usher/interface.rb +12 -5
- data/lib/usher/interface/email_interface.rb +1 -1
- data/lib/usher/interface/rack_interface.rb +31 -13
- data/lib/usher/interface/rails2_2_interface.rb +3 -4
- data/lib/usher/interface/rails2_3_interface.rb +3 -4
- data/lib/usher/interface/rails3_interface.rb +57 -0
- data/lib/usher/node.rb +121 -73
- data/lib/usher/route.rb +45 -11
- data/lib/usher/route/path.rb +50 -11
- data/lib/usher/route/util.rb +65 -0
- data/lib/usher/route/variable.rb +22 -11
- data/lib/usher/splitter.rb +4 -141
- data/lib/usher/util.rb +6 -0
- data/lib/usher/util/generate.rb +129 -0
- data/lib/usher/util/parser.rb +145 -0
- data/spec/private/email/recognize_spec.rb +2 -4
- data/spec/private/generate_spec.rb +86 -32
- data/spec/private/grapher_spec.rb +5 -6
- data/spec/private/parser_spec.rb +75 -0
- data/spec/private/path_spec.rb +35 -4
- data/spec/private/rack/dispatch_spec.rb +100 -15
- data/spec/private/recognize_spec.rb +88 -50
- data/spec/spec_helper.rb +22 -0
- metadata +13 -7
- data/lib/usher/generate.rb +0 -131
- data/spec/private/split_spec.rb +0 -76
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
class Usher
|
4
|
+
module Util
|
5
|
+
class Parser
|
6
|
+
|
7
|
+
def self.for_delimiters(router, valid_regex)
|
8
|
+
ParserInstance.new(
|
9
|
+
router,
|
10
|
+
Regexp.new('((:|\*)?' + valid_regex + '|' + router.delimiters_regex + '|\(|\)|\||\{)')
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
class ParserInstance
|
15
|
+
|
16
|
+
def initialize(router, split_regex)
|
17
|
+
@router = router
|
18
|
+
@split_regex = split_regex
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_route(unprocessed_path, conditions, requirements, default_values, generate_with)
|
22
|
+
match_partially = if unprocessed_path.is_a?(String)
|
23
|
+
unprocessed_path = parse(unprocessed_path, requirements, default_values)
|
24
|
+
if unprocessed_path[-1] == ?*
|
25
|
+
unprocessed_path.slice!(-1)
|
26
|
+
true
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
else
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
unless unprocessed_path.first.is_a?(Route::Util::Group)
|
35
|
+
group = Usher::Route::Util::Group.new(:all, nil)
|
36
|
+
unprocessed_path.each{|p| group << p}
|
37
|
+
unprocessed_path = group
|
38
|
+
end
|
39
|
+
|
40
|
+
paths = Route::Util.expand_path(unprocessed_path)
|
41
|
+
|
42
|
+
paths.each do |path|
|
43
|
+
path.each_with_index do |part, index|
|
44
|
+
part.default_value = default_values[part.name] if part.is_a?(Usher::Route::Variable) && default_values && default_values[part.name]
|
45
|
+
case part
|
46
|
+
when Usher::Route::Variable::Glob
|
47
|
+
part.look_ahead = path[index + 1, path.size].find{|p| !p.is_a?(Usher::Route::Variable) && !router.delimiter_chars.include?(p[0])} || nil
|
48
|
+
when Usher::Route::Variable
|
49
|
+
part.look_ahead = path[index + 1, path.size].find{|p| router.delimiter_chars.include?(p[0])} || router.delimiters.first
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Route.new(
|
55
|
+
paths,
|
56
|
+
router,
|
57
|
+
conditions,
|
58
|
+
requirements,
|
59
|
+
default_values,
|
60
|
+
generate_with,
|
61
|
+
match_partially
|
62
|
+
)
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def parse_and_expand(path, requirements = nil, default_values = nil)
|
68
|
+
Usher::Route::Util.expand_path(parse(path, requirements, default_values))
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse(path, requirements = nil, default_values = nil)
|
72
|
+
parts = Usher::Route::Util::Group.new(:all, nil)
|
73
|
+
ss = StringScanner.new(path)
|
74
|
+
current_group = parts
|
75
|
+
while !ss.eos?
|
76
|
+
part = ss.scan(@split_regex)
|
77
|
+
case part[0]
|
78
|
+
when ?*
|
79
|
+
var_name = part[1, part.size - 1].to_sym
|
80
|
+
current_group << Usher::Route::Variable::Glob.new(part[1, part.size - 1], nil, requirements && requirements[var_name])
|
81
|
+
when ?:
|
82
|
+
var_name = part[1, part.size - 1].to_sym
|
83
|
+
current_group << Usher::Route::Variable::Single.new(part[1, part.size - 1], nil, requirements && requirements[var_name])
|
84
|
+
when ?{
|
85
|
+
pattern = ''
|
86
|
+
count = 1
|
87
|
+
variable = ss.scan(/[!:\*]([^,]+),/)
|
88
|
+
until count.zero?
|
89
|
+
regex_part = ss.scan(/\{|\}|[^\{\}]+/)
|
90
|
+
case regex_part[0]
|
91
|
+
when ?{
|
92
|
+
count += 1
|
93
|
+
when ?}
|
94
|
+
count -= 1
|
95
|
+
end
|
96
|
+
pattern << regex_part
|
97
|
+
end
|
98
|
+
pattern.slice!(pattern.length - 1)
|
99
|
+
regex = Regexp.new(pattern)
|
100
|
+
if variable
|
101
|
+
variable_type = variable.slice!(0).chr.to_sym
|
102
|
+
variable_class = case variable_type
|
103
|
+
when :'!' then Usher::Route::Variable::Greedy
|
104
|
+
when :* then Usher::Route::Variable::Glob
|
105
|
+
when :':' then Usher::Route::Variable::Single
|
106
|
+
end
|
107
|
+
|
108
|
+
variable_name = variable[0, variable.size - 1].to_sym
|
109
|
+
current_group << variable_class.new(variable_name, regex, requirements && requirements[variable_name])
|
110
|
+
else
|
111
|
+
current_group << regex
|
112
|
+
end
|
113
|
+
when ?(
|
114
|
+
new_group = Usher::Route::Util::Group.new(:any, current_group)
|
115
|
+
current_group << new_group
|
116
|
+
current_group = new_group
|
117
|
+
when ?)
|
118
|
+
current_group = current_group.parent.group_type == :one ? current_group.parent.parent : current_group.parent
|
119
|
+
when ?|
|
120
|
+
unless current_group.parent.group_type == :one
|
121
|
+
detached_group = current_group.parent.pop
|
122
|
+
new_group = Usher::Route::Util::Group.new(:one, detached_group.parent)
|
123
|
+
detached_group.parent = new_group
|
124
|
+
detached_group.group_type = :all
|
125
|
+
new_group << detached_group
|
126
|
+
new_group.parent << new_group
|
127
|
+
end
|
128
|
+
current_group.parent << Usher::Route::Util::Group.new(:all, current_group.parent)
|
129
|
+
current_group = current_group.parent.last
|
130
|
+
else
|
131
|
+
current_group << part
|
132
|
+
end
|
133
|
+
end unless !path || path.empty?
|
134
|
+
parts
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
attr_reader :router
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'lib/usher'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
3
|
def build_email_mock(email)
|
6
4
|
request = mock "Request"
|
7
5
|
request.should_receive(:email).any_number_of_times.and_return(email)
|
@@ -24,14 +22,14 @@ describe "Usher (for email) route recognition" do
|
|
24
22
|
it "should recognize a wildcard domain" do
|
25
23
|
receiver = mock('receiver')
|
26
24
|
receiver.should_receive(:action).with({:domain => 'gmail.com'}).exactly(1)
|
27
|
-
@route_set.for('joshbuddy
|
25
|
+
@route_set.for('joshbuddy@{!domain,.*}') { |params| receiver.action(params) }
|
28
26
|
@route_set.act('joshbuddy@gmail.com')
|
29
27
|
end
|
30
28
|
|
31
29
|
it "should recognize a complex email" do
|
32
30
|
receiver = mock('receiver')
|
33
31
|
receiver.should_receive(:action).with({:subject => 'sub+ect', :id => '123', :sid => '456', :tok => 'sdqwe123ae', :domain => 'mydomain.org'}).exactly(1)
|
34
|
-
@route_set.for(':subject.{
|
32
|
+
@route_set.for(':subject.{!id,\d+}-{!sid,\d+}-{!tok,\w+}@{!domain,.*}') { |params| receiver.action(params) }
|
35
33
|
@route_set.act('sub+ect.123-456-sdqwe123ae@mydomain.org')
|
36
34
|
end
|
37
35
|
|
@@ -4,138 +4,192 @@ require 'rack'
|
|
4
4
|
describe "Usher URL generation" do
|
5
5
|
|
6
6
|
before(:each) do
|
7
|
-
@route_set = Usher.new
|
7
|
+
@route_set = Usher.new(:generator => Usher::Util::Generators::URL.new)
|
8
8
|
@route_set.reset!
|
9
|
-
@url_generator = Usher::Generators::URL.new(@route_set)
|
10
9
|
end
|
11
10
|
|
12
11
|
it "should generate a simple URL" do
|
13
12
|
@route_set.add_named_route(:sample, '/sample', :controller => 'sample', :action => 'action')
|
14
|
-
@
|
13
|
+
@route_set.generator.generate(:sample, {}).should == '/sample'
|
15
14
|
end
|
16
15
|
|
17
16
|
it "should generate a simple URL with a single variable" do
|
18
17
|
@route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample')
|
19
|
-
@
|
18
|
+
@route_set.generator.generate(:sample, {:action => 'action'}).should == '/sample/action'
|
20
19
|
end
|
21
20
|
|
22
21
|
it "should generate a simple URL with a single variable (and escape)" do
|
23
22
|
@route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample')
|
24
|
-
@
|
23
|
+
@route_set.generator.generate(:sample, {:action => 'action time'}).should == '/sample/action%20time'
|
25
24
|
end
|
26
25
|
|
27
26
|
it "should generate a simple URL with a single variable (thats not a string)" do
|
28
27
|
@route_set.add_named_route(:sample, '/sample/:action/:id', :controller => 'sample')
|
29
|
-
@
|
28
|
+
@route_set.generator.generate(:sample, {:action => 'action', :id => 123}).should == '/sample/action/123'
|
30
29
|
end
|
31
30
|
|
32
31
|
it "should generate a simple URL with a glob variable" do
|
33
32
|
@route_set.add_named_route(:sample, '/sample/*action', :controller => 'sample')
|
34
|
-
@
|
33
|
+
@route_set.generator.generate(:sample, {:action => ['foo', 'baz']}).should == '/sample/foo/baz'
|
35
34
|
end
|
36
35
|
|
37
36
|
it "should generate a mutliple vairable URL from a hash" do
|
38
37
|
@route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
|
39
|
-
@
|
38
|
+
@route_set.generator.generate(:sample, {:first => 'zoo', :second => 'maz'}).should == '/sample/zoo/maz'
|
40
39
|
end
|
41
40
|
|
42
41
|
it "should generate a mutliple vairable URL from an array" do
|
43
42
|
@route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
|
44
|
-
@
|
43
|
+
@route_set.generator.generate(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
|
45
44
|
end
|
46
45
|
|
47
46
|
it "should generate append extra hash variables to the end" do
|
48
47
|
@route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
|
49
|
-
@
|
48
|
+
@route_set.generator.generate(:sample, {:first => 'maz', :second => 'zoo', :third => 'zanz'}).should == '/sample/maz/zoo?third=zanz'
|
50
49
|
end
|
51
50
|
|
52
51
|
it "should generate append extra hash variables to the end (when the first parts are an array)" do
|
53
52
|
@route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
|
54
|
-
['/sample/maz/zoo?four=jane&third=zanz', '/sample/maz/zoo?third=zanz&four=jane'].include?(@
|
53
|
+
['/sample/maz/zoo?four=jane&third=zanz', '/sample/maz/zoo?third=zanz&four=jane'].include?(@route_set.generator.generate(:sample, ['maz', 'zoo', {:third => 'zanz', :four => 'jane'}])).should == true
|
55
54
|
end
|
56
55
|
|
57
56
|
it "should generate append extra hash variables to the end using [] syntax if its an array" do
|
58
57
|
@route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
|
59
|
-
@
|
58
|
+
@route_set.generator.generate(:sample, {:first => 'maz', :second => 'zoo', :third => ['zanz', 'susie']}).should == '/sample/maz/zoo?third%5B%5D=zanz&third%5B%5D=susie'
|
60
59
|
end
|
61
60
|
|
62
61
|
it "should generate a mutliple vairable URL from an array" do
|
63
62
|
@route_set.add_named_route(:sample, '/sample/:first/:second', :controller => 'sample')
|
64
|
-
@
|
63
|
+
@route_set.generator.generate(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
|
65
64
|
end
|
66
65
|
|
67
66
|
it "should generate a simple URL with a format" do
|
68
67
|
@route_set.add_named_route(:sample, '/sample/:action.:format', :controller => 'sample')
|
69
|
-
@
|
68
|
+
@route_set.generator.generate(:sample, {:action => 'action', :format => 'html'}).should == '/sample/action.html'
|
70
69
|
end
|
71
70
|
|
72
71
|
it "should generate from parameters" do
|
73
72
|
caf = @route_set.add_route('/:controller/:action.:format')
|
74
73
|
ca = @route_set.add_route('/:controller/:action')
|
75
|
-
@
|
76
|
-
@
|
74
|
+
@route_set.generator.generate(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
|
75
|
+
@route_set.generator.generate(nil, {:controller => 'controller', :action => 'action', :format => 'html'}).should == '/controller/action.html'
|
77
76
|
end
|
78
77
|
|
79
78
|
it "should use the first route when generating a URL from two ambiguous routes" do
|
80
79
|
@route_set.add_route('/:controller/:action')
|
81
80
|
@route_set.add_route('/:action/:controller')
|
82
|
-
@
|
81
|
+
@route_set.generator.generate(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
|
83
82
|
end
|
84
83
|
|
85
84
|
it "should accept an array of parameters" do
|
86
85
|
caf = @route_set.add_named_route(:name, '/:controller/:action.:format')
|
87
|
-
@
|
86
|
+
@route_set.generator.generate(:name, ['controller', 'action', 'html']).should == '/controller/action.html'
|
88
87
|
end
|
89
88
|
|
90
89
|
it "should generate a route with a specific host" do
|
91
90
|
caf = @route_set.add_named_route(:name, '/:controller/:action.:format', :generate_with => {:host => 'www.slashdot.org', :port => 80})
|
92
|
-
@
|
91
|
+
@route_set.generator.generate_full(:name, Rack::Request.new(Rack::MockRequest.env_for("http://localhost:8080")), ['controller', 'action', 'html']).should == 'http://www.slashdot.org/controller/action.html'
|
93
92
|
end
|
94
93
|
|
95
94
|
it "should require all the parameters (hash) to generate a route" do
|
96
|
-
proc
|
95
|
+
proc{@route_set.generator.generate(@route_set.add_route('/:controller/:action'), {:controller => 'controller'})}.should raise_error(Usher::MissingParameterException)
|
97
96
|
end
|
98
97
|
|
99
98
|
it "should generate from a route" do
|
100
|
-
@
|
99
|
+
@route_set.generator.generate(@route_set.add_route('/:controller/:action'), {:controller => 'controller', :action => 'action'}).should == '/controller/action'
|
101
100
|
end
|
102
101
|
|
103
102
|
it "should require all the parameters (array) to generate a route" do
|
104
103
|
@route_set.add_named_route(:name, '/:controller/:action.:format')
|
105
|
-
proc {@
|
104
|
+
proc {@route_set.generator.generate(:name, ['controller', 'action'])}.should raise_error(Usher::MissingParameterException)
|
106
105
|
end
|
107
106
|
|
108
107
|
it "should generate a route when only one parameter is given" do
|
109
108
|
@route_set.add_named_route(:name, '/:controller')
|
110
|
-
@
|
109
|
+
@route_set.generator.generate(:name, 'controller').should == '/controller'
|
111
110
|
end
|
112
111
|
|
113
112
|
it "should generate the correct route from a route containing optional parts" do
|
114
113
|
@route_set.add_named_route(:name, '/:controller(/:action(/:id))')
|
115
|
-
@
|
116
|
-
@
|
117
|
-
@
|
114
|
+
@route_set.generator.generate(:name, {:controller => 'controller'}).should == '/controller'
|
115
|
+
@route_set.generator.generate(:name, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
|
116
|
+
@route_set.generator.generate(:name, {:controller => 'controller', :action => 'action', :id => 'id'}).should == '/controller/action/id'
|
118
117
|
end
|
119
118
|
|
120
119
|
it "should generate a route using defaults for everything but the first parameter" do
|
121
120
|
@route_set.add_named_route(:name, '/:one/:two/:three', {:default_values => {:one => 'one', :two => 'two', :three => 'three'}})
|
122
|
-
@
|
121
|
+
@route_set.generator.generate(:name, {:one => "1"}).should == '/1/two/three'
|
123
122
|
end
|
124
123
|
|
125
124
|
it "should generate a route using defaults for everything" do
|
126
125
|
@route_set.add_named_route(:name, '/:one/:two/:three', {:default_values => {:one => 'one', :two => 'two', :three => 'three'}})
|
127
|
-
@
|
126
|
+
@route_set.generator.generate(:name).should == '/one/two/three'
|
128
127
|
end
|
129
128
|
|
130
129
|
it "should generate a route using defaults and optionals using the last parameter" do
|
131
130
|
@route_set.add_named_route(:opts_with_defaults, '/:one(/:two(/:three))', {:default_values => {:one => '1', :two => '2', :three => '3'}})
|
132
|
-
@
|
131
|
+
@route_set.generator.generate(:opts_with_defaults, {:three => 'three'}).should == '/1/2/three'
|
133
132
|
end
|
134
133
|
|
135
134
|
it "should generate a route with optional segments given two nested optional parameters" do
|
136
135
|
@route_set.add_named_route(:optionals, '/:controller(/:action(/:id))(.:format)')
|
137
|
-
@
|
136
|
+
@route_set.generator.generate(:optionals, {:controller => "foo", :action => "bar"}).should == '/foo/bar'
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "nested generation" do
|
140
|
+
before do
|
141
|
+
@route_set2 = Usher.new(:generator => Usher::Util::Generators::URL.new)
|
142
|
+
@route_set3 = Usher.new(:generator => Usher::Util::Generators::URL.new)
|
143
|
+
@route_set4 = Usher.new(:generator => Usher::Util::Generators::URL.new)
|
144
|
+
|
145
|
+
@route_set.add_named_route(:simple, "/mount_point").match_partially!.to(@route_set2)
|
146
|
+
@route_set.add_route("/third/:foo", :default_values => {:foo => "foo"}).match_partially!.to(@route_set3)
|
147
|
+
@route_set.add_route("/fourth/:bar").match_partially!.to(@route_set4)
|
148
|
+
|
149
|
+
@route_set2.add_named_route(:nested_simple, "/nested/simple", :controller => "nested", :action => "simple")
|
150
|
+
@route_set2.add_named_route(:nested_complex, "/another_nested(/:complex)", :controller => "nested", :action => "complex")
|
151
|
+
|
152
|
+
@route_set3.add_named_route(:nested_simple, "/nested/simple", :controller => "nested", :action => "simple")
|
153
|
+
@route_set3.add_named_route(:nested_complex, "/another_nested(/:complex)", :controller => "nested", :action => "complex")
|
154
|
+
|
155
|
+
@route_set4.add_named_route(:nested_simple, "/nested/simple", :controller => "nested", :action => "simple")
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should generate a route for the simple nested route" do
|
159
|
+
@route_set2.generator.generate(:nested_simple).should == "/mount_point/nested/simple"
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should generate a simple route without optional segments" do
|
163
|
+
@route_set2.generator.generate(:nested_complex).should == "/mount_point/another_nested"
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should generate a route with optional segements" do
|
167
|
+
@route_set2.generator.generate(:nested_complex, :complex => "foo").should == "/mount_point/another_nested/foo"
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should genearte a route with the specified value for the parent route" do
|
171
|
+
@route_set3.generator.generate(:nested_simple, :foo => "bar").should == "/third/bar/nested/simple"
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should generate a route with the default value from the parent route" do
|
175
|
+
@route_set3.generator.generate(:nested_simple).should == "/third/foo/nested/simple"
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should generate a route with an optional segement in the parent and child" do
|
179
|
+
@route_set3.generator.generate(:nested_complex, :complex => "complex").should == "/third/foo/another_nested/complex"
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should generate a route without the optional value from the child" do
|
183
|
+
@route_set3.generator.generate(:nested_complex).should == "/third/foo/another_nested"
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should raise an exception when trying to generate a route where the parent variable is not defined and does not have a default value" do
|
187
|
+
lambda do
|
188
|
+
@route_set4.generator.generate(:nested_simple)
|
189
|
+
end.should raise_error(Usher::MissingParameterException)
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
|
138
194
|
end
|
139
|
-
|
140
|
-
|
141
195
|
end
|
@@ -4,31 +4,30 @@ require 'lib/usher'
|
|
4
4
|
describe "Usher grapher" do
|
5
5
|
|
6
6
|
before(:each) do
|
7
|
-
@route_set = Usher.new
|
7
|
+
@route_set = Usher.new(:generator => Usher::Util::Generators::URL.new)
|
8
8
|
@route_set.reset!
|
9
|
-
@url_generator = Usher::Generators::URL.new(@route_set)
|
10
9
|
end
|
11
10
|
|
12
11
|
it "should find a simple path" do
|
13
12
|
@route_set.add_route('/:a/:b/:c')
|
14
|
-
@
|
13
|
+
@route_set.generator.generate(nil, {:a => 'A', :b => 'B', :c => 'C'}).should == '/A/B/C'
|
15
14
|
end
|
16
15
|
|
17
16
|
it "should pick a more specific route" do
|
18
17
|
@route_set.add_route('/:a/:b')
|
19
18
|
@route_set.add_route('/:a/:b/:c')
|
20
|
-
@
|
19
|
+
@route_set.generator.generate(nil, {:a => 'A', :b => 'B', :c => 'C'}).should == '/A/B/C'
|
21
20
|
end
|
22
21
|
|
23
22
|
it "should fail to generate a route when none matches" do
|
24
23
|
@route_set.add_route('/:a/:b')
|
25
|
-
proc {@
|
24
|
+
proc {@route_set.generator.generate(nil, {:c => 'C', :d => 'D'}) }.should raise_error Usher::UnrecognizedException
|
26
25
|
end
|
27
26
|
|
28
27
|
it "should find the most specific route and append extra parts on as a query string" do
|
29
28
|
@route_set.add_route('/:a/:b/:c')
|
30
29
|
@route_set.add_route('/:a/:b')
|
31
|
-
@
|
30
|
+
@route_set.generator.generate(nil, {:a => 'A', :b => 'B', :d => 'C'}).should == '/A/B?d=C'
|
32
31
|
end
|
33
32
|
|
34
33
|
# FIXME
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'lib/usher'
|
2
|
+
|
3
|
+
describe "Usher route tokenizing" do
|
4
|
+
|
5
|
+
|
6
|
+
it "should split / delimited routes" do
|
7
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/test/this/split').should == [['/', 'test', '/','this', '/', 'split']]
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should split / delimited routes with a regex in it" do
|
11
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/test/{this}/split').should == [['/', 'test', '/', /this/, '/', 'split']]
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should split on ' ' delimited routes as well" do
|
15
|
+
Usher.new(:delimiters => [' '], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('test this split').should == [['test', ' ', 'this', ' ', 'split']]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should split on email delimiters as well" do
|
19
|
+
Usher.new(:delimiters => ['@', '+', '-', '.'], :valid_regex => '[a-zA-Z0-9]+').parser.parse_and_expand('one+more.12345-09876-alphanum3ric5@domain.com').should == [["one", '+', "more", ".", "12345", '-', "09876", '-', "alphanum3ric5", "@", "domain", ".", "com"]]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should split on ' ' delimited routes for more complex routes as well" do
|
23
|
+
Usher.new(:delimiters => [' '], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('(test|this) split').should == [['test', ' ', 'split'], ['this', ' ', 'split']]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should group optional parts with brackets" do
|
27
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/test/this(/split)').should == [
|
28
|
+
['/', 'test', '/', 'this'],
|
29
|
+
['/', 'test', '/', 'this', '/', 'split']
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should group exclusive optional parts with brackets and pipes" do
|
34
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/test/this(/split|/split2)').should == [
|
35
|
+
['/', 'test', '/', 'this','/', 'split'],
|
36
|
+
['/', 'test', '/', 'this','/', 'split2']
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should group exclusive optional-optional parts with brackets and pipes" do
|
41
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/test/this((/split|/split2))').should == [
|
42
|
+
['/', 'test','/', 'this'],
|
43
|
+
['/', 'test','/', 'this', '/', 'split'],
|
44
|
+
['/', 'test','/', 'this', '/', 'split2']
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should group optional parts with brackets (for non overlapping groups)" do
|
49
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/test/this(/split)(/split2)') == [
|
50
|
+
['/', "test", '/', "this"],
|
51
|
+
['/', "test", '/', "this", '/', "split"],
|
52
|
+
['/', "test", '/', "this", '/', "split2"],
|
53
|
+
['/', "test", '/', "this", '/', "split", '/', "split2"]
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should group nested-optional parts with brackets" do
|
58
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/test/this(/split(.:format))') == [
|
59
|
+
['/', "test", '/', "this"],
|
60
|
+
['/', "test", '/', "this", '/', "split"],
|
61
|
+
['/', "test", '/', "this", '/', "split", '.', Usher::Route::Variable::Single.new(:format)]
|
62
|
+
]
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should to_s all different variable types" do
|
66
|
+
Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/:split/*splitter').first.collect{|v| v.to_s} ==
|
67
|
+
[ ':split', '*splitter' ]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should == variable types" do
|
71
|
+
parts = Usher.new(:delimiters => ['/', '.'], :valid_regex => '[0-9A-Za-z\$\-_\+!\*\',]+').parser.parse_and_expand('/:split/:split').first
|
72
|
+
parts[1].should == parts[3]
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|