Capybara can't find selector on page - ruby-on-rails

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.

Related

Submit button does not submit form data in bootstrap

I am trying to submit a form in a bootstrap framework and cannot get past the validation, even with correct data.
I think there might be an error with this syntax,
<form name=form1 method=post action=signupck.php onsubmit='return validate(this)'><input type=hidden name=todo value=post>
then the form fields... which all display correctly - so no problems there - in the style:
<div class="row">
<div class="col-xs-2">
<label for="fname">Forename</label>
<input type="text" class="form-control" id="fname" placeholder="Forename"><br></br>
</div>
<div class="col-xs-2">
<label for="sname">Surname</label>
<input type="text" class="form-control" id="sname" placeholder="Surname">
</div>
</div>
and then,
<input type=submit value=Signup>
<input type="reset" class="btn btn-default" value="Reset">
The form on submission displays signupck.php, signalling validation messages when is should be submitted ok. I have got this working outside the bootstrap, but when I put this inside the template, in the form above, I get the problems.
Any help would be most appreciated.

Capybara can find but not fill_in

I am having some very strange behaviour with Capybara. It stubbornly refuses to fill in the fields of my login form.
<fieldset>
<div class="clearfix">
<label for="user_email">E-Mail Adresse</label>
<div class="input">
<input id="user_email" name="user[email]" size="30" type="email" value="">
</div>
</div>
<div class="clearfix">
<label for="user_password">Passwort</label>
<div class="input">
<input id="user_password" name="user[password]" size="30" type="password" value="">
</div>
</div>
<div class="clearfix">
<div class="input">
<input name="user[remember_me]" type="hidden" value="0">
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
<label for="user_remember_me">angemeldet bleiben</label>
</div>
</div>
</fieldset>
And here is where the fun begins:
within("#login_form"){ find("#user_email")}
=> #<Capybara::Element tag="input" path="/html/body/div[2]/div[#id='content']/div/div[1]/form[#id='login_form']/fieldset/div[1]/div/input[#id='user_email']">
within("#login_form"){ fill_in("#user_email", with: "foo#example.com")}
Capybara::ElementNotFound: Unable to find field "#user_email"
I don't quite understand how it is possible to be able to find, and yet not find, an element.
Another pair of eyes on this would be appreciated.
The locator for find and fill_in are different:
find - When the first parameter is not a symbol, it is assumed to be the Capybara.default_selector - ie a css-selector or xpath.
fill_in - The first parameter is the field's name, id or label text.
The string "#user_email" represents a css-selector. This is why it works in find but not fill_in.
For fill_in to work, you need to just pass in the id value - ie just "user_email".
within("#login_form"){ fill_in("user_email", with: "foo#example.com")}
you can do find("#user_email").set "foo#example.com". See answer https://stackoverflow.com/a/8544650/3163914
if it is an autocomplete field, you can use this:
def fill_in_autocomplete(id, value)
page.execute_script("document.getElementById('#{id}').setAttribute('value', '#{value}');")
end

Using Capybara how would I would I overwrite an existing field value?

I am currently testing a form on a page with Capybara that has existing values filled out in the form's fields. I want to test being able to put new values into the fields and submitting the form with the new values.
When I try using Capybara's fill_in method it ignores the fields that have existing values. Is there anyway to overwrite fields with existing values in Capybara?
I'll include the form below:
<form accept-charset="UTF-8" action="/submissions/1/reviews/4" class=
"simple_form edit_review" id="edit_review_4" method="post" novalidate="novalidate"
name="edit_review_4">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓"><input name="_method" type=
"hidden" value="put"><input name="authenticity_token" type="hidden" value=
"gJ/KKAodeIJD8PPnRNeN4GaGb/yqvUDHrsnl9LqLP/c=">
</div>
<div class="input integer optional">
<label class="integer optional control-label" for=
"review_rating">Rating</label><input class="numeric integer optional" id=
"review_rating" name="review[rating]" step="1" type="number" value="33">
</div>
<div class="input text required">
<label class="text required control-label" for="review_comment"><abbr title=
"required">*</abbr> Comment</label>
<textarea class="text required" cols="40" id="review_comment" name=
"review[comment]" rows="20">
hellofsdf
</textarea>
</div><input class="btn" name="commit" type="submit" value="Update Review">
</form>
The Capybara code I've tried is:
find(:xpath, "//*[(#id = 'review_comment')]").set "hello"
I've also tried a similar approach with the rating field since the rating is a text field and the comment is a text area, but I still can't get it to change.
using find with XSLT expression should do the trick
find(:xpath, "//input[#id='field_with_default_value_id']").set "my value"
Use a javascript driver like phantomjs/poltergeist and then use javascript to set values like that.
page.evaluate_script("document.getElementById('#some-id').value = 'some-value'");
Similar to my answer on this question.

Checking checkboxes with Capybara

Using Capybara I cannot for the life of me select a checkbox on my form.
In my request spec I've tried:
check("First Name")
page.check("First Name")
page.check("pickem_option_ids_10")
find(:css, "#pickem_option_ids_11[value='11']").set(true)
find(:css, "#pickem_option_ids_11").set(true)
Snippet from my form:
<div class="control-group check_boxes optional">
<label class="check_boxes optional control-label">Options:</label>
<div class="controls">
<label class="checkbox">
<input class="check_boxes optional" id="pickem_option_ids_10" name="pickem[option_ids][]" type="checkbox" value="10" />First Name
</label>
<label class="checkbox">
<input class="check_boxes optional" id="pickem_option_ids_11" name="pickem[option_ids][]" type="checkbox" value="11" />Middle Name
</label>
</div>
</div>
I got some of the find() ideas from this SO thread.
I've had some success in other specs where I have a single checkbox with a label of Active and I just say check("Active").
Had the same problem today, I looked around and this seemed to work:
find(:xpath, "//input[#value='10']").set(true)
of course you can replace '10' with anything you want - just check your HTML and use your value.
Hope that helps.
Capybara can't find checkbox "First Name" because your html is wrong. Your html should look like
<label class="checkbox" for="pickem_option_ids_10">First Name</label>
<input class="check_boxes optional" id="pickem_option_ids_10" name="pickem[option_ids][]" type="checkbox" value="10" />
In your view code
= label_tag "pickem_option_ids_10", "First Name"
= check_box_tag "pickem_option_ids_10", 10
Then check("First Name") should work.
Otherwise you can find("#pickem_option_ids_10").check

How do you customize Ruby on Rails validation errors?

Currently when there is a validation error, a div with class="field_with_errors" gets rendered in my form:
<form method="post" action="/users" accept-charset="UTF-8">
<div class="field_with_errors">
<input id="user_email" type="text" value="tom#test.com" name="user[email]">
</div>
<input id="user_password" type="password" value="mypass" size="30" name="user[password]">
<input id="user_submit" type="submit" value="Submit" name="commit">
</form>
Without the use of an additional gem and in a Rails 3 environment, is there a way to modify how the validation error is rendered? For example, I want the validation error div to be rendered after the input tag with the error:
<input id="user_email" type="text" value="tom#test.com" name="user[email]"><div class="field_with_errors"></div>
Also, is there a way to render a specific error? If it was an email error, then render the div after the input textbox and produce a "Re-enter your email" message.
(Most of the searches I have done so far use gems as the solution.)
1.You can remove the field_with_errors wrapper by overriding ActionView::Base.field_error_proc.It can be done by putting this in your config/application.rb:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| "#{html_tag}".html_safe }
Refer
Rails 3: "field-with-errors" wrapper changes the page appearance. How to avoid this?
2.You can display error message on specific field.
<input id="user_email" type="text" value="tom#test.com" name="user[email]">
<% if #user.errors.on(:email).present? %>
<span class="error">Re-enter your email(or)<%= #user.errors.on(:email) %></span>
<% end %>
Then in your CSS
.error {
color: red;
}

Resources