Capybara have_text Passes When It Should Fail - ruby-on-rails

I have an test written with RSpec and Capybara that should not be passing, however it is:
it 'should have the given text' do
visit root_path
expect(page).to have_text("This is not here")
end
I then included this in the test to look for the issue:
puts page.text
It returns a lot more text than is on the page, and included in that is:
Extracted source (around line #12):
10 11 12 13
})
visit root_path
expect(page).to have_text("This is not here")
It looks like whatever I put in my test will come up when it calls has_text?. Why does it contain all this text that is not on the page?

This is because you have an error in your app/code and a gem rendering the error, and surrounding code, to the returned page enabled in test mode. You want to disable all those types of gems (better_errors, etc) when in test mode (so it's closer to production mode). You can do that by moving them to a development only group in your Gemfile. You can also look in test.log to see what error is being thrown.

Related

Cucumber/Capybara: Test is not accurately reflecting real world use. It is ignoring page errors and passing tests

I did a total rearrangement of my routes so I'm having to go back and change some path names. I ran a cucumber test for my navigation and it came back a success. Knowing that I have some old routes to change I thought that was an odd result so I did some manual checking to confirm my suspicions.
As an example I clicked on a page that was supposed to have a old and obsolete path <li><%= link_to p.title, forum_post_path(p) %></li> that's breaks the page when I am manually clicking around I get a no method error as I should.
But, when I run the cucumber test and use launchy to save and open page. I don't get that error. It loads like there isn't a problem at all. The launchy page that I'm given loads the link_to helper with the bad _path like there isn't a problem at all...
The only thing I can think of is that the words that it is expecting would be there and perhaps the page is loading correctly for a brief moment before Rails spits out the method error and Cucumber is picking up on the positive result first before it returns an error.
Any possible things I can look at? I would hate to get false positives.
Edit: I just added a 1 second sleep timer (should be more than enough) and cucumber still gives me a pass.
Here are the tests so you can view it:
# navigation.feature
Scenario: As a user I want to be able to view a specific forum and it's posts within.
Given There is a User
Given There is a Forum
Given I am on the index
When I click the "Test forum name" link
Then I should see "Name: Test forum name"
Then I should see "Description: test description with a minimum of 20 characters.."
And...
#navigation_steps.rb
Given(/^There is a User$/) do
User.create!(email: "user#test.com", password: "password#1")
expect(User.first.email).to eq("user#test.com")
end
Given(/^I am on the index$/) do
visit root_path
end
Given(/^There is a Forum$/) do
Forum.create!(name: "Test forum name", description: "test description with a minimum of 20 characters..", user_id: User.first.id)
expect(Forum.last.name).to eq("Test forum name")
end
When(/^I click the "([^"]*)" link$/) do |link|
click_link link
end
Then(/^I should see "([^"]*)"$/) do |message|
expect(page).to have_content(message)
end
Screenshots:
You don't say what exactly your tests are checking for, but a couple of possible reasons for this are:
You're using something like spring to keep your test environment loaded - If you are it may not be seeing changing to routes.rb and may require restarting before it knows the routes have changed. Solution: Restart spring or whatever your are using to keep the test env loaded
You incorrectly have the web-console gem in the test environment (it should only be in the development environment) which catches any errors and produces the nice error page. If that error page has the text on it your test checks for (possible since it includes the surrounding code) then your test can pass - Solution: remove web-console from the test environment in your Gemfile.

Using rspec failed tests (to map the program out) is resulting in errors?

Note: I'm following a tutorial for Ruby on Rails, and thus I'm a complete noob
Basically, in the tutorial I am following, it shows you how to make failed tests that you meet as you go along, like a checklist for your program. My problem is that when I do the test, it sort of outputs what it should, but in errors, which isn't good (I think) because it doesn't match the output of the instructions.
Output: http://pastebin.com/0xyf3aBf (and show below)
Output
Failures:
1) Static pages Home page should have the content 'Sample App'
←[31mFailure/Error:←[0m ←[31mexpect(page).to have_content('Sample App')←[0m
←[31mexpected #has_content?("Sample App") to return true, got false←[0m
←[36m # ./spec/requests/static_pages_spec.rb:9:in `block (3 levels) in <top
(required)>'←[0m
Finished in 0.07 seconds
←[31m1 example, 1 failure←[0m
Failed examples:
←[31mrspec ./spec/requests/static_pages_spec.rb:7←[0m ←[36m# Static pages Home p
age should have the content 'Sample App'←[0m
Randomized with seed 10853
My static_pages_specs.rb file: http://pastebin.com/L0LHACR4 (and shown below)
static_pages_specs.rb
require 'spec_helper'
describe "Static pages" do
describe "Home page" do
it "should have the content 'Sample App'" do
visit '/static_pages/home'
expect(page).to have_content('Sample App')
end
end
end
Other than the extra control codes (which might just be a symptom from your console or the cut&paste), this looks like a normal test failure. Which you should expect if you have written the test first.
One important part of TDD is indeed to get a simple failing test - with this kind of failure (the have_content matcher has failed to match) - and to then "fix" the failure.
It is also possible to get problems with the test code, which would also need fixing of course. But I don't see anything wrong with your test in this case.
If there was something wrong with the test, you would have to debug it in the more traditional way of applying critical thinking and experience when you read the code. So try to keep the test code simple, and to the point. Break down long complex tests into many short small ones.
Possibly the have_content matcher could be improved to give better context, rather than make a sub-test that you were not aware of . . . that was written by someone else though, and isn't too bad, it still makes some sense (there is presumably no content at all on the target page).

xpath can't find anything in rspec test

UPDATE 2 - adding before(:each) block
before(:each) do
...
post_via_redirect(
sub_domain(
path: login_view_path(
#p
),
subdomain: #account.subdomain
),
first_name: "Capybara",
last_name: "RSpec"
)
expect(response).to render_template(:show)
end
UPDATE
response.body has the data I'm looking for
but page.html only has a doctype.
ORIGINAL
I'm trying to do some integration testing. I have this:
require "spec_helper"
feature "Tracking without Javascript" do
...
scenario "when navigating to a content" do
...
# this passes so I know there is a body
expect(response.body).to include(c.name)
find(:xpath, "/html") # see if xpath works...
end
end
and I get the error:
Failure/Error: find(:xpath, "/html")
Capybara::ElementNotFound:
Unable to find xpath "/html"
any ideas?
post_via_redirect doesn't involve Capybara - that directly (more-or-less) interacts with Rails, but not through a browser. That would be why Capybara never points an actual page.
Original (misguided) answer for posterity:
If you are using the newest versions of everything, then Capybara will not find invisible elements by default. Could you try find(:xpath, "/html", visible: false) and see if that works? The other thing I can think of is that your XPath may not be matching as you expect. Try //html instead.
On the meta level, you'll almost never see this kind of assertion, as the end-user doesn't care if you have an html element or not. You will get more useful tests by checking for things that the user can see. I also prefer to use CSS selectors, as other things (JavaScript and CSS) tend to care about them as well. Our whole test suite has maybe one or two XPath selectors for very ugly cases.

Cucumber Strange Behaviour

While using cucumber for BDD, i have found a very strange scenario where my "I should see" method (default implementation is failling).
Here is my scenario definition:
When I go to signup page
And I fill in "Username" with "ben#test.com"
And I press "Sign up"
Then I should see "Anything that i type here. ABC XYZ"
Obviously, the text "Anything that i type here. ABC XYZ" is not on the page but the cucumber wouldnt fail the scenario. Here is the definition of "I should see"
Then /^(?:|I )should see "([^"]*)"$/ do |text|
if page.respond_to? :should
page.should have_content(text)
else
assert page.has_content?(text)
end
end
A bit more digging, and it seems that the problem is that 1.8.7 is not supported in capybara. Instead of complaining loudly, it simply performs badly. Things like filling in forms work etc but the has_content fails miserably. Maybe it would be better if it shouted loudly that it needed 1.9.x.
Anyway I changed my Gemfile to
gem "capybara", "1.1.4", :group => :test
and it all seems to be working again.
Should I log this as an issue against capybara? The idea would be to just scream that it wont work with 1.8.7.
More on this discussion: https://groups.google.com/forum/?fromgroups=#!topic/cukes/B3UbbyG5k6s

Check content of web page in cucumber test

I'm starting to explore BDD and Cucumber.
So I want to check if my page displays the content of 2 articles I have.
This is the step I'm using the check if the content is there:
Then /^I should see "([^"]*)"$/ do |desc|
page.should have_content desc
expected = Article.find_by_description(desc)
page.should have_content(expected.navision_code)
page.should have_content(expected.category.name)
end
Normally this should do the trick I guess but when I run the test I got this error message:
expected there to be content "---\n- tenetur\n" in "Alfa Paints Order System\n\n\n\nAlfa Paints\n\n\n\nSeth abernathy, admin\n\n\nVerander paswoord\n\nLogout\n\n\n\n\n\n\n\n\n\n\n\nAlfa Paints\nordering system\n\n\n\n\n\nOverzicht van alle artikelen\n\n\n\nBack\n\n\n\n\n\n\nProduct ID\nBeschrijving\nCategorie\n3001\nPaint\n---\n- tenetur\n\n3002\nBrush\n---\n- tenetur\n\n\n\n\n\n\n\n\n\n\n
(RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/admin_articles_steps.rb:41:in `/^I should see "([^"]*)"$/'
features/admin_articles.feature:10:in `Then I should see "Paint"'
As you can see I expect paint and the error message shows the content has paint inside.
But somehow cucumber isn't recognizing it.
I'm new to cucumber and I'm probably missing something but maybe somebody could help me on my way.
You are testing for three things at once, so it is difficult to tell which of the expectations is failing. As a first step, try commenting out everything but the first expectation just to make sure its failing where you think.
Then /^I should see "([^"]*)"$/ do |desc|
page.should have_content desc
// expected = Article.find_by_description(desc)
// page.should have_content(expected.navision_code)
// page.should have_content(expected.category.name)
end
If you still have the same problem, add debugger so that you can experiment and see what is going on from inside your test environment. This is a skill worth developing if you plan to do much cucumber testing.
Then /^I should see "([^"]*)"$/ do |desc|
debugger
page.should have_content desc
end
From debug console, see what the desc variable and page look like:
p desc
p page.content

Resources