Click on buttons on the page that has got the same class using capybara with siteprism - ruby

There are 20 different buttons to expect and needs to be clicked through to expect and verify the urls inside the code. I have tried different ways to implement my tests but they are failing.
I'm trying something like:
page.all(:class => 'action red').each do |button|
c = button.find(:class => 'action view red')
c.click
page.driver.browser.switch_to.window(#new_window)
expect('some element on those 20 different browsers sessions before closing them')
page.driver.browser.close
end
end
I'm getting this error:
ArgumentError: invalid keys :class, should be one of :count, :minimum,
:maximum, :between, :text, :visible, :exact, :match, :wait
Any can help me in the code how to perform get the elements of all the 20 buttons, store them and click them to expect the url each of them before closing it

Your "buttons" aren't buttons - since they are <a> elements they are actually links, styled to look like buttons.
Assuming that clicking each of these links actually opens a new window (since you're attempting to switch to a new window) then the code would be something like
page.all(:link, class: ['action', 'red']).each do |link|
win = page.window_opened_by { link.click }
page.within_window(win) do
expect(page).to ... # whatever you need to expect
end
win.close()
end
Note this doesn't use any driver specific (.driver.browser...) methods - you should stay away from them whenever possible since they are generally a sign you're doing something wrong. Additionally, the :class option wasn't universally available on all of Capybaras builtin selector types until v2.10, so you will need to be using a newer version of Capybara for that.

Related

How to handle windows pop up in IE using Ruby

Please help me how to handle this pop ups.
Based on your last question, I assume you are using Watir-Classic (even though you have also listed Watir-Webdriver).
As #orde mentioned in the comments, Watir has an Alert class for handling these types of dialogs. Unfortunately, in terms of clicking buttons, Watir-Classic only has an #ok method defined:
# Press the "OK" button on the JavaScript dialog.
def ok
dialog.button(:value => "OK").click
wait_until_not_exists
end
This will not work for this dialog as there is a "Yes" and "No" button rather than an "OK" button. You will need to duplicate this functionality with the right value.
Note that the dialog is a RAutomation window and no longer Watir specific code. As a result, the button values are not always intuitive - it is not always just the text you see. To get the right values, you should ask the dialog what values it sees:
browser.alert.send(:dialog).buttons.map(&:value)
#=> ["&Yes", "&No"]
We can then make the same calls as the #ok method, but with the correct value:
alert = browser.alert
alert.send(:dialog).button(:value => '&Yes').click
alert.wait_while_present
This code is working fine to handle this type of pop ups:
save_dialog = WIN32OLE.new("AutoItX3.Control") save_dialog.ControlClick("Windows Internet Explorer", "Yes", "[CLASS:Button;INSTANCE:1]")

Watir-webdriver throws 'not clickable' error even when element is visible, present

I am trying to automate tests in Ruby using the latest Watir-Webdriver 0.9.1, Selenium-Webdriver 2.53.0 and Chrome extension 2.21. However the website that I am testing has static headers at the top or sometimes static footers at the bottom. Hence since Watir auto-scrolls an element into view before clicking, the elements get hidden under the static header or the static footer. I do not want to set desired_capabitlites (ElementScrollBehavior) to 1 or 0 as the websites I am testing can have both - static header or static footer or both.
Hence the question are:
1) Why does Watir throw an exception Element not clickable even when the element is visible and present? See ruby code ( I have picked a random company website for an example) and the results below.
2) How can I resolve this without resorting to ElementScrollBehaviour?
Ruby code:
require 'watir-webdriver'
browser = Watir::Browser.new :chrome
begin
# Step 1
browser.goto "shop.coles.com.au/online/mobile/national"
# Step 2 - click on 'Full Website' link at the bottom
link = browser.link(text: "Full website")
#check if link exists, present and visible?
puts link.exists?
puts link.present?
puts link.visible?
#click on link
link.click
rescue => e
puts e.inspect
ensure
sleep 5
end
puts browser.url
browser.close
Result:
$ ruby link_not_clickable.rb
true
true
true
Selenium::WebDriver::Error::UnknownError: unknown error: Element is not clickable at point (460, 1295). Other element would receive the click: div class="shoppingFooter"...div
(Session info: chrome=50.0.2661.75)
(Driver info: chromedriver=2.21.371459 (36d3d07f660ff2bc1bf28a75d1cdabed0983e7c4),platform=Mac OS X 10.10.5 x86_64)>
http://shop.coles.com.au/online/mobile/national
thanks!
You can do a click at any element without getting it visible. Check this out:
link.fire_event('click')
BUT It is very very very not good decision as far as it will click the element even if it is not actually visible or in case when it is just impossible to click it (because of broken sticky footer for example).
That's why much better to wait the fooler, scroll the page and then click like:
browser.div(id: "footerMessageArea").wait_until_present
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
link.click
The sticky footer is blocking webdriver from performing the click, hence the message that says 'other element would receive the click'.
There are several different ways you can get around this.
Scroll down to the bottom of the page before the click
Hide/Delete the sticky footer before any/all link clicks
Focus on an element below the element you want to click before you perform the click
I Guess your element is visible in the screen.
Before clicking on the element first you have to scroll the webpage so that element is visible then perform the click. Hope it should work.
I had similar issue,
I just used following javascript code with watir:
link = browser.link(text: "Full website")
#browser.execute_script("arguments[0].focus(); arguments[0].click();", link)
Sometimes I have to use .click! which i believe is the fire_event equivalent. Basically something is layered weird, and you just have to go around the front end mess.

Testing a 'stale' element with Selenium and rspec

Still a newbie to RSpec and Ruby, so apologies for any obvious errors, omissions, etc in my question.
What I'm looking to test using RSpec (with Selenium Webdriver) is the following;
1) I've (randomly) selected a make of car from a drop down menu
2) From this selected make, I then (randomly) selected a corresponding model of car from a drop down menu
3) Then pressed "Search" button and a list of, for example, BMW 3-Series cars were correctly displayed.
What I now need to do using RSpec is test that the (randomly selected) make and model names are displayed in a page heading and in the URL.
For example, selecting BMW 3-Series will result in the URL ending in /bmw/3-series and a heading on the page will read "BMW 3-Series Cars For Sale".
However, the problem I'm having is that a 'Stale Element' error message is being displayed when I run the test.
I know why the error is displayed (because the elements used to select the make and model are 'lost' when the Search button is pressed, as a new page opens which does not contain these elements), but I don't know how to get around this problem.
Any help would be greatly appreciated.
# This generates a random manufacturer
manuselect = #driver.find_element(:id, 'ctl00_contentHolder_topFullWidthContent_ctlCarsForSaleSearch_ctlUsedCarsSearchTab_ddlManufacturer_Control')
manufacturer = manuselect.find_elements(:tag_name => 'value').sample
#puts manufacturer.text
manufacturer.click
sleep 7
# This generates a random model
modelselect = #driver.find_element(:id, 'ctl00_contentHolder_topFullWidthContent_ctlCarsForSaleSearch_ctlUsedCarsSearchTab_ddlRange_Control')
carmodelrange = modelselect.find_elements(:tag_name => 'value').sample
puts carmodelrange.text
carmodelrange.click
sleep 5
# Click on the Search button
#driver.find_element(:id, 'ctl00_contentHolder_topFullWidthContent_ctlCarsForSaleSearch_ctlUsedCarsSearchTab_btnSearch').click
You just need to store the text you're going to look for into variables before the elements disappear from the page
manufacturer_name = manufacturer.text
modelrange_name = carmodelrange.text
#click the search button...
# the following expectations require Capybaras matchers, use whatever expecations are equivalent with whatever you're using
expect(page).to have_current_path(/#{Regexp.quote(manufacturer_name)}\/#{Regexp.quote(modelrange_name)}$/)
expect(page).to have_text("#{manufacturer_name} #{modelrange_name}")

Watir: How I can click button in IE popup windows

I have a customized popup IE window where there are buttons included into iframe. I can't click on any button in it. I know how to work with iframes, but I can't switch to this window. Window has title and URL.
I wrote this method:
def confirm_ok
self.in_iframe(:id => 'frmMain') do |frame|
self.button_element(:id => 'btnOK', :frame => frame).click
end
end
But I get this error:
Watir::Exception::UnknownFrameException: unable to locate iframe using {:id=>"frmMain", :tag_name=>"iframe"}
I use Watir, PageObject. And run scenarios under IE.
Watir's method doesn't work:
browser.window(:title => "annoying popup").use do
browser.button(:id => "close").click
end
I get error
NoMethodError: undefined method `window' for #<PA_Main:0x33f6780>
As best as I can tell you have two separate issues.
Firstly, I have no idea how you set your browser variable to a page object instance. The Page Object Module definitely sets browser as a readable attribute.
So if the code is within a class that has import PageObject, you should be able to do browser.window(...) just fine.
If you are using the code outside of such a class, you need to make sure that you are in a scope that has access to the Watir::Browser instance. If you have a page object defined, you can use it like: my_page_object.browser.window(...)
Secondly - based on what you are describing, the iframe usage has to be combined with the window usage:
browser.window(title: "annoying popup") do
browser.iframe(id: 'frmMain').button(id: "close").click
end

Duplicate Checkbox in Page-Object is not defined?

I am trying to click a checkbox that enables a purchase button to appear. When I try to use it, I get a "NoMethodError: undefined method 'eula' for Cart:0x101f54810" error. I think it may be because there are two identical checkboxes, but I am just not certain.
HTML:
<p id="eula-box" class="annoy cc"><input type="checkbox" name="terms_of_service" value="terms_of_service" tabindex=20 />I have read & agree to the End-User License Agreement.</p>
<p id="eula-box" class="annoy pp"><input type="checkbox" name="terms_of_service" value="terms_of_service" tabindex=20 />I have read & agree to the End-User License Agreement.</p>
My class:
require 'rubygems'
require 'page-object'
require 'page-object/page_factory'
require 'watir-webdriver'
CART_URL = 'http://www.anonymizer.com/cart/checkout.html?SKU=ANONUNV12'
class Cart
include PageObject
page_url CART_URL
checkbox(:eula, :class=>"annoy_cc")
button(:purchase, :value=>'purchase')
def complete_order(data = {})
self.eula.click
end
end
Udpated: I was changing the object type around trying to get it to work. Element was the last type I tried. I changed my example back to checkbox (my original attempt). Thanks for pointing that out.
When you call the class level checkbox method in page-object it generates five methods. The call:
checkbox(:summary, :id => 'valid_checkbox')
will generate:
check_summary # check the checkbox
uncheck_summary # uncheck the checkbox
summary_checked? # returns true if it is checked. otherwise false
summary_element # returns the Checkbox object
summary? # returns true if the element exists. otherwise false
These are the method to interact with when using the checkbox.
PageObject's checkbox generate the following method to check (i.e. click) it.
check_eula
See http://rubydoc.info/gems/page-object/0.6.3/PageObject/Accessors:checkbox
I'm not very familiar with page-objects, but is element a valid accessor? I'm looking at the documentation and don't see it. Perhaps it would be better to use the checkbox accessor?
As an aside, the easiest way to see if your problem is caused by having two similar checkboxes, would be to just remove one and see if the problem goes away!

Resources