Ruby Watir if then statement - ruby

I've looked around the internet but without much success as well as checked through here.
I'm new to ruby watir and mini test but i'm trying to write some automation that checks the value in a select list drop down and if it finds a value it changes it a 2nd value. If it finds the 2nd value the next time it runs i want it to change the first value.
I've created variables of;
$Title1 = "Dr"
$Title2 = "Mr"
and the code I'm trying to run is attempting to use an if, then, else series of statements;
#Title
if $browser.select_list(id: "title") == $Title2 then
$browser.select_list(:id, "title").select($Title1)
else
if $browser.select_list(id: "title") == $Title1 then
$browser.select_list(:id, "title").select($Title2)
end
however, nothing happens and no errors are triggered.
Any help would be greatly appreciated

Problem
The problem is that the if statements are comparing apples to oranges (ie two different things). You are comparing a Watir::SelectList, from $browser.select_list(id: "title"), with a string, from $Title2.
For Watir elements, the == is used to check if two elements are the same element on the page. The element will never equal a string.
Solution
What you actually want to compare to the Title2 is the selected options of the select list. Watir select lists have a selected? method for checking this.
You could do something like:
if $browser.select_list(id: "title").selected?($Title2)
$browser.select_list(:id, "title").select($Title1)
else
$browser.select_list(:id, "title").select($Title2)
end

Related

Return the count of courses using satisfies contains XQuery

I have been struggling to return the count of courses from this XML file that contain "Cross-listed" as their description. The problem I encounter is because I am using for, it iterates and gives me "1 1" instead of "2". When I try using let instead I get 13 which means it counts all without condition even when I point return count($c["Cross-listed"]. What am I doing wrong and how can I fix it? Thanks in advance
for $c in doc("courses.xml")//Department/Course
where some $desc in $c/Description
satisfies contains($desc, "Cross-listed")
return count($c)
The problem I encounter is because I am using for
You are quite correct. You don't need to process items individually in order to count them.
You've made things much too difficult. You want
count(doc("courses.xml")//Department/Course[Description[contains(., "Cross-listed"]])
The key thing here is: you want a count, so call the count() function, and give it an argument which selects the set of things you want to include in the count.

How can I get Watir to make a fresh reference on a non-stale element?

A portion of some tests I am writing calls for checking if an option gets removed from a select list once that option has been used. I am inconsistently getting this error: timed out after 60 seconds, waiting for {:xpath=>"//select[#id = 'newIdentifierType']//option", :index=>31} to be located (Watir::Exception::UnknownObjectException)
It causes my test to fail maybe 2-3 times out of 10 runs and seems kind of random. I think Watir is looking for the "old" select list with this ID since it caches the element and may also include that it had 32 items, but it times out since a select list with this ID and 32 items no longer exists. The new select list has the same ID but only 31 items.
Is there a way to always get a new reference on this element even though it's not technically going stale? Am I experiencing this problem due to a different issue?
My current code for getting the options in the select list:
#browser.elements(:xpath => "//select[#id = 'newIdentifierType']//option")
I am using Ruby/Cucumber with Selenium and Watir Webdriver level. I first tried defining the element as a select_list in a page-object but moved it to the step definitions using #browser.element to see if that would stop the timeout. I thought it may ignore Watir's cached elements and get the most current one with the ID, but that does not appear to be the case.
Please avoid using XPath with Watir. Everything you can do with XPath, Watir has a much more readable API to handle.
To check for a specific option not being there, you should avoid collections and locate directly:
el = browser.select_list(id: "newIdentifierType").option(value: "31"))
# or
el = browser.select_list(id: "newIdentifierType").option(text: "This one"))
Then to see if it has gone away:
el.stale?
# or
el.wait_until(:stale?)
That won't test the right thing if the entire DOM has changed, though, so you might need to just relocate:
browser.select_list(id: "newIdentifierType").option(text: "This one")).present?
If you are intent on using a collection, the correct way to get the list of options is:
options = #browser.select(id: 'newIdentifierType').options
el = options.find { |o| o.text == 'This one' }
# Do things
el.stale?

How do I copy certain elements of an array to a location before it in Ruby?

I have a CSV file, Original.csv, where I am checking all the rows to see if the element in the 28th column is empty. If it is not empty, I want to copy the 28th, 31st, 33rd and 34th elements to their previous positions; if it is empty, then I don't want to do anything. And then, I want to store the content in a new file, New.csv. This is my code:
require 'csv'
CSV.open('New.csv', "wb") do |csv|
CSV.foreach('Original.csv') do |row|
if row[28]!=nil
row[27]=row[28]
row[30]=row[31]
row[32]=row[33]
row[33]=row[34]
end
csv<<row
end
end
But, the program copies the columns without checking the condition! What is wrong?
EDIT: I figured out the bug. Turns out, what I thought was empty, i.e., "", was actually a space, i.e., " ". This stupid thing took 4 hours of my time! So, if anyone is facing a similar issue, the takeaway is - what something appears as is not necessarily what it actually is. So beware. And one way to do that is not open the file in MS Excel, but rather in some primitive application like Notepad, Sublime, etc.
It certainly looks as though if row[28]!=nil is evaluating as false when you don't expect it to. There are a few possible reasons for that:
As commenter undur_gongor wrote:
"In Ruby, the empty string '' does not compare equal to nil. They are even different classes"
Therefore:
if row[28]!=nil will evaluate to true unless row[28] actually contains the nil object. If it contains an empty string (e.g. '' or "") it will evaluate to false.
Solution:
Make sure that your "if" statement is actually evaluating as you expect it to. My guess is that you want something like row[28].empty? or row[28].strip.empty? if it turns out the problem is you have a few white spaces.

collect all xpath results into an array in ruby

I have a very poorly coded JSP that I am trying to run automation on. There are a series of checkboxes with names (no IDs) of "delete[x]" where X is the item number of the item populated. I am trying to select all the checkboxes so I can delete every entry. Here is what I have
check_boxes = []
check_boxes.push(#browser.checkbox(:xpath, "//input[contains(#name,'delete')]"))
puts check_boxes.size
check_boxes.each do |check_box|
check_box.set
The problem with this is it only selects the first instance (node) that matches the xpath to dump into the array. I know I can iterate through the xpath adding an index to the node, and then put a rescue in that drops me out when the index goes out of bounds, but that seems like the dirty way to do it.
I know there is an "as" tag that gets a set of anchors and i was wondering if there was a method like that for taking the whole selection of checkboxes
I don't think the problem is the xpath itself. It is the #browser.checkbox that is causing only the first checkbox to be returned.
If you want all matching checkboxes, you should use (notice the plural):
#browser.checkboxes
Note that checkboxes returns a collection of checkboxes. Unless you are doing something really fancy, you usually do not need to convert it to an array.
You can simply do:
#browser.checkboxes(:name => /delete/).each do |checkbox|
checkbox.set
end

How to assert on number of html table rows in ruby using capybara + cucumber

I am trying to get to grips with BDD web development in Ruby using cucumber + capybara and I am stuck at what should be an easy task - just to check the number of rows in a table. The intention of what I'm trying to achieve is something along the lines of:
page.should have_xpath("//table[#id='myTable']")
find("//table[#id='myTable']/tr").length.should == 3
But this doesn't work (missing method length) and I can't find a way to assert against the table length.
Any ideas anyone (please be easy on me tho' I'm a ruby nooby)
Thanks in advance
Neil
Even though have_css? will do the trick, your tests should tell you how they failed, rather than just saying some condition was supposed to be true and it was false. With this in mind, the first example below reads much better than the second:
# IF FAILED => "expected 10, got 7"
page.all('table#myTable tr').count.should == 10
# IF FAILED => "expected true, got false"
page.should have_css("table#myTable tr", :count=>10)
I think you can do this:
page.should have_css("table#mytable tr", :count=>3)
For some reason "has_css" does not work for me, however "all(selector)" works really wel
all("table#movies tr").count
I went with this in the end:
Then /^I should see "(.*)" once$/ do |text|
within_table('myTable') do
should have_xpath("//tr", :text => text, :count => 1)
end
end
which seemed suitably elegant.
I realise the other answers work but this seems to read well.
Any comments?
The method #find only returns one element (I think it just returns the first one if there are several matches) so you don't get a #length method because the result of #find is a Node not an Array.
To prove this to yourself, try
puts find("//table[#id='myTable']/tr").class
What you want is #all, which will return you an Array of all the matching nodes.
In this way you can learn the number of lines in the html table.
area = find_by_id('#areaID').all('tr').size
Assume that there are columns at the beginning of the table.You can reach the actual number in this way.
area = area-1

Resources