ruby mechanize find and fill input tag value - ruby

I need to fill the value of an input tag not surrounded by a form tag, I do not need to submit it, just fill in a value.
I have the code below:
input = my_page.at("#crn_id1")
my_page.form_with(:id => 'crn_id1').value = '90098'
input = agent.click(my_page.at('[#value="Submit Changes"]'))
puts input.content
I am getting an error but what I am trying to do is fill out the input tag which has html of:
<TD style=padding:10px; CLASS="dedefault"><p class="centeraligntext"></p>
<LABEL for=crn_id1><SPAN class="fieldlabeltextinvisible">CRN</SPAN></LABEL>
<INPUT TYPE="text" NAME="CRN_IN" SIZE="8" MAXLENGTH="5" ID="crn_id1">
</TD>
I just want to fill out the input tag which in NO way is surrounded by a form tag with a value of 09987. I have the correct html page but cant seem to set the value of the input and tag to set it and set it in mechanize.

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.

Ruby Mechanize, save html as file after filling a form

I want to save the html after filling a form. lets say:
page.form.field.value = 'testing'
page.save 'test.html'
the generated test.html file don't have the modified value attribute
<input name='something' value=''>
I'm expecting:
<input name='something' value='testing'>
You want to use dom functions for that:
page.at('[name=something]')['value'] = 'testing'
In other words there's no reason to expect that changes to the Form fields will update the dom.

XPath / Selenium can't locate an element using a partial id with contains / start-with

I have the following HTML generated with an AjaxFormLoop.
<div id="phones">
<div class="t-forminjector tapestry-forminjector" id="rowInjector_13b87fdd8b6">
<input id="number_13b87fdd8b6" name="number_13b87fdd8b7" type="text"/>
<a id="removerowlink_13b87fdd8b6" href="#" name="removerowlink_13b87fdd8b6">remove</a>
</div>
<div class="t-forminjector tapestry-forminjector" id="rowInjector_13b87fdda70" style="background-image: none; background-color: rgb(255, 255, 251);">
<input id="number_13b87fdda70" name="number_13b87fdda70" type="text" />
<a id="removerowlink_13b87fdda70" href="#" name="removerowlink_13b87fdda70">remove</a>
</div>
</div>
I'm trying to access the second input field in child 2 using a partial ID, however I have not been successful in getting this to work.
What I've tried thus far.
String path = "//input[contains(#id,'number_')][2]";
String path = "(//input[contains(#id,'number_')])[2]";
I can't even access input 1 using 1 instead of 2, however if I remove [2] and only use
String path = "//input[contains(#id,'number_')]";
I'm able to access the first field without issue.
If I use the exact id, I'm able to access either field without issue.
I do need to use the id if possible as there is many more fields in each t-forminjector row that are not present in this example.
Implementation with Selenium.
final String path = "(//input[starts-with(#id,'quantity_')])[2]";
new Wait() {
#Override
public boolean until() {
return isElementPresent(path);
}
}.wait("Element should be present", TIMEOUT);
Resolved
I'm noticing I can't seem to use the following starts-with / contains to locate any element within to dom, however if I use a complete id, it works.
//Partial ID - fails
//*[starts-with(#id,"quantity_")]
//Exact ID - works
//*[starts-with(#id,"quantity_-112409575185705")]
The generated output you pasted here simply does not contain the string number_ anywhere in it. It does contain Number_ -- note the capital N -- but it's not the first part of the string. Perhaps you meant something like this (which at least selects something):
(//input[contains(#id, 'Number_')])[2]
Or:
(//input[starts-with(#id,'catalogNumber_')])[2]
As Iwburk stated, this was a namespace issue. According to the Selenium API,
http://release.seleniumhq.org/selenium-remote-control/0.9.0/doc/java/com/thoughtworks/selenium/Selenium.html
while using an xpath expression, I needed to used xpath=xpathExpression changing my query string to:
String path = "xpath=(//input[starts-with(#id,'quantity_')])[2]";
I found a related post here,
Element is found in XPath Checker but not in Selenium
you can't access it because you are not locating the element as to be unique in the page.
use an xpath that makes it unique ,
- you're xpath look ok .
more info here
http://www.seleniumhq.org/docs/appendix_locating_techniques.jsp
Besides the selenium syntax problem there's an xpath issue related to markup structure.
xpath 1: //input[starts-with(#id,'number_')][1]
xpath 2: (//input[starts-with(#id,'number_')])[1]
In the sample below xpath 1 will return 2 nodes (incorrect) and xpath 2 will be correct because input nodes are not siblings so surrounding parenthesis are needed to refer to the resulting nodeset
<div id="phones">
<div>
<input id="number_1" name="number_1" type="text"/>
</div>
<div>
<input id="number_2" name="number_2" type="text" />
</div>
</div>
Result without parenthesis
/ > xpath //input[starts-with(#id,'number_')][1]
Object is a Node Set :
Set contains 2 nodes:
1 ELEMENT input
ATTRIBUTE id
TEXT
content=number_1
ATTRIBUTE name
TEXT
content=number_1
ATTRIBUTE type
TEXT
content=text
2 ELEMENT input
ATTRIBUTE id
TEXT
content=number_2
ATTRIBUTE name
TEXT
content=number_2
ATTRIBUTE type
TEXT
content=text
In this next sample, parenthesis will not make a difference because nodes are siblings
<div id="other">
<input id="pre_1" type="text"/>
<input id="pre_2" type="text" />
<div>a</div>
</div>
With parenthesis
/ > xpath (//input[starts-with(#id,'pre_')])[1]
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT input
ATTRIBUTE id
TEXT
content=pre_1
ATTRIBUTE type
TEXT
content=text
Without parenthesis
/ > xpath //input[starts-with(#id,'pre_')][1]
Object is a Node Set :
Set contains 1 nodes:
1 ELEMENT input
ATTRIBUTE id
TEXT
content=pre_1
ATTRIBUTE type
TEXT
content=text
Testing was done with xmllint shell
xmllint --html --shell test.html

get form values other than by name in codeigniter

hi i am using codeigniter . i have a form , there i add hidden fields dynamically . so every hidden field is <input type='hidden' name='hidden' value="+$(this).attr('title')+"> so the name is equal .
the problem is when i submit the form and try to get my hiden field values i can only get one hidden field value , because the names are same
i print my form values
print_r($this->input->post());
i have 2 hidden fields but i get only one
Array
(
[hidden] => march
[textbox] => march
[mysubmit] => Submit
)
i can change the name dynamically of hidden field when creating , but then i don't know exactly the name of my hidden field ,
how can i get hidden field values with same name ?? is there any way to get form values other than by name ?? i tried and can not find an answer , please help .............
You'll need to use brackets in your name attributes:
<input type='hidden' name='hidden[]'>
<!-- ^^^^ -->
This will allow PHP to accept multiple inputs with the same name as an array of values, so in this case, $_POST['hidden'] will return an array of strings.
By default they are indexed starting at 0, so $_POST['hidden'][0] will get you the first one, $_POST['hidden'][1] will get you the second, etc., however - you can explicitly index them if it's easier for you, either with numbers or strings.
<input type='hidden' name='hidden[first]'>
<input type='hidden' name='hidden[second]'>
Or:
<input type='hidden' name='hidden[0]'>
<input type='hidden' name='hidden[1]'>
You can nest these as deep as you want like hidden[first][1][], and they will be treated similarly to a PHP array when you get the $_POST values, but you need the brackets in the HTML.
Without brackets, only the last field's value will be available in the $_POST array. This is a PHP feature, Codeigniter can't do anything about it.

Validating input type number in html5

I want to restrict entry of input onto a field of type number such that input cannot be outside range of min-max specified in the html.
input type = "number" min = "1" max = "5"
Is there a way of outputting the number field without the text box and i would rather not use
"input type = range"
as slider does not show value currently selected
Please help.
Thanks.
Based on what you said, I suggest using a simple input text field and check it's value validity on submission via JavaScript (as #Kush mentions above). You could also check it as the user types, or moves focus away from that field.
<form>
Only 1 to 100 <input type="text" name="number" pattern="\d{1,2}(?!\d)|100" title="one to hundreed only">
<input type="submit">
</form>

Resources