projectdx-subdomain_routes 0.3.2

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.
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe "subdomain route recognition" do
4
+ before(:each) do
5
+ @request = ActionController::TestRequest.new
6
+ @request.host = "www.example.com"
7
+ @request.request_uri = "/items/2"
8
+ end
9
+
10
+ it "should add the host's subdomain to the request environment" do
11
+ request_environment = ActionController::Routing::Routes.extract_request_environment(@request)
12
+ request_environment[:subdomain].should == "www"
13
+ end
14
+
15
+ it "should add an empty subdomain to the request environment if the host has no subdomain" do
16
+ @request.host = "example.com"
17
+ request_environment = ActionController::Routing::Routes.extract_request_environment(@request)
18
+ request_environment[:subdomain].should == ""
19
+ end
20
+
21
+ context "for a single specified subdomain" do
22
+ it "should recognise a route if the subdomain matches" do
23
+ map_subdomain(:www) { |www| www.resources :items }
24
+ params = recognize_path(@request)
25
+ params[:controller].should == "www/items"
26
+ params[:action].should == "show"
27
+ params[:id].should == "2"
28
+ end
29
+
30
+ it "should not recognise a route if the subdomain doesn't match" do
31
+ map_subdomain("admin") { |admin| admin.resources :items }
32
+ lambda { recognize_path(@request) }.should raise_error(ActionController::RoutingError)
33
+ end
34
+ end
35
+
36
+ context "for a nil or blank subdomain" do
37
+ [ nil, "" ].each do |subdomain|
38
+ it "should recognise a route if there is no subdomain present" do
39
+ map_subdomain(subdomain) { |map| map.resources :items }
40
+ @request.host = "example.com"
41
+ lambda { recognize_path(@request) }.should_not raise_error
42
+ end
43
+ end
44
+ end
45
+
46
+ context "for multiple specified subdomains" do
47
+ it "should recognise a route if the subdomain matches" do
48
+ map_subdomain(:www, :admin, :name => nil) { |map| map.resources :items }
49
+ lambda { recognize_path(@request) }.should_not raise_error
50
+ end
51
+
52
+ it "should not recognise a route if the subdomain doesn't match" do
53
+ map_subdomain(:support, :admin, :name => nil) { |map| map.resources :items }
54
+ lambda { recognize_path(@request) }.should raise_error(ActionController::RoutingError)
55
+ end
56
+ end
57
+
58
+ context "for a :model subdomain" do
59
+ before(:each) do
60
+ map_subdomain(:model => :user) { |user| user.resources :articles }
61
+ end
62
+
63
+ context "when a nested route is requested" do
64
+ before(:each) do
65
+ @request.host = "mholling.example.com"
66
+ @request.request_uri = "/articles"
67
+ end
68
+
69
+ it "should match the route if there is a subdomain" do
70
+ lambda { recognize_path(@request) }.should_not raise_error
71
+ end
72
+
73
+ it "should put the subdomain into the params as :model_id" do
74
+ recognize_path(@request)[:user_id].should == "mholling"
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe "resource" do
4
+ describe "mappings" do
5
+ it "should pass the specified subdomains to any nested routes" do
6
+ map_subdomain(:admin) do |admin|
7
+ admin.resources(:users) { |user| user.options[:subdomains].should == [ "admin" ] }
8
+ admin.resource(:config) { |config| config.options[:subdomains].should == [ "admin" ] }
9
+ end
10
+ end
11
+ end
12
+
13
+ describe "routes" do
14
+ before(:each) do
15
+ map_subdomain(:admin) do |admin|
16
+ admin.resources :users
17
+ admin.resource :config
18
+ end
19
+ end
20
+
21
+ it "should include the subdomains in the routing conditions" do
22
+ ActionController::Routing::Routes.routes.each do |route|
23
+ route.conditions[:subdomains].should == [ "admin" ]
24
+ end
25
+ end
26
+
27
+ it "should include the subdomains in the routing requirements" do
28
+ ActionController::Routing::Routes.routes.each do |route|
29
+ route.requirements[:subdomains].should == [ "admin" ]
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ActionController::Routing::Routes" do
4
+ before(:each) do
5
+ map_subdomain(:www, nil) { |www| www.root :controller => "homes", :action => "show" }
6
+ end
7
+
8
+ it "should know a list of its reserved subdomains" do
9
+ ActionController::Routing::Routes.reserved_subdomains.should == [ "www", "" ]
10
+ ActionController::Routing::Routes.clear!
11
+ ActionController::Routing::Routes.reserved_subdomains.should be_empty
12
+ end
13
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec'
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'rubygems'
5
+ require 'active_support'
6
+ require 'action_controller'
7
+ require 'active_record' # only required for testing optional features, not required by the gem
8
+ require 'action_mailer' # only required for testing optional features, not required by the gem
9
+
10
+ require 'subdomain_routes'
11
+
12
+ require 'action_controller/test_process'
13
+ require 'action_view/test_case'
14
+ require 'test_unit_matcher'
15
+
16
+ ActiveSupport::OptionMerger.send(:define_method, :options) { @options }
17
+
18
+
19
+ Spec::Runner.configure do |config|
20
+ config.before(:each) do
21
+ ActionController::Routing::Routes.clear!
22
+ SubdomainRoutes::Config.stub!(:domain_length).and_return(2)
23
+ end
24
+ config.include(SubdomainRoutes::TestUnitMatcher)
25
+ end
26
+
27
+ def map_subdomain(*subdomains, &block)
28
+ ActionController::Routing::Routes.draw do |map|
29
+ map.subdomain(*subdomains, &block)
30
+ end
31
+ end
32
+
33
+ def recognize_path(request)
34
+ ActionController::Routing::Routes.recognize_path(request.path, ActionController::Routing::Routes.extract_request_environment(request))
35
+ end
36
+
37
+ def in_controller_with_host(host, options = {}, &block)
38
+ spec = self
39
+ Class.new(ActionView::TestCase::TestController) do
40
+ include Spec::Matchers
41
+ end.new.instance_eval do
42
+ request.host = host
43
+ request.instance_eval do
44
+ @env.merge! 'HTTPS' => 'on','SERVER_PORT' => 443 if options[:protocol] =~ /^https(:\/\/)?$/
45
+ @env.merge! 'SERVER_PORT'=> options[:port] if options[:port]
46
+ end
47
+ copy_instance_variables_from(spec)
48
+ instance_eval(&block)
49
+ end
50
+ end
51
+
52
+ def in_object_with_host(host, options = {}, &block)
53
+ spec = self
54
+ Class.new do
55
+ include Spec::Matchers
56
+ include ActionController::UrlWriter
57
+ end.new.instance_eval do
58
+ self.class.default_url_options = { :host => host }
59
+ self.class.default_url_options.merge! options.slice(:port, :protocol)
60
+ copy_instance_variables_from(spec)
61
+ instance_eval(&block)
62
+ end
63
+ end
64
+
65
+ def with_host(host, options = {}, &block)
66
+ in_controller_with_host(host, options.dup, &block)
67
+ in_object_with_host(host, options.dup, &block)
68
+ end
69
+
70
+ ActiveRecord::Base.class_eval do
71
+ alias_method :save, :valid?
72
+ def self.columns() @columns ||= []; end
73
+
74
+ def self.column(name, sql_type = nil, default = nil, null = true)
75
+ columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type, null)
76
+ end
77
+ end
@@ -0,0 +1,46 @@
1
+ module SubdomainRoutes
2
+ module TestUnitMatcher
3
+ class Base
4
+ class TestCase < ActionController::TestCase
5
+ end
6
+
7
+ def initialize(count_method, messages, spec)
8
+ @count_method, @messages, @spec = count_method, messages, spec
9
+ end
10
+
11
+ def run_test(target)
12
+ result = Test::Unit::TestResult.new
13
+ spec = @spec
14
+ TestCase.send :define_method, :test do
15
+ copy_instance_variables_from(spec)
16
+ instance_eval(&target)
17
+ end
18
+ TestCase.new(:test).run(result) {}
19
+ result
20
+ end
21
+
22
+ def matches?(target)
23
+ @result = run_test(target)
24
+ @result_count = @result.send(@count_method)
25
+ @result_count > 0
26
+ end
27
+
28
+ def failure_message
29
+ "Expected #{@count_method.to_s.humanize.downcase} to be more than zero, got zero.\n"
30
+ end
31
+
32
+ def negative_failure_message
33
+ "Expected #{@count_method.to_s.humanize.downcase} to be zero, got #{@result_count}:\n" +
34
+ @result.instance_variable_get(@messages).map(&:inspect).join("\n")
35
+ end
36
+ end
37
+
38
+ def have_errors
39
+ Base.new(:error_count, :@errors, self)
40
+ end
41
+
42
+ def fail
43
+ Base.new(:failure_count, :@failures, self)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,262 @@
1
+ require 'spec_helper'
2
+
3
+ describe "URL writing" do
4
+ { "nil" => nil, "an IP address" => "207.192.69.152" }.each do |host_type, host|
5
+ context "when the host is #{host_type}" do
6
+ it "should raise an error when a subdomain route is requested" do
7
+ map_subdomain(:www) { |www| www.resources :users }
8
+ with_host(host) do
9
+ lambda { www_users_path }.should raise_error(SubdomainRoutes::HostNotSupplied)
10
+ lambda { url_for(:controller => "users", :action => "index", :subdomains => ["www"]) }.should raise_error(SubdomainRoutes::HostNotSupplied)
11
+ end
12
+ end
13
+
14
+ context "and a non-subdomain route is requested" do
15
+ before(:each) do
16
+ ActionController::Routing::Routes.draw { |map| map.resources :users }
17
+ end
18
+
19
+ it "should not raise an error when the route is a path" do
20
+ with_host(host) do
21
+ lambda { users_path }.should_not raise_error
22
+ lambda { url_for(:controller => "users", :action => "index", :only_path => true) }.should_not raise_error
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ [ [ "single", :admin, "admin.example.com" ],
30
+ [ "nil", nil, "example.com" ] ].each do |type, subdomain, host|
31
+ context "when a #{type} subdomain is specified" do
32
+ before(:each) do
33
+ map_subdomain(subdomain, :name => nil) { |map| map.resources :users }
34
+ @url_options = { :controller => "users", :action => "index", :subdomains => [ subdomain.to_s ] }
35
+ @path_options = @url_options.merge(:only_path => true)
36
+ end
37
+
38
+ it "should not change the host for an URL if the host subdomain matches" do
39
+ with_host(host) do
40
+ users_url.should == "http://#{host}/users"
41
+ url_for(@url_options).should == "http://#{host}/users"
42
+ end
43
+ end
44
+
45
+ it "should change the host for an URL if the host subdomain differs" do
46
+ with_host "other.example.com" do
47
+ users_url.should == "http://#{host}/users"
48
+ url_for(@url_options).should == "http://#{host}/users"
49
+ end
50
+ end
51
+
52
+ it "should not force the host for a path if the host subdomain matches" do
53
+ with_host(host) do
54
+ users_path.should == "/users"
55
+ url_for(@path_options).should == "/users"
56
+ end
57
+ end
58
+
59
+ it "should force the host for a path if the host subdomain differs" do
60
+ with_host "other.example.com" do
61
+ users_path.should == "http://#{host}/users"
62
+ url_for(@path_options).should == "http://#{host}/users"
63
+ end
64
+ end
65
+
66
+ [ [ "port", { :port => 8080 }, "http://#{host}:8080/users" ],
67
+ [ "protocol", { :protocol => "https" }, "https://#{host}/users" ] ].each do |variant, options, url|
68
+ it "should preserve the #{variant} when forcing the host" do
69
+ with_host "other.example.com", options do
70
+ users_path.should == url
71
+ url_for(@path_options).should == url
72
+ end
73
+ end
74
+ end
75
+
76
+ context "and a subdomain different from the host subdomain is explicitly requested" do
77
+ it "should change the host if the requested subdomain matches" do
78
+ with_host "other.example.com" do
79
+ users_path(:subdomain => subdomain).should == "http://#{host}/users"
80
+ url_for(@path_options.merge(:subdomain => subdomain)).should == "http://#{host}/users"
81
+ end
82
+ end
83
+
84
+ it "should raise a routing error if the requested subdomain doesn't match" do
85
+ with_host(host) do
86
+ lambda { users_path(:subdomain => :other) }.should raise_error(ActionController::RoutingError)
87
+ lambda { url_for(@path_options.merge(:subdomain => :other)) }.should raise_error(ActionController::RoutingError)
88
+ end
89
+ end
90
+ end
91
+
92
+ context "and the current host's subdomain is explicitly requested" do
93
+ it "should not force the host for a path if the subdomain matches" do
94
+ with_host(host) do
95
+ users_path(:subdomain => subdomain).should == "/users"
96
+ url_for(@path_options.merge(:subdomain => subdomain)).should == "/users"
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ [ [ "", [ :books, :dvds ], [ "books.example.com", "dvds.example.com" ] ],
104
+ [ " including nil", [ nil, :www ], [ "example.com", "www.example.com" ] ] ].each do |qualifier, subdomains, hosts|
105
+ context "when multiple subdomains#{qualifier} are specified" do
106
+ before(:each) do
107
+ args = subdomains + [ :name => nil ]
108
+ map_subdomain(*args) { |map| map.resources :items }
109
+ @url_options = { :controller => "items", :action => "index", :subdomains => subdomains.map(&:to_s) }
110
+ @path_options = @url_options.merge(:only_path => true)
111
+ end
112
+
113
+ it "should not change the host for an URL if the host subdomain matches" do
114
+ hosts.each do |host|
115
+ with_host(host) do
116
+ items_url.should == "http://#{host}/items"
117
+ url_for(@url_options).should == "http://#{host}/items"
118
+ end
119
+ end
120
+ end
121
+
122
+ it "should not force the host for a path if the host subdomain matches" do
123
+ hosts.each do |host|
124
+ with_host(host) do
125
+ items_path.should == "/items"
126
+ url_for(@path_options).should == "/items"
127
+ end
128
+ end
129
+ end
130
+
131
+ it "should raise a routing error if the host subdomain doesn't match" do
132
+ with_host "other.example.com" do
133
+ lambda { item_url }.should raise_error(ActionController::RoutingError)
134
+ lambda { item_path }.should raise_error(ActionController::RoutingError)
135
+ lambda { url_for(@url_options) }.should raise_error(ActionController::RoutingError)
136
+ lambda { url_for(@path_options) }.should raise_error(ActionController::RoutingError)
137
+ end
138
+ end
139
+
140
+ context "and a subdomain different from the host subdomain is explicitly requested" do
141
+ it "should change the host if the requested subdomain matches" do
142
+ [ [ subdomains.first, hosts.first, hosts.last ],
143
+ [ subdomains.last, hosts.last, hosts.first ] ].each do |subdomain, new_host, old_host|
144
+ with_host(old_host) do
145
+ items_path(:subdomain => subdomain).should == "http://#{new_host}/items"
146
+ url_for(@path_options.merge(:subdomain => subdomain)).should == "http://#{new_host}/items"
147
+ end
148
+ end
149
+ end
150
+
151
+ it "should preserve the port when changing the host" do
152
+ [ [ subdomains.first, hosts.first, hosts.last ],
153
+ [ subdomains.last, hosts.last, hosts.first ] ].each do |subdomain, new_host, old_host|
154
+ with_host(old_host, :port => 8080) do
155
+ items_path(:subdomain => subdomain).should == "http://#{new_host}:8080/items"
156
+ url_for(@path_options.merge(:subdomain => subdomain)).should == "http://#{new_host}:8080/items"
157
+ end
158
+ end
159
+ end
160
+
161
+ it "should preserve the protocol when changing the host" do
162
+ [ [ subdomains.first, hosts.first, hosts.last ],
163
+ [ subdomains.last, hosts.last, hosts.first ] ].each do |subdomain, new_host, old_host|
164
+ with_host(old_host, :protocol => "https") do
165
+ items_path(:subdomain => subdomain).should == "https://#{new_host}/items"
166
+ url_for(@path_options.merge(:subdomain => subdomain)).should == "https://#{new_host}/items"
167
+ end
168
+ end
169
+ end
170
+
171
+ it "should raise a routing error if the requested subdomain doesn't match" do
172
+ [ [ hosts.first, hosts.last ],
173
+ [ hosts.last, hosts.first ] ].each do |new_host, old_host|
174
+ with_host(old_host) do
175
+ lambda { items_path(:subdomain => :other) }.should raise_error(ActionController::RoutingError)
176
+ lambda { url_for(@path_options.merge(:subdomain => :other)) }.should raise_error(ActionController::RoutingError)
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ it "should downcase a supplied subdomain" do
185
+ map_subdomain(:www1, :www2, :name => nil) { |map| map.resources :users }
186
+ [ [ :Www1, "www1" ], [ "Www2", "www2" ] ].each do |mixedcase, lowercase|
187
+ with_host "www.example.com" do
188
+ users_url(:subdomain => mixedcase).should == "http://#{lowercase}.example.com/users"
189
+ url_for(:controller => "users", :action => "index", :subdomains => [ "www1", "www2" ], :subdomain => mixedcase).should == "http://#{lowercase}.example.com/users"
190
+ end
191
+ end
192
+ end
193
+
194
+ context "when a :model subdomain is specified" do
195
+ before(:each) do
196
+ map_subdomain(:model => :city) { |city| city.resources :events }
197
+ class City < ActiveRecord::Base; end
198
+ @boston = City.new
199
+ @boston.stub!(:new_record?).and_return(false)
200
+ @boston.stub!(:to_param).and_return("boston")
201
+ @url_options = { :controller => "city/events", :action => "index", :subdomains => :city_id, :city_id => @boston }
202
+ @path_options = @url_options.merge(:only_path => true)
203
+ end
204
+
205
+ it "should not change the host if the object has the same to_param as the current subdomain" do
206
+ with_host "boston.example.com" do
207
+ city_events_url(@boston).should == "http://boston.example.com/events"
208
+ city_events_path(@boston).should == "/events"
209
+ url_for(@url_options).should == "http://boston.example.com/events"
210
+ url_for(@path_options).should == "/events"
211
+ end
212
+ end
213
+
214
+ it "should force the host if the object has a different to_param from the current subdomain" do
215
+ with_host "example.com" do
216
+ city_events_url(@boston).should == "http://boston.example.com/events"
217
+ city_events_path(@boston).should == "http://boston.example.com/events"
218
+ url_for(@url_options).should == "http://boston.example.com/events"
219
+ url_for(@path_options).should == "http://boston.example.com/events"
220
+ end
221
+ end
222
+
223
+ [ [ "port", { :port => 8080 }, "http://boston.example.com:8080/events" ],
224
+ [ "protocol", { :protocol => "https" }, "https://boston.example.com/events" ] ].each do |variant, options, url|
225
+ it "should preserve the #{variant} when forcing the host" do
226
+ with_host "example.com", options do
227
+ city_events_url(@boston).should == url
228
+ city_events_path(@boston).should == url
229
+ url_for(@url_options).should == url
230
+ url_for(@path_options).should == url
231
+ end
232
+ end
233
+ end
234
+
235
+ it "should raise an error if the object to_param is an invalid subdomain" do
236
+ @newyork = City.new
237
+ @newyork.stub!(:new_record?).and_return(false)
238
+ @newyork.stub!(:to_param).and_return("new york")
239
+ with_host "www.example.com" do
240
+ lambda { city_events_url(@newyork) }.should raise_error(ActionController::RoutingError)
241
+ lambda { city_events_path(@newyork) }.should raise_error(ActionController::RoutingError)
242
+ lambda { url_for(@url_options.merge(:city_id => @newyork)) }.should raise_error(ActionController::RoutingError)
243
+ lambda { url_for(@path_options.merge(:city_id => @newyork)) }.should raise_error(ActionController::RoutingError)
244
+ end
245
+ end
246
+
247
+ it "should not allow the subdomain to be manually overridden in a named route" do
248
+ with_host "www.example.com" do
249
+ city_events_url(@boston, :subdomain => :canberra).should == "http://boston.example.com/events"
250
+ city_events_path(@boston, :subdomain => :canberra).should == "http://boston.example.com/events"
251
+ end
252
+ end
253
+
254
+ it "should raise a routing error if no subdomain object is supplied to the named route" do
255
+ with_host "www.example.com" do
256
+ [ lambda { city_events_url }, lambda { city_event_url("id") } ].each do |lamb|
257
+ lamb.should raise_error(ActionController::RoutingError) { |e| e.message.should include(":city_id") }
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end