Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
can't set default_url_options for integration tests #546
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
josevalim
May 13, 2011
Contributor
I believe you have to define the default_url_options in your test case. Defining it in ActiveSupport::TestCase will probably be fine. The different is that you don't have access to params.
I believe you have to define the default_url_options in your test case. Defining it in ActiveSupport::TestCase will probably be fine. The different is that you don't have access to params. |
josevalim
closed this
May 13, 2011
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
nickurban
May 13, 2011
Yes, but there needs to be a way to set it from params. Otherwise, applications that use scopes with parameters are simply untestable!
nickurban
commented
May 13, 2011
Yes, but there needs to be a way to set it from params. Otherwise, applications that use scopes with parameters are simply untestable! |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
nickurban
commented
May 13, 2011
Furthermore, I just tried defining it in the test case, and it wasn't used. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
josevalim
May 13, 2011
Contributor
Damn, I see what is happening. You would need to define the default_url_options in the integration session object:
I am reopening this then.
Damn, I see what is happening. You would need to define the default_url_options in the integration session object: I am reopening this then. |
josevalim
reopened this
May 13, 2011
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
benzittlau
Jun 1, 2011
This is a big problem for me. Trying to use a scope for a locale and it works fine in the application but is completely crashing all my cucumber tests.
benzittlau
commented
Jun 1, 2011
This is a big problem for me. Trying to use a scope for a locale and it works fine in the application but is completely crashing all my cucumber tests. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
nickurban
Jun 2, 2011
Yes, it's very annoying. There needs to be a way to conveniently set default_url_options from params.
nickurban
commented
Jun 2, 2011
Yes, it's very annoying. There needs to be a way to conveniently set default_url_options from params. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
benzittlau
Jun 2, 2011
I've monkey patched this by adding the following into a cucumber support file:
#monkey patch to fix the fact that ActionDispatch::Integration::Session blows
#away the ApplicationController default_url_options which are necessary
#for the locale scope to work
module ActionDispatch
module Integration
class Session
def default_url_options
{ :host => host, :protocol => https? ? "https" : "http" }.merge!(ApplicationController.new.default_url_options)
end
end
end
end
benzittlau
commented
Jun 2, 2011
I've monkey patched this by adding the following into a cucumber support file: #monkey patch to fix the fact that ActionDispatch::Integration::Session blows
#away the ApplicationController default_url_options which are necessary
#for the locale scope to work
module ActionDispatch
module Integration
class Session
def default_url_options
{ :host => host, :protocol => https? ? "https" : "http" }.merge!(ApplicationController.new.default_url_options)
end
end
end
end |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
nickurban
Jun 2, 2011
Thanks for sharing your solution. Unfortunately that doesn't work for me, because I read my option from params, which won't be defined on a new ApplicationController.
nickurban
commented
Jun 2, 2011
Thanks for sharing your solution. Unfortunately that doesn't work for me, because I read my option from params, which won't be defined on a new ApplicationController. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
nickurban
Jun 6, 2011
I ended up hacking around this by storing my path param in a global variable in my cucumber steps and then monkey patching default_url_options to use that global. It's pretty kludgy, but at least I can run my test suite again.
nickurban
commented
Jun 6, 2011
I ended up hacking around this by storing my path param in a global variable in my cucumber steps and then monkey patching default_url_options to use that global. It's pretty kludgy, but at least I can run my test suite again. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
keeran
Jun 15, 2011
I've been hitting a hurdle trying to upgrade to 3.1 with Rspec, could it be related?
I was about to put in a monkey patch as per @benzittlau but wanted to find the cause before blindly hacking the framework(s).
keeran
commented
Jun 15, 2011
I've been hitting a hurdle trying to upgrade to 3.1 with Rspec, could it be related? I was about to put in a monkey patch as per @benzittlau but wanted to find the cause before blindly hacking the framework(s). |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
hardipe
Jul 10, 2011
@nickurban, can you please give a more precise description of your workaround. I am not using cucumber, just the plain integration testing framework shipped with Rails.
Where do I need to assign the params, so that it's globally accessible, and how do I monkey patch default_url_options to use that?
hardipe
commented
Jul 10, 2011
@nickurban, can you please give a more precise description of your workaround. I am not using cucumber, just the plain integration testing framework shipped with Rails. Where do I need to assign the params, so that it's globally accessible, and how do I monkey patch default_url_options to use that? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
nickurban
Jul 10, 2011
I made a file in features/support/default_url_options.rb:
def default_url_options(options = {})
# set site_prefix from global variable. The $site_prefix global is set during various login steps.
options.merge( :host => host, :protocol => https? ? "https" : "http", :site_prefix => $site_prefix )
end
When my features make use of URL helpers, they find this method and use the prefix.
In my login steps, I have a "When I log into account..." which works entirely through the UI and a "Given I am logged in as
X..." which creates a user directly. Once the user has been created, both of them call a method which sets $site_prefix.
Like I said, it's not the most elegant solution, but after several days of not being able to run tests, it was good enough for me! It might be time for me to revisit this now and redo it properly :)
nickurban
commented
Jul 10, 2011
I made a file in features/support/default_url_options.rb: def default_url_options(options = {})
# set site_prefix from global variable. The $site_prefix global is set during various login steps.
options.merge( :host => host, :protocol => https? ? "https" : "http", :site_prefix => $site_prefix )
end When my features make use of URL helpers, they find this method and use the prefix. In my login steps, I have a "When I log into account..." which works entirely through the UI and a "Given I am logged in as Like I said, it's not the most elegant solution, but after several days of not being able to run tests, it was good enough for me! It might be time for me to revisit this now and redo it properly :) |
bartocc
commented
Jul 11, 2011
I've submitted issue #2031 related to default_url_options but with callbacks interaction rather than params. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
spastorino
Jul 14, 2011
Owner
Can you guys provide a patch with a test case or at least just a failing test case?. Thanks.
Can you guys provide a patch with a test case or at least just a failing test case?. Thanks. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
hardipe
Jul 14, 2011
Here's a fresh rails project to demonstrate that
https://github.com/hardipe/Rails-Issue-546
rake test:functionals passes
rake test:integration fails
they are testing the same thing
hardipe
commented
Jul 14, 2011
Here's a fresh rails project to demonstrate that https://github.com/hardipe/Rails-Issue-546 rake test:functionals passes |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
mmack
Jul 22, 2011
@nickurban, your monkey patch works. thx. I had the problem with a :locale option in the url.
mmack
commented
Jul 22, 2011
@nickurban, your monkey patch works. thx. I had the problem with a :locale option in the url. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
logical42
Jul 24, 2011
er.. i think the scope method in the router is messed up. i think that whatever name you are trying to pass into the scope you're specifying isn't getting passed.
Using your code example from above:
require 'test_helper'
class PrefixTest < ActionDispatch::IntegrationTest
test "path prefix" do
#foos_path
#instead you replace the line above with this:
foos_path[(:path_prefix)]
end
end
The above will pass.
But you should realize that any parameter sent in there will actually pass. If you go into the browser and try typing any string as your scope-prefix, like '/test/foos' or '/asdf/foos', then the router will route you along.
I suspect the underlying issue is with the router's scope method, since if the scope isn't passing whatever you're 'scoping' (i.e. 'test' or 'scopedpath'), the router can't reasonably be expected to generate a helper method that actually directs to your path.
logical42
commented
Jul 24, 2011
er.. i think the scope method in the router is messed up. i think that whatever name you are trying to pass into the scope you're specifying isn't getting passed. Using your code example from above: require 'test_helper' end The above will pass. But you should realize that any parameter sent in there will actually pass. If you go into the browser and try typing any string as your scope-prefix, like '/test/foos' or '/asdf/foos', then the router will route you along. I suspect the underlying issue is with the router's scope method, since if the scope isn't passing whatever you're 'scoping' (i.e. 'test' or 'scopedpath'), the router can't reasonably be expected to generate a helper method that actually directs to your path. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
logical42
Jul 24, 2011
oh yeah and if you delete the method from the application controller, it has no effect on anything whatsoever.
logical42
commented
Jul 24, 2011
oh yeah and if you delete the method from the application controller, it has no effect on anything whatsoever. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
dyba
Jul 24, 2011
Contributor
I uploaded a sample app to show what @logical42 mentioned when he said there's something wrong with the routing in Rails. See this link. Let me put the important parts here in brief:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
end
# config/routes.rb
RailsIssue546::Application.routes.draw do
# The priority is based upon order of creation:
# first created -> highest priority.
scope ':path_prefix' do
resources :foos
end
end
# rest/integration/prefix_test.rb
require 'test_helper'
class PrefixTest < ActionDispatch::IntegrationTest
test "path prefix" do
get 'test/foos'
assert_response :failure
get 'asdf/foos'
assert_response :failure
end
end
The above two tests don't pass.
I uploaded a sample app to show what @logical42 mentioned when he said there's something wrong with the routing in Rails. See this link. Let me put the important parts here in brief: # app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
end # config/routes.rb
RailsIssue546::Application.routes.draw do
# The priority is based upon order of creation:
# first created -> highest priority.
scope ':path_prefix' do
resources :foos
end
end # rest/integration/prefix_test.rb
require 'test_helper'
class PrefixTest < ActionDispatch::IntegrationTest
test "path prefix" do
get 'test/foos'
assert_response :failure
get 'asdf/foos'
assert_response :failure
end
end The above two tests don't pass. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
logical42
commented
Jul 24, 2011
Awesome! Thanks for doing that Dan! |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
dyba
Jul 24, 2011
Contributor
@spastorino, here's the failing test you had asked for. I hope I was able to capture the problem with the test setup I created. I'll welcome any feedback.
@spastorino, here's the failing test you had asked for. I hope I was able to capture the problem with the test setup I created. I'll welcome any feedback. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
ipoval
Jul 25, 2011
@josevalim, @spastorino
The ticket says that should be a way to "set default_url_options for integration tests".
This way looks like something what we are looking for:
app.default_url_options = { :path_prefix => 'ivan_poval' }
Taking into account that we have the routes set like this:
scope ':path_prefix' do
resources :foos
end
The example of usage looks like this:
class TestFlowTest < ActionDispatch::IntegrationTest
fixtures :all
def setup
app.default_url_options = { :path_prefix => 'ivan_poval' }
end
test "the truth" do
puts foos_path
end
end
@josevalim, you mentioned that #default_url_options should be set through the Session object. I would argue that because the routes are global to the application and app.default_url_options = { :path_prefix => 'ivan_poval' } seems to do its job fine.
IMHO: the ticket should be closed without any further code changes, but there is a question about the purpose of these lines:
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb#L187
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb#L188
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb#L189
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb#L190
ipoval
commented
Jul 25, 2011
@josevalim, @spastorino This way looks like something what we are looking for: Taking into account that we have the routes set like this: The example of usage looks like this:
end @josevalim, you mentioned that #default_url_options should be set through the Session object. I would argue that because the routes are global to the application and app.default_url_options = { :path_prefix => 'ivan_poval' } seems to do its job fine. IMHO: the ticket should be closed without any further code changes, but there is a question about the purpose of these lines: |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
hardipe
commented
Jul 25, 2011
@ipoval |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
dyba
Jul 26, 2011
Contributor
@hardpipe
I changed my sample app with the following changes. The error I'm getting has to do with Rails not being able to find the route 'test/foos'. Are you getting the same thing?
require 'test_helper'
class PrefixTest < ActionDispatch::IntegrationTest
def setup
app.default_url_options = { :path_prefix => 'test' }
end
test "path prefix" do
get 'test/foos'
assert_response :success
assert_generates "/test/foos", { :controller => "foos", :action => "index" }
end
end
>_ rake test:recent
Loaded suite /Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@Rails310RC4/gems/rake-0.9.2/lib/rake/rake_test_loader
Started
PrefixTest:
ERROR path prefix (0.10s)
ActionController::RoutingError: No route matches {:controller=>"foos"}
/Users/danieldyba/.rvm/gems/ruby-1.9.2-p180@Rails310RC4/gems/actionpack-3.1.0.rc4/lib/action_dispatch/routing/route_set.rb:464:in `raise_routing_error'
Finished in 0.100495 seconds.
1 tests, 1 assertions, 0 failures, 1 errors, 0 skips
rake aborted!
Command failed with status (1): [/Users/danieldyba/.rvm/rubies/ruby-1.9.2-p...]
1 Issue #546: Failing test, no matching route {:controller => "foos"}
Tasks: TOP => test:recent
(See full trace by running task with --trace)
@hardpipe require 'test_helper'
class PrefixTest < ActionDispatch::IntegrationTest
def setup
app.default_url_options = { :path_prefix => 'test' }
end
test "path prefix" do
get 'test/foos'
assert_response :success
assert_generates "/test/foos", { :controller => "foos", :action => "index" }
end
end
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
hardipe
commented
Jul 26, 2011
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
thoefer
Aug 7, 2011
- Url helpers in integration tests respect default url options from the 'last used controller' with the above commit:
class OptionsTest < ActionDispatch::IntegrationTest
test "default url options" do
get "/store/index"
assert_redirected_to root_url # now passes, as :apples => 5 is included
end
end
This test is from hardipe´s mentioned sample project (https://github.com/hardipe/Rails-Issue-546/). Drawback is that is only works for the last used controller:
class OptionsTest < ActionDispatch::IntegrationTest
test "default url options" do
get "/store/index"
# This makes StoreController is our last used controller. Now, imagine there´s an Items- and PeopleController also....
items_path
# should use defaults from ItemsController but uses those from the last used controller.
people_path
# should use defaults from PeopleController but also uses those from the last used controller.
end
end
As far as I can see the behaviour under 2. is the same as in the app´s controllers and functional tests. But I don´t think this is right at all as a call to items_path should include the defaults from the ItemsController and not the one from the calling controller (resp. test), right? Or not?
thoefer
commented
Aug 7, 2011
class OptionsTest < ActionDispatch::IntegrationTest
test "default url options" do
get "/store/index"
assert_redirected_to root_url # now passes, as :apples => 5 is included
end
end This test is from hardipe´s mentioned sample project (https://github.com/hardipe/Rails-Issue-546/). Drawback is that is only works for the last used controller: class OptionsTest < ActionDispatch::IntegrationTest
test "default url options" do
get "/store/index"
# This makes StoreController is our last used controller. Now, imagine there´s an Items- and PeopleController also....
items_path
# should use defaults from ItemsController but uses those from the last used controller.
people_path
# should use defaults from PeopleController but also uses those from the last used controller.
end
end As far as I can see the behaviour under 2. is the same as in the app´s controllers and functional tests. But I don´t think this is right at all as a call to items_path should include the defaults from the ItemsController and not the one from the calling controller (resp. test), right? Or not? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
hardipe
Aug 7, 2011
I don't really know which behaviour is better. The only thing I have used default_url_options for so far is for filling in the :locale in my routes. When I set the default_url_options in the ApplicationController, all the controllers that inherit from it automatically use the same locale everywhere , which is what I want. (doesn't matter if they get the defaults from the previous controller or the controller that's associated with the route helpers (items_path and people_path)).
Would be nice if anyone else could give their opinion on this though.
hardipe
commented
Aug 7, 2011
I don't really know which behaviour is better. The only thing I have used default_url_options for so far is for filling in the :locale in my routes. When I set the default_url_options in the ApplicationController, all the controllers that inherit from it automatically use the same locale everywhere , which is what I want. (doesn't matter if they get the defaults from the previous controller or the controller that's associated with the route helpers (items_path and people_path)). Would be nice if anyone else could give their opinion on this though. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
thoefer
commented
Aug 7, 2011
Can one of the core team members shortly express the desired behaviour? |
ghost
assigned
josevalim
Oct 9, 2011
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Ping @josevalim & @spastorino |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Is this still an issue? |
nickurban commentedMay 13, 2011
When writing integration tests, it would be preferable if url generation automatically made use of default_url_options as specified in ApplicationController. That said, the next best thing would be for default_url_options to be settable in the test environment, but I can't find any way to do that. This makes it impossible (or at least extremely awkward) to run integration tests when using a scope with a parameter in it.
Here's a simplified use case:
in routes.rb:
in application_controller.rb
foos_path will now resolve to /test/foos when referenced within controllers and views.
in test/integration/prefix_test.rb:
When running the test (rake test:integration), I get the following error:
In my real case, path_prefix gets its value from params[:path_prefix] unless no prefix is specified. For example, something like this: