usher 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest.txt +35 -0
- data/README.rdoc +126 -0
- data/Rakefile +72 -0
- data/VERSION.yml +4 -0
- data/lib/usher/exceptions.rb +5 -0
- data/lib/usher/generate.rb +131 -0
- data/lib/usher/grapher.rb +65 -0
- data/lib/usher/interface/email_interface.rb +27 -0
- data/lib/usher/interface/merb_interface.rb +61 -0
- data/lib/usher/interface/rack_interface/mapper.rb +0 -0
- data/lib/usher/interface/rack_interface/route.rb +9 -0
- data/lib/usher/interface/rack_interface.rb +37 -0
- data/lib/usher/interface/rails2_2_interface/mapper.rb +44 -0
- data/lib/usher/interface/rails2_2_interface.rb +135 -0
- data/lib/usher/interface/rails2_3_interface.rb +135 -0
- data/lib/usher/interface.rb +27 -0
- data/lib/usher/node.rb +138 -0
- data/lib/usher/route/path.rb +24 -0
- data/lib/usher/route/request_method.rb +22 -0
- data/lib/usher/route/variable.rb +37 -0
- data/lib/usher/route.rb +58 -0
- data/lib/usher/splitter.rb +159 -0
- data/lib/usher.rb +184 -0
- data/rails/init.rb +8 -0
- data/spec/private/email/recognize_spec.rb +38 -0
- data/spec/private/generate_spec.rb +141 -0
- data/spec/private/grapher_spec.rb +41 -0
- data/spec/private/path_spec.rb +68 -0
- data/spec/private/rack/dispatch_spec.rb +29 -0
- data/spec/private/rails2_2/compat.rb +1 -0
- data/spec/private/rails2_2/generate_spec.rb +28 -0
- data/spec/private/rails2_2/path_spec.rb +16 -0
- data/spec/private/rails2_2/recognize_spec.rb +79 -0
- data/spec/private/rails2_3/compat.rb +1 -0
- data/spec/private/rails2_3/generate_spec.rb +28 -0
- data/spec/private/rails2_3/path_spec.rb +16 -0
- data/spec/private/rails2_3/recognize_spec.rb +79 -0
- data/spec/private/recognize_spec.rb +178 -0
- data/spec/private/request_method_spec.rb +15 -0
- data/spec/private/split_spec.rb +76 -0
- data/spec/spec.opts +7 -0
- metadata +120 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'compat')
|
2
|
+
require 'lib/usher'
|
3
|
+
|
4
|
+
route_set = Usher::Interface.for(:rails2_2)
|
5
|
+
|
6
|
+
describe "Usher (for rails 2.2) URL generation" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
route_set.reset!
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should fill in the controller from recall" do
|
13
|
+
route_set.add_route('/:controller/:action/:id')
|
14
|
+
route_set.generate({:action => 'thingy'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/sample/thingy'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should skip the action if not provided" do
|
18
|
+
route_set.add_route('/:controller/:action/:id')
|
19
|
+
route_set.generate({:controller => 'thingy'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/thingy'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should pick the correct param from optional parts" do
|
23
|
+
route_set.add_route('/:controller/:action(.:format)')
|
24
|
+
route_set.generate({:action => 'thingy', :format => 'html'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/sample/thingy.html'
|
25
|
+
route_set.generate({:action => 'thingy'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/sample/thingy'
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'compat')
|
2
|
+
require 'lib/usher'
|
3
|
+
|
4
|
+
route_set = Usher::Interface.for(:rails2_2)
|
5
|
+
|
6
|
+
describe "Usher (for rails 2.2) route adding" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
route_set.reset!
|
10
|
+
end
|
11
|
+
|
12
|
+
it "shouldn't allow routes without a controller to be added" do
|
13
|
+
proc { route_set.add_route('/bad/route') }.should raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'compat')
|
2
|
+
require 'lib/usher'
|
3
|
+
require 'action_controller'
|
4
|
+
|
5
|
+
route_set = Usher::Interface.for(:rails2_2)
|
6
|
+
|
7
|
+
def build_request_mock(path, method, params)
|
8
|
+
request = mock "Request"
|
9
|
+
request.should_receive(:path).any_number_of_times.and_return(path)
|
10
|
+
request.should_receive(:method).any_number_of_times.and_return(method)
|
11
|
+
params = params.with_indifferent_access
|
12
|
+
request.should_receive(:path_parameters=).any_number_of_times.with(params)
|
13
|
+
request.should_receive(:path_parameters).any_number_of_times.and_return(params)
|
14
|
+
request
|
15
|
+
end
|
16
|
+
|
17
|
+
SampleController = Object.new
|
18
|
+
|
19
|
+
describe "Usher (for rails 2.2) route recognition" do
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
route_set.reset!
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should recognize a simple request" do
|
26
|
+
route_set.add_route('/sample', :controller => 'sample', :action => 'action')
|
27
|
+
route_set.recognize(build_request_mock('/sample', 'get', {:controller => 'sample', :action => 'action'})).should == SampleController
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should interpolate action :index" do
|
31
|
+
route_set.add_route('/sample', :controller => 'sample')
|
32
|
+
route_set.recognize(build_request_mock('/sample', 'get', {:controller => 'sample', :action => 'index'})).should == SampleController
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should correctly distinguish between multiple request methods" do
|
36
|
+
route_set.add_route('/sample', :controller => 'not_sample', :conditions => {:method => :get})
|
37
|
+
correct_route = route_set.add_route('/sample', :controller => 'sample', :conditions => {:method => :post})
|
38
|
+
route_set.add_route('/sample', :controller => 'not_sample', :conditions => {:method => :put})
|
39
|
+
route_set.recognize(build_request_mock('/sample', :post, {:controller => 'sample', :action => 'index'})).should == SampleController
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should prefer the static route to the dynamic route" do
|
43
|
+
route_set.add_route('/sample/:action', :controller => 'not_sample')
|
44
|
+
route_set.add_route('/sample/test', :controller => 'sample', :action => 'action')
|
45
|
+
route_set.recognize(build_request_mock('/sample/test', 'get', {:controller => 'sample', :action => 'action'})).should == SampleController
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should raise based upon an invalid param" do
|
49
|
+
route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample', :requirements => {:action => /\d+/})
|
50
|
+
proc { route_set.recognize(build_request_mock('/sample/asdqwe', :post, {})) }.should raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should raise based upon an invalid route" do
|
54
|
+
route_set.add_named_route(:sample, '/sample', :controller => 'sample', :action => 'test')
|
55
|
+
proc { route_set.recognize(build_request_mock('/test/asdqwe', :post, {})) }.should raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should add /:controller and /:controller/:action if /:controller/:action/:id is added" do
|
59
|
+
route_set.add_route('/:controller/:action/:id')
|
60
|
+
route_set.route_count.should == 3
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should correctly recognize a format (dynamic path path with . delimiter)" do
|
64
|
+
route_set.add_route('/:controller/:action/:id.:format')
|
65
|
+
route_set.recognize(build_request_mock('/sample/test/123.html', 'get', {:controller => 'sample', :action => 'test', :id => '123', :format => 'html'})).should == SampleController
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should support root nodes" do
|
69
|
+
route_set.add_route('/', :controller => 'sample')
|
70
|
+
route_set.recognize(build_request_mock('/', :get, {:controller => 'sample', :action => 'index'})).should == SampleController
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should default action to 'index' when controller (and not index) is specified" do
|
74
|
+
route_set.add_route('/:controller/:action')
|
75
|
+
route_set.recognize(build_request_mock('/sample', :get, {:controller => 'sample', :action => 'index'})).should == SampleController
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'activesupport'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'compat')
|
2
|
+
require 'lib/usher'
|
3
|
+
|
4
|
+
route_set = Usher::Interface.for(:rails2_3)
|
5
|
+
|
6
|
+
describe "Usher (for rails 2.3) URL generation" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
route_set.reset!
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should fill in the controller from recall" do
|
13
|
+
route_set.add_route('/:controller/:action/:id')
|
14
|
+
route_set.generate({:action => 'thingy'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/sample/thingy'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should skip the action if not provided" do
|
18
|
+
route_set.add_route('/:controller/:action/:id')
|
19
|
+
route_set.generate({:controller => 'thingy'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/thingy'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should pick the correct param from optional parts" do
|
23
|
+
route_set.add_route('/:controller/:action(.:format)')
|
24
|
+
route_set.generate({:action => 'thingy', :format => 'html'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/sample/thingy.html'
|
25
|
+
route_set.generate({:action => 'thingy'}, {:controller => 'sample', :action => 'index', :id => 123}, :generate).should == '/sample/thingy'
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'compat')
|
2
|
+
require 'lib/usher'
|
3
|
+
|
4
|
+
route_set = Usher::Interface.for(:rails2_3)
|
5
|
+
|
6
|
+
describe "Usher (for rails 2.3) route adding" do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
route_set.reset!
|
10
|
+
end
|
11
|
+
|
12
|
+
it "shouldn't allow routes without a controller to be added" do
|
13
|
+
proc { route_set.add_route('/bad/route') }.should raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'compat')
|
2
|
+
require 'lib/usher'
|
3
|
+
require 'action_controller'
|
4
|
+
|
5
|
+
route_set = Usher::Interface.for(:rails2_3)
|
6
|
+
|
7
|
+
def build_request_mock(path, method, params)
|
8
|
+
request = mock "Request"
|
9
|
+
request.should_receive(:path).any_number_of_times.and_return(path)
|
10
|
+
request.should_receive(:method).any_number_of_times.and_return(method)
|
11
|
+
params = params.with_indifferent_access
|
12
|
+
request.should_receive(:path_parameters=).any_number_of_times.with(params)
|
13
|
+
request.should_receive(:path_parameters).any_number_of_times.and_return(params)
|
14
|
+
request
|
15
|
+
end
|
16
|
+
|
17
|
+
SampleController = Object.new
|
18
|
+
|
19
|
+
describe "Usher (for rails 2.3) route recognition" do
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
route_set.reset!
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should recognize a simple request" do
|
26
|
+
route_set.add_route('/sample', :controller => 'sample', :action => 'action')
|
27
|
+
route_set.recognize(build_request_mock('/sample', 'get', {:controller => 'sample', :action => 'action'})).should == SampleController
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should interpolate action :index" do
|
31
|
+
route_set.add_route('/sample', :controller => 'sample')
|
32
|
+
route_set.recognize(build_request_mock('/sample', 'get', {:controller => 'sample', :action => 'index'})).should == SampleController
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should correctly distinguish between multiple request methods" do
|
36
|
+
route_set.add_route('/sample', :controller => 'not_sample', :conditions => {:method => :get})
|
37
|
+
correct_route = route_set.add_route('/sample', :controller => 'sample', :conditions => {:method => :post})
|
38
|
+
route_set.add_route('/sample', :controller => 'not_sample', :conditions => {:method => :put})
|
39
|
+
route_set.recognize(build_request_mock('/sample', :post, {:controller => 'sample', :action => 'index'})).should == SampleController
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should prefer the static route to the dynamic route" do
|
43
|
+
route_set.add_route('/sample/:action', :controller => 'not_sample')
|
44
|
+
route_set.add_route('/sample/test', :controller => 'sample', :action => 'action')
|
45
|
+
route_set.recognize(build_request_mock('/sample/test', 'get', {:controller => 'sample', :action => 'action'})).should == SampleController
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should raise based upon an invalid param" do
|
49
|
+
route_set.add_named_route(:sample, '/sample/:action', :controller => 'sample', :requirements => {:action => /\d+/})
|
50
|
+
proc { route_set.recognize(build_request_mock('/sample/asdqwe', :post, {})) }.should raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should raise based upon an invalid route" do
|
54
|
+
route_set.add_named_route(:sample, '/sample', :controller => 'sample', :action => 'test')
|
55
|
+
proc { route_set.recognize(build_request_mock('/test/asdqwe', :post, {})) }.should raise_error
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should add /:controller and /:controller/:action if /:controller/:action/:id is added" do
|
59
|
+
route_set.add_route('/:controller/:action/:id')
|
60
|
+
route_set.route_count.should == 3
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should correctly recognize a format (dynamic path path with . delimiter)" do
|
64
|
+
route_set.add_route('/:controller/:action/:id.:format')
|
65
|
+
route_set.recognize(build_request_mock('/sample/test/123.html', 'get', {:controller => 'sample', :action => 'test', :id => '123', :format => 'html'})).should == SampleController
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should support root nodes" do
|
69
|
+
route_set.add_route('/', :controller => 'sample')
|
70
|
+
route_set.recognize(build_request_mock('/', :get, {:controller => 'sample', :action => 'index'})).should == SampleController
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should default action to 'index' when controller (and not index) is specified" do
|
74
|
+
route_set.add_route('/:controller/:action')
|
75
|
+
route_set.recognize(build_request_mock('/sample', :get, {:controller => 'sample', :action => 'index'})).should == SampleController
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'lib/usher'
|
2
|
+
|
3
|
+
route_set = Usher.new
|
4
|
+
|
5
|
+
def build_request(opts)
|
6
|
+
request = mock "Request"
|
7
|
+
opts.each do |k,v|
|
8
|
+
request.should_receive(k).any_number_of_times.and_return(v)
|
9
|
+
end
|
10
|
+
request
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "Usher route recognition" do
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
route_set.reset!
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should recognize a specific domain name" do
|
20
|
+
target_route = route_set.add_route('/sample', :controller => 'sample', :action => 'action', :conditions => {:protocol => 'http'})
|
21
|
+
route_set.add_route('/sample', :controller => 'sample', :action => 'action2', :conditions => {:protocol => 'https'})
|
22
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample', :protocol => 'http'})).path.route.should == target_route
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should recognize a regex domain name" do
|
26
|
+
target_route = route_set.add_route('/sample', :controller => 'sample', :action => 'action', :conditions => {:domain => /^admin.*$/})
|
27
|
+
route_set.add_route('/sample', :controller => 'sample', :action => 'action2', :conditions => {:domain => 'www.host.com'})
|
28
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample', :domain => 'admin.host.com'})).path.route.should == target_route
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should recognize a format-style variable" do
|
32
|
+
target_route = route_set.add_route('/sample.:format', :controller => 'sample', :action => 'action')
|
33
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [[:format , 'html']])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should recognize a glob-style variable" do
|
37
|
+
target_route = route_set.add_route('/sample/*format', :controller => 'sample', :action => 'action')
|
38
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample/html/json/apple'})).params.should == [[:format, ['html', 'json', 'apple']]]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should recgonize only a glob-style variable" do
|
42
|
+
target_route = route_set.add_route('/*format')
|
43
|
+
response = route_set.recognize(build_request({:method => 'get', :path => '/sample/html/json/apple'}))
|
44
|
+
response.params.should == [[:format, ['sample', 'html', 'json', 'apple']]]
|
45
|
+
response.path.route.should == target_route
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should recgonize a regex static part" do
|
49
|
+
target_route = route_set.add_route('/test/part/{one|two}')
|
50
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/one'})).path.route.should == target_route
|
51
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/two'})).path.route.should == target_route
|
52
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/three'})).should == nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it "shouldn't accept a nil variable" do
|
56
|
+
target_route = route_set.add_route('/:one')
|
57
|
+
route_set.recognize(build_request({:method => 'get', :path => '/one'})).path.route.should == target_route
|
58
|
+
route_set.recognize(build_request({:method => 'get', :path => '/'})).should == nil
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should recgonize a regex static part containing {}'s" do
|
62
|
+
target_route = route_set.add_route('/test/part/{^o{2,3}$}')
|
63
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/oo'})).path.route.should == target_route
|
64
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/ooo'})).path.route.should == target_route
|
65
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/oooo'})).should == nil
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should recgonize a regex single variable" do
|
69
|
+
target_route = route_set.add_route('/test/part/{:test,hello|again}')
|
70
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello'})).path.route.should == target_route
|
71
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello'})).params.should == [[:test, 'hello']]
|
72
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/again'})).path.route.should == target_route
|
73
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/again'})).params.should == [[:test, 'again']]
|
74
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/world'})).should == nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should recgonize a regex glob variable" do
|
78
|
+
target_route = route_set.add_route('/test/part/{*test,^(hello|again|\d+)$}')
|
79
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello/again/123/hello/again'})).path.route.should == target_route
|
80
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello/again/123/hello/again'})).params.should == [[:test, ['hello', 'again', '123', 'hello', 'again']]]
|
81
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello/agaim/123/hello/again'})).should == nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should recgonize a regex glob variable terminated by a static part" do
|
85
|
+
target_route = route_set.add_route('/test/part/{*test,^(hello|again|\d+)$}/onemore')
|
86
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello/again/123/hello/again/onemore'})).path.route.should == target_route
|
87
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello/again/123/hello/again/onemore'})).params.should == [[:test, ['hello', 'again', '123', 'hello', 'again']]]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should recgonize a regex glob variable terminated by a single regex variable" do
|
91
|
+
target_route = route_set.add_route('/test/part/{*test,^(hello|again|\d+)$}/{:party,onemore}')
|
92
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello/again/123/hello/again/onemore'})).path.route.should == target_route
|
93
|
+
route_set.recognize(build_request({:method => 'get', :path => '/test/part/hello/again/123/hello/again/onemore'})).params.should == [[:test, ['hello', 'again', '123', 'hello', 'again']], [:party, 'onemore']]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should recgonize two glob-style variables separated by a static part" do
|
97
|
+
target_route = route_set.add_route('/*format/innovate/*onemore')
|
98
|
+
response = route_set.recognize(build_request({:method => 'get', :path => '/sample/html/innovate/apple'}))
|
99
|
+
response.params.should == [[:format, ['sample', 'html']], [:onemore, ['apple']]]
|
100
|
+
response.path.route.should == target_route
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should recgonize only a glob-style variable with a condition" do
|
104
|
+
target_route = route_set.add_route('/*format', :conditions => {:domain => 'test-domain'})
|
105
|
+
response = route_set.recognize(build_request({:method => 'get', :path => '/sample/html/json/apple', :domain => 'test-domain'}))
|
106
|
+
response.params.should == [[:format, ['sample', 'html', 'json', 'apple']]]
|
107
|
+
response.path.route.should == target_route
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should recognize a format-style literal" do
|
111
|
+
target_route = route_set.add_route('/:action.html', :controller => 'sample', :action => 'action')
|
112
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [[:action , 'sample']])
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should recognize a format-style variable along side another variable" do
|
116
|
+
target_route = route_set.add_route('/:action.:format', :controller => 'sample', :action => 'action')
|
117
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample.html', :domain => 'admin.host.com'})).should == Usher::Node::Response.new(target_route.paths.first, [[:action , 'sample'], [:format, 'html']])
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should recognize a specific route when several http-style restrictions are used" do
|
121
|
+
target_route_http_admin = route_set.add_route('/sample', :controller => 'sample', :action => 'action', :conditions => {:protocol => 'http', :domain => 'admin.spec.com'})
|
122
|
+
target_route_http_www = route_set.add_route('/sample', :controller => 'sample', :action => 'action', :conditions => {:protocol => 'http', :domain => 'www.spec.com'})
|
123
|
+
target_route_https_msie = route_set.add_route('/sample', :controller => 'sample', :action => 'action2', :conditions => {:protocol => 'https', :user_agent => 'MSIE 6.0'})
|
124
|
+
target_route_https_admin = route_set.add_route('/sample', :controller => 'sample', :action => 'action2', :conditions => {:protocol => 'https', :domain => 'admin.spec.com'})
|
125
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample', :protocol => 'http', :domain => 'admin.spec.com', :user_agent => nil})).path.route.should == target_route_http_admin
|
126
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample', :protocol => 'http', :domain => 'www.spec.com', :user_agent => nil})).path.route.should == target_route_http_www
|
127
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample', :protocol => 'https', :domain => 'admin.spec.com', :user_agent => 'MSIE 6.0'})).path.route.should == target_route_https_msie
|
128
|
+
route_set.recognize(build_request({:method => 'get', :path => '/sample', :protocol => 'https', :domain => 'admin.spec.com', :user_agent => nil})).path.route.should == target_route_https_admin
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should correctly fix that tree if conditionals are used later" do
|
132
|
+
noop_route = route_set.add_route('/noop', :controller => 'products', :action => 'noop')
|
133
|
+
product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:method => 'get'})
|
134
|
+
route_set.recognize(build_request({:method => 'get', :path => '/noop', :domain => 'admin.host.com'})).path.route.should == noop_route
|
135
|
+
route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com'})).path.route.should == product_show_route
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should use conditionals that are boolean" do
|
139
|
+
# hijacking user_agent
|
140
|
+
insecure_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:user_agent => false, :method => 'get'})
|
141
|
+
secure_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:user_agent => true, :method => 'get'})
|
142
|
+
|
143
|
+
secure_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com', :user_agent => true})).path.route
|
144
|
+
insecure_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com', :user_agent => false})).path.route
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should use conditionals that are arrays" do
|
148
|
+
# hijacking user_agent
|
149
|
+
www_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['www'], :method => 'get'})
|
150
|
+
admin_product_show_route = route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['admin'], :method => 'get'})
|
151
|
+
|
152
|
+
admin_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['admin'], :user_agent => true})).path.route
|
153
|
+
www_product_show_route.should == route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['www'], :user_agent => false})).path.route
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should use a requirement (proc) on incoming variables" do
|
157
|
+
route_set.add_route('/:controller/:action/:id', :id => proc{|v| Integer(v)})
|
158
|
+
proc {route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :domain => 'admin.host.com'}))}.should_not raise_error Usher::ValidationException
|
159
|
+
proc {route_set.recognize(build_request({:method => 'get', :path => '/products/show/123asd', :domain => 'admin.host.com'}))}.should raise_error Usher::ValidationException
|
160
|
+
end
|
161
|
+
|
162
|
+
it "shouldn't care about mildly weird characters in the URL" do
|
163
|
+
route = route_set.add_route('/!asd,qwe/hjk$qwe/:id')
|
164
|
+
route_set.recognize(build_request({:method => 'get', :path => '/!asd,qwe/hjk$qwe/09AZaz$-_+!*\'', :domain => 'admin.host.com'})).params.rassoc('09AZaz$-_+!*\'').first.should == :id
|
165
|
+
end
|
166
|
+
|
167
|
+
it "shouldn't care about non-primary delimiters in the path" do
|
168
|
+
route = route_set.add_route('/testing/:id/testing2/:id2/:id3')
|
169
|
+
route_set.recognize(build_request({:method => 'get', :path => '/testing/asd.qwe/testing2/poi.zxc/oiu.asd'})).params.should == [[:id, 'asd.qwe'], [:id2, 'poi.zxc'], [:id3, 'oiu.asd']]
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should should raise if malformed variables are used" do
|
173
|
+
route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:method => 'get'})
|
174
|
+
proc {route_set.recognize(build_request({:method => 'get', :path => '/products/show/qweasd', :domain => 'admin.host.com'}))}.should raise_error
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'lib/usher'
|
2
|
+
|
3
|
+
describe "Usher request method" do
|
4
|
+
|
5
|
+
it "support eql? and ==" do
|
6
|
+
Usher::Route::RequestMethod.new(:method, 'blah').should == Usher::Route::RequestMethod.new(:method, 'blah')
|
7
|
+
Usher::Route::RequestMethod.new(:method, 'blah').should.eql?(Usher::Route::RequestMethod.new(:method, 'blah'))
|
8
|
+
end
|
9
|
+
|
10
|
+
it "support hash" do
|
11
|
+
Usher::Route::RequestMethod.new(:method, 'blah').hash.should == (Usher::Route::RequestMethod.new(:method, 'blah')).hash
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'lib/usher'
|
2
|
+
|
3
|
+
describe "Usher route tokenizing" do
|
4
|
+
|
5
|
+
|
6
|
+
it "should split / delimited routes" do
|
7
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this/split').should == [['/', 'test', '/','this', '/', 'split']]
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should split / delimited routes with a regex in it" do
|
11
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').
|
12
|
+
split('/test/{this}/split').should == [['/', 'test', '/', /this/, '/', 'split']]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should split on ' ' delimited routes as well" do
|
16
|
+
Usher::Splitter.for_delimiters([' '], '[0-9A-Za-z\$\-_\+!\*\',]+').split('test this split').should == [['test', ' ', 'this', ' ', 'split']]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should split on email delimiters as well" do
|
20
|
+
Usher::Splitter.for_delimiters(['@', '+', '-', '.'], '[a-zA-Z0-9]+').split('one+more.12345-09876-alphanum3ric5@domain.com').should == [["one", '+', "more", ".", "12345", '-', "09876", '-', "alphanum3ric5", "@", "domain", ".", "com"]]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should split on ' ' delimited routes for more complex routes as well" do
|
24
|
+
Usher::Splitter.for_delimiters([' '], '[0-9A-Za-z\$\-_\+!\*\',]+').split('(test|this) split').should == [['test', ' ', 'split'], ['this', ' ', 'split']]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should group optional parts with brackets" do
|
28
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split)').should == [
|
29
|
+
['/', 'test', '/', 'this'],
|
30
|
+
['/', 'test', '/', 'this', '/', 'split']
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should group exclusive optional parts with brackets and pipes" do
|
35
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split|/split2)').should == [
|
36
|
+
['/', 'test', '/', 'this','/', 'split'],
|
37
|
+
['/', 'test', '/', 'this','/', 'split2']
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should group exclusive optional-optional parts with brackets and pipes" do
|
42
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this((/split|/split2))').should == [
|
43
|
+
['/', 'test','/', 'this'],
|
44
|
+
['/', 'test','/', 'this', '/', 'split'],
|
45
|
+
['/', 'test','/', 'this', '/', 'split2']
|
46
|
+
]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should group optional parts with brackets (for non overlapping groups)" do
|
50
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split)(/split2)') == [
|
51
|
+
['/', "test", '/', "this"],
|
52
|
+
['/', "test", '/', "this", '/', "split"],
|
53
|
+
['/', "test", '/', "this", '/', "split2"],
|
54
|
+
['/', "test", '/', "this", '/', "split", '/', "split2"]
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should group nested-optional parts with brackets" do
|
59
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/test/this(/split(.:format))') == [
|
60
|
+
['/', "test", '/', "this"],
|
61
|
+
['/', "test", '/', "this", '/', "split"],
|
62
|
+
['/', "test", '/', "this", '/', "split", '.', Usher::Route::Variable.new(:':', :format)]
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should to_s all different variable types" do
|
67
|
+
Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/:split/*splitter').first.collect{|v| v.to_s} ==
|
68
|
+
[ ':split', '*splitter' ]
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should == variable types" do
|
72
|
+
parts = Usher::Splitter.for_delimiters(['/', '.'], '[0-9A-Za-z\$\-_\+!\*\',]+').split('/:split/:split').first
|
73
|
+
parts[1].should == parts[3]
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|