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

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

Related

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.

Appium-Capybara-ruby running automation on Physical device and some of the capybara function not working

I have setup Appium - Capybara and was able to run automation suites on physical device, but facing issue with few methods
I was able to successfully run Capybara methods like
fill_in field, :with => text
click_button button_text
expect(page).to have_content(text)
But facing issues with below method ( it works on regular chrome on laptop but not on mobile )
page.first(:link, link_text).click
can you please help me to understand if appium capybara supports all the capybara methods or only few of them.
Below is the error message
undefined method `click' for nil:NilClass (NoMethodError)
In the above code, first the link with link_text is being searched on the page. If no link is found then nil is returned.
Thus, to make this code work, we need to wait for the link with the link text to appear on the page and then click it.
So you can use any one of the below mentioned code before clicking the fink
page.should have_content(link_text)
page.find_link(link_text)
If the above code doesn't works then you can also try increasing the default wait time as shown below:
Capybara.default_wait_time = 30
page.should have_content(link_text)
page.first(:link, link_text).click
Capybara.default_wait_time = DEFAULT_WAIT_TIME
DEFAULT_WAIT_TIME for Capybara tests is set in your environment file.
Hope this helps :)
undefined method 'click' for nil:NilClass (NoMethodError) is telling you that #first isn't returning an element (#first returns immediately with a matching element, or nil if there is none). Is there a reason you are using first rather than find?? If there is only one matching link on the page you should really prefer find over first (in this case find_link), or try to scope to a part of the page where the would only be one link, since it will throw an error explaining why it didn't find the link (rather than returning nil) and also has waiting behavior for elements to show up (first can have the same behavior but it doesn't by default)

Is "enabled?" method available on Watir and/or Page-Objects for a link?

Yesterday i was working on determining is this link was or not enabled, waiting until enabled in order to click it. I'm using Cucumber + Ruby + Watir + Page-Object gem. The link is very similar to:
<a id="the_link" href="#" disabled="disabled">Proceed with your order</a>
Once you fill some fields, the link is enabled and the source changes to:
<a id="the_link" href="#">Proceed with your order</a>
The idea is to wait until the link is enabled in this way, which works with buttons:
def click_on_link
Watir::Wait.until { self.the_link_element.element.enabled? }
self.the_link
end
...but does not work with the link. I made it work determining if the attribute exists, this way:
def click_on_proceed_form
Watir::Wait.until { !self.the_link_element.element.attribute_value('disabled') }
self.proceed_form_submit
end
Looking for the "enabled?" method at the Watir documentation here or at the Page-Object gem here, it seems that is available for all elements. But looking for the same method in the Watir documentation here, seems it's only available for Buttons, Selects and Inputs.
So, i wonder is there is an "enabled?" method for links (anchors) and, if it exists, how to use it. Can you help clarify this issue, please? Thank you very much!
Watir-webdriver does not support the enabled? method for links. I believe this is because the disabled attribute is not a standard attribute for links.
On the other hand, Watir-classic does support the enabled? method for links. However, it will always return false (again because links cannot be disabled).
Therefore, I think your approach is correct (unless you want to monkey patch the link elements to support the enabled?).
However, you should try to avoid using Watir-webdriver directly where possible. The page-object gem has its own methods for waiting and getting attribute values:
def click_on_proceed_form
wait_until{ !the_link_element.attribute('disabled') }
proceed_form_submit
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!

Selenium 2.0 Webdriver & Ruby, link element methods other than .text? Navigate.to links in array?

I'm a bit further along in converting some sample test/specs from Watir to Selenium. After my last question here and suggested response, I began using Selenium 2.0 with WebDriver instead of Selenium 1.
The example in question deals with gathering all links within a table into an array -- that part is complete. However, once the links are in the array, the only meaningful way that I can interact with them appears to be .text. Using #driver.navigate.to Array[1] gives a URL format error in the browser, and link.href or .src are not valid options.
The Watir implementation gathered these links (pages added by users via CMS), stored them in an array and then visited each page one by one, submitting a lead form. I believe I could get this to work using Selenium and revisiting the "home" page that contains all of the links between lead form submissions, but that could mean hundreds of extra page loads, cached or not.
The code so far:
' #countries = Array.new
#browser.navigate.to "http://www.testingdomain{$env}.com/global"
#browser.find_elements(:xpath, "//table[#class='global-list']//a").each do |link|
#countries << [link.text, link.href] ## The original WATIR line that needs an update
end #links
#countries.uniq! #DEBUG for false CMS content'
The closest item I could find in the selenium-webdriver documentation was the (string).attribute method, but again, am unsure of what attributes
I was not sure of the format for use with the attribute method, but after some experimenting I was able to move past this step.
#countries = Array.new
#browser.navigate.to "http://www.testingdomain{$env}.com/global"
#browser.find_elements(:xpath, "//table[#class='global-list']//a").each do |link|
text = link.attribute("text")
href = link.attribute("href")
#countries << [text, href]
end #links
`#countries.uniq! #DEBUG for false CMS content
Looks like you found your answer to your question on your own.
Indeed, element.attribute allows you to pull any HTML attribute a tag could possibly have. Thus, since you were wanting to pull the URL of the element, you used element.attribute('href') to return the element's href="" attribute. The same can be done for any other attributes, including class, id, style, etc.

Resources