usher 0.4.8

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.
Files changed (43) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +35 -0
  3. data/README.rdoc +126 -0
  4. data/Rakefile +72 -0
  5. data/VERSION.yml +4 -0
  6. data/lib/usher/exceptions.rb +5 -0
  7. data/lib/usher/generate.rb +131 -0
  8. data/lib/usher/grapher.rb +65 -0
  9. data/lib/usher/interface/email_interface.rb +27 -0
  10. data/lib/usher/interface/merb_interface.rb +61 -0
  11. data/lib/usher/interface/rack_interface/mapper.rb +0 -0
  12. data/lib/usher/interface/rack_interface/route.rb +9 -0
  13. data/lib/usher/interface/rack_interface.rb +37 -0
  14. data/lib/usher/interface/rails2_2_interface/mapper.rb +44 -0
  15. data/lib/usher/interface/rails2_2_interface.rb +135 -0
  16. data/lib/usher/interface/rails2_3_interface.rb +135 -0
  17. data/lib/usher/interface.rb +27 -0
  18. data/lib/usher/node.rb +138 -0
  19. data/lib/usher/route/path.rb +24 -0
  20. data/lib/usher/route/request_method.rb +22 -0
  21. data/lib/usher/route/variable.rb +37 -0
  22. data/lib/usher/route.rb +58 -0
  23. data/lib/usher/splitter.rb +159 -0
  24. data/lib/usher.rb +184 -0
  25. data/rails/init.rb +8 -0
  26. data/spec/private/email/recognize_spec.rb +38 -0
  27. data/spec/private/generate_spec.rb +141 -0
  28. data/spec/private/grapher_spec.rb +41 -0
  29. data/spec/private/path_spec.rb +68 -0
  30. data/spec/private/rack/dispatch_spec.rb +29 -0
  31. data/spec/private/rails2_2/compat.rb +1 -0
  32. data/spec/private/rails2_2/generate_spec.rb +28 -0
  33. data/spec/private/rails2_2/path_spec.rb +16 -0
  34. data/spec/private/rails2_2/recognize_spec.rb +79 -0
  35. data/spec/private/rails2_3/compat.rb +1 -0
  36. data/spec/private/rails2_3/generate_spec.rb +28 -0
  37. data/spec/private/rails2_3/path_spec.rb +16 -0
  38. data/spec/private/rails2_3/recognize_spec.rb +79 -0
  39. data/spec/private/recognize_spec.rb +178 -0
  40. data/spec/private/request_method_spec.rb +15 -0
  41. data/spec/private/split_spec.rb +76 -0
  42. data/spec/spec.opts +7 -0
  43. 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
data/spec/spec.opts ADDED
@@ -0,0 +1,7 @@
1
+ --colour
2
+ --format
3
+ specdoc
4
+ --loadby
5
+ mtime
6
+ --reverse
7
+ --backtrace