How to find a field using placeholder text in Watir? - ruby

I have two search fields and I want to find the second one to set some text.
I have tried using div however it always finds the first search field.
Does anyone one have a suggestion on how to find the second object or use the unique placeholder text "Search..." ?
HTML:
input type="text" name="searchString" id="searchString" projects="" for="" placeholder="Search" class="form-control"
input type="text" name="searchString" id="searchString" placeholder="Search..." class="form-control"
Ruby - Watir:
#b.link(:text => "http://ml-test.mytest.com/Client/Profile/ab295b41-2c5e-4100-bdee-e757405238bb").click
#b.text_field{div(:class => "col-sm-4 col-md-3", :placeholder => "Search...")}.set "Automation (Test)"

It looks like the problem might simply be a typo in the code. Notice in the line:
#b.text_field{div(:class => "col-sm-4 col-md-3", :placeholder => "Search...")}.set "Automation (Test)"
That a block, seen by the {}, is being passed to the text_field method. The text_field method does not do anything with blocks, as a result the code is really just doing:
#b.text_field.set "Automation (Test)"
As there is no locator supplied to the text field, it will input the first text field on the page.
To locate the text field based on the placeholder attribute (or any other locator), it needs to be passed as an argument instead of a block:
#b.text_field(:placeholder => "Search...").set "Automation (Test)"
You had included a div as well. Assuming that it is an ancestor element need to find the text field, it should be:
#b.div(:class => "col-sm-4 col-md-3").text_field(:placeholder => "Search...").set "Automation (Test)"

Related

How to locate, using Xpath, an input field without using its id

I'm working with a web page with the following HTML where I want to identify the first <input> field inside the <span> using a text_field from within a page-object.
<div id="131:"> Please enter your name:
<span class="autocompspan " style="position:static;">
<input style="position: static;" class="autocompinput yui-ac-input" id="132:" name="132:"
onfocus="juic.fire("132:","_focus",event);"
onchange="juic.fire("132:","_despatchChange",event);"
onblur="juic.fire("132:","_blur",event);" size="60"
onkeydown="juic.fire("132:","_onkeydown",event);"
onkeyup="juic.fire("132:","_onkeyup",event);" aria-disabled="false" value=""
role="combobox" aria-autocomplete="list" aria-owns="132:_divList"
aria-activedescendant="132:_divAD" findtype="proxy" delimchar="" hideusername="false"
fetchusername="false" autocomplete="off" type="text">
<input value="" id="132:_hidden" name="132:_hidden" type="hidden">
</span>
</div>
If I use :id => '132:' to identify the field things work fine. I.e. text_field(:target_user_name, :id => '132:' ) works.
The issue is that this HTML is generated by the underlying app (SAP) which does not always generated the same value for the <input> field id so using the id cannot be relied upon to consistently identify the element.
So, given the above HTML what other ways might I go about reliably finding this <input> field.
I've tried the following, none of which work. Most of them time out waiting for the element to be located.
text_field(:target_user_name, :xpath => "//*[#class='autocompinput yui-ac-input' and #role = 'combobox']" )
text_field(:target_user_name, :xpath => "//*[#class='autocompinput' and #role = 'combobox']" )
text_field(:target_user_name, :xpath => "//span/input[#class='autocompinput yui-ac-input' and #role = 'combobox']" )
text_field(:target_user_name, :xpath => "//input[#class='autocompinput yui-ac-input' and #role = 'combobox']" )
text_field(:target_user_name, :class => 'autocompinput yui-ac-input')
Any thoughts?
When an element does not have unique identifiable attributes, you should look at the elements around it. In this case, there is user visible text that helps a user identify the purpose of the field. That same text can be used to identify the element in Watir.
As the surrounding div only contains the labelling text, you can search for that div by its text and get the only text field in it:
browser.div(text: 'Please enter your name:').text_field
As a page-object accessor:
text_field(:target_user_name) { div_element(text: 'Please enter your name:').text_field_element }
Firstly, Watir is designed to make it so that you shouldn't have to use XPATH.
It depends on how many different elements/ids are on the page, but I've found that using regular expressions often works well with dynamically generated ids. So either grab the id and use it elsewhere:
id = browser.text_field(id: /\d\d\d/).tr(':', '')
or just use it directly:
text_field(:target_user_name, id: /\d\d\d:/)
In this particular case you can check the first input field after 'Please enter your name:' text using below xpath:
//div[text()='Please enter your name:']//following::input[1]
In general if you encounter fields that does not have a unique identifier you can rely on static text or fields and then use xpath functions such as following, preceding etc.

Error running ruby code containing a regular expression and index value

Getting the following error running a ruby script:
C:/Ruby/test3.rb:30: syntax error, unexpected tINTEGER, expecting ')'
...41afa164b242__Rate/ => :index 1).set "00.10"
...
#b.text_field(:id, /Contracts_[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}__ContractTranslationQualities_[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}__ContractPrices_[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}__ContractPriceWordRates_0ec7c68c-663a-40aa-9ab6-41afa164b242__Rate/ => :index 1).set "00.10"
BTW the regex is checked against the html code using Rubular.com and it checks out. I am successfully using this method in other pages that do not contain multiple elements with the same id. However on this page I am testing there are 4 text fields with this id so I need to index unless you have another suggestion. Thanks for the help.
<td>
<div class="symbol-left-inner-addon">
<span class="CurrencySymbol" title="USD">$</span>
<input id="Contracts_b05b4efc-fc08-427b-9319-6a25409eded1__ContractTranslationQualities_f056e412-af83-4965-8fbd-c516f17fb8cf__ContractPrices_9d79ae47-3295-4cbc-9ed5-5b96e53ed1c1__ContractPriceWordRates_b5356ba9-bdc8-49a8-855a-8c2271078f61__Rate" class="form-control numericInput text-right valid" type="text" value="0.00" name="Contracts[b05b4efc-fc08-427b-9319-6a25409eded1].ContractTranslationQualities[f056e412-af83-4965-8fbd-c516f17fb8cf].ContractPrices[9d79ae47-3295-4cbc-9ed5-5b96e53ed1c1].ContractPriceWordRates[b5356ba9-bdc8-49a8-855a-8c2271078f61].Rate" data-val-required="The Rate field is required." data-val-number="The field Rate must be a number." data-val="true">
</div>
</td>
^
When using multiple locators, it has to be passed as a Hash. It would look like (with the ID condensed for readability):
#b.text_field(:id => /Contracts/, :index => 1).set "00.10"
Or if you prefer the newer style:
#b.text_field(id: /Contracts/, index: 1).set "00.10"

Using watir-webdriver with chrome - can't locate input field?

I have the following HTML:
<input type="email" class="form-control" name="email" placeholder="Email">
And I am trying to retrieve this element with the following code:
b = Watir::Browser.new :chrome
b.goto('localhost:3000')
puts b.input(:name => "email").exists?
This returns false, but is most definitely true. I have also tried using b.text_field(:name => 'email').exists?, but it returns false as well.
The end goal is to change the text of the input, but I can't even locate the element right now. The page loads fine, and after loading it outputs false.
The issue is your code is actually being executed before the element is finished loading. You need to chain a few methods (namely .when_present and .exists? to ensure your element is loaded before attempting to check it's existence:
puts b.input(:name => "email").when_present.exists?
Good luck!

XPATH required for an input text field?

i have a text box in my web application,Where i need to give input. I am trying to find the xpath of the text box. the following error is thrown.
Unable to locate element: {"method":"xpath","selector":"
HTML code:
<div class="input">
<input id="firstName" class="long" type="text" maxlength="50" value="" name="firstName
I want the xpath for firstName textbox.
//input[#type='text']
And this for generally targeting a text input (what I was after)
Try this one:
//input[#id='firstName']
Explanation:
// search on all levels
input for element nodes with the name of "input"
[#id='firstName'] having an attribute (#) with the name of "id" and a value of "firstName"
at least 3 simple ways to get this:
1)Driver.FindElement(By.XPath("//input[#id='firstName']"));
2)Driver.FindElement(By.Id("firstName"));
3)Driver.FindElement(By.CssSelector("#firstName"));
//*[text()[contains(.,'firstName')]]
finding by text would always work.

what does this xpath expression mean?

//input[#type="hidden" and #name="val" and position() = 1]/#value
does this mean get the text typed inside the input box ?
Read from right to left, it means "Get the value attribute of all of the input tags whose type attribute is 'hidden', whose name attribute is 'val', and which appears as the first element in its enclosing (form) tag".
I think it means grab the value attribute of an input whose type attribute is 'hidden' in addition its name attribute is 'val' and its position amongst its siblings is 1 ( first I believe, not sure if 0 is the start in xpath ).
<input type="hidden" name="val" value="test">
<input type="hidden" name="foo">

Resources