Reputation: 791
I'm stumped in a particular part of M. Hartl's Rails guide (Ch 8) with integration testing. I am trying to validate user login/logout, here's my testing code(not working):
##doesnt work
test "should display user logout behavior" do
get login_path
assert_template 'sessions/new'
assert_select "a[href=?]", signup_path, count: 3
assert_select "a[href=?]", login_path, count: 2
post_via_redirect login_path, session: {email: @user.email,
password: "password"}
assert_redirected_to @user
assert logged_in?
assert_select "a[href=?]", signup_path, count: 0
assert_select "a[href=?]", login_path, count: 0
delete logout_path
follow_redirect!
assert_template 'static_pages/home'
assert_not logged_in?
assert_select "a[href=?]", login_path, count: 2
assert_select "a[href=?]", signup_path, count: 3
end
however, making these modifications will make it work:
#works
test "should display user logout behavior" do
get login_path
assert_template 'sessions/new'
assert_select "a[href=?]", signup_path, count: 3
assert_select "a[href=?]", login_path, count: 2
post login_path, session: {email: @user.email,
password: "password"}
assert_redirected_to @user
follow_redirect!
assert logged_in?
assert_select "a[href=?]", signup_path, count: 0
assert_select "a[href=?]", login_path, count: 0
delete logout_path
follow_redirect!
assert_template 'static_pages/home'
assert_not logged_in?
assert_select "a[href=?]", login_path, count: 2
assert_select "a[href=?]", signup_path, count: 3
end
The part that fails is the assert_redirected_to
. I have checked via response.body
and everything gets rendered as expected...
Essentially the only difference is post
v. post_via_redirect
.
Looking at the source code of 'via_redirect', I believe they should work as all they
are doing is following redirects until there are none left. In addition, I have no further redirects than those I'm testing for:
def create
user = User.find_by email: params[:session][:email]
if user && user.authenticate(params[:session][:password].downcase)
log_in(user)
redirect_to user_path(user.id)
else
flash.now[:danger] = "Invalid username/password combination"
render 'new'
end
end
def destroy
reset_session
redirect_to root_path
end
From that standpoint, here's the questions:
Do the redirection options get lost whenever we call a via_redirect
, and thus testing
'assert_redirected_to @user' fails?
Is there one more jump I'm making when running via_redirect
? All I see the follow_redirect!
doing is running get(response.location)
.
Many thanks!
Upvotes: 2
Views: 1065
Reputation: 791
I'm posting here for completeness, but I was able to find my own answer. Here it is:
via_redirect
, and thus testing assert_redirected_to @user
fails?Yes! Because of the way request_via_redirect
works:
# File actionpack/lib/action_dispatch/testing/integration.rb, line 92
def request_via_redirect(http_method, path, parameters = nil, headers_or_env = nil)
process(http_method, path, parameters, headers_or_env)
follow_redirect! while redirect?
status
end
After all the redirects are processed, you will end up with a @response
object that will be compared in the following way:
# File actionpack/lib/action_dispatch/testing/assertions/response.rb, line 55
def assert_redirected_to(options = {}, message=nil)
#....
redirect_is = normalize_argument_to_redirection(@response.location)
redirect_expected = normalize_argument_to_redirection(options)
After your final redirect is process, your response_code
will be 200
and your @response.location
will be nil
. So yes, your response headers will be lost and assert_redirected_to
will be false.
via_redirect
? All I see the follow_redirect!
doing is running get(response.location)
.It depends, with your router/controller settings you may have more than one redirect. No matter the case, you will end up with a @response
that has no location
redirected (if you're not in an infinite redirect loop) and you won't have your headers available.
Thanks to @dre-hh for giving me the insight to start thinking about this.
Upvotes: 1
Reputation: 8044
I suppose the issue is just within
assert_redirected_to @user
This assertions just checks the response headers of the previous action, which is fine. However if you follow the redirect the previous redirect response is already gone and you have the response after the redirect.
As this is an integration test there is no need to check every step of it. Because if the redirect fails the next assertion
assert logged_in?
will also fail.
So if using post_via_redirect just check something which applies for the next page.
Upvotes: 1