Ruby-Watir Warning - Selenium::WebDriver::Error::ObsoleteElementError - ruby

Hey y'all I'm getting a warning running my watir test automation code and even though it works I want to address it.
The Warning: 2020-02-12 08:35:47 WARN Selenium [DEPRECATION]
Selenium::WebDriver::Error::ObsoleteElementError is deprecated. Use
Selenium::WebDriver::Error::StaleElementReferenceError (ensure the
driver supports W3C WebDriver specification) instead.
The offending line of code:
iframe.select(:id => 'col0').wait_until(&:present?)
from this larger snippet.
iframe = #b.iframe(:title => /Mass Delete/)
iframe.wait_until(&:present?)
if iframe.present?
iframe.link(:visible_text => /Mass Delete #{type}/).click
iframe.select(:id => 'col0').wait_until(&:present?)
iframe.option(:text => /Owner Alias/).select
iframe.option(:text => 'equals').select
iframe.text_field(:id => "fval0").set user
iframe.button(:title => "Search").click
else
raise "Unable to locate the Salesforce Iframe"
end
Here's the page html:
Page Html
I've tried using different locators to interact with that element but to no avail.

This will be addressed in the next version of Watir - exact release date is TBD. In the short-term, you have a couple of options to hide the warning.
Log to File
I would suggest sending the Selenium logs to a file. This keeps it separated and still available if you happen to need it.
Selenium::WebDriver.logger.output = 'selenium.log'
Ignore Warnings
Usually you do not need the Selenium warnings as they should get addressed by Watir changes. Therefore you could change the Selenium logger to ignore warnings:
Selenium::WebDriver.logger.level = :error

Related

Log Javascript console output in Laravel Dusk

I am using Laravel 5.6 and Laravel Dusk 3.0.9.
Dusk is pretty handy, but when a test fails on a page where there is some Javascript functionality it can be pretty hard to work out what went wrong. Dusk generates a screenshot, which helps, but what I really need is to see the output from the Javascript console.
Apparently this is possible - Dusk creates a tests/Browser/console directory as part of its installation, and this PR suggests the JS console output is logged, or at least loggable.
There is no documentation (that I can find) about how to actually do that though. Browsing the diffs in that PR, I see a new method logConsole() (later renamed to storeConsoleLog() as #Jonas pointed out in the comments), but I can't seem to get it to do anything, eg:
$browser->visit('/somewhere')
->select('#foo', '2')
->value('#date', '2018-07-29')
->storeConsoleLog('bar')
->assertEnabled('button[type=submit]');
This test fails, and generates a nice screenshot, but there is no sign of any logfile. I've tried moving the position of ->storeConsoleLog('bar') around in the chain, eg first or last, and as a separate line before or after the chain:
$browser->visit('/somewhere')
->...full chain here;
$browser->storeConsoleLog('bar');
But none of them make any difference. My JS has a series of console.log()s which I use when testing myself in a browser, and which will tell me exactly what went wrong. I was expecting this functionality to log those messages.
Am I misunderstanding that PR, is this even possible? If so, how?
UPDATE
By debugging the storeConsoleLog() method in vendor/laravel/dusk/src/Browser.php I can see that the method is being called correctly, but there is no console content to log. If I manually repeat the steps the test is taking in Chrome, there are lines being written to Chrome devtools console, in fact 3 are written on page load. Why can't Dusk see those?
UPDATE 2
I found that if you remove '--headless' from the driver() method in DuskTestCase, the browser will be displayed during tests. You can then display the dev tools for that browser, and watch the console output live as the tests run. It is too fast to really be useful, and if there is an error the browser closes and you lose whatever was on the console anyway (unless there's a way to leave the browser open on failure?), but adding this here in case it is useful to someone!
There is apparently no way to get non-error console output from the browser.
There are other log types, but Chrome only supports browser (used by Dusk) and driver.
You'll probably have to use alerts. But screenshots don't contain alerts, so you have to get the text:
$browser->driver->switchTo()->alert()->getText()
You could also use something like document.write() and check the output on the screenshot.
It is possible. There's an answer here written in Python from 2014 that shows it's been possible since at least that long.
Override \Laravel\Dusk\TestCase::driver:
protected function driver()
{
$desired_capabilities = new DesiredCapabilities([
'browserName' => 'chrome',
'platform' => 'ANY',
]);
// the proper capability to set to get ALL logs stored
$desired_capabilities->setCapability('loggingPrefs', [
'browser' => 'ALL',
'driver' => 'ALL',
]);
// return the driver
return RemoteWebDriver::create(
'http://localhost:9515',
$desired_capabilities
);
}

Unable to generate results with allure / ruby cucumber

I have been working on a new auto framework in ruby, but I am unable to get allure reporting results created, I have tried various different things but ultimately end up with the following errors:
DevTools listening on ws://127.0.0.1:12177/devtools/browser/498a65da-7ba2-4387-8243-8d0e5be0424e
WARNING: The formatter AllureCucumber::Formatter is using the deprecated formatter API which will be removed in v4.0 of Cucumber.
undefined method 'name' for #<Cucumber::Core::Test::Step:0x00000000059673a0> (No MethodError)
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/allure-cucumber-0.5.8/lib/allure-cucumber/formatter.rb:121:in 'after_test_step'
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/cucumber-3.1.0/lib/cucumber/formatter/ignore_missing_messages.rb:11:in 'method_missing'
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/cucumber-3.1.0/lib/cucumber/formatter/legacy_api/adapter.rb:32:in 'block in initialize'
I have followed the documentation and have good experience using the reporting with java, is it likely my version of cucumber is unsupported? At best I can get an empty results directory created but the cucumber tests always error out with the above message.
This post is 8 months old so hopefully you got it worked out, but incase anyone else lands here, you can patch the cucumber-ruby gem with the following to get your tests to pass:
class Cucumber::Core::Test::Step
def name
return text if self.text == 'Before hook'
return text if self.text == 'After hook'
"#{source.last.keyword}#{text}"
end
end
The warning about API depreciation past 4.0 will remain, though. Hopefully it will be fixed before then: https://github.com/allure-framework/allure-cucumber/issues/63

Selenium can't find fields with type number

I'm having a problem getting Cucumber to find fields with the HTML5 type="number". I'm not a big fan of the way they look in the browser, but I have a few fields that need the number keyboard on mobile, and this seems to be the easiest way to get it. I'm using SimpleForm to build forms and when I set :as => :text everything works, but if I set :as => :number, the fields don't get filled out. I don't get any error, the field just doesn't get filled.
To be specific, when I have a step like this:
And I fill in "application_form_age" with "52"
then this tag won't get filled in:
<input class=​"numeric integer required" id=​"application_form_age" min=​"0" name=​"application_form[age]​" size=​"50" step=​"1" type=​"number">​
but this one works:
<input class=​"string required" id=​"application_form_age" name=​"application_form[age]​" size=​"50" type=​"text">​
Also, it only happens in #javascript scenarios. In situations where #javascript isn't necessary and the scenario doesn't launch a browser, that works fine too.
Versions of things:
capybara (2.2.1)
cucumber (1.3.14)
selenium-webdriver (2.41.0)
simple_form (2.1.1)
webrat (0.7.3)
Firefox 29.0
I'm stumped. I tried yanking out a bunch of my application JS and CSS to see if something I'm doing is breaking it, but no luck with that. I'm just patching it out by forcing those fields not to have HTML5 type number in my test environment, but I don't want to live like that. Is anyone else seeing this? I haven't been able to find any references to it, which makes it seem like it's something I'm doing. But I haven't been able to figure it out.
Ok, I have found firefox has an option to disable number input field support: 'dom.forms.number'.
So if you add the following lines in your env.rb, number input gets disabled and tests work again.
Capybara.register_driver :selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile["dom.forms.number"] = false
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end
First off, I think you have some confusion regarding those frameworks. Cucumber is a BDD framework, which doesn't automate browsers in any way, so this question has nothing to do with it (This is why I removed it from your question title).
Looks like you are using Capybara, which is an ATDD framework. You might probably consider showing us the Capybara code you use in order diagnose your problem.
Under the hood, I assume you use Selenium WebDriver, I can confirm that Selenium works fine with <input type="number"> (Tested with Firefox 28, which is the one selenium-webdriver (2.41.0) supports to).
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
DEMO_PAGE = <<-eos
data:text/html,
<input class=​"numeric integer required" id=​"application_form_age" min=​"0" name=​"application_form[age]​" size=​"50" step=​"1" type=​"number">
eos
driver.get(DEMO_PAGE)
driver.find_element(:tag_name, 'input').send_keys('25')
So you might want to create a similar demo using Capybara to test this functionality.
If the demo works, then we need take a closer look at your application.
Othwewise, please raise a ticket for Capybara developers.

Using Cucumber and Ruby to Download File

I've written some Ruby code (connected with Cucumber) that will go to a website and click a file that I'd like to download. The browser I'm using for this is Google Chrome.
Typically, when you go to download a file in Chrome, it doesn't ask for permission. However, when I run the code I made, it says:
"This type of file can harm your computer. Do you want to keep file_name.exe anyway?" It gives 2 options, "keep" or "discard". I have to click keep.
Obviously, you don't want all executables to just start downloading; however, this particular website/file should always be trustworthy.
Is there a command in Ruby or Cucumber that allows you to click the "keep" button automatically? This could just be a general "click at this pixel" or something. Or is there a way to mark a particular website in Chrome as safe. You can't inspect the element because it's not part of the website, but, instead, part of the browser. Preferably without having to download other software.
With this being said, this suggests that if it is possible, it should also be possible to automate an installation (as in clicking next -> next -> etc) for you. Hopefully this is correct?
Thanks in advance.
You can implement it in any browser. But, for Google Chrome, here is the solution -
profile = Selenium::WebDriver::Chrome::Profile.new
profile['download.prompt_for_download'] = false
profile['download.default_directory'] = "Absolute or relative path to your download directory"
browser = Selenium::WebDriver.for :chrome, :profile => profile
You haven't specified which gem you use for browser. But, even if you use watir-webdriver, you can use the same profile you created above with watir-webdriver.
browser = Watir::Browser.new :chrome, :profile => profile
I actually switched to using Sikuli, which worked pretty well. Thanks for the help, though.
Do you really need or want the browser to download the file? Are you really testing the browser's download feature, or do you want to verify that the server can serve the file and that it is what you expect?
I found the idea of setting up a default directory and having to check for the file clumsy, fragile and prone to errors, especially when setting up on a new host, especially for tests that run in multiple browsers.
My solution is to just use Ruby (or whatever language) features to download the file directly, and then validate that it is the file it's supposed to be. I'm not testing the browser, I'm testing the software. The only exception to that idea I can think of is if you use some javascript logic or something browser-dependent to redirect you to a link, but please don't ever do that.
However, you run into a problem if you have to log in to access your file; you either have to implement auth in your Ruby code, which isn't technically part of your Cucumber specification, or you need the cookies. I use this code to copy the cookies to avoid logging in again, and grab the file:
def assert_file_link(uri, filename, content_type)
f = open_uri_with_cookies uri
attachment_filename = f.meta["content-disposition"].sub("Attachment;filename=", "") # "Attachment;filename=Simple Flow - Simple Form.rtf"
content_length = Integer(f.meta["content-length"])
assert(f.status == ["200", "OK"], "Response was not 200 OK")
assert(f.content_type == content_type, "Expected content-type of '#{content_type}' but was '#{f.content_type}'")
assert(attachment_filename == filename, "Expected filename of '#{filename}' but was '#{attachment_filename}'")
assert(content_length > 0, "Expected content-length > 0 but was '#{content_length}'")
end
def open_uri_with_cookies(uri)
# hack the cookies from the existing session so we don't need to log in!
cookies = ""
#driver.manage.all_cookies.each { |cookie| cookies.concat("#{cookie[:name]}=#{cookie[:value]}; ") }
if block_given?
open(uri, "Cookie" => cookies, :proxy => nil) do |f|
yield f
end
else
open(uri, "Cookie" => cookies, :proxy => nil)
end
end
Hope this helps.

how to remove the log of ie web driver?

I am using watir-webdriver + ruby + win7 to test same pages. and I would get these logs while I start the ie explorer by using watir-webdriver:
Started InternetExplorerDriver server (32-bit)
2.32.3.0
Listening on port 5555
are there any methods to remove these logs? any help would be appreciated!
IEDriver supports a --silent flag that suppresses diagnostic output when the server is started.
Unfortunately, at least to my knowledge, it is not configurable when creating a browser instance. Instead, you need to directly modify the Selenium::Webdriver::IE::Server class' server_args method. You can modify the lib\selenium\webdriver\ie\server.rb file directly, but it is probably easier to monkey patch.
To monkey patch the silent flag, add the following to your code some point after requiring watir-webdriver (ie selenium-webdriver) but before opening the browser.
class Selenium::WebDriver::IE::Server
old_server_args = instance_method(:server_args)
define_method(:server_args) do
old_server_args.bind(self).() << "--silent"
end
end
For example, the following will no longer log any messages.
require 'watir-webdriver'
class Selenium::WebDriver::IE::Server
old_server_args = instance_method(:server_args)
define_method(:server_args) do
old_server_args.bind(self).() << "--silent"
end
end
b = Watir::Browser.new :ie

Resources