Select checkbox from excel with ruby - ruby

I would like to select a checkbox from an excel spreadsheet for a data driven test.
code for the checkbox:
Not Checked:
<input type="checkbox" class="greenopt" name="Accounts[0][greenopt]" id="" value="0">
Checked:
<input type="checkbox" class="greenopt" name="Accounts[0][greenopt]" id="" value="1">
I tried the following but get the error: Unable to locate element, using {:value=>"1"}
greenopt_check=worksheet.cells(rows,"O").value
browser.checkbox(:value => greenopt_check).set
this is kind of similar to my previous question regarding radio buttons
Select Radio buttons from excel with ruby

Please review the watir checkbox documentation. in that case you can checkbox.set or checkbox.clear depending on your goals.
You want to use something that is unique, and consistent/predictable to select elements
checkbox_class = worksheet.cells(rows,"A").value
puts 'retrieved checkbox_class from spreadsheet is:' + checkbox_class #for debugging, make sure you got the correct thing from the spreadsheet
browser.checkbox(:class => checkbox_class).set
or
checkbox_name = worksheet.cells(rows,"A").value
puts 'retrieved checkbox_name from spreadsheet is:' + checkbox_name #for debugging, make sure you got the correct thing from the spreadsheet
browser.checkbox(:name => checkbox_name).set

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.

Automation Capybara extract value from checked radio button

I am looking for a way to check what radio is selected and save the value of that option into a variable.
once i have the variable i want to build a switch statement which will give me the logic to decide what to do.
here is the HTML:
<input type="radio" value="option_1" name="registration[registrationType]" id="option_1_id" class="radio">
(Option 1)
<input type="radio" value="option_2" name="registration[registrationType]" id="option_2_id" class="radio">
(Option 2)
<input type="radio" value="option_3" name="registration[registrationType]" id="option_3_id" class="radio" checked="checked">
(Option 3)
option 3 is the checked option (checked="checked")
I want to extract the value of option 3 (option_3) and save it in a variable
default_option = #the code that extracts the default option
case default_option
when "option_1"
puts 'lets do something with this'
when "option_2"
puts 'lets do something with this'
when "option_3"
puts 'lets do something with this'
else
puts 'cant do much with this'
end
Thanks in advance!
Since you want the value of the checked radio in a group of them you want to use the shared name and the checked filter
find(:radio_button, 'registration[registrationType]', checked: true).value
In the case the 'option_3_id` is checked, you can find its value by
find(:radio_button, 'option_3_id', checked: true).value
But as you don't know which radio button is checked, you should first find all the options and verify which one is currently checked (checked:true/false), and then retrieve its value.

Issues in declaring variables

am trying to make a Petition form for a local company (A required project for graduation).
This is part of my page where I am facing troubles:
<FORM METHOD="POST" ACTION="InsertPetition.asp?EmpID=<%=Request.QueryString("EmpID")%>&BRANCH=<%=Session("BRANCH")%>" name=frmNewClaim>
<table>
<tr>
<td>From Date</td>
<td><SELECT name=cboFromDateDay>
<%For i = 1 To 31%>
<%if i=day(date()) then%>
<OPTION VALUE="<%=i%>" Selected="True"><%=i%></OPTION>
<%else%>
<OPTION VALUE="<%=i%>"><%=i%></OPTION>
<%end if%>
<%Next%>
</SELECT>
<SELECT name=cboFromDateMonth>
<%For i = 1 To 12%>
<%if i=month(date()) then%>
<OPTION VALUE="<%=i%>" Selected="True"><%=MonthName(i)%></OPTION>
<%else%>
<OPTION VALUE="<%=i%>"><%=MonthName(i)%></OPTION>
<%end if%>
<%Next%>
</SELECT>
<SELECT name=cboFromDateYear>
<%For i = Year(Date())-1 To Year(Date()) + 10%>
<%if i=year(date()) then%>
<OPTION VALUE="<%=i%>" Selected="True"><%=i%></OPTION>
<%else%>
<OPTION VALUE="<%=i%>"><%=i%></OPTION>
<%end if%>
<%Next%>
</SELECT>
</td>
<td><INPUT type="button" value="Submit" name=cmdSubmit></td>
</tr>
</table>
<SCRIPT LANGUAGE="VBSCRIPT">
Sub cmdClose_OnClick()
window.close
End Sub
Sub cmdSubmit_OnClick()
Dim fromdate2
Dim todate2
fromdate2="Trim(frmNewClaim.cboFromDateDay.Value) & "/" & Trim(frmNewClaim.cboFromDateMonth.Value) & "/" & Trim(frmNewClaim.cboFromDateYear.Value)"
todate2="Trim(frmNewClaim.cboToDateDay.Value) & "/" & Trim(frmNewClaim.cboToDateMonth.Value) & "/" & Trim(frmNewClaim.cboToDateYear.Value)"
Select case frmNewClaim.txtPTNGroup.Value
'If type is Birth
case 30
if DateDiff("d",fromdate2,todate2) > 45 then
msgbox "Days value exceeded the limit of days allowed!",16,"Data Entry Error"
frmNewClaim.txtPTNGroup.focus
Exit Sub
end if
case else
End Select
frmNewClaim.submit
End Sub
In this form, the user is required to insert day, month, year in the from date and the to date table row after selecting the type of the petition for example : Birth
In the script, i declared variables fromdate2 and todate2which are supposed to contain the date for example like this: "03/12/2015"
and in the select case case 30, the datediff function which will give me the amount of days between the fromdate2 todate2 and if it is less then 45 then a message box would appear (yes, i know it only works on IE) say the days exceeded the limit
The problem is when i test it and click submit nothing happens
Am pretty sure the error is in the fromdate2 todate2 variables
Help me and thank you in advance
I'm confused as to how you are trying to collect your form data. Unless I'm missing something you appear to be mixing server side and client side code.
Classic ASP is a server side technology, VBScript is the language it usually uses, (you can specify JavaScript if you prefer.)
Your subroutines are contained within <SCRIPT LANGUAGE="VBSCRIPT">. This means that it will be run client side - and as you are aware it will only work on IE
I think what you need to do is to first move your code to the server side. You can do this either by putting it inside <% %> delimiters, or by using <SCRIPT LANGUAGE="VBSCRIPT" runat="server">
Instead of onclick events use the request object to populate variables retrieved from your form fields, eg cboFromDateDay = Request.Form("cboFromDateDay")
Finally your vbs script seems designed to generate popup alerts. This wouldn't work with server side code. You could use Response.Write to have error messages appear within the text of your page.
If you desperately want popup alerts then you could have them triggered when the page loads, and put the code which triggers them within an asp conditional statement so that it only appears in the server output if certain conditions are met. I would suggest though that this is more trouble than it's worth

how do i select datepicker using page-object-gem and jqueryui_widgets

I'm trying to use jqueryui_widgets combined with page-object-gem to test a datepicker, but I am failing on the first step.
on(HasADatepickerPage).the_datepicker = date
I get this error:
Watir::Exception::ObjectReadOnlyException: object is read only {:id=>"datepicker", :tag_name=>"input or textarea", :type=>"(any text type)"}
./features/step_definitions/datepicker_steps.rb:8:in `/^I enter the date "([^\"]*)"$/'
./features/has_a_datepicker.feature:8:in `When I enter the date "10/05/2015"'
has_a_date_picker_page.rb ( jqueryui_widgets example datepicker_page.rb )
class HasADatepickerPage
include PageObject
jqueryui_datepicker(:the_datepicker, :id => 'datepicker')
end
Questions:
What do I need to do prior to on(HasADatepickerPage).the_datepicker = date ?
What do I need to do prior to on(HasADatepickerPage).the_datepicker_select_day day ?
I cloned the jqueryui_widgets project, ran datepicker feature test, works fine. I modelled my solution as closely as I could to it.
I included snipets from my html page and the rest of the glory details I could think of below.
Thanks,
Tim
The Gory Details
my site html vs ( jqueryui_widgets example datepicker.html )
<div class="forms">
<div class="ajaxformitem" rel="Please select the number of passengers traveling">
<div class="ajaxformitem" rel="Please Enter the Date of Travel" style="background: transparent none repeat scroll 0% 0%;">
<div class="ajaxformitemleft">
<div class="ajaxformitemright">
<input id="datepicker" class="corner required hasDatepicker" type="text" placeholder="Pick Up Date" value="" readonly="true" name="PickUpTime[Date]"/>
<select id="hour" class="corner required" name="PickUpTime_Hour">
<select id="minute" class="corner required" name="PickUpTime[Mnute]">
</div>
</div>
ui-datepicker-div:
<div id="ui-datepicker-div" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all" style="position: absolute; top: 199px; left: 635.5px; z-index: 12; display: block;">
<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix ui-corner-all">
<a class="ui-datepicker-prev ui-corner-all" title="Prev" onclick="DP_jQuery_1440799766008.datepicker._adjustDate('#datepicker', -1, 'M');">
<a class="ui-datepicker-next ui-corner-all" title="Next" onclick="DP_jQuery_1440799766008.datepicker._adjustDate('#datepicker', +1, 'M');">
<div class="ui-datepicker-title">
</div>
<table class="ui-datepicker-calendar">
<thead>
<tbody>
</table>
</div>
has_a_datepicker.feature - same as example
Feature: Using the JQueryUI Datepicker widget
Background:
Given I am on the has datepicker page
Scenario: Testing datepicker jqueryui_widgets
When I enter the date "10/05/2015"
And I select day "25"
Then the date should be "10/25/2015"
datepicker_steps.rb - the_datepicker vs (datepicker_one and datepicker_two)
Given(/^I am on the has datepicker page$/) do
visit(HomePage)
on(HomePage).select_radio_for 'From'
on(HomePage).select_service 'Airport'
end
When(/^I enter the date "([^\"]*)"$/) do |date|
on(HasADatepickerPage).the_datepicker = date
end
And(/^I select day "(\d+)"$/) do |day|
on(HasADatepickerPage).the_datepicker_select_day day
end
Then(/^the date should be "([^\"]*)"$/) do |day|
#on(DatepickerPage).datepicker_one.should == day
expect(on(HasADatepickerPage).the_datepicker).to eql day
end
Selecting a Date
If you look at the datepicker methods, all of the interactions with the calendar assume that the calendar is already displayed. If you look at the gem's test (features), you will see they always inputted the text field first, which opens the calendar. Only after that do the tests try to interact with the calendar.
However, since your text field is read-only, you cannot input the text field to trigger the popup. As a result, you need to click the text field. The datepicker accessor creates a {name}_element method for accessing the text field. Therefore, you can do:
page.the_datepicker_element.click
page.the_datepicker_select_day('15')
Setting a Date
The {name}= method for directly setting the date will not work for your control. The method simply types into the text field, which being read-only is not valid.
You seem to have 2 options:
Click the Next/Previous Month controls until you get the right month and then select the day.
Use JavaScript to input the text field directly.
Unless there are events the application excepts to be raised when inputting the date, I would suggest going with option 2. It is quicker and less error prone. While it does not mimic the user, testing the interactions within a jQuery widget should not be your responsibility.
date = '08/13/2015'
page.execute_script("arguments[0].value='#{date}';", page.the_datepicker_element)
If you really want to input the value like a user:
# These libraries are added to help with doing date comparisons
require 'date'
require 'active_support/time'
# The date you want to set
date = '12/13/2015'
# Open the calender
page.the_datepicker_element.click
# Determine if we need to navigate to a prior or future month
final_date = Date.strptime(date, '%m/%d/%Y')
current_date = Date.strptime(
"#{page.the_datepicker_month} #{page.the_datepicker_year}",
'%B %Y'
)
difference = (final_date.year * 12 + final_date.month) - (current_date.year * 12 + current_date.month)
# Navigate to the required month/year
if difference < 0
difference.abs.times { page.the_datepicker_previous_month }
else
difference.abs.times { page.the_datepicker_next_month }
end
# Select the day
page.the_datepicker_select_day(final_date.day.to_s)
As you can see, having to click the next/previous controls adds a lot of complexity.
Your ui-datepicker-div has: <input id="datepicker" readonly="true">
Watir won't let you send text to an element that is set to be readonly. Remove that attribute and this should work.

Watir. Select multiple radio button options

The issue I'm dealing with, and unable to solve due to my ignorance, is that I have a page on a browser with different education requirements which each have four radio buttons. I want to be able to select a certain radio button for each education requirement.
The code I have is like this:
radios = browser.radios
radios.each do |radio|
radio.input(:value => "very").set
end
However this keep giving me an error message saying: "undefined method 'set' for #Watir::Input:0x103a5d508"
I did something similar for select_lists where I changed the option of all select_lists on a page to the 2nd option which worked:
lists = browser.select_lists
lists.each do |list|
list.option(:index, 1).select
end
For my code for the radio buttons I tried using radio.option but it gave me a similar error: "NoMethodError: undefined method `set' for #Watir::Option:0x103a466a0"
Problem
The code
radios = browser.radios
radios.each do |radio|
radio.input(:value => "very").set
end
Says that for each radio button on the page, set the first input element with value "very". This suggests that you are looking for html like:
<radio>
<input value="very" />
</radio>
This is probably not what the html looks like.
Solution
I assume the html you really want to set is like:
<input type="radio" value="very" />
To set each radio button with value "very", the code should be:
# Get a collection of all radios with value "very"
radios = browser.radios(:value => "very")
# Iterate through each radio button in the collection and set it
radios.each do |radio|
radio.set
end
This can be shortened to simply:
browser.radios(:value => "very").each(&:set)

Resources