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

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.

Related

Please help to extract date using xpath

<div class='postbodytop">
<a class="xxxxxxxxxxxxxxxx" href="xxxxxxxxxxxxxx">tonyd</a>
"posted this 4 minutes ago "
<span class="hidden-xs"> </span>
</div>
Hello, I want to extract the "posted this 4 minutes ago" or just "4 minutes" using xpath. Can anybody help me? Thank you
The div whose class equals postbodytop contains three child nodes: a span, a text node, and another span. Your path should start at the div and then select the child text node, for which the appropriate test is text().
div/text()
Of course this is just a fragment of a bigger page, and your XPath may need to have something at the start e.g. /html/body/ etc. and if there are other div elements at the same level as the <div class=postbodytop>, then you should be more specific about the div, e.g. div[#class="postbodytop"] instead of just div in that XPath expression.

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 to get text of help tag in RUBY Capybara.Fail get the text help tag(Default value is 180 days and allowed value range is 30-180)any one help me

<label for='zip'>Password Duration – maximum days:</label>
<input Value="180" id="PasswordExpiryDays" name="PasswordExpiryDays" type="text"/>
<a class="links" id="PasswordAge_Tip" tabindex="-1"
onblur="HideLayer('PasswordAge')"
onmouseover="ShowLayer('PasswordAge')"
onmouseout="HideLayer('PasswordAge')" href="#">?</a>
<span id="PasswordAge" style="VISIBILITY: hidden;">
<table>
<tr>
<td>
Default value is 180 days and allowed value range is 30-180
</td>
</tr>
</table>
</span>
Fail get the text help tag value (Default value is 180 days and allowed value range is 30-180)any one help me.
That element has visibility set to 'hidden'. Did you configured capybara to work on hidden elements?
Reformatting your html so it's readable would help, and the id in the xpath that is failing is for a span in your html not for an input
span = page.find(:xpath,"//span[#id='PasswordAge']/table/tr/td", visible: false) # page.find('#PasswordAge td', visible: false) would be easier to read
value = span.text(:all) # The all is necessary to get non-visible text

Select checkbox from excel with 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

how to access this element

I am using Watir to write some tests for a web application. I need to get the text 'Bishop' from the HTML below but can't figure out how to do it.
<div id="dnn_ctr353_Main_ctl00_ctl00_ctl00_ctl07_Field_048b9dfa-bc64-42e4-8bd5-b45385e5f45b_view" style="display: block;">
<div class="workprolabel wpFieldLabel">
<span title="Please select a courtesy title from the list.">Title</span> <span class="validationIndicator wpValidationText"></span>
</div>
<span class="wpFieldViewContent" id="dnn_ctr353_Main_ctl00_ctl00_ctl00_ctl07_Field_048b9dfa-bc64-42e4-8bd5-b45385e5f45b_view_value"><p class="wpFieldValue ">Bishop</p></span>
</div>
Firebug tells me the xpath is:
html/body/form/div[5]/div[6]/div[2]/div[2]/div/div/span/span/div[2]/div[4]/div[1]/span[1]/div[2]/span/p/text()
but I cant format the element_by_xpath to pick it up.
You should be able to access the paragraph right away if it's unique:
my_p = browser.p(:class, "wpFieldValue ")
my_text = my_p.text
See HTML Elements Supported by Watir
Try
//span[#id='dnn_ctr353_Main_ctl00_ctl00_ctl00_ctl07_Field_048b9dfa-bc64-42e4-8bd5b45385e5f45b_view_value']//text()
EDIT:
Maybe this will work
path = "//span[#id='dnn_ctr353_Main_ctl00_ctl00_ctl00_ctl07_Field_048b9dfa-bc64-42e4-8bd5b45385e5f45b_view_value']/p";
ie.element_by_xpath(path).text
And check if the span's id is constant
Maybe you have an extra space in the end of the name?
<p class="wpFieldValue ">
Try one of these (worked for me, please notice trailing space after wpFieldValue in the first example):
browser.p(:class => "wpFieldValue ").text
#=> "Bishop"
browser.span(:id => "dnn_ctr353_Main_ctl00_ctl00_ctl00_ctl07_Field_048b9dfa-bc64-42e4-8bd5-b45385e5f45b_view_value").text
#=> "Bishop"
It seems in run time THE DIV style changing NONE to BLOCK.
So in this case we need to collect the text (Entire source or DIV Source) and will collect the value from the text
For Example :
text=ie.text
particular_div=text.scan(%r{div id="dnn_ctr353_Main_ctl00_ctl00_ctl00_ctl07_Field_048b9dfa-bc64-42e4-8bd5-b45385e5f45b_view" style="display: block;(.*)</span></div>}im).flatten.to_s
particular_div.scan(%r{ <p class="wpFieldValue ">(.*)</p> }im).flatten.to_s
The above code is the sample one will solve your problem.

Resources