How to check for visibility if the class exists in capybara? - ruby

With capybara and minitest, how would you check for visibility of a element if the element exists on the page? The class isn't always guaranteed to be there, so I need to check if it is on the page first.
All I can think of is:
assert find(".class-name").visible? if has_css?(".class-name", :wait=>0)
Are there any other ways of doing this?

By default Capybara only finds visible elements, so
if has_css?(".class-name", wait: 0)
will only return true if the element is visible on the page
If you want to verify the element is either not on the page, or if it is in the source of the page it must be visible then you could do something like
assert_css('.class-name') if has_css?('.class-name', visible: :all)
or just
refute_css('.class-name', visible: :hidden) # ensure there is no non-visible element with the class name

Related

XPath - get a button inside another element with class

I need to find a button element using XPath. The problem is, the button has no unique identifier like Id or name, but is located inside another element which has a unique class (i.e. a class that no other element on page uses). I know how to get to that element and identify it by class but I don't know how to access the button inside that element.
.//mat-header-cell[#class='mat-header-cell cdk-column-delete mat-column-delete ng-star-inserted']
Any suggestions?
SOLUTION I FOUND:
Just added '//button' to the end of xpath and it works now!
.//mat-header-cell[#class='mat-header-cell cdk-column-delete mat-column-delete ng-star-inserted']//button

Cannot find link using Capybara and Rspec while writing an integration test

I am trying to find a link by CSS classes and ids but always getting an error: Capybara::ElementNotFound: Unable to find css ...
The actual piece of code is:
find('#bucket_resources_containers > #user_base_widget.widget >
div.widget_header > div.right.may-
edit.control.button.add.icon.add_options > a.tasksy.options').click
The page source is: enter image description here
You gave us the answer in your comment, the element was not visible.
Short answer: find_link(selector, visible: :all).click
As capybara shows in the documentation:
By default Capybara will only locate visible elements. This is because a real user would not be able to interact with non-visible elements.
Only locate visible elements is an smart design of capybara, it avoids thinking that a user would be able to find the element.
The find_link method documentation doesn't help much when finding for hidden links because it only show these options: wait, href, id, title, alt, class:
#find_link([locator], options = {}) ⇒ Capybara::Node::Element
But you see on the finding documentation there was a visible option:
find_link('Hello', :visible => :all).visible?
find_link(class: ['some_class', 'some_other_class'], :visible => :all).visible?
This option visible comes from #all method, where you can see here. It can have these values:
true - only finds visible elements.
false - finds invisible and visible elements.
:all - same as false; finds visible and invisible elements.
:hidden - only finds invisible elements.
:visible - same as true; only finds visible elements.
So, in your case, you could use visible: false, if you really mean it to be hidden, or visible: :all if you don't care about the visibility.

How to find a css element on the page if it is display: none?

I'm running automated testing in Ruby.
I'm trying to write a script that finds id with display:none (visible only in mobile form), and clicks it.
Here is my code:
def open_menu
page.find[:css, "a[id='mobile-nav-link']", visible: false].click
end
It gives me an error:
Selenium::WebDriver::Error::InvalidSelectorError:
invalid selector: No selector specified
A quick search reveals similar code using round brackets, not square. I.e.:
def open_menu
page.find(:css, "a[id='mobile-nav-link']", visible: false).click
end
Selenium only interacts with elements the way a user would.
If the link is only visible in mobile, I would suggest one of the following.
View the page via the mobile URL.
It's possible that you may be able to use Ruby's javascript execute to either update the control to be visible, or set the value that indicates you are viewing the page via a mobile device.
Updating the control to be visible
This link discusses how to set an element to visible using javascript execute: Selenium Webdriver - click on hidden elements
This link discusses how to use ruby's javascript execute: How to execute Javascript in Ruby written Webdriver test?
Put the two together, and you get something like this?
def open_menu
elem = page.find[:css, "a[id='mobile-nav-link']", visible: false]
js = "arguments[0].style.height='auto' arguments[0].style.visibility='visible';"
driver.execute_script(js , elem)
page.find[:css, "a[id='mobile-nav-link']", visible: true].click
end
I'm not entirely familiar with Ruby syntax, so I make no guarantees it will work copy/paste.

SitePrism: sometimes find elements, sometimes doesn't while Capabara can

I am using Capybara and Selenium for testing my website. I also use with Site Prism for Page Object model. I can make every thing work now, however, I don't understand why sometimes actions with page elements donot work, while using "natively" Capybara work.
For example, I have a Page object:
class MyPage < SitePrism::Page
element :sign_in_link, :css, 'a.signin-link'
element :join_link, :css, "a.join-link"
end
and its implementation:
#mypage = MyPage.new
#mypage.sign_in_link.click
# It works at first, then after some repeated test round, it doesn't work sometimes, with error: NoMethodError <br>
While I use:
find(:css, 'a.signin-link').click #=> always work, but not Page Object model
So, why it happens? Have anyone experienced this problem?
By default site_prism disables Capybaras implicit waiting behavior while finding elements. This means to have the same behavior as your capybara example you would need to do
#mypage = MyPage.new
#mypage.wait_for_sign_in_link
#mypage.sign_in_link.click
You can read more about this in the site_prism README under "Using Capybara Implicit Waits"
Another options is to use site prisms "Load Validations" feature to ensure pages are loaded before starting to click on their elements

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