Getting assert_select to show me what an element actually was - ruby-on-rails

I have the following test:
test "users title when logged out" do
get users_path
assert_select "title", 'Correct title"
end
If we assume that users_path returns a page with <title>Wrong title</title>, then I get the following output:
FAIL["test_users_title_when_logged_out", SiteLayoutTest, 1.0830602300120518]
test_users_title_when_logged_out#SiteLayoutTest (1.08s)
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.
test/integration/site_layout_test.rb:37:in `block in <class:SiteLayoutTest>'
I would like to replace the assert_select with something like assert_equal "Correct title", page.title so that the test failure message actually shows me what the page's title is, which would make tracing the problem much easier! (Naturally, the page shows the correct title in development mode…)
However, page.title does not seem to be available, and my efforts at searching are only turning up stuff like "you can do it with Capybara", which is a bit bulky for this purpose!
Is there a way to write this test so that it shows something like Expected page title to be "Correct title" but got "Wrong title" instead? [Edit for clarity: "Wrong title" is the title in the returned page, not a literal string — that is, I need the error to tell me what was actually returned.]

It looks like the answer is assert_equal 'Correct title', css_select('title').first.content.
This gives the more helpful failure message
FAIL["test_users_title_when_logged_out", SiteLayoutTest, 1.0830602300120518]
test_users_title_when_logged_out#SiteLayoutTest (1.08s)
Expected: "Correct title"
Actual: "Wrong title"
(though I suspect it may be better style to revert to the original assert_select once I've found the problem!)

Related

How to properly evaluate if a page has certain content with capybara?

I am currently trying to evaluate the result of clicking the "Pay" button on my site with Capybara if the form has invalid params. It seems like the test is doing everything correctly, filling out all fields correctly, clicking the "Pay" button, but then it is not "seeing" my .alert selector with the text "Email can't be blank, Email is invalid". I am not sure why it is not "seeing" this. Its as if its not even there. My controller is setting flash and then rendering the page with the flash method. Is Capybara trying to evaluate if the current page has the flash? The code for my current test is below. Any help is appreciated. Ive been going through the documentation but must be missing something about expect().
feature "order features", type: :feature do
feature "making a new order" do
before(:each) do
visit "/orders/new"
end
scenario "with invalid params", js: true do
fill_in "Your Name *", with: "Benedict Cumberbatch"
select("CAM Academy", from: 'order_school_name')
fill_in "Street Address *", with: "221b Baker St."
fill_in "City", with: "Vancouver"
select("WA", from: 'order_state')
fill_in "Zip code *", with: "98671"
fill_in "groupNumberBooks", with: 1
fill_stripe_elements(card: '4242 4242 4242 4242', selector: "#card-element-1 > div > iframe")
click_button "Pay"
expect(page).to have_selector('.alert', text: "Email can't be blank, Email is invalid")
end
end
end
On a side note, I have also tried expect(page).to have_content("Email can't be blank"). This also does not work. What am I missing here?
edit: the exact error message I am getting is:
Failures:
1) order features making a new order with invalid params
Failure/Error: expect(page).to have_selector('alert', text: "Email can't be blank, Email is invalid")
expected to find css "alert" but there were no matches
# ./spec/features/order_features_spec.rb:19:in `block (3 levels) in <top (required)>'
I have gone to the specified path and have manually filled out these fields and have evaluated what is being presented on the page when the render is called and the flash[:alert] is set.
It sounds like your test is probably hitting the real stripe (sandbox instance) which means the failure is going to take longer than most of your tests. This means that Capybara.default_max_wait_time isn't long enough for the page to actually update to show the error message. You could increase Capybara.default_max_wait_time or you can tell individual expectations to allow longer wait times for a match using the wait parameter
expect(page).to have_selector('.alert', text: "Email can't be blank, Email is invalid", wait: 20)
which will wait up to 20 seconds for the expected element to appear on the page

minitest assert_select with capybara click_link

How can I achieve checking presence of my link and then clicking on it? I tried the following:
assert_select "a", "show/hide comments"
click_link('show/hide comments')
I am using minitest, capybara, and the 'minitest-rails-capybara' gem. I have added the following include statements in my integration test:
include Capybara::DSL
include Capybara::Assertions
I get the following error:
Unused parameters passed to Capybara::Queries::SelectorQuery : ["show/hide comments"]
MethodError: NoMethodError: undefined method `failure_message' for Capybara::Helpers:Module
test/integration/user_flow_test.rb:215:in `block in <class:UserFlowTest>'
Can I use both minitest's assert link and capybara's click_link?
Thanks
Firstly there is no need to assert on the presence of an element before clicking it since click_link will wait up to Capybara.default_max_wait_time seconds for the link to appear on the page and then click it. If the link doesn't appear in that time it will raise an error, so asserting on its presence is superfluous.
The error you're getting is because minitest-capybara isn't compatible with Capybara 2.9+ - https://github.com/wojtekmach/minitest-capybara/pull/17 - and the fact that assert_select doesn't take 2 strings as parameters. It just takes the id, name, or label text of a select element. So I'm guessing that's not actually the method you mean to be calling.
To clarify the previous answer:
Wrong:
assert_select "a", "show/hide comments"
Correct:
assert_select "a", text: "show/hide comments"

Testing ruby with rails, Element not found

I get the error:
Capybara::ElementNotFound:
Unable to find field "user_email"
And this is the test code:
feature 'User' do
given!(:user) { User.new(email: 'testuserid#example.com', encrypted_password: 'test') }
scenario 'opens sign_up page' do
visit new_user_session_path
expect(page).to have_content 'unique text on the page'
end
scenario 'signs in with invalid email' do
visit new_user_session_path
fill_in('user_email',with: 'ssd')
expect(page).to have_content 'unique text on the page'
end
end
My HTML file consists of this code literally:
unique text on the page
<br>
<input type="text" id="user_email">
So this proves that the path is correct because my first scenario runs correctly. It is visiting the right page. But still I get this error for second scenario in fill_in.
I have also tried element = page.find("user_email"), it gives same error.
What am I possibly doing wrong?
I have been scratching my head like hell.
Usually the reason for this is that the input isn't actually visible on the page. You can verify this by doing
fill_in('user_email', with: 'ssd', visible: false)
If that succeeds in finding the element, then you need to change your test to first perform whatever actions make the field visible before attempting to fill it in.
Your code seems right. Maybe you are visiting wrong url or you have used user_email id once more. But you can give a try with alternative syntax like following :
find("input[id$='user_email']").set "ssd"

hashes, flash and assert_not - how do I assert_not a hash

I'm trying to finish the exercises in the Mhartl RoR tutorial.
The question asks you to complete the following integration test
assert_not 'flash.FILLIN'
assert_select 'div#FILLIN'
assert_select 'div.FILLIN'
And I have a flash that shows either
{:success => "success message here"}
or upon error,
<% flash.each do |message_type, message| %>
taking the standard #user.errors.fullmessages.
My questions are:
How would I go about finding the list of #users.errors.fullmessages, and how do assert_not error?
assert_not 'flash.errors'
yields no exit:success... :(
any help appreciated, the link to the exercise is here: https://draft.railstutorial.org/book/sign_up#sec-signup_exercises
Turns out that it is
assert_not flash.nil?
and some helpful places to look: Check for array not empty: any?
:)
assert_not flash.empty?
Michael Hartl says "I prefer only to test that the flash isn’t empty" at
http://3rd-edition.railstutorial.org/book/sign_up#sec-signup_exercises
And he writes the same test at
http://3rd-edition.railstutorial.org/book/updating_and_deleting_users#code-successful_edit_test
To assert that there is no flash message of a particular type set (:error in this example), you can do:
assert_predicate flash[:error], :nil?

Capybara can't click link, response contains shows the link

I'm trying to write a test that clicks a link but when I run the test, Capybara returns the following error:
"no link with title, id or text 'New Mwod post' found
so I put a 'debugger' and printed the response. The body contained the following:
New Mwod post
the test has the following code:
describe "GET /mwod_posts/new" do
it "creates a new mwod post" do
FactoryGirl.create(:mwod_tag)
get mwod_posts_path
debugger
response.status.should be(200)
click_link "New Mwod post"
end
end
Any ideas why capybara can't click the link?
The problem is that you're using get when you should be using visit.
Switch:
get mwod_posts_path
to:
visit mwod_posts_path
That will let you click links with click_link etc. To parse the response, you'll need to change:
response.status.should be(200)
to:
page.response_code.should be(200)
I haven't actually confirmed that this works, but discussion elsewhere would seem to indicate you can check response codes this way from page. Although, as noted in that discussion, this is not something you should really be doing in integration tests.
For more see on the difference between get and visit see this answer and this post. (This is a common point of confusion.).

Resources