Can't find element to click on using Capybara + Rails3 - ruby-on-rails

Background: I'm using Capybara with Rspec to test a Rails 3 app.
Driver used: Selenium
Problem:
I can't find the "Sign in" button in order to click on from within my test.
HTML code:
<form accept-charset="UTF-8" action="/" class="filter_form" id="login" method="post">
<fieldset>
<div class="modal-body">
<div class="clearfix login-fields">
<label for="user_email">Email</label>
<div class="input login-inputs">
<input class="input-text" id="user_email" name="user[email]" placeholder="email" size="30" type="email" value="">
</div>
</div>
<div class="clearfix login-fields">
<label for="user_password">Password</label>
<div class="input login-inputs">
<input class="input-text" id="user_password" name="user[password]" placeholder="password" size="30" type="password">
</div>
</div>
</div>
<div class="modal-footer">
<input class="btn btn-primary login_btn" id="btn_login" name="commit" type="submit" value="Sign in">
Forgot password...
Cancel
</div>
</fieldset>
</form>
Failing test
it "should login correctly if the right credentials are given", :js => true do
Capybara.default_wait_time = 5
Capybara.reset_sessions!
visit '/'
click_link('login_link') #this will bring a modal window with the code posted above using js
within("#login") do
fill_in 'user_email', :with => "my-email#example.com"
fill_in 'user_password', :with => "mypwd"
end
response.should have_selector('input#btn_login') #This passes
click_on("input#btn_login") #Here it fails, saying it can't find an element with that selector
response.should have_selector(:xpath, '//div[#class="alert-message block-message info"]')
end
My test file is inside spec/requests.
Any ideas?
Thanks!

Please try this:
page.find("#btn_login").click

This: https://stackoverflow.com/a/11348065/1504796
Is the right answer.
click_on does not take a CSS selector, but instead the text or id of a link. You want click_on("btn_login"). No hash sign or anything.

try
find('#id',:visible => true).click

Try adding "gem 'launchy'" to your Gemfile and put
"save_and_open_page" line before failed line in step file.
REFERENCE: http://techiferous.com/2010/04/using-capybara-in-rails-3/

It looks like you're trying to click on a submit button inside some modal css. You'll need to invoke whatever displays that modal element first.

I don't think click_on will take a locator like that--I think it may want just an id, name or value. As an experiment, try replacing click_on("input#btn_login") with:
page.find('#btn_login').click

click_button("Sign in")
find(:xpath, "//*[#id='btn_login']").click (or .trigger('click'))
If else fails, go through the console and see if you can check the presence of the button: document.getElementById("btn_login")

If you know the link text, you can use page.find_link(text).click. (source)

Try adding a save_and_open_page before the line in question. This should allow you to see the page and any errors that may prevent the clicking action.

I use capybara with chrome
Capybara.register_driver :chrome do |app| Capybara::Selenium::Driver.new(app,
:browser => :chrome)
end
Capybara.javascript_driver = :chrome
and install chrome driver:
brew install chromedriver
http://collectiveidea.com/blog/archives/2011/09/27/use-chrome-with-cucumber-capybara/

Related

Capybara can't find selector on page

I'm trying to test the presence of some form fields in the bootstrap navbar and can't find the right combination of Capybara selectors to find them.
I've tried the following options in Capybara:
should have_selector('id', text: 'email')
should have_selector('name', text: 'email')
should have_selector('div.input.id', text: 'email')
should have_selector('div.input.placeholder', text: 'email')
and I always get the error:
Failure/Error: expect (should have_selector('div.input.placeholder', text: 'email'))
expected to find visible css "div.input.placeholder" with text "email" but there were no matches
I'm fairly new to capybara, which is probably my problem, but I've looked through the documentation and this seems like it should work.
I'm guessing this has something to do with it being hidden, but it is visible to a user when you go to the page, so I'm not sure how to get it to be visible to capybara.
Here is the HTML code that is being presented:
<div class="navbar-collapse collapse">
<form class="navbar-form navbar-right" role="form" action="/sessions" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="klUhJ9epE/Sr/N0okPq5WMWi2XJuQXiAPmdg/9Qf2d8TBX+htbIdUPRh01YPWqMTRin8vTlVG/ECUtvKNczc+A==" />
<div class="form-group">
<input type="text" name="email" id="email" class="form-control" placeholder="Email" />
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control" placeholder="Password" />
</div>
<input type="submit" name="commit" value="Sign in" class="btn btn-primary" />
</form>
</div><!--/.navbar-collapse -->
Here is the view of the actual page:
div.input.placeholder is a CSS selector that would select a div element with the classes 'input' and 'placeholder' - I'm assuming that's not what you're actually trying to check for.
If you are trying to test the attribute values you would do
have_selector('input[id="email"][placeholder="Email"]')
or better yet since you're using CSS
have_css('input[id="email"][placeholder="Email"]')
or you could use Capybaras built-in :field selector type and do
have_field(id: 'email', placeholder: 'Email')
Realistically though - checking attributes like this is overkill for a feature test. Just fill in the fields
fill_in('Email', with: 'my_email#blah.com')
which will confirm the relevant field exists, can be located by label or placeholder of the string 'Email' and can be filled in.

have trouble with using capybara-webkit attach_file upload an image

I want to test the function to add an image to the application. How can I do this. attach_file method is not work. I don't know why.
html:
<form id="edit_user_5577b0c4a851ac600c000002" class="form-horizontal user-settings" method="post" enctype="multipart/form-data" action="/tardis54" accept-charset="UTF-8">
<div id="upload-avatar" class="control-group">
::before
<label class="control-label" for="user_avatar">
Setting avatar
</label>
<div class="controls">
<div class="form-fileupload">
<div class="image-preview">
<img class="gravatar img-circle" width="60" height="60" src="http://gravatar.com/avatar/7046a07b25397e4a0c838a47c88d8742?default=identicon&secure=false&size=60" data-retina-url="http://gravatar.com/avatar/7046a07b25397e4a0c838a47c88d8742?default=identicon&secure=false&size=120" alt="tardis54"></img>
</div>
<span class="btn btn-fileinput btn-default">
<span>
Choose file ...
</span>
<input id="user_avatar" class="input-file" type="file" name="user[avatar]"></input>
</span>
</div>
</div>
</div>
<div class="form-actions pull-right">
<input class="btn btn-large btn-primary" type="submit" value="Update" name="commit"></input>
</div>
</form>
test code:
scenario "upload a custom avatar" do
attach_file("user[avatar]", Rails.root + "temp4.png")
end
error log:
Failure/Error: attach_file("user[avatar]", Rails.root + "temp4.png")
Capybara::Webkit::ClickFailed:
Failed to click element /html/body/div[#id='content']/div/div/div/div/div/div[2]/form[#id='edit_user_5580e19da851ac6a51000002']/div[#id='upload-avatar']/div/div/span/input[#id='user_avatar']
because of overlapping element /html/body/div[#id='content']/div/div/div/div/div at position 740, 627;
It looks like you're using CSS to overlay another element on top of the HTML input. Some people do this because it's difficult to style HTML file inputs directly. However, doing so breaks capybara-webkit, because it needs to click on the actual HTML input field and the styled element is positioned on top of it.
This is being discussed in a GitHub issue.
You can work around it in the test by using execute_script to hide the overlay element, and then attempting to upload the file.
I find a way to solve this problem.
script = "$('#user_avatar').css({opacity: 100, display: 'block', position: 'relative', left: ''});"
page.execute_script(script)
I could assume that input[type=file] is not visible, thus you need initially make it visible f.e. execute javascript $("input[type=file]").show() and than attach file
Here's my implementation of #tardis answer (which itself is an implementation of #joe-ferris' suggestion). I put it as an answer to be able to use code formatting.
# spec/support/file_uploads.rb
module FileUploads
# Enables file uploads by capybara-webkit on pages that
# style file their input fields
def attach_file_styled_input(element_id, file)
page.execute_script("$('##{element_id}')" +
".css({opacity: 100, display: 'block', position: 'relative', left: ''});")
attach_file element_id, file
end
end
Don't forget to include this support module in spec/rails_helper.rb:
config.include FileUploads
Then use it in your feature spec like this (not spectacular):
attach_file_styled_input 'my_input_id', 'my_file'

RSPEC sign in method returns error

I am trying to sign in a user via rspec and capybara. This is the first time I've written my own tests and I'm not sure what the problem is, as if I click through my application it works fine. It seems either the problem is RSPEC is not correctly filling in the fields, or not clicking the link or button but I am not sure which or how to find out.
Here is the test (edited to add this):
it "logs the user in and redirects them to speakeasy home on success" do
sign_up_as_hello_world
page.should have_content 'INSTANT MACHINE TRANSLATION'
end
Here is the failure
1) Sign up logs the user in and redirects them to speakeasy home on success
Failure/Error: page.should have_content 'INSTANT MACHINE TRANSLATION'
expected to find text "INSTANT MACHINE TRANSLATION" in "Speakeasy Technology + Humanity Sign In Invalid username or password New users start out with $5 demo credit Sign Up"
# ./spec/features/auth_spec.rb:40:in `block (2 levels) in <top (required)>'
Here is the "sign up" method in my spec helper
def sign_up(username)
visit "/session/new"
click_link "signUpLink"
fill_in "username", with: username
fill_in "email", with: 'email#email.com'
fill_in "password", with: 'abcdef'
find('input[id="submitButton"]').click
end
I've also tried it with this as the last line but it doesn't work either
click_button "Sign Up"
And the html for the form is here (clicking the sign up link changes the submit button's value to sign up:
<form class="login" action="<%= session_url %>" method="post" id="mainForm">
<%= auth_token_input%>
<input type="text" placeholder="Username" name="user[username]" id="username"/>
<input type="text" placeholder="Email" name="user[email]" id="email"/>
<input type="password" placeholder="Password" name="user[password]" id="password"/>
<input type="submit" value="Sign In" class="btn btn-success btn-sm" id="submitButton"/>
<div style="text-align:center">
<p>New users start out with $5 demo credit</p>
Sign Up
</div>
</form>

How to click a link within a hidden div via capybara

I am using capybara, rspec, and poltergeist in a Rails 4 application and am trying to click on the following link button via capybara.
<div class="form-group">
<input id="invoice_invoice_items_attributes_0__destroy" name="invoice[invoice_items_attributes][0][_destroy]" type="hidden" value="false">
<a class="btn btn-warning remove_fields existing" href="#">Remove Invoice Item</a>
</div>
If I have the following in rspec/capybara, it finds the hidden element:
find(:xpath, '//input[#id="invoice_invoice_items_attributes_0__destroy"]', visible: false)
If I try this, it doesn't find the link element:
find(:xpath, '//input[#id="invoice_invoice_items_attributes_0__destroy"]/a', visible: false)
The end goal is to do this:
find(:xpath, '//input[#id="invoice_invoice_items_attributes_0__destroy"]/a', visible: false)
How do I get there?
Your a tag isn't inside of the input field, so unless form-group div is hidden, you should be able to just do:
click_link 'Remove Invoice Item'
If form-group is hidden, then try:
find(".remove_fields", visible: false).click

Can't find element in Capybara even though it exists

I am writing some Capybara tests, and am failing at what seemed to be quite straight forward search. I have HTML:
<div id="divId">
<div class="unimportantClass">
</div>
<form id="formId">
<div>
</div>
<h2>Irrelevant text</h2>
<p>Equally irrelevant</p>
<span class="remarkableSpan">
<i class="whatever"> </i>
Some text
<input id="targetTag">
</input>
</span>
</form>
</div>
I am trying to confirm existence of "targetTag"
Everything goes well in
expect(page).to have_css('div#divId form#formId span.remarkableSpan')
but with
expect(page).to have_css('div#divId form#formId span.remarkableSpan input')
or
expect(page).to have_css('div#divId form#formId span.remarkableSpan input#targetTag')
it fails to find it. Any ideas what is causing it?

Resources