-
Notifications
You must be signed in to change notification settings - Fork 22k
Description
Steps to reproduce
I generated a new rails 5.0.0.rc1 app along with a home controller and a sessions controller:
# in routes.rb
get '/login', to: 'sessions#new', as: 'login'
root to: 'home#show'
# sessions controller
class SessionsController < ApplicationController
def new
if session[:user_id]
redirect_to root_url, notice: 'Already logged in'
end
end
end
Now the first thing I notice is that my auto generated test file inherits from ActionDispatch::IntegrationTest:
# test/controllers/sessions_controller_test.rb
class SessionsControllerTest < ActionDispatch::IntegrationTest
end
So lets try to write a test where we set the user_id
session key so we can ensure that our logged in user is redirected to the root path when they visit the login page. According to the Edge Guide we're supposed to use named arguments with HTTP requests in tests now:
# test/controllers/sessions_controller_test.rb
class SessionsControllerTest < ActionDispatch::IntegrationTest
test 'should redirect to root path if a logged in user visits the login page' do
get login_url, session: { user_id: 42 }
assert_redirected_to root_url, 'Did not redirect'
end
end
This test fails because the redirect is not followed and we also see the following deprecation message:
DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only
the following keyword arguments in future Rails versions:
params, headers, env, xhrExamples:
get '/profile',
params: { id: 1 },
headers: { 'X-Extra-Header' => '123' },
env: { 'action_dispatch.custom' => 'custom' },
xhr: true
So rails is not letting us set the session in the way we are advised to in the Edge Guide.
It looks like the code that enables the use of a kw_arg named 'session' lives in ActionController::TestCase and in order to fix this issue I had to do the following:
1 - Change SessionsControllerTest to inherit from ActionControllerTestCase:
class SessionsControllerTest < ActionController::TestCase
2 - Use symbolized action names instead of URL's with http verbs
# changed from
get '/login', session: { user_id: 42 }
# to
get :new, session: { user_id: 42 }
It's worth pointing out that we can't even set session variables manually when inheriting from ActionDispatch::IntegrationTest i.e:
test 'some test' do
session[:user_id] = 42
assert something
end
NoMethodError: undefined method `session' for nil:NilClass
Expected behavior
I was expecting to be able to pass keyword arguments to HTTP verbs in my controller tests like so:
get '/some-url', session: { cart_id: 42 }
Actual behavior
Keyword arguments appear to be ignored unless you inherit from ActionController::TestCase
System configuration
Rails version:
5.0.0.rc1
Ruby version:
mri 2.3.0p0