Can an assert_select work after an assert_redirected_to? I have the following controller action and I'm getting a failure.
test "get switchboard" do
...
assert_redirected_to employees_url # success
assert_select 'div' # fail
end
This question is old, but I'll go ahead and answer it since I ran into a similar problem. assert_select can work after a redirect, but you must first tell the test to "follow" the redirect. So, in your case, you could do something like this:
test "get switchboard" do
...
assert_redirected_to employees_url # redirected, not "success" per se
follow_redirect! # this is what you need to do
assert_response :success # if you still want to...
assert_select 'div'
end
assert_select works just as its described in the docs.
I assume that you are trying to do the assert_select on some element on the page that you are redirecting to. The problem with this is that that redirected route is actually not getting rendered.
The first thing that I would do if I were you is toss a binding.pry right in front of that assert_select and take a look at the response.body which will reveal what is actually being rendered. My guess is that you will see something like :
<html><body>You are being redirected.</body></html>"
rather than actual page that you is going to be redirected to.
The answer is stated above in the comments:
add follow_redirect! after assert_redirected_to and your assert_select statements will pass
Related
I'm new to testing rails applications as I usually just do manual testing... but I'm trying to do it the right way this time.
Why is this basic test failing?
test "once you go to to app you are asked to sign in" do
get "/"
assert_redirected_to "/users/sign_in"
assert_select "title", "Home Sign-In"
end
The first assertion is successful but not the second. The title seems correct when I view source.
<title>Home Sign-In</title>
If you have redirect call in your controller method it is not acturally rendered. That's why you can't use assert_select.
You may try to divide your test case into two:
test "once you go to to app you are asked to sign in" do
get "/"
assert_redirected_to "/users/sign_in"
end
test "sign in page title is correct" do
get "/users/sign_in"
assert_select "title", "Home Sign-In"
end
#Pavel is right.
A simple way to check the response after get request is #response.body.
So in your case
test "once you go to to app you are asked to sign in" do
get "/"
assert_redirected_to "/users/sign_in"
byebug #print #response.body here. At this point #response.body will
# be "You are being redirected to /users/sign_in".
assert_select "title", "Home Sign-In"
end
So you can modify it as Pavel has suggested
test "sign in page title is correct" do
get "/users/sign_in"
assert_select "title", "Home Sign-In"
end
I'm completing the exercise to add a Contact page, but the testing fails on the page title.
Here is my testing file:
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
def setup
#base_title = "Ruby on Rails Tutorial Sample App"
end
test "should get root" do
get root_url
assert_response :success
end
test "should get home" do
get static_pages_home_url
assert_response :success
assert_select "title", "Home | #{#base_title}"
end
test "should get help" do
get static_pages_help_url
assert_response :success
assert_select "title", "Help | #{#base_title}"
end
test "should get about" do
get static_pages_about_url
assert_response :success
assert_select "title", "About | #{#base_title}"
end
test "should get contact" do
get static_pages_about_url
assert_response :success
assert_select "title", "Contact | #{#base_title}"
end
end
Here is the contact.html.erb file:
<% provide(:title, "Contact") %>
<h1>Contact</h1>
<p>
Contact the Ruby on Rails Tutorial about the sample app at the
contact page.
</p>
I've also completed the following:
Added the appropriate route
Added the appropriate action
However I get this error message:
test_should_get_contact#StaticPagesControllerTest (0.45s)
<Contact | Ruby on Rails Tutorial Sample App> expected but was
<About | Ruby on Rails Tutorial Sample App>..
Expected 0 to be >= 1.
test/controllers/static_pages_controller_test.rb:35:in `block in <class:StaticPagesControllerTest>'
Please also note that
The page displays correctly, with the expected page title (Contact not About)
I tested again using a completely new page, but had the same result with 'About' being returned in page title
Really not sure why it's returning this as I've followed Tutorial closely. I want to progress in Tutorial, but if I cannot resolve this basic testing issue, I'm not sure I'll get very far!
Please check your code on the second line of this code block.
test "should get contact" do
# get static_pages_about_url # This is wrong correct it to as below
get static_pages_contact_url
assert_response :success
assert_select "title", "Contact | #{#base_title}"
end
You have given a test case to check the contact page title on the about url which obviously will fail the test.
You should be testing for contact page title on the contact url like above.
Make the change and you should get going!
Also a word of motivation, just keep going even if things don't make sense right now cause later they will. Cheers :)
I think you might try to replace the line get static_pages_about_url (under test "should get contact" do) with:
get static_pages_contact_url
What happens is that your test is calling the wrong url (about, instead of contact), causing the error when checking the <title>.
I am using Wicked which redirects to a self-defined link after finishing the wizard. This happens with a second redirect.
So, a PUT update triggers a 302 to /orders/1/finish_wicked, which then redirects to /orders/1. This works as expected, but is hard to test in my controller tests.
it "must redirect to the order" do
put :update
assert_redirected_to "/orders/1/finish_wicked" #=> This passes, but I am not interested in this
assert_redirected_to order #=> This fails, yet, in the end, the user is being redirected here.
end
How can I test a second redirect in my functional -controller- tests?
Right now, I have it split into two tests:
describe "finalize" do
it "should redirect to the wicked_finish page" do
put :update, id: :finalize, order_id: order.id, order: { accepted: true }
assert_redirected_to controller: "build", action: :update, id: :wicked_finish, order_id: order.id
end
describe "wicked_finish" do
it "should redirect to the order page" do
get :show, id: :wicked_finish, order_id: order.id
assert_redirected_to order
end
end
end
One tests that it is redirected to the wicked-provided finish-path, the other to define that if a user lands there, she is redirected to the order.
This is overly verbose; is it not possible to follow redirects in a controller-test? Or is this a bad idea and should the tests be kept split-up, like I have?
It is possible by following the first redirection, use follow_redirect!:
test 'assert second redirect' do
put :update
assert_redirected_to "/orders/1/finish_wicked"
follow_redirect!
assert_redirected_to order
end
Apidock follow_redirect!
Uhmmmmm not sure if this is a proper answer but i have seen some bad code that do something like this. Make the call, when you have redirected it to a page, the response contains redirecting to bla bla bla. In my case the redirection page depended on the params passed hence i knew the link before hand and i asserted the presence of the url/link there.
I have a user_controller_spec.rb that is failing, and I'm not sure why.
require 'spec_helper'
describe UsersController do
describe "GET 'index'" do
it "should be successful" do
get 'index'
response.should be_success
end
end
end
When I run rspec it says:
Failures:
1) UsersController GET 'index' should be successful
Failure/Error: response.should be_success
expected success? to return true, got false
# ./spec/controllers/users_controller_spec.rb:8
Finished in 0.17047 seconds
1 example, 1 failure
Going to the /home/ page in the browser works fine.
Is there a way to get a more detailed reason why it is failing?
Note:
This is rails3, and I am using rspec.
I also have the capybara gem, and searching my solution shows the only reference to capybara is in my gem and gem.lock file.
You can try outputting the response body to see what the message is. Could be anything from the user you're logged in as not having the correct permissions (or visiting a page anonymously that you must be logged in to see) to a strange view error in test environment.
get 'index'
puts response.body.inspect
puts response.status.inspect
...
response.should be_success
response.body will contain the HTML output of the response, so you should be able to tell why it's not a success (hopefully it will have a stack trace or be a redirect or something). Also keep in mind redirecting is not "success". If I remember correctly be_success makes sure the HTTP status code is one of the 200s, redirects are usually 302 or 304 so do not count. If a redirect is intended, try response.should be_redirect.
It could be that you do not just render the page, but redirect. To check on what may be wrong, i would do in my spec something like :
response.should == 1
in order to see what the actual response is. This would give you a good clue on what is happening.
I'm trying to figure out how to run integration tests that are storybased and where AJAX redirects appear during the 'story'.
Simple login example: I login to the website using
def user.logs_in(email, pwd)
get root_path
assert_response :success
assert_template 'index'
post :post, session_path, :email => email, :pwd => pwd
assert_response :redirect
assert_redirect_to backend_path
follow_redirect!
assert_response :success
assert_template 'index'
assert session[:user_id]
end
Unfortunately the login process is AJAX based and insted of a 301-redirect it returns
document.location.href = "<%= backend_path >";
which gives back a 200-code meaning that
assert_response :redirect
fails.
How can i handle AJAX redirects in my integration tests?
If there is no redirect, of course you won't be able to (successfully) test for it. So instead test for what you are doing: You want the response to be a 200 and the body to be a Javascript snippet. Or just use assert_template, too.
If you want to test if your Javascript-Login-Button actually evals the js body and how the browser reacts to that you would have to use something like Selenium.