I have been trying to set up Capybara to test a form but I keep getting the error
cannot fill in, no text field, text area or password field with id, name, or label 'Name' found
Here is what I have in my view:
<%= form_for(#user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
...
<%= f.submit "Create Account", class: "btn btn-large btn-primary" %>
<% end %>
which renders the following html:
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" size="30" type="text" />
So it seems like it should be finding the field based on the label.
Here is what my user_pages_test.rb file has (I am using Test::Unit and shoulda-context):
context "sign up page" do
should "add user to database when fields are filled in" do
fill_in "Name", with: "Bubbles"
...
click_button "Create Account"
end
end
Here is what I've tried so far:
1) changing the call to fill_in to match the id with fill_in "user_name", with: "Bubbles"
2) changing the call to fill_in to page.fill_in "Name", with: "Bubbles" to match the example in the documentation
3) changing the view to manually add the id "Name" with <%= f.text_field :name, id: "Name" %> (this answer)
4) changing the call to get sign_up_path to get "/sign_up" (in case it was an issue with the routing)
All these still give me the same error, which makes me think that the page isn't being loaded correctly for some reason. However, I have a different (passing) test in the same context that asserts the page has the correct title, so I know the page does get loaded correctly (in the setup).
Based on this (and according to this answer), it seems like the problem might just be that the fill_in method isn't waiting for the page to load before trying to access the fields. According to this suggestion, I added the line puts page.body in my test to see that the HTML was being loaded completely before it was trying to fill in the fields, and got the following output:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
So, I was pretty sure that fill_in just wasn't waiting for the page to load. I then tried
5) changing the Capybara.default_wait_time according to this answer, but this had no effect. I tried setting it in the ActionDispatch::IntegrationTest class in the test_helper file (where Capybara is included), and also in the test itself.
Then I tried adding puts page.body in the passing test (both before and after it asserts the correct title), and I got the same output. THEN, I found this answer, and finally got the console to print out the page's HTML. I tried one more thing to get Capybara to fill in the fields:
6) changed the call to fill_in to say #response.fill_in, since #response seems to do what I thought the page variable was supposed to do.
So, I have two questions about this:
1) What does the page variable actually refer to? The doctype declaration for my app is just <!DOCTYPE html>, so I have no idea where it gets the old one from.
2) Why isn't Capybara able to find/fill_in these fields?
You need to use the visit method to get the page object setup properly. The capybara documentation indicates that '/' is visited by default and if you want to visit some other page you need to do an explicit call. It may also be helpful to read a bit about the difference between visit and get.
Related
I'm using Capybara with a webkit driver and when I'm running tests with js: true it raises error listed below. When I do same things in other tests without js: true everything works fine.
PS. There is no need for js :true in this test. This code is actually inside a helper but I put it here like test , so it will be easier to understand.I'm using js: true in the other test that invokes this helper method.
Code below raises Capybara::Webkit::ClickFailed:
Failed to find position for element /html/body/div/div/div/div[2]/a[12]
scenario "adding logged days", js: true do
visit '/logged_days'
find(:xpath, "//a[contains(.,'12')]").click
# click_link("12") raises same error
expect(current_path).to eq("/logged_days/new")
fill_in "Опис виконаної роботи", with: "Some description"
fill_in "Кількість відпрацьованих годин", with: 40
click_button "Додати"
expect(current_path).to eq("/logged_days")
expect(page).to have_content("40")
end
/logged_days:
<div class="page-header">
<h2>Logged Days <small>March</small></h2>
</div>
<div class="conteiner-fluid logged_days_container">
<% for i in 1..31 %>
<%= link_to new_logged_day_path(:cal_date => "#{i}"), method: :get do %>
<div class="calendar_cell">
<p class="cell_date"><%= i %></p>
<p class= "cell_text"></p>
</div>
<% end %>
<% end %>
</div>
I think I had this error exactly once in all my years and it was about an element being covered or otherwise not being clickable.
A thorough investigation with your browser's webinspector is necessary here: You have to figure what your js does to that click target.
When using js:true your page not only runs JS but also has CSS processed. This means you can end up with elements that are are non-visible, overlapped, or moving. You need to look at what is done to the element in a real browser and make sure the element is actually clickable, or what other actions a user would have to do first to make it clickable.
Secondly, don't use .eq with current_path - it'll lead to flaky tests as you use js capable drivers. Instead use the has_current_path matcher
expect(page).to have_current_path('/logged_days/new')
I have been encountering a problem when running cucumber to test the functionality of some of my checkboxes. The checkboxes are located on the edit profile page for users and allow users to check off their interests. However, every time I run cucumber it says that it is unable to find the checkbox. But this does not happen for all of the checkboxes on the page, only the checkboxes for the interests. Originally we thought that it was because the checkboxes did not have unique IDs, but now we have updated the checkboxes to have unique ids and they still cannot be found by capybara and cucumber.
The view code looks like this:
<% #interests.each do |interest| %>
<div class="form-group">
<%= label_tag 'interests', interest.name, class: 'col-sm-2 control-label' %>
<div class="col-sm-6">
<%= check_box_tag 'interests[]', interest.id, resource.interest_ids.include?(interest.id), {class: 'form-control', id: "interest_#{interest.id}"} %>
</div>
</div>
<% end %>
The step definition is:
When /^(?:|I )check "([^"]*)"$/ do |field|
check(field)
end
The feature look like this:
Feature: Edit Profile as a User
As a BoardBank User
So I can keep my info up to date
I want to be able to edit my profile
Background:
Given I login as a User
And I am on the home page
Scenario: Edit profile
When I follow "Profile"
And I follow "Edit Profile"
And I fill in "user_firstname" with "User"
And I fill in "user_lastname" with "Joe"
And I fill in "user_address" with "123 userville"
And I fill in "user_city" with "Userton"
And I select "Alabama" from "user_state"
And I fill in "user_zipcode" with "90210"
And I fill in "user_phonenumber" with "555-555-5555"
And I select "Bachelors" from "user_education"
And I fill in "user_areaofstudy" with "Magic"
And I check "interest_2"
And I check "user_previous_experience"
And I fill in "user_current_password" with "password"
And I press "Update"
Then I should see "Your account has been updated successfully."
And I should be on the homepage
When I run cucumber this is what happens:
And I check "interest_2" #features/step_definitions/web_steps.rb:89
Unable to find checkbox "interest_2" (Capybara::ElementNotFound)
./features/step_definitions/web_steps.rb:90:in `/^(?:|I )check "([^"]*)"$/'
features/edit_profile.feature:23:in `And I check "interest_2"'
We think that it must be an issue with the view code and how the checkboxes are appearing on the page, but we could not find any solution to this issue when searching.
Try the find the checkboxes in this way:
within('.form-group') do
page.find('input[type=checkbox]').set(true)
end
If you use chrome, you can inspect the element and copy the css or xpath. That helps me a lot. Also, if you use the pry gem, I sometimes set js: true on capybara, so I can see what's going on in the browser, then walk through step by step until I get what I want. For me, it's way easier to do it that way.
I have searched this for some good time in SO, and on Google. I am a newbie(only 7 months in development), but I'd like an explanation as to why capybara's click_button does not respond to buttons that are not in forms
take and example of this
<div id="btn-div">
<%= button_tag('Attach new file', id: "attach-file-btn", class: "btn btn-info") %>
</div>
in this case when you are writing tests you get an error of the type
undefined method `node_name' for nil:NilClass
however when you put this in a form like this it works
<form id="btn-form">
<%= button_tag('Attach new file', id: "attach-file-btn", class: "btn btn-info") %>
</form>
if you may, please provide an explanation as to why this happens.
and take the following into consideration
the button is not submitting anything, it is only causing JavaScript to show a form
when I try to find the button by using xpath or find it is available, however click_button does not work for it
update
code for click button is similar to this:
describe "Getting to the deployable tools page" do
before do
#tool = FactoryGirl.create(:tool)
#tool.set_status(1)
end
before { visit assigned_tools_path }
before { click_button('attach-file-btn') }
it { should have_content('select tools to add') }
it { should have_css('#non-successful-tool-adding') }
end
Try using a capybara finder, and then invoke click on it, like so:
page.find('#attach-file-btn').click
If you just want to click the file show at broswer with text Attach new file, use:
click_button 'Attach new file'
I was trying Capybara for the first time and having trouble with it finding my form. I'm using Rspec, Capybara, Rails 3.2.8, and Twitter Bootstrap.
In my test, I had:
before do
choose "Residential"
choose "Storage"
fill_in "Customer Location", with: 30082
fill_in "datepicker", with: 2012-12-02
fill_in "Email", with: "jesse#test.com"
fill_in "Phone", with: "555-555-5555"
end
And was getting the error:
Failure/Error: choose "Residential"
Capybara::ElementNotFound:
cannot choose field, no radio button with id, name, or label 'Residential' found
In my form, I had (excerpt):
<%= quote.radio_button :customer_type, "Residential"%>
<%= quote.label "Residential", class:"radio inline" %>
When I fired up the server, I could see the form and Firebug showed that I had a label named "Residential" associated with the form element.
After searching for the problem and finding this post: Capybara not finding form elements (among others), I couldn't figure out why it wasn't working.
I ultimately went back to Capybara's Rubydocs ( http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions ) and found the section on the "Choose" method.
I didn't dive deep into the documentation, but I saw that it was looking for a "locator" in the :radio_button and so tried associating one directly.
I thus changed my form to (notice I added "id" to the form element):
<%= quote.radio_button :customer_type, "Residential", id:"Residential"%>
<%= quote.label "Residential", class:"radio inline" %>
and that portion of the test passed! I repeated with each of my form elements and everything performed as expected.
Hope this is useful to someone else.
I am starting with Cucumber and I am running this simple scenario:
Scenario: Creating a project
Given I go to the new project page
And I fill in "Name" with "xxx"
...
The new project form is already in place and looks like this:
<% form_for (#project) do |f| %>
<%= f.text_field :name %>
...
<% end %>
As you can see I haven't defined a label (don't need one). The problem is that cucumber doesn't find the field:
Given I go to the new project page
And I fill in "Name" with "I need something" #
features/step_definitions/web_steps.rb:68
cannot fill in, no text field, text area or password field with id,
name, or label 'Name' found
(Capybara::ElementNotFound)
However it finds it if I add the label. I find it a little bit suspicious that it can't match the name I gave with the appropriate text field.
What is wrong?
Thank you
Try changing your cucumber feature to read:
Scenario: Creating a project
Given I go to the new project page
And I fill in "project_name" with "xxx"
Or...
Scenario: Creating a project
Given I go to the new project page
And I fill in "project[name]" with "xxx"
The reason this is failing is because if you have no label, capybara (which cucumber uses) looks for the ID or name attribute of the field. As apneadiving mentions, you can check these values by looking at the source of the generated file. You'll see something like:
<input id="project_name" name="project[name]" type="text">
The name of your textfield is by default:
project[name]
Actually it follows the rule:
object[field]
You should look at your dom and check it.
Edit:
Jus FYI, It's weird to see:
<% form_for (#project) do |f| %>
instead of:
<%= form_for (#project) do |f| %>
I had the same problem and I fixed it by simply changing
<% form_for ... %>
to
<%= for_for ... %>
The addition of the '=' enables the display of the form fields, which allows Capybara to correctly identify it.