usher 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
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