The cheatsheets and docs on Watir show something like this to set a radio button
b.radio(:id => "radio").set
How can I select a Radio button based on the text next to it?
Sometimes this text is inside the label tag , sometimes its just inside some div/form tag. How do we handle this in Watir??
(Label texts in CAPS in below examples)
Example 1:
<form action="">
<input type="radio" value="male" name="sex"/>
MALE
<br/>
<input type="radio" value="female" name="sex"/>
FEMALE
</form>
Example 2 :
<div class="isoversixteen_false_container">
<input id="isoversixteen_false" class="radio" type="radio" value="0" name="isoversixteen" autocomplete="off"/>
<label class="isoversixteen_false_label" for="isoversixteen_false">
<span class="label_main">UNDER 16</span>
</label>
</div>
<div class="isoversixteen_true_container">
<input id="isoversixteen_true" class="radio" type="radio" value="1" name="isoversixteen" autocomplete="off" checked="checked"/>
<label class="isoversixteen_true_label" for="isoversixteen_true">
<span class="label_main">16 OR OVER</span>
</label>
</div>
Orde's comment about using attributes of the input element is a good idea as it is the easiest to program. However, to answer the question:
Example 1 - Adjacent text node
In this example, the desired text is in an adjacent text node. Given that the radio buttons share the same parent, I think the easiest solution would be to use XPath:
browser.radio(xpath: '//input[following-sibling::text()[1][normalize-space(.) = "MALE"]]').set
browser.radio(xpath: '//input[following-sibling::text()[1][normalize-space(.) = "FEMALE"]]').set
The XPath says to:
Find an input element where
The following text node - ie the [1]
Has the text "MALE" or "FEMALE", ignoring the leading/following spaces - ie the [normalize-space(.) = "FEMALE"]
Example 2 - Label text
In this example, the checkboxes have a properly associated label element - ie the id of the checkbox matches the for attribute of the label. Watir supports locating elements by their label text through the :label locator:
browser.radio(label: 'UNDER 16').set
browser.radio(label: '16 OR OVER').set
Example - First following non-blank text node
If you want a single solution that works with both examples, the following seems to work:
browser.radio(xpath: '//input[following::text()[normalize-space(.) != ""][1][normalize-space(.) = "UNDER 16"]]').set
browser.radio(xpath: '//input[following::text()[normalize-space(.) != ""][1][normalize-space(.) = "16 OR OVER"]]').set
browser.radio(xpath: '//input[following::text()[normalize-space(.) != ""][1][normalize-space(.) = "MALE"]]').set
browser.radio(xpath: '//input[following::text()[normalize-space(.) != ""][1][normalize-space(.) = "FEMALE"]]').set
The intent here is to find the first text node after the checkbox that has text (the [normalize-space(.) != ""][1] portion) and that text matches the expected text (the [normalize-space(.) = "UNDER 16" portion).
This is HTML structure I have in my example:
<div class="radio-inline">
<label for="job_type">Second Type</label>
<input id="job_service" name="job" type="radio" value="remote">
</div>
Normally I'd select it with:
#browser.input(:value => 'remote').click
However, per your question, I tried to see if I could select by text. I found this works, but may be dependent on the labels being nested in a div.
#browser.label(:text => /Second Type/).click
The / around "Second Type" were due to some weird line breaks in the HTML, may work with just quotes.
Related
I have a list of similar looking DIVs without any Div ID, except one has a check box checked and others doesn't. What i need is to find the value from a child tag only if a radio button is selected.
Below is a simpler version of my code.
<div class = "XYZ">
<input type="radio" checked>
<input type="hidden" value="This is a great thing 1">
</div>
<div class = "XYZ">
<input type="radio">
<input type="hidden" value="This is a great thing 2">
</div>
Result needed is
This is a great thing 1
Unfortunately the source code cannot be changed.
Your xpath should look for a div that contains the checked input and to get the value for the one that has value attribute.
First selector returns the input, the second returns the value.
//div[.//input[#checked]]/input[#value]
//div[.//input[#checked]]/input/#value
As an alternative you can use the following sibling:
//input[#checked]/following-sibling::input
If you want to also use the class of the parent div:
//div[#class='XYZ']/input[#checked]/following-sibling::input
I have to click on element whose Id is changeable,means dynamic value assign to text box everytime . I have to insert value in text box.
Following is the inspect element code of text box
<div class="invoicing-details">
<div>
<label for="PaidToName_b62b89226e5f4fcbb74d0d27a9db88ca"> To </label>
<input id="PaidToContactID" type="hidden" value="" name="PaidToContactID">
<div class="controls">
<input id="PaidToName_b62b89226e5f4fcbb74d0d27a9db88ca" type="hidden" style="display:none;" value="" name="PaidToName_b62b89226e5f4fcbb74d0d27a9db88ca">
<input id="PaidToName_b62b89226e5f4fcbb74d0d27a9db88ca_value" class=" autocompleter field " type="text" style="width:127px;" tabindex="10" value="" maxlength="255" name="PaidToName_b62b89226e5f4fcbb74d0d27a9db88ca_value" autocomplete="off">
<div id="PaidToName_b62b89226e5f4fcbb74d0d27a9db88ca_suggestions" class="autocomplete" style="display: none; height: 200px; width: 200px;"> </div>
<script type="text/javascript">
</div>
</div>
"PaidToName_b62b89226e5f4fcbb74d0d27a9db88ca_value" this is text box id.
I used following code
self.set_text_value('div.invoicing-details input' ,"my value",true)
but it does not work and getting syntax error.
Can anyone help me and provide syntax how to write ruby script for seleinum.
Dynamic ids very bad for automation. You can try to add other property to input element with stable name. As i clearly understood you need to click on element and then input text in it?! I'm not good at ruby, but i think this should look like:
element = driver.find_elements(:css,".invoicing-details .autocompleter")
element.click
element.send_keys "Some text"
You can try to find id of an element using next xpath: //input[#id=(//label[contains(text(),'To')]/#for)]. Here you find a label by its text and then get for attribute (it is needed id).
element = driver.find_elements(:xpath,"//input[#id=(//label[contains(text(),'To')]/#for)]")
element.click
element.send_keys "Some text"
Below is my html
<div class="right" data-bindattr-13="13">
<h3>Company Name</h3>
<div class="input-row">
<input id="ember4258" class="ember-view ember-text-field" type="text"/>
</div>
<h3>Full Company Legal Name</h3>
<div class="input-row">
<input id="ember4259" class="ember-view ember-text-field" type="text"/>
</div>
<h3>Company Phone</h3>
<div class="input-row">
<input id="ember4260" class="ember-view ember-text-field" type="text"/>
</div>
<h3>Federal Tax / Employer ID (EIN)</h3>
<div class="input-row">
<input id="ember4261" class="ember-view ember-text-field" type="text"/>
</div>
</div>
Since class value off all the text fields and respective parent div class attributes are same I need to fill these text fields without using nth-of-type.
I have done work around to create a CSS selector that should point the text box that is immediately after <h3>Full Company Legal Name</h3> .
h3:contains(^Company Name$)+div>input
But my Capybara script is not recognizing the above way and throwing the below error.
annotateInvalidSelectorError_': The given selector h3:contains(^Company Name$)+div>input is either invalid or does not result in a WebElement. The following error occurred: (Selenium::WebDriver::Error::InvalidSelectorError)
InvalidSelectorError: An invalid or illegal selector was specified
Can any one provide a CSS that matches my requirement?
Regards,
Avinash Duggirala
The contains pseudo class was deprecated, which is why the InvalidSelectorError occurs. There is currently no way to check text nodes using CSS-selectors.
Instead, you can use XPath to traverse the DOM to sibling elements.
text_field = page.find(:xpath, '//h3[text() = "Company Name"]/following-sibling::div[1]/input')
text_field.set('some value')
I need to read text value from span tag inside a selected radio button using capyvara
I have a list of radio button followed by text and its count in brackets.
For eg: radiobutton with Thank You(82)
What I want is to read the selected radio button count 82 inside bracket.
I used following code..but it is not working
value=page.find(".cardFilterItemSelection[checked='checked'] + span.itemCount").text
and tried using Xpath but not getting anything
value=page.find(:xpath,"//input[#class = 'cardFilterItemSelection' and #checked = 'checked']/span[#class = 'itemCount']/text()")
How it is possible?
<label id="thankyou_label" for="thankyou_radio" class="itemName radio">
<input checked="checked" tagtype="Occasion" value="Thank You" id="thankyou_radio" name="occasionGroup" class="cardFilterItemSelection" type="radio">
<span class="occasion_display_name">
Thank You
</span>
<span class="itemCount">
(82)
</span>
</label>
<label id="spring_label" class="itemName radio" for="spring_radio">
<input id="spring_radio" class="cardFilterItemSelection" type="radio" name="occasionGroup" value="Spring" tagtype="Occasion">
<span class="occasion_display_name">
Spring
</span>
<span class="itemCount">
(0)
</span>
</label>
I think you were on the right track. But you should have query not for the text node contained by span, but for the span itself and use XPath axes
span = page.find(:xpath,"//input[#class = 'cardFilterItemSelection' and #checked = 'checked']/following-sibling::span[#class = 'itemCount']")
value = span.text
However I personally find css selectors more readable (unless you need to make complex query)
span = page.find(:css, 'input.cardFilterItemSelection[checked=checked] ~ span.itemCount')
value = span.text
I have this simple kendo-template script:
<!-- popup editor template -->
<script id="userEditor" type="text/x-kendo-template">
<div id="popServerErrorSummaryPlaceholder" style="display:none"></div>
<div class="control-row">
<label class="span2" for="FirstName">Vorname</label>
<input Id="FirstName" class="span4" data-bind="value:FirstName" maxlength="50" name="FirstName" required="true" type="text" />
<span class="k-invalid-msg" data-for="FirstName"></span>
</div>
<div class="control-row">
<label class="span2" for="LastName">Nachname</label>
<input Id="LastName" class="span4" data-bind="value:LastName" maxlength="50" name="LastName" required="true" type="text" />
<span class="k-invalid-msg" data-for="LastName"></span>
</div>
</script>
Which is used while editing a single row within the Kend-UI grid.
I have got right now two issues:
a) The documentation states that I can control the position for validation messages via a "span" element that has a class "k-invalid-msg".
The behaviour right now is that this span Element gets replaced with a div element and it is positioned below the label element. I would like to get the message next to the input.
b) The validation is triggered immediately when the pop up is displayed.The validation should be trigger either when leaving the input or clicking the "update" button.
Someone out there who can help me here?
Things I am not quite sure how to handle:
c) Some validations are performed at the server. I get them back to the browser via the DataSource error event (custom JSON which is basically a list of field name and associated error messages). I would like to display the error messages within the validation span. I can create custom validation rules as documented here.
How do I get the validator that is associated with the pop up editor window? Or is there foreach input a validator created?
Anyone did this before?
Thanks for any help!
Updates:
regarding to point a)
OnaBai pointed me to the right direction. Thanks for that.