Background
I want to write the following test for my Ruby on Rails application.
Log in as user.
Visit edit user page.
Click link in nav to go to About Us page.
Actually visit the About Us page and confirm its the correct template.
The reason is that I found a bug where for the link About Us I have it be referential for '/welcome/about/' and so it goes to /users/welcome/about which doesn't exist.
My Code
My test code is as follows:
test 'welcome page from user page works' do
log_in_as(#user)
get edit_user_path(#user)
assert_select "a", { :text=> "About Us" }
click_on ("About Us")
assert_template 'welcome/about'
end
Error Message
ERROR["test_welcome_page_from_user_page_works", WelcomePageTest, 1.42307711095782]
test_welcome_page_from_user_page_works#WelcomePageTest (1.42s)
Capybara::ElementNotFound: Capybara::ElementNotFound: Unable to find link or button "About Us"
test/integration/welcome_page_test.rb:13:in `block in <class:WelcomePageTest>'
Finished in 1.42605s
1 tests, 1 assertions, 0 failures, 1 errors, 0 skips
Since there is 1 assertion this makes me think that the assertion the link exists pasts but somehow click_link can't find it?
EDIT This was my final code for the test:
test 'welcome page from user page works' do
log_in_as(#user)
visit edit_user_path(#user)
click_on ("About Us")
assert_template 'welcome/about'
end
Note I also changed the routes to be just hardcoded in:
get 'about' => 'welcome#about'
For capybara use the visit method instead of get
visit edit_user_path(#user)
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>.
Getting the following errors when I run 'bundle exec rspec spec/requests/static_pages_spec.rb:
9 examples, 2 failures
Failed examples:
rspec ./spec/requests/static_pages_spec.rb:56 # Static pages Contact page should have the title 'Contact page'
rspec ./spec/requests/static_pages_spec.rb:51 # Static pages Contact page should have the content 'Contact page'
I can't figure out how to get the two tests to pass here.
Trying to get through the tutorial here, learning, very new (I believe this is the code):
describe "Contact page" do
it "should have the content 'Contact'" do
visit '/static_pages/contact'
expect(page).to have_content('Contact')
end
it "should have the title 'Contact'" do
visit '/static_pages/contact'
expect(page).to have_content("Ruby on Rails Tutorial Sample App | Contact")
end
end
end
Additionally, the html file:
<% provide(:title, 'Contact') %>
<h1>Contact</h1>
<p>
Contact Ruby on Rails Tutorial about the sample app at the
contact page.
</p>
You're expecting the title with have_content and expecting the content with have_title.
Try
expect(page).to have_title('Contact')
and
expect(page).to have_content("Ruby on Rails Tutorial Sample App | Contact")
Actually you need to reword this last one a little because this is not the content you have in the view but you get the idea.
I've searched around and this seems like a common enough issue, but nothing has worked for me. Here goes!
Firstly, I'm working through the Hartl RoR tutorial. I'm towards the end of section 9 (video 905) and I'm trying to test a failing user login. Here's the code in user_spec.rb:
describe "failure" do
it "should not log the user in" do
visit login_path
puts response.body
fill_in 'session_email', with: ""
fill_in 'session_password', with: ""
click_button
response.should have_selector('div.login_error', content: "Invalid")
response.should render_template('sessions/new')
end
end
and here's the autotest error:
1) User login failure should not log the user in
Failure/Error: visit login_path
NameError:
undefined local variable or method `login_path' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_5::Nested_1:0x00000102c79248>
# ./spec/models/user_spec.rb:176:in `block (4 levels) in <top (required)>'
I tried writing visit login_path as visit '/login', and still got an error, although it changed to this:
Failure/Error: visit '/login'
NoMethodError:
undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_5::Nested_1:0x00000102c2d140>
Which makes me think this is maybe a webrat issue, as I read somewhere that 'visit' comes from webrat (and not rspec). I also know that it's not getting past the first line, as the puts response.body isn't showing up on the autotest failure. More confusing is that in another part of my app, I have other test code that's virtually identical and it works fine.
layout_links_spec.rb:
before(:each) do
#user = Factory(:user)
visit login_path
# puts response.body
fill_in 'session_email', with: #user.email
fill_in 'session_password', with: #user.password
click_button
end
Any ideas?
I had to do a lot of updates to get your code running. I haven't done Rails on my home machine for a while so it was good to get it all up to date.
Found a solution to getting named routes to work but that just led to another problem. Finally the light went on. You are doing the test in the wrong place. The user model spec is not where you test login. As you mentioned, another similar test works. That is in the Request specs. The visit command and named routes are designed to work in that directory.
I'm creating a multilanguage CMS with Rails, Rspec (for test) and capybara.
the problem appear when i wrote this test
it "redirect and create a new post" do
visit posts_path
create_new_post = I18n.t('posts.index.create_new_post')
click_link create_new_post
current_path.should == new_post_path
end
problem is in last line and i got this
expected: "/posts/new"
got: "/en/posts/new" (using ==)
i want to use something like "new_post_path", not "/en/posts/new"
the main problem depicted when i use something like this
it "redirect to show link" do
visit posts_path
page.should have_content 'show'
click_link 'show'
current_path.should == post_path(#post)
end
any help is appreciate.
Check this StackOverflow question for some ideas on this subject. My preferred way is this answer on the same question. But, using your current code, to get your expectations right you would perhaps do something like this (assuming you want to test all of your locales):
I18n.available_locales.each do |locale|
it "should redirect and create a new post" do
visit posts_path(locale)
create_new_post = I18n.t('posts.index.create_new_post')
click_link create_new_post
current_path.should == new_post_path(locale)
end
it "should redirect to show link" do
visit posts_path(locale)
page.should have_content 'show'
click_link 'show'
current_path.should == post_path(locale, #post)
end
end