Find and fill in input field by data attribute - ruby-on-rails

I want to find elements by a "test" data attribute and fill them in like the following:
When(/^I sign in with valid credentials$/) do
email = page.find("data-test='email'")
password = page.find("data-test='password'")
fill_in email, with: #user.email
fill_in password, with: #user.password
submit = page.find("[data-test='submit']")
submit.click
end
The button works fine, but the inputs throw the following error:
Unable to find field #<Capybara::Element tag="input"> (Capybara::ElementNotFound)
Is there a way to do this in capybara? Thanks in advance for the help.

fill_in method accepts element's id, name or label text, so it might not work with the result the find method returns. In your case try the set method:
find("input[data-test='email']").set(#user.email)

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

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"

Check the content of a field populated by javascript with Capybara before submit

I have a field whcih I am auto populating based on a dropdown on the page.
i.e. I select task_type and the task_name has task_type populated.
I can't work out how to test this. I basically just want to test what the current content of the field is.
Everything I try seems to be able to find the field but not check the content of it.
Then(/^"(.*?)" should contain "(.*?)"$/) do |field, text|
page.should have_field(field, :text => value)
end
I'm assuming I need to do some js trickery to get the info from the browser, but can't seem to work it out.
And I should see "Annual Accounts" in "task[name]"
Have tried task_name aswell and both fail with
find(field).should have_text(text)
With message
Unable to find css "task[name]"
if I use
page.should have_field(field, :text => text)
Then they fail with:
expected to find field "task_name" with text "Annual Accounts" but there were no matches. Also found "",
You can use the have_text helper
find(field).should have_text(text)
Right, both of these work:
Not sure what the difference between them is.
I also think this does an exact match. If anyone could let me know how to do a "contains" type match that would be really handy.
Then(/^I should see "(.*?)" in "(.*?)"$/) do |text, field|
# page.has_field?(field, :with => text)
page.should have_field(field, :with => text)
end

Devise/Capybara Ambiguous match

I am using devise to create a sign up wizard,
but capybara(2.0.2) raises
Feature: Signing up
In order to be attributed for my work
As a user
I want to be able to sign u
Scenario: Signing up
Given I am on the homepage
When I follow "Sign up"
And I fill in "Email" with "user#ticketee.com"
And I fill in "Password" with "password"
Ambiguous match, found 2 elements matching field "Password" (Capybara::Ambiguous)
./features/step_definitions/web_steps.rb:10:in `/^(?:|I )fill in "([^"]*)" with "([^"]*)"$/'
features/signing_up.feature:10:in `And I fill in "Password" with "password"'
And I fill in "Password confirmation" with "password"
And I press "Sign up"
Then I should see "You have signed up successfully."
step definition is
When /^(?:|I )fill in "([^"]*)" with "([^"]*)"$/ do |field, value|
fill_in(field, :with => value)
end
With Capybara 2.1, this works:
fill_in("Password", with: '123456', :match => :prefer_exact)
fill_in("Password confirmation", with: '123456', :match => :prefer_exact)
From here :prefer_exact is the behaviour present in Capybara 1.x. If multiple matches are found, some of which are exact, and some of which are not, then the first eaxctly matching element is returned.
In version 2.0 Capybara's find method raises a Capybara::Ambiguous exception when several elements matching specified locator where found. Capybara doesn't want to make an ambiguous choice for you.
The proper solution is to use another locator (e.g. find('#id').set('password') or fill_in('field_name', with: 'password')
Read "Ambiguous Matches" section of Capybara 2.0 Upgrade guide for a bit longer explanation of the same.

How do I check that a form is pre-populated with values using Cucumber and Webrat?

I am learning Cucumber and Webrat with Rails and would like some advice on the best way to test an "edit" form. When I browse to a user's profile I am presented with an edit form with the user's information pre-populated in the form fields. I would like to be able to test that the fields do in fact contain the information I expect. Here's my scenario:
Scenario: View My Profile
Given I am logged in as "Mike" with password "secret"
When I go to my profile page
Then I should see "Mike" in the "Login" field
And I should see "mike#email.com" in the "Email" field
And I should see a blank "Password" field
And I should see a blank "Password confirmation" field
Cucumber tells me, correctly, that I need to define the following custom steps:
Then /^I should see "([^\"]*)" in the "([^\"]*)" field$/ do |arg1, arg2|
pending
end
Then /^I should see a blank "([^\"]*)" field$/ do |arg1|
pending
end
I'm sure I can figure out some nasty regex to implement evaluating these steps, but I feel there must be something already existing or more elegant that I can do. How do you evaluate forms with data pre-populated in the form fields?
Have a look at features/step_definitions/webrat_steps.rb, the following step definition looks like what you are looking for:
Then /^the "([^\"]*)" field should contain "([^\"]*)"$/ do |field, value|
field_labeled(field).value.should =~ /#{value}/
end

Resources