Ruby Watir Form Pulldown Not Found - ruby

Does anybody have any insight as to how to trigger a selection in a pulldown using Watir? I can't seem to get this to find that first field. I've tried class (deprecated apparently), id, and name.
require 'webdrivers/chromedriver'
require 'open-uri'
require 'json'
Selenium::WebDriver::Chrome.path = '/Applications/RF_Utilities/Google Chrome.app/Contents/MacOS/Google Chrome'
url = 'https://www.finditatmpg.com/Default.aspx'
a = Watir::Browser.new :chrome, headless: false
a.goto url
# a.select(id: 'dpdCemetery_Input').select('Beechwood')
a.select(name: 'dpdCemetery').select('Beechwood') # doesn't work
puts "cemetery selected" # a marker
a.text_field(id: 'txtSurname').set 'Smith' # this works if set first
puts "last name selected" # a marker
a.text_field(id: 'txtFirstname').set 'John'
puts "first name selected" # a marker
a.button(id: 'btnSearch_input').click # submit
The error:
timed out after 5 seconds, waiting for false condition on #<Watir::Select: located: false; {:name=>"dpdCemetery", :tag_name=>"select"}> (Watir::Wait::TimeoutError)
Update: Here is the copied syntax of the form:
<div id="dpdCemetery" class="RadComboBox RadComboBox_Bootstrap" style="width:300px;white-space:normal;">
<!-- 2021.1.119.45 --><table summary="combobox" style="border-width:0;border-collapse:collapse;width:100%">
<tbody><tr>
<td class="rcbInputCell rcbInputCellLeft" style="width:100%;">
<input name="dpdCemetery" type="text" class="rcbInput radPreventDecorate" id="dpdCemetery_Input" value="Select a Cemetery" autocomplete="off">
</td>
<td class="rcbArrowCell rcbArrowCellRight">
<a id="dpdCemetery_Arrow" style="overflow: hidden;display: block;position: relative;outline: none;">select</a>
</td>
</tr>
</tbody></table><div class="rcbSlide" style="z-index:6000;display:none;"><div id="dpdCemetery_DropDown" class="RadComboBoxDropDown RadComboBoxDropDown_Bootstrap "><div class="rcbScroll rcbWidth"></div></div></div><input id="dpdCemetery_ClientState" name="dpdCemetery_ClientState" type="hidden" autocomplete="off">
</div>

The problem is that these are not "real" HTML Select/Option element dropdowns, so you can't use the Select class. The tag name is a div not a select.
You'll need to use something like (update - correct locator is an id not a name):
a.div(id: 'dpdCemetary').click
a.li(text: /Beechwood/).click

Solved:
a.text_field(name: 'dpdCemetery').set('Beechwood')
Seems it behaves like a text field. JS provides the dropdown list. I was under the impression Watir could handle that sort of thing.

Related

Find two text field that seem to have the same class using selenium ruby

I am writing a simple script to find and enter text into First name and Last name fields for a web page profile in firefox. I have navigated to the page and inspected the element, however I have tried everything i can think of the find the element but nothing seems to work. How can I find these fields using ruby, is there another way to inspect the field?
Both of these fields have field labels
First name inspect result
<div class="input__label">First Name</div>
<div class="input_row">
<div class="split_control">
<input class="input__input_wide" step="any" value="Bob">
Last name inspect result
<div class="input__label">Last Name</div>
<div class="input_row">
<div class="split_control">
<input class="input__input_wide" step="any" value="Smith">
You can try with following x-paths:
First Name element: //div[text()='First Name']/following-sibling::div/div/input
Last Name element: //div[text()='Last Name']/following-sibling::div/div/input
In code,
first_name = driver.find_element(:xpath, "//div[text()='First Name']/following-sibling::div/div/input")
first_name.send_keys "FName"
last_name = driver.find_element(:xpath, "//div[text()='Last Name']/following-sibling::div/div/input")
last_name.send_keys "LName"
Write the xpath like given below
driver.find_element(xpath: "//div[normalize-space()='First Name']/following::input").send_keys "FirstName"
For LastName
driver.find_element(xpath: "//div[normalize-space()='Last Name']/following::input").send_keys "LastName"

Unable to check/uncheck specific checkbox based on text

I am trying to check and uncheck checkboxes based on following requirements:
If a particular text is present, I need to check the checkbox for it.
If some other text has checkbox set, I need to uncheck that checkbox
<table class="adm">
<tbody>
<tr class="action">
<td width="20px">
<input class="checkbox" type="checkbox" name="checkbox1">
</td>
<td>
<span class="label">
<script id="start"></script>
Action1
<script id="end"></script>
</span>
<p class="desc">
<script id="start"></script>
Description1
<script id="end"></script>
</p>
</td>
</tr>
</tbody>
</table>
<table class="adm">
<tbody>
<tr class="action">
<td width="20px">
<input class="checkbox" type="checkbox" name="checkbox2">
</td>
<td>
<span class="label">
<script id="start"></script>
Action2
<script id="end"></script>
</span>
<p class="desc">
<script id="start"></script>
Description2
<script id="end"></script>
</p>
</td>
</tr>
</tbody>
</table>
And there are 5 checkbox classes like the one above.
So , I need to check :
Find "Action1" -> check it's checkbox.
If "Action2" has checkbox set -> uncheck that checkbox.
So, need to set checkbox as per requirements and uncheck all other checkboxes.
I found this to check/uncheck all checkboxes:
checkbox_class = /checkbox/
#browser.checkboxes(:class => checkbox_class).each do |checkbox|
if(!checkbox.checked?)
p "checkbox not set"
checkbox.set
else
p "checkbox set"
checkbox.clear
end
end
But I am unable to cater this as per my requirements, tried this:
checkbox_class = /checkbox/
action_class = /label/
#browser.checkboxes(:class => checkbox_class).each do |checkbox|
if(!#browser.span(:class=>action_class,:text=>"some_action").checkbox.checked?)
p "checkbox not set"
checkbox.set
else
p "checkbox set"
checkbox.clear
end
end
The problem is that your loop and your conditional are out of sync.
#browser.span(:class=>action_class,:text=>"some_action").checkbox
is the same thing as:
#browser.span(:class=>action_class,:text=>"some_action").checkbox(:index => 0)
It refers to the same element on the page, regardless of the checkbox in your loop.
It might be easiest to uncheck all checkboxes with the code you found, then find checkbox with the action you want and just check that box.
Given that the labels and checkboxes are related by their shared ancestor, the table element, I think it is easier to iterate through the tables. Within each table, you can check the label text and then decided whether to set/clear the checkbox.
The following will set the "Action1" checkbox and uncheck the rest:
action = 'Action1'
browser.tables(:class => 'adm').each do |table|
# Check if the label matches the action we want to check
value = (table.span(:class => 'label').text == action)
# Set the checkbox if the label matches, otherwise clears
table.checkbox.set(value)
end
I think the following will work:
action_trs = #browser.trs(class: ‘action’)
action_trs.each do |action_tr|
if action_tr.td(index: 1).span.text == ‘some_action’
action_tr.checkbox.set unless action_tr.checkbox.set?
else
action_tr.checkbox.clear
end
end
Good luck! :)

Setting/clearing AngularJS md-checkbox with Watir

I'm trying to perform automated testing using Watir gem. I need to test whether the checkbox works by setting and clearing it.
The HTML for the checkbox is:
<md-checkbox aria-label="Remove" aria-invalid="false" aria-checked="false" tabindex="0" class="ng-pristine ng-valid md-default-theme ng-touched" role="checkbox" ng-model="user.remove_photo" style="margin-top: 0px;">
<div class="md-container" md-ink-ripple="" md-ink-ripple-checkbox="">
<div class="md-icon"></div>
<div class="md-ripple-container"></div>
</div>
<div ng-transclude="" class="md-label">
<span class="ng-scope">Remove</span>
</div>
</md-checkbox>
My test script:
require 'watir'
require 'watir-webdriver/wait'
browser = Watir::Browser.new :firefox
browser.goto 'https://54.69.254.137/webui#/landing'
browser.driver.manage.window.maximize
browser.button(:class =>'sign-in md-button md-default-theme').click
browser.text_field(:id =>'input_001').set('abcadmin#example.com')
browser.text_field(:id =>'input_002').set('password')
browser.button(:class =>'md-primary md-raised md-button md-default-theme').click
browser.button(:class =>'md-icon-button md-primary main-menu-toggle md-button md-default-theme').when_present.click
browser.link(:text =>'Edit Profile').when_present.click
browser.checkbox(:class => 'ng-pristine ng-valid md-default-theme-ng-touched').set
browser.button(:class => 'md-primary md-raised md-button md-default-theme').click
Gives following error:
unable to locate element using checkbox(:class => 'ng-pristine ng-valid md-default-theme- ng-touched').
The problem with the checkbox is that it is not an HTML checkbox - ie <input type="checkbox">. Instead it is a md-checkbox, which I believe is from the Angular Material library. As a result, Watir's checkbox method will not see it.
You will need to treat the md-checkbox as a generic element and use the click method to set/clear it:
browser.element(class: 'ng-pristine ng-valid md-default-theme-ng-touched').click
The class attribute does not look unique. You might want to use one of the other attributes instead. For example:
browser.element(aria_label: 'Remove').click

Watir-Webdriver text_field deprecation - use textarea (but method does not seem to work)

The new version of watir-webdriver (0.8.0) has been released. I have installed it and have been running my suites to check for changes. During this process I have noticed the text_field methods I am using to set text in <input id="some_id" type="text"> tags has been deprecated from the message Locating textareas with '#text_field' is deprecated. Please, use '#textarea' method instead. I changed the text_field method to textarea, but once I do this the element can no longer be located.
Am I using the method wrong? I tried to use it as browser.textarea(:id=> 'some_id').when_present.set "Text". Once the method times out, I get the message saying the element with the tagname textarea could not be located. Was wondering if there is something else I need the do to use the textarea method to set text in a <input id="some_id" type="text"> tag.
EDITED => html I am trying to automate on:
<form action="some_href" method="post">
<p class="align">
<label for="user">Username</label>
<input id="login" type="text" value="">
</p>
<p class="align">
<label for="pass">Password</label>
<input id="password" type="password" value="">
</p>
</form>
EDITED Watir code used to automate page
#RUBY CODE
class Login
def open
#browser = Watir::Browser.new :firefox
#browser.goto some_website_url #URL leading to page with form HTML above
end
def login_as
user_field.when_present(10).set username
password_field.when_present(10).set password
login_link.when_present(10).click
end
def user_field
#browser.text_field(:id=> "login")
end
def password_field
#browser.text_field(:id=> 'password')
end
def username
"user123"
end
def password
"p#ssw0rd"
end
def login_link
#browser.link(:text=> 'Sign-in')
end
end#Login
#STEP DEFINITION
Given(/^login to website$/) do
login = Login.new
login.open
login.login_as
end
The previous versions I have been using without the deprecation message is:
watir-webdriver (0.6.11)
selenium-webdriver (2.44.0)
Any answers would be appreciated if someone has some insight on the problem.

Using Ruby Watir, how can I select a checkbox that has a changing ID?

This is the HTML I'm working with:
<div class="pbSubsection">
<table class="detailList" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td class="labelCol">
<label for="00Ni0000003bw8O">Becomes Asset</label>
</td>
<td class="dataCol col02">
<input id="00Ni0000003bw8O" type="checkbox" value="1" tabindex="8" name="00Ni0000003bw8O" checked="checked">
</td>
I need to select the checkbox.
I cannot use the ID because I'm doing this across multiple orgs, and the ID is different in every org. Is there a way I can select by the label text or by the tabindex?
It is probably safer to get the checkbox by the label text rather than the tabindex.
Solution 1 - :label locator:
If you are using watir-webdriver, it possible to locate an element directly based on its label text - via the :label locator. You can do the following:
#Exact match of label text:
b.checkbox(:label => 'Becomes Asset').set
#Partial match of label text using regex:
b.checkbox(:label => /Asset/).set
Note that this assumes that the 'for' attribute of the label matches the 'id' attribute of the input element.
Solution 2 - Matching label to input:
For a solution that works in watir-classic (as well as watir-webdriver), you can:
Get the label element by text
Get the for attribute of the label element
Get the associated checkbox by its id, which matches the label element's for attribute
The following will work for your page to clear the checkbox:
label = browser.label(:text => 'Becomes Asset')
browser.checkbox(:id => label.for).set
To select the checkbox based on the tabindex, using a :css or :xpath locater should do the trick:
b.checkbox(:xpath => "//input[#tabindex='8']").set
b.checkbox(:css => 'input[tabindex="8"]').set

Resources