Acceptance Test (Capybara) can't find my Submit Button - capybara

Question:
How can I get my feature test to recognize my button?
Explanation:
I'm writing an acceptance test with Capybara for "User can add a product to a shopping list".
In my setup I log in as a user, I am able to click on a current shopping list and be directed to the page with the search input for a new product.
I then ask to click the button with
click_button "Search"
Search is the name for my button and is what appears on the page. When I run the actual program everything works, but when I am running the test it keeps telling me that it can't find the Search button.
What I've Tried:
I've tried putting a value instead of a name on my submit button.
I've also tried passing in the id of the button
Instead of clicking on the button I tried adding \n to the input field to hit enter
All of these work when I actually run the program, but they won't work in my testing.
Here is my code! Would love any insight you might have :) Many thanks in advance.
My Code:
The form:
<form method="GET" action="products/show" />
<label for="search_input">Search Products:</label>
<input type="text" name="search_input" id="search_input_field" />
<input type="submit" value="Search" id="submit_search"/>
</form>
The Testing Code:
require 'spec_helper'
describe "a user can add a product to their shopping list" do
let!(:user_one) { FactoryGirl.create(:user) }
let!(:households) do
user_one.shopping_lists.create!({
title: "households",
date: Date.today
})
end
it "will add product to the list" do
login(user_one)
click_link "View Shopping Lists"
click_link "households"
fill_in "search_input_field", with: "toothpaste"
# save_and_open_page
click_button "Search"
# expect(page).to
# first(:button, "Add Item").click
# expect(page).to have_button "Delete"
end
def login(user)
visit root_path
fill_in :email, with: user.email
fill_in :password, with: user.password
click_button "Login!"
end
end

I believe the main issue is that Capybara is looking for an html tag rather than the input as a button.
In your test for the button portion try using
click_on 'Login'

Related

Rails integration test to select for presence of correct button text

I am running through the Hartl Rails Tutorial and have completed the exercises in 9.60, 9.61, 9.62 that call for refactoring of the new and edit form code with a new partial. The forms now use 'provide' to supply button text as in:
<% provide(:button_text, 'Create my account') %>
Which is rendered on the page with 'yield' as in:
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
While not part of the exercise, I am not trying to write an integration test that will test for the correct text on the button for each page. For example this code will test the sign up form page:
test "signup page" do
get signup_path
assert_select "title", full_title("Sign up")
assert_select "input[type=submit]", value: "Create my account"
end
However I have not been able to figure out the correct code for selecting the button and specifying the correct value for the button text. I have made the button text incorrect to try to get the test to fail, but have not found the correct test syntax that succeeds at failing ;-)
Documentation for ActionDispatch did not have a specific example that was helpful for this test case.
Ok found my own answer. The correct for selecting the button and validating the text:
test "signup page" do
get signup_path
assert_select "title", full_title("Sign up")
assert_select "input[value=?]", "Create my account"
end
What I learned is that 1. an attribute of an element should be enclosed in square brackets. 2. Use 'attribute=?' to match that attribute value to the value you are testing for: in this case "Create my account"

How to test a file attach with rspec in a rails project?

I put a file upload tag in my view source:
<%= form_tag(confirm_path, method: :post, multipart: true) do %>
<%= file_field_tag 'my_file' %>
<button type='submit'>Submit</button>
<% end %>
I want to test if user select a file and click submit button, then redirect to next page. Here is my spec source:
require 'rails_helper'
feature 'MyTest', type: :feature do
describe 'File test' do
before do
visit index_path
end
it 'If select a file, then go to next page' do
attach_file 'my_file', my_real_file_path # I am sure this file exists
click_button 'Submit'
expect(page).to have_content('Confirm Page')
end
end
end
But after I run this spec test, it said:
Failure/Error: attach_file 'my_file', my_real_file_path
Capybara::ElementNotFound:
Unable to find file field 'my_file'
This is usually because the actual file field is being hidden and overlayed with a "button" or some JavaScript driven interface so it can be styled to look the same across multiple browsers. If this is the case here you generally need to execute some JavaScript, using execute_script, to override whatever css is hiding the file field so it becomes visible on the screen and then call attach_file

What causes the failure to click buttons that are not in forms when using capybara?

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'

Capybara + Selenium: save_and_open_page shows button, but capybara can't find it

My capybara test includes these lines:
click_button "SHARE"
fill_in 'Email Address', :with => #user_two.email
save_and_open_page
click_button 'CONFIRM'
the share button would make a modal visible. Filling in the email address text box of this modal seems to go off without a hitch, but I receive the following error for the button
Capybara::ElementNotFound:
Unable to find button "CONFIRM"
However, when I save_and_open_page, the button is visible.
I've tried switching to
page.find("#id-of-button").click
but Capybara can't find that either.
It's interesting to note the save_and_open_page shows me a page where the field for email hasn't been filled in.
I think I might be missing something basic about how save_and_open_page works because if that is the page Capybara is seeing in its totality then these errors make no sense to me...
edit: Modal view code
.title.aaux
Title
.content
.line-separator
#intro
Enter Email:
= form_for(patient, url: {controller: "dashboard/patients", action: "share_with_user"}, method: :post, html: {id: "share-patient-form"}) do |f|
%fieldset.bordered
= f.text_field :share_user_email, placeholder: "Email Address", class: "aaux form-control"
.line-separator
#button-row
%button.btn.btn-success.aaux.pull-right#confirm-share-patient{type: "submit"}
CONFIRM
%button.btn.btn-cancel.aaux.pull-right#close-modal-share-patient
CANCEL
edit: source code generated for button
<button type="submit" id="confirm-share-patient-button" class="btn btn-success aaux pull-right">
CONFIRM
</button>
I changed from selenium webdrive to capybara-webkit, and the issue no longer occurred.

Why isn't Capybara filling in these form elements?

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.

Resources