usher 0.4.8 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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@*domain') { |params| receiver.action(params) }
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.{:id,^\d+$}-{:sid,^\d+$}-{:tok,^\w+$}@*domain') { |params| receiver.action(params) }
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
- @url_generator.generate(:sample, {}).should == '/sample'
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
- @url_generator.generate(:sample, {:action => 'action'}).should == '/sample/action'
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
- @url_generator.generate(:sample, {:action => 'action time'}).should == '/sample/action%20time'
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
- @url_generator.generate(:sample, {:action => 'action', :id => 123}).should == '/sample/action/123'
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
- @url_generator.generate(:sample, {:action => ['foo', 'baz']}).should == '/sample/foo/baz'
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
- @url_generator.generate(:sample, {:first => 'zoo', :second => 'maz'}).should == '/sample/zoo/maz'
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
- @url_generator.generate(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
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
- @url_generator.generate(:sample, {:first => 'maz', :second => 'zoo', :third => 'zanz'}).should == '/sample/maz/zoo?third=zanz'
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?(@url_generator.generate(:sample, ['maz', 'zoo', {:third => 'zanz', :four => 'jane'}])).should == true
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
- @url_generator.generate(:sample, {:first => 'maz', :second => 'zoo', :third => ['zanz', 'susie']}).should == '/sample/maz/zoo?third%5B%5D=zanz&third%5B%5D=susie'
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
- @url_generator.generate(:sample, ['maz', 'zoo']).should == '/sample/maz/zoo'
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
- @url_generator.generate(:sample, {:action => 'action', :format => 'html'}).should == '/sample/action.html'
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
- @url_generator.generate(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
76
- @url_generator.generate(nil, {:controller => 'controller', :action => 'action', :format => 'html'}).should == '/controller/action.html'
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
- @url_generator.generate(nil, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
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
- @url_generator.generate(:name, ['controller', 'action', 'html']).should == '/controller/action.html'
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
- @url_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'
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 {@url_generator.generate(@route_set.add_route('/:controller/:action'), {:controller => 'controller'})}.should raise_error Usher::MissingParameterException
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
- @url_generator.generate(@route_set.add_route('/:controller/:action'), {:controller => 'controller', :action => 'action'}).should == '/controller/action'
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 {@url_generator.generate(:name, ['controller', 'action'])}.should raise_error Usher::MissingParameterException
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
- @url_generator.generate(:name, 'controller').should == '/controller'
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
- @url_generator.generate(:name, {:controller => 'controller'}).should == '/controller'
116
- @url_generator.generate(:name, {:controller => 'controller', :action => 'action'}).should == '/controller/action'
117
- @url_generator.generate(:name, {:controller => 'controller', :action => 'action', :id => 'id'}).should == '/controller/action/id'
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
- @url_generator.generate(:name, {:one => "1"}).should == '/1/two/three'
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
- @url_generator.generate(:name).should == '/one/two/three'
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
- @url_generator.generate(:opts_with_defaults, {:three => 'three'}).should == '/1/2/three'
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
- @url_generator.generate(:optionals, {:controller => "foo", :action => "bar"}).should == '/foo/bar'
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
- @url_generator.generate(nil, {:a => 'A', :b => 'B', :c => 'C'}).should == '/A/B/C'
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
- @url_generator.generate(nil, {:a => 'A', :b => 'B', :c => 'C'}).should == '/A/B/C'
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 {@url_generator.generate(nil, {:c => 'C', :d => 'D'}) }.should raise_error Usher::UnrecognizedException
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
- @url_generator.generate(nil, {:a => 'A', :b => 'B', :d => 'C'}).should == '/A/B?d=C'
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