Using Capybara how would I would I overwrite an existing field value? - ruby-on-rails

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.

Related

Teneray (Elvis) Operator in Thymeleaf on number input

I have an object bound in a form called licence. The licence has a map as a property called additionalProperties and I'm trying to populate an input; so that if there is a value use that and if not then use '1'. The form starts with:
<form action="#" th:action="#{/admin/createLicence.html}" th:object="${licence}" method="post" class="needs-validate" novalidate>
Then later down the input is:
<input class="form-group col-1" min="1" id="samplesNumberOfSystems" type="number" th:field="*{additionalProperties['NumberSystems']}" th:value="${#maps.containsKey(licence.additionalProperties, 'NumberSystems') ? additionalProperties['NumberSystems'] : 1}" />
To check this i have a span next that does the same thing:
When this is rendered the span works:
<span>1</span>
However the input does not:
<input class="form-group col-1" min="1" id="samplesNumberOfSystems" type="number" value="" name="additionalProperties['NumberSystems']" />
How can I make the number input work properly?

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.

Getting text from a textfield

I am trying to get username and password from the textfield. This is the HTML code:
<form class="navbar-form pull-left">
<input type="text" class="span2">
<input type="text" class="span2">
<button type="submit" class="btn">Submit</button>
</form>
How can I get this username & password in the LoginController to check for authentication?
First, you need to add a name property to your input fields. Then specify the action and method attributes for the form. The form would look like this then:
<form action="your_route_goes_here" method="post" class="navbar-form pull-left">
<input name="username" type="text" class="span2">
<input name="password" type="password" class="span2">
<button type="submit" class="btn">Submit</button>
</form>
In your LoginController, you can then access the username and password like so, respectively:
params[:username]
params[:password]

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

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

Resources