Watir can't locate frame which houses an element in Firefox but works fine in IE - ruby

I have a script:
BROWSER.frame( :name, 'FRAME_NAVIGATION' ).span(:text=>'foo').fire_event('onmouseup')
which clicks on elements of a tree view (inside a frame) which works great in IE, but when I set:
require 'watir'
Watir::Browser.default = 'firefox'
and run it I get:
Failure/Error:
BROWSER.frame( :name, 'FRAME_NAVIGATION').span(:text=>'foo').fire_event('onmouseup')
Watir::Exception::UnknownFrameException:
Unable to locate a frame using name and FRAME_NAVIGATION.
I get this with any elements inside a frame on my page. Not just the tree view. I've tried requiring firewatir as well, or just on its own with no luck.
Any insight would be greatly appreciated!
Thanks,
-M

You're not using the frame method correctly. Try this way:
BROWSER.frame(:name => 'FRAME_NAVIGATION').span(:text => 'foo').fire_event('onmouseup')

You may be able to diagnose the problem by adding a BROWSER.show_frames call. That would tell you what Firefox thinks it can see.

Related

WATIR: Is there a reason why browser scrolling won't work?

I'm trying to use browser.scroll.to :bottom but nothing happens.
I know that it works because I've tried it on public facing sites such as the BBC and Wikipedia, but for some reason, these scroll commands don't work on our in-house browser based app.
Does anyone know of any reasons or settings that could be preventing this from happening?
Things such as browser.refresh and browser.window.maximize work fine but the scrolling literally refuses to budge.
Here's what my code looks like:
require 'watir'
require_relative 'regression_config_bob01.rb'
require 'date'
require 'faker'
require 'slack-notifier'
require 'watir-scroll'
user_name = "blah"
password = "blah"
test_env = "the Site"
browser = Watir::Browser.new
browser.goto(test_env)
# Login
browser.text_field(:name => 'P101_USERNAME').set user_name
browser.text_field(:tabindex=> '2').set password
browser.link(:text => "Log in").click
sleep 20
browser.wd.action.scroll_by(0, 1000).perform # Suggested Scroll line
print "done"
sleep 30
temporary_exp.rb:62:in <main>': undefined method scroll_by' for #<Selenium::WebDriver::W3CActionBuilder:0x000000014ac54bd0 #bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 #capabilities=#<Selenium::WebDriver::Remote::W3C::Capabilities:0x000000014ac1e940 #capabilities={:proxy=>nil, :browser_name=>"chrome", :browser_version=>"106.0.5249.119", :platform_name=>"mac os x", :accept_insecure_certs=>false, :page_load_strategy=>"normal", :implicit_timeout=>0, :page_load_timeout=>300000, :script_timeout=>30000, :remote_session_id=>nil, :accessibility_checks=>nil, :profile=>nil, :rotatable=>nil, :device=>nil, "chrome"=>{"chromedriverVersion"=>"105.0.5195.52 (412c95e518836d8a7d97250d62b29c2ae6a26a85-refs/branch-heads/5195#{#853})", "userDataDir"=>"/var/folders/hb/h_0h2t79183fkkppsr6r19nc0000gn/T/.com.google.Chrome.BV85VD"}, "goog:chromeOptions"=>{"debuggerAddress"=>"localhost:50818"}, "networkConnectionEnabled"=>false, "setWindowRect"=>true, "strictFileInteractability"=>false, "unhandledPromptBehavior"=>"dismiss and notify", "webauthn:extension:credBlob"=>true, "webauthn:extension:largeBlob"=>true, "webauthn:virtualAuthenticators"=>true}>, #session_id="8c59128dd44054681f62819d2fed25cf", #http=#<Watir::HttpClient:0x000000014ab6e298 #open_timeout=60, #read_timeout=nil, #server_url=#<URI::HTTP http://127.0.0.1:9515/>, #proxy=nil, #http=#<Net::HTTP 127.0.0.1:9515 open=true>>, #file_detector=nil, #escaper=#URI::RFC2396_Parser:0x000000014b0cbbc8, #manage=#<Selenium::WebDriver::W3CManager:0x000000014ab640b8 #bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 ...>, #window=#<Selenium::WebDriver::Window:0x000000014aa17ca0 #bridge=#<Selenium::WebDriver::Remote::W3C::Bridge:0x000000014ac1e440 ...>>>>, #devices=[#<Selenium::WebDriver::Interactions::PointerInput:0x000000014ac54f40 #name="mouse", #actions=[], #kind=:mouse>, #<Selenium::WebDriver::Interactions::KeyInput:0x000000014ac54d38 #name="keyboard", #actions=[]>], #async=false> (NoMethodError)
The current scroll implementation is using javascript to move the page around. For some reason your app is not responding to the JS commands in the normal way.
Selenium has recently released native scrolling via the drivers that Watir has not yet been updated. Take a look at the Selenium documentation on it: https://www.selenium.dev/documentation/webdriver/actions_api/wheel/?language=ruby
To use this in watir, you just need to add the line to the top: driver = browser.wd
So to scroll down by 2000 pixels, you can do:
driver = browser.wd
driver.action
.scroll_by(0, 2000)
.perform
like Titus said, Watir is a wrapper for Selenium and lets you write shorter and prettier code, like
browser.scroll.to :bottom
browser.scroll.to :top
browser.element(id: "asd").scroll.to
but when (for any reason) it doesn't work you can use Selenium syntax directly by sending commands to browser.wd instead browser like this:
browser.wd.action.scroll_by(0, 1000).perform #this scrolls bottom
browser.wd.action.scroll_by(0, -1000).perform #this scrolls top
browser.wd.action.scroll_to(browser.wd.find_element(id: "asd")).perform
but instead of writing browser.wd every time you need to talk to driver directly, you can type driver = browser.wd so your code is more clear:
driver = browser.wd
driver.action.scroll_by(0, 1000).perform #this scrolls bottom
driver.action.scroll_by(0, -1000).perform #this scrolls top
some_element = driver.find_element(id: "asd")
driver.action.scroll_to(some_element).perform
There are countless examples where using Watir is more efficient than talking to driver directly, you just happened to encounter an edge case.
Also try avoiding sleep when possible, instead, wait for something to show, like:
browser.element(id: 'asd').wait_until(&:present?)
browser.element(id: 'asd').wait_until({ |el| el.text == "Success" })
some_element = browser.element(id: 'asd')
browser.wait_until(30){some_element.present?}
Instead of .element you can use correct subclass like .div, .button, .span etc

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)

Capybara Unable To Find Input Field

I am using the Ruby gem Capybara for automation purposes (having read the instructions on this website). I have a simple script that shows the problem I am having:
require 'capybara'
session = Capybara::Session.new(:selenium)
session.visit 'https://service.ringcentral.com/'
session.fill_in 'LoginName', with: '555-555-5555'
I have tried many different suggestions here on SO, and from other websites, with no success. I think this simply has something to do with the RingCentral website itself, because I do not have as much issue with other websites (such as google.com).
Since the login field is invisible (opacity: 0 to allow the emptyText to show through from below) Capybara won't find it by default. You can pass visible: false to fill_in to find non-visible elements, and in this case that will then trigger focus on the element, which will trigger it to change to opacity: 1 and proceed to fill in the data.
require 'capybara'
session = Capybara::Session.new(:selenium)
session.visit 'https://service.ringcentral.com/'
session.fill_in 'login-form-username-field-LoginName', visible: false, with: '555-555-5555'
I found the solution here! Capybara by default ignores hidden elements. I wanted to post my answer because the other solution was so hard to find because I didn't know that the field I was trying to fill in was a hidden element, so I do not consider this post a duplicate. If you are having a difficult time getting Capybara to find and fill in fields, try setting the ignore_hidden_elements option to false, even if your field is completely visible.
require 'capybara'
session = Capybara::Session.new(:selenium)
Capybara.ignore_hidden_elements = false
session.visit 'https://service.ringcentral.com/'
session.fill_in 'login-form-username-field-LoginName', with: '555-555-5555'

Save image with watir-webdriver

How could i save image, which is loaded via watir-webdriver? All manuals and examples show only fetching src of image, and using open-uri saving it. But i need to save that image, which was generated when my page was loaded. How can i do this?
Could i use watir, and watir-webdriver at the same time? For example:
require 'watir-webdriver'
require 'watir'
#driver = Watir::Browser.new :firefox
#driver.goto (#base_url)
#img = #driver.image(id: 'CaptchaImage').save("2131.png")
How can i do something like this? Or else how to get it from cache?
Could anybody help me with it?
OpenURI will help you ..
require "watir-webdriver"
require "open-uri"
b = Watir::Browser.new :chrome
b.goto "http://stackoverflow.com/"
File.open("target_file.jpg", 'wb') do |f|
f.write open(b.img(:class, "sponsor-tag-img").src).read
end
Hope you are not doing anything bad.. :)
Please let me know if it helped.
require 'watir-webdriver'
And if you're doing it frequently, you can extend Watir's Image class with:
Watir::Image.class_eval do
def save path_to_new_file
#so that src can be opened without raising:
#Errno::ENOENT: No such file or directory # rb_sysopen
require 'open-uri'
open(path_to_new_file, 'wb') do |file|
file << open(src).read
end
end
end
so it can be used as follows:
browser = Watir::Browser.start 'google.com'
image = browser.img
image.save 'our_images/hi.png'
According to the watir-webdriver documentation, there is no Image#save method because it hasn't been implemented.
On the other hand, watir-classic does have a Image#save method. This is the example from the rdoc:
browser.image.save("c:/foo/bar.jpg")
This turned out to be a lil harder than it should be, but I needed to accomplish this since an image was only accessible when a valid session cookie is set. This is how I finally managed to accomplish this:
1. Install watir-extentions-element-screenshot
https://github.com/ansoni/watir-extensions-element-screenshot
You probably want to do gem install watir-extensions-element-screenshot.
2. Resize the browser window
This also works with headless phantomJS. After you initialize the browser, set the window size to something rather big to prevent a bug from happening when the image is larger than the browser window.
browser = Watir::Browser.new :phantomjs
browser.window.resize_to(1900, 1080)
3. Get the image element and screenshot it
In my case, the entire site is an image. Luckily, browser.html does show that the image is still encapsulated in an <img> tag, so we can access the image (in this example all images on the page) like so:
browser.elements( :tag_name => "img" ).each do |x|
x.screenshot("file_name.png")
end
This will save the image to file_name.png. It's not the exact same file, rather a screenshot of it. But as far as image download is concerned, this is a perfect solution for me and hopefully for others too!

Element is not clickable at point (617, 690.5). Other element would receive the click: <th>...</th> (Selenium::WebDriver::Error::UnknownError)

I get the error above when trying to press the "add" button on the integration test I am trying to implement. I thought that was a delay with the javascript, and I tried the following, but none of them worked:
Then /^I should click "([^"]*)"$/ do |selector|
# if page.should have_selector(selector)
# find(selector).click
# end
# page.execute_script("$(#{selector}).click()")
find(selector).click
end
I tried all of the above, but that didn't solve the problem.
This is hardly a great answer, but I'll give it anyway...
I've only ever seen this problem when testing with Chrome. There are two solutions that worked for me:
Use Firefox instead of Chrome
Instead of find(selector).click, use page.execute_script("$(#{selector}).click()")
But since you've tried the second option and it didn't work, try using Firefox instead. Sorry :(
I found resizing the browser window made a similar problem go away:
Given(/^I open a new browser window$/) do
Capybara.current_session.current_window.resize_to(1000, 1000)
end
I was getting the same error in Capybara when trying to click_button a 'Save' button at the end of a page. Scrolling and bringing the element to view using JS proved to be an effective workaround.
def scroll_to(element)
script = <<-JS
arguments[0].scrollIntoView(true);
JS
Capybara.current_session.driver.browser.execute_script(script, element.native)
element # return the element
end
scroll_to(
find(:xpath, '//button[text()=\'Save\']')
).click
Update
For me, it turned out to be a mismatch between the version of installed Chrome and Chromedriver and no code change was necessary after all.
Chrome 61+ includes modifications to scrolling behaviors. A quick examination of Chromedriver page revealed that I had to upgrade my Chromedriver (from 2.29 to 2.32) in order to make the driver compatible with those changes. This was part of the Chromedriver 2.30 (Supports Chrome v59-61) release notes:
Fixes a bug where Chromedriver fails to click due to page scrolling changes in Chrome 61+.
I had a sticky header that was preventing Selenium from sending the click to the right radio button on both Chrome and Firefox (though Poltergeist worked fine). This is a hack to delete all fixed elements (like sticky headers), and it worked for me:
def kill_sticky_headers
# https://alisdair.mcdiarmid.org/kill-sticky-headers/
script = <<-EOS
(function () {
var i, elements = document.querySelectorAll('body *');
for (i = 0; i < elements.length; i++) {
if (getComputedStyle(elements[i]).position === 'fixed') {
elements[i].parentNode.removeChild(elements[i]);
}
}
})();
EOS
page.execute_script script
end
I was facing a similar problem where I have to check two check boxes one after the other. But I was getting the same above error, hence I added a wait in between my steps for checking the checkboxes. It's working fine and great.
Here are the steps:-
When I visit /administrator/user_profiles
And I press xpath link "//*[#id='1']"
Then I should see "Please wait for a moment..."
When I wait for 5 seconds
And I press xpath link "//*[#id='2']"
Then I should see "Please wait for a moment..."
When I visit /administrator/user_profiles_updates

Resources