usher 0.5.11 → 0.5.12

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 (39) hide show
  1. data/Rakefile +48 -53
  2. data/VERSION.yml +2 -2
  3. data/lib/usher.rb +12 -12
  4. data/lib/usher/delimiters.rb +7 -7
  5. data/lib/usher/interface.rb +19 -30
  6. data/lib/usher/interface/{email_interface.rb → email.rb} +1 -1
  7. data/lib/usher/interface/{merb_interface.rb → merb.rb} +1 -1
  8. data/lib/usher/interface/{rack_interface.rb → rack.rb} +14 -10
  9. data/lib/usher/interface/{rack_interface → rack}/mapper.rb +0 -0
  10. data/lib/usher/interface/rack/route.rb +16 -0
  11. data/lib/usher/interface/rails20.rb +7 -0
  12. data/lib/usher/interface/{rails2_2_interface.rb → rails22.rb} +18 -18
  13. data/lib/usher/interface/{rails2_2_interface → rails22}/mapper.rb +2 -2
  14. data/lib/usher/interface/{rails2_3_interface.rb → rails23.rb} +1 -1
  15. data/lib/usher/interface/rails23/mapper.rb +44 -0
  16. data/lib/usher/interface/{rails3_interface.rb → rails3.rb} +1 -1
  17. data/lib/usher/interface/{text_interface.rb → text.rb} +1 -1
  18. data/lib/usher/node.rb +71 -57
  19. data/lib/usher/route.rb +10 -5
  20. data/lib/usher/route/static.rb +9 -0
  21. data/lib/usher/route/variable.rb +28 -9
  22. data/lib/usher/util.rb +3 -3
  23. data/lib/usher/util/generate.rb +55 -18
  24. data/lib/usher/util/parser.rb +25 -18
  25. data/rails/init.rb +24 -8
  26. data/spec/private/generate_spec.rb +116 -1
  27. data/spec/private/generate_with_spec.rb +28 -0
  28. data/spec/private/rack/dispatch_spec.rb +23 -2
  29. data/spec/private/rack/route_spec.rb +50 -0
  30. data/spec/private/rails2_2/generate_spec.rb +1 -1
  31. data/spec/private/rails2_2/path_spec.rb +1 -1
  32. data/spec/private/rails2_2/recognize_spec.rb +1 -1
  33. data/spec/private/rails2_3/generate_spec.rb +1 -1
  34. data/spec/private/rails2_3/path_spec.rb +1 -1
  35. data/spec/private/rails2_3/recognize_spec.rb +1 -1
  36. data/spec/private/recognize_spec.rb +4 -5
  37. data/spec/private/url_parts_spec.rb +116 -0
  38. metadata +26 -12
  39. data/lib/usher/interface/rack_interface/route.rb +0 -16
@@ -1,8 +1,24 @@
1
- if Rails::VERSION::MAJOR == 2 && Rails::VERSION::MINOR == 3
2
- ActionController::Routing.module_eval "remove_const(:Routes); Routes = Usher::Interface.for(:rails2_3)"
3
- elsif Rails::VERSION::MAJOR == 2 && Rails::VERSION::MINOR >= 2
4
- class Usher::Interface::Rails2_2Interface::Mapper
5
- include ActionController::Resources
6
- end
7
- ActionController::Routing.module_eval "remove_const(:Routes); Routes = Usher::Interface.for(:rails2_2)"
8
- end
1
+ rails_version = "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
2
+
3
+ case rails_version
4
+ when '2.3'
5
+ ActionController::Routing.module_eval "remove_const(:Routes); Routes = Usher::Interface.for(:rails23)"
6
+
7
+ when '2.2'
8
+ class Usher::Interface::Rails22::Mapper
9
+ include ActionController::Resources
10
+ end
11
+ ActionController::Routing.module_eval "remove_const(:Routes); Routes = Usher::Interface.for(:rails22)"
12
+
13
+ when '2.0'
14
+ class Usher::Interface::Rails20::Mapper
15
+ include ActionController::Resources
16
+ end
17
+
18
+ ActionController::Routing.module_eval <<CODE
19
+ remove_const(:Routes);
20
+ interface = Usher::Interface.for(:rails20);
21
+ interface.configuration_file = File.join(RAILS_ROOT, 'config', 'routes.rb')
22
+ Routes = interface;
23
+ CODE
24
+ end
@@ -137,6 +137,122 @@ describe "Usher URL generation" do
137
137
  @route_set.generator.generate(:optionals, {:controller => "foo", :action => "bar"}).should == '/foo/bar'
138
138
  end
139
139
 
140
+ describe "when named route was added with string key" do
141
+ before :each do
142
+ @route_set.add_named_route 'items', '/items', :controller => 'items', :action => 'index'
143
+ end
144
+
145
+ it "should generate a named route by given symbolic key" do
146
+ @route_set.generator.generate(:items).should == '/items'
147
+ end
148
+ end
149
+
150
+ describe "#generate_start" do
151
+ before :all do
152
+ UrlParts = Usher::Util::Generators::URL::UrlParts
153
+ @url_parts_stub = UrlParts.new :some_path, :some_request
154
+ UrlParts.stub! :new => @url_parts_stub
155
+ end
156
+
157
+ describe "when url does not end with /" do
158
+ before :each do
159
+ @url_parts_stub.stub! :url => 'http://localhost'
160
+ end
161
+
162
+ it "should just return an url given by UrlParts" do
163
+ @route_set.generator.generate_start(:some_path, :some_request).should == 'http://localhost'
164
+ end
165
+ end
166
+
167
+ describe "when url ends with /" do
168
+ before :each do
169
+ @url_parts_stub.stub! :url => 'http://localhost/'
170
+ end
171
+
172
+ it "should strip trailing slash" do
173
+ @route_set.generator.generate_start(:some_path, :some_request).should == 'http://localhost'
174
+ end
175
+ end
176
+ end
177
+
178
+ describe "#generate_full" do
179
+ shared_examples_for "correct routes generator" do
180
+ describe "when request is a Rack::Request (Rails >= 2.3)" do
181
+ before :each do
182
+ @route_set.add_named_route :items, '/items'
183
+ @request = Rack::Request.new(Rack::MockRequest.env_for(@url))
184
+ end
185
+
186
+ it "should generate an URL correctly" do
187
+ @route_set.generator.generate_full(:items, @request).should == @url + '/items'
188
+ end
189
+ end
190
+
191
+ describe "when request is a AbstractRequest (Rails <= 2.2)" do
192
+ before :each do
193
+ @route_set.add_named_route :items, '/items'
194
+
195
+ @request = Struct.new(:url, :protocol, :host, :port).new(@url.dup, "#{@scheme}://", @host, @port)
196
+ end
197
+
198
+ it "should generate an URL correctly" do
199
+ @route_set.generator.generate_full(:items, @request).should == @url + '/items'
200
+ end
201
+ end
202
+
203
+ describe "when data is provided in @generated_with" do
204
+ before :each do
205
+ @route_set.add_named_route :items, '/items', :generate_with => { :scheme => @scheme, :host => @host, :port => @port }
206
+ @request = Rack::Request.new(Rack::MockRequest.env_for('ftp://something-another:9393'))
207
+ end
208
+
209
+ it "should generate an URL correctly" do
210
+ @route_set.generator.generate_full(:items, @request).should == @url + '/items'
211
+ end
212
+ end
213
+ end
214
+
215
+ describe "when protocol is http" do
216
+ describe "whem port is 80" do
217
+ before :each do
218
+ @scheme, @host, @port = 'http', 'localhost', 80
219
+ @url = 'http://localhost'
220
+ end
221
+
222
+ it_should_behave_like "correct routes generator"
223
+ end
224
+
225
+ describe "when port is custom" do
226
+ before :each do
227
+ @scheme, @host, @port = 'http', 'localhost', 8080
228
+ @url = 'http://localhost:8080'
229
+ end
230
+
231
+ it_should_behave_like "correct routes generator"
232
+ end
233
+ end
234
+
235
+ describe "when protocol is https" do
236
+ describe "whem port is 443 (standard)" do
237
+ before :each do
238
+ @scheme, @host, @port = 'https', 'localhost', 443
239
+ @url = 'https://localhost'
240
+ end
241
+
242
+ it_should_behave_like "correct routes generator"
243
+ end
244
+
245
+ describe "when port is custom" do
246
+ before :each do
247
+ @scheme, @host, @port = 'https', 'localhost', 8443
248
+ @url = 'https://localhost:8443'
249
+ end
250
+
251
+ it_should_behave_like "correct routes generator"
252
+ end
253
+ end
254
+ end
255
+
140
256
  describe "nested generation" do
141
257
  before do
142
258
  @route_set2 = Usher.new(:generator => Usher::Util::Generators::URL.new)
@@ -272,5 +388,4 @@ describe "Usher URL generation" do
272
388
  @r2.generator.generate(:route).should == "/r2"
273
389
  end
274
390
  end
275
-
276
391
  end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+ require "usher"
3
+
4
+ describe Usher::Route::GenerateWith, "#empty?" do
5
+ before :all do
6
+ GenerateWith = Usher::Route::GenerateWith
7
+ end
8
+
9
+ describe "when all fields are nil" do
10
+ before :each do
11
+ @empty_generate_with = GenerateWith.new
12
+ end
13
+
14
+ it "should return true" do
15
+ @empty_generate_with.empty?.should be_true
16
+ end
17
+ end
18
+
19
+ describe "when at least one field is filled" do
20
+ before :each do
21
+ @filled_generate_with = GenerateWith.new('http')
22
+ end
23
+
24
+ it "should return false" do
25
+ @filled_generate_with.empty?.should be_false
26
+ end
27
+ end
28
+ end
@@ -56,6 +56,25 @@ describe "Usher (for rack) route dispatching" do
56
56
  response.status.should eql(404)
57
57
  end
58
58
 
59
+ describe "shortcuts" do
60
+ describe "get" do
61
+ before(:each) do
62
+ route_set.reset!
63
+ route_set.get('/sample').to(@app)
64
+ end
65
+
66
+ it "should dispatch a GET request" do
67
+ response = route_set.call_with_mock_request("/sample", "GET")
68
+ response.body.should eql("Hello World!")
69
+ end
70
+
71
+ it "should dispatch a HEAD request" do
72
+ response = route_set.call_with_mock_request("/sample", "HEAD")
73
+ response.body.should eql("Hello World!")
74
+ end
75
+ end
76
+ end
77
+
59
78
  describe "mounted rack instances" do
60
79
  before do
61
80
  @bad_app = mock("bad_app")
@@ -181,7 +200,8 @@ describe "Usher (for rack) route dispatching" do
181
200
  it "should allow me to set a default application to use" do
182
201
  @app.should_receive(:call).with{|e| e['usher.params'].should == {:middle => :ware}}
183
202
 
184
- u = Usher::Interface::RackInterface.new(@app)
203
+ u = Usher::Interface.for(:rack)
204
+ u.app = @app
185
205
  u.add("/foo", :default_values => {:middle => :ware}).name(:foo)
186
206
 
187
207
  u.call(Rack::MockRequest.env_for("/foo"))
@@ -190,7 +210,8 @@ describe "Usher (for rack) route dispatching" do
190
210
  it "should use the default application when no routes match" do
191
211
  env = Rack::MockRequest.env_for("/not_a_route")
192
212
  @app.should_receive(:call).with(env)
193
- u = Usher::Interface::RackInterface.new(@app)
213
+ u = Usher::Interface.for(:rack)
214
+ u.app = @app
194
215
  u.call(env)
195
216
  end
196
217
 
@@ -0,0 +1,50 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
2
+ require "usher"
3
+
4
+ describe "Rack interface extensions for Usher::Route" do
5
+ before(:each) do
6
+ @route_set = Usher::Interface.for(:rack)
7
+ @app = MockApp.new("Hello World!")
8
+ @env = Rack::MockRequest.env_for("/index.html")
9
+ end
10
+
11
+ describe "basic functinality" do
12
+ it "should set redirect headers" do
13
+ @route_set.get("/index.html").redirect("/")
14
+ raw_response = @route_set.call(@env)
15
+ response = Rack::MockResponse.new(*raw_response)
16
+ response.should be_redirect
17
+ end
18
+
19
+ it "should redirect '/index.html' to '/'" do
20
+ @route_set.get("/index.html").redirect("/")
21
+ status, headers, body = @route_set.call(@env)
22
+ headers["Location"].should eql("/")
23
+ end
24
+ end
25
+
26
+ describe "chaining" do
27
+ it "should be chainable" do
28
+ @route_set.get("/index.html").redirect("/").name(:root)
29
+ url = @route_set.router.generator.generate(:root)
30
+ url.should eql("/index.html")
31
+ end
32
+
33
+ it "should not influence actual invoking" do
34
+ @route_set.get("/index.html").redirect("/").name(:root)
35
+ @route_set.call(@env)
36
+ end
37
+ end
38
+
39
+ describe "custom status" do
40
+ it "should enable to set custom HTTP status" do
41
+ @route_set.get("/index.html").redirect("/", 303)
42
+ status, headers, body = @route_set.call(@env)
43
+ status.should eql(303)
44
+ end
45
+
46
+ it "should raise an exception if given HTTP code isn't a redirection" do
47
+ lambda { @route_set.get("/index.html").redirect("/", 200) }.should raise_error(ArgumentError)
48
+ end
49
+ end
50
+ end
@@ -2,7 +2,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_hel
2
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'compat'))
3
3
  require "usher"
4
4
 
5
- route_set = Usher::Interface.for(:rails2_2)
5
+ route_set = Usher::Interface.for(:rails22)
6
6
 
7
7
  describe "Usher (for rails 2.2) URL generation" do
8
8
 
@@ -2,7 +2,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_hel
2
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'compat'))
3
3
  require "usher"
4
4
 
5
- route_set = Usher::Interface.for(:rails2_2)
5
+ route_set = Usher::Interface.for(:rails22)
6
6
 
7
7
  describe "Usher (for rails 2.2) route adding" do
8
8
 
@@ -3,7 +3,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'compat'))
3
3
  require "usher"
4
4
  require 'action_controller'
5
5
 
6
- route_set = Usher::Interface.for(:rails2_2)
6
+ route_set = Usher::Interface.for(:rails22)
7
7
 
8
8
  def build_request_mock(path, method, params)
9
9
  request = mock "Request"
@@ -2,7 +2,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_hel
2
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'compat'))
3
3
  require "usher"
4
4
 
5
- route_set = Usher::Interface.for(:rails2_3)
5
+ route_set = Usher::Interface.for(:rails23)
6
6
 
7
7
  describe "Usher (for rails 2.3) URL generation" do
8
8
 
@@ -2,7 +2,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_hel
2
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'compat'))
3
3
  require "usher"
4
4
 
5
- route_set = Usher::Interface.for(:rails2_3)
5
+ route_set = Usher::Interface.for(:rails23)
6
6
 
7
7
  describe "Usher (for rails 2.3) route adding" do
8
8
 
@@ -3,7 +3,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'compat'))
3
3
  require "usher"
4
4
  require 'action_controller'
5
5
 
6
- route_set = Usher::Interface.for(:rails2_3)
6
+ route_set = Usher::Interface.for(:rails23)
7
7
 
8
8
  def build_request_mock(path, method, params)
9
9
  request = mock "Request"
@@ -64,13 +64,12 @@ describe "Usher route recognition" do
64
64
  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
65
65
  end
66
66
 
67
- it "should use conditionals that are arrays" do
67
+ it "should use flatten and use conditionals that are arrays" do
68
68
  # hijacking user_agent
69
- www_product_show_route = @route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['www'], :method => 'get'})
70
- admin_product_show_route = @route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['admin'], :method => 'get'})
69
+ www_product_show_route = @route_set.add_route('/products/show/:id', :id => /\d+/, :conditions => {:subdomains => ['www', 'admin'], :method => 'get'})
71
70
 
72
- admin_product_show_route.should == @route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['admin'], :user_agent => true})).path.route
73
- www_product_show_route.should == @route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => ['www'], :user_agent => false})).path.route
71
+ www_product_show_route.should == @route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => 'admin', :user_agent => true})).path.route
72
+ www_product_show_route.should == @route_set.recognize(build_request({:method => 'get', :path => '/products/show/123', :subdomains => 'www', :user_agent => false})).path.route
74
73
  end
75
74
  end
76
75
 
@@ -0,0 +1,116 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+ require "usher"
3
+ require 'rack/test'
4
+
5
+ module PathAndRequestHelper
6
+ def stub_path_with(scheme, host, port)
7
+ generate_with = Usher::Route::GenerateWith.new(scheme, port, host)
8
+
9
+ route = stub 'route'
10
+ route.stub! :generate_with => generate_with
11
+
12
+ path = stub 'path'
13
+ path.stub! :route => route
14
+
15
+ path
16
+ end
17
+
18
+ def stub_path
19
+ stub_path_with nil, nil, nil
20
+ end
21
+
22
+ def rack_request_for(url)
23
+ Rack::Request.new(Rack::MockRequest.env_for(url))
24
+ end
25
+ end
26
+
27
+ describe Usher::Util::Generators::URL::UrlParts do
28
+ include PathAndRequestHelper
29
+
30
+ before :all do
31
+ UrlParts = Usher::Util::Generators::URL::UrlParts
32
+ end
33
+
34
+ describe "#url" do
35
+ describe "when generate_with is provided" do
36
+ before :each do
37
+ @path = stub_path_with 'https', 'overridden', 9443
38
+ @request = rack_request_for 'http://localhost'
39
+ end
40
+
41
+ it "should return url with parts provided by generate_with" do
42
+ url_parts = UrlParts.new(@path, @request)
43
+ url_parts.url.should == "https://overridden:9443"
44
+ end
45
+
46
+ describe "when port is standard" do
47
+ describe "when scheme is https" do
48
+ before :each do
49
+ @path = stub_path_with 'https', 'overridden', 443
50
+ @request = rack_request_for 'http://localhost:8080'
51
+ end
52
+
53
+ it "should not add port to url" do
54
+ url_parts = UrlParts.new(@path, @request)
55
+ url_parts.url.should == "https://overridden"
56
+ end
57
+ end
58
+
59
+ describe "when scheme is http" do
60
+ before :each do
61
+ @path = stub_path_with 'http', 'overridden', 80
62
+ @request = rack_request_for 'http://localhost:8080'
63
+ end
64
+
65
+ it "should not add port to url" do
66
+ url_parts = UrlParts.new(@path, @request)
67
+ url_parts.url.should == "http://overridden"
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "when scheme is not given" do
73
+ before :each do
74
+ @path = stub_path_with nil, 'overridden', 8443
75
+ end
76
+
77
+ describe "when request is Rack's one" do
78
+ before :each do
79
+ @request = rack_request_for 'https://localhost'
80
+ end
81
+
82
+ it "should extract scheme from request" do
83
+ url_parts = UrlParts.new(@path, @request)
84
+ url_parts.url.should == "https://overridden:8443"
85
+ end
86
+ end
87
+
88
+ describe "when request is an AbstractRequest (Rails < 2.3)" do
89
+ before :each do
90
+ @request = stub 'request'
91
+ @request.stub! :protocol => 'https://'
92
+ end
93
+
94
+ it "should call #protocol, not #scheme" do
95
+ url_parts = UrlParts.new(@path, @request)
96
+ url_parts.url.should == "https://overridden:8443"
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "when generate_with is empty" do
103
+ before :each do
104
+ @path = stub_path
105
+ @request = mock 'request'
106
+ end
107
+
108
+ it "should just extract the url" do
109
+ @request.should_receive(:url).and_return('http://localhost')
110
+
111
+ url_parts = UrlParts.new(@path, @request)
112
+ url_parts.url.should == 'http://localhost'
113
+ end
114
+ end
115
+ end
116
+ end