Robot framework Selenium: How to disable popup blocking in firefox? - selenium-webdriver

I try to disable popup blocking in Robot Framework for Firefox in different ways: by setting preference dom.disable_beforeunload=False, setting capabilities and profile. It does not work. Pop up confirmation windows are not shown. See Open Firefox browser keyword:
*** Keywords ***
Open Firefox browser
${options}= Evaluate sys.modules['selenium.webdriver'].FirefoxOptions() sys
Call Method ${options} set_preference dom.disable_beforeunload False
Call Method ${options} set_capability unhandledPromptBehavior ignore
Call Method ${options} set_capability unexpectedAlertBehaviour ignore
${profile}= Evaluate sys.modules['selenium.webdriver'].FirefoxProfile() sys
Call Method ${profile} set_preference dom.disable_beforeunload False
${desired_capabilities}= Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.FIREFOX sys
Set To Dictionary ${desired_capabilities} unhandledPromptBehavior ignore
Set To Dictionary ${desired_capabilities} unexpectedAlertBehaviour ignore
Open Browser ${LOGIN_URL} Firefox options=${options} ff_profile_dir=${profile} desired_capabilities=${desired_capabilities}
For Chrome there is no such a problem. Everything works by adding the argument --disable-popup-blocking.
Open Chrome browser
${options}= Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys
Call Method ${options} add_argument --disable-popup-blocking
Call Method ${options} add_argument --ignore-certificate-errors
Open Browser ${LOGIN_URL} Chrome options=${options}

Related

In Selenium webdriver, for remote Firefox how to use OSS bridge instead of w3c bridge for handshaking

I am using selenoid for remote browser testing in ruby.
In that I am using 'selenium-webdriver', 'capybara', 'rspec' for automation. And I am using attach_file method for uploading file to browser
I want to upload file on Firefox and Chrome browser but it raises error on both;
In chrome
Selenium::WebDriver::Error::UnknownCommandError: unknown command: unknown command: session/***8d32e045e3***/se/file
In firefox
unexpected token at 'HTTP method not allowed'
So After searching I found the solution for chrome which is to set w3c option false in caps['goog:chromeOptions'] > caps['goog:chromeOptions'] = {w3c: false}
So now chrome is using OSS bridge for handshaking but I don't know how to do it in Firefox. Similar solution is not available for Firefox.
My browser capabilities are following:
if ENV['BROWSER'] == 'firefox'
caps = Selenium::WebDriver::Remote::Capabilities.new
caps['browserName'] = 'firefox'
# caps['moz:firefoxOptions'] = {w3c: false} ## It is not working
else
caps = Selenium::WebDriver::Remote::Capabilities.new
caps["browserName"] = "chrome"
caps["version"] = "81.0"
caps['goog:chromeOptions'] = {w3c: false}
end
caps["enableVNC"] = true
caps["screenResolution"] = "1280x800"
caps['sessionTimeout'] = '15m'
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, browser: :remote,
:desired_capabilities => caps,
:url => ENV["REMOTE_URL"] || "http://*.*.*.*:4444/wd/hub"
)
end
Capybara.configure do |config|
config.default_driver = :selenium
end
I have found the problem. There is bug in selenium server which run on java so I have to change my selenium-webdriver gem version 3.142.7 and monkey-patch.
You can find more information here about the bug and resolution.
For now I have to change my gem and monkey patch the selenium-webdriver-3.142.7\lib\selenium\webdriver\remote\w3c\commands.rb file. check for below line which is on line no 150.
upload_file: [:post, 'session/:session_id/se/file']
and update it to
upload_file: [:post, 'session/:session_id/file']
i had a similar issue with rails 7. the issue is connected with the w3c standard. the core problem is that the webdriver for chrome uses a non-w3c standard url for handling file uploads. when uploading a file, the webdriver uses the /se/file url path to upload. this path is only supported by the selenium server. subsequently, the docker image provided by selenium works fine. yet, if we use chromedriver, the upload fails. more info.
we can solve this, by forcing the webdriver to use the standard-compliant url by overriding the :upload_file key in Selenium::WebDriver::Remote::Bridge::COMMANDS. since, the initialization of this the COMMANDS constant does not happen when the module is loaded, we can override the attach_file method to make sure the constant is set correctly. here the hacky code:
module Capybara::Node::Actions
alias_method :original_attach_file, :attach_file
def attach_file(*args, **kwargs)
implement_hacky_fix_for_file_uploads_with_chromedriver
original_attach_file(*args, **kwargs)
end
def implement_hacky_fix_for_file_uploads_with_chromedriver
return if #hacky_fix_implemented
original_verbose, $VERBOSE = $VERBOSE, nil # ignore warnings
cmds = Selenium::WebDriver::Remote::Bridge::COMMANDS.dup
cmds[:upload_file] = [:post, "session/:session_id/file"]
Selenium::WebDriver::Remote::Bridge.const_set(:COMMANDS, cmds)
$VERBOSE = original_verbose
#hacky_fix_implemented = true
end
end
In Firefox images we support /session/<id>/file API by adding Selenoid binary which emulates this API instead of Geckodriver (which does not implement it).

AngularJS testing with Protractor- call to click() never seems to be performed

I am developing a suite of tests for an AngularJS application, and have recently added the following test script to my spec.js file:
it('should navigate to the Charts page', function() {
console.log("Start Charts page test ");
browser.waitForAngularEnabled(false);
browser.wait(EC.presenceOf(chartsMenuBtn), 5000).then(
browser.actions().mouseMove(chartsMenuBtn).perform().then(
chartsMenuBtn.click().then(
browser.wait(EC.elementToBeClickable(closeDlgBtn)).then(
function(){
closeDlg();
expect(browser.getCurrentUrl()).toBe(VM + '/#/charts');
}
)
//)
)
)
)
})
Currently, when I run my tests, all of the tests written before this one run & execute correctly, then when this test is run, I get the following output in the command line where I'm running protractor conf.js:
...Alarms page test completed
.Start Charts page test
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
Start final Browser page test
Browser menu button clicked
End Browser page test (then call)
.
Failures:
1) App should navigate to the Charts page
Message:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
Stack:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at ontimeout (timers.js:386:11)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
Message:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
Stack:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
at ontimeout (timers.js:386:11)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
6 specs, 1 failure
Finished in 64.989 seconds
In the browser window that is opened by the script (the window where the tests are being run), I can see that the chartsMenuBtn element is highlighted (i.e. when the test moves the cursor to it), but at that point, the script appears to freeze, and the call to chartsMenuBtn.click() never appears to be run...
If I add a call to browser.pause() into my script, so that I manually have to tell the script to continue at every executable line, then the script behaves exactly as I expect, and everything passes.
But when I remove the call to browser.pause(), and watch the script run through on its own, it always gets stuck at the same point.
It's clear that the line:
browser.actions().mouseMove(chartsMenuBtn).perform().then(
is executed, because I can see that the chartsMenuBtn element is highlighted in the browser. But for some reason, the script never then seems to execute the line:
chartsMenuBtn.click().then(
If it did, I would expect the browser to navigate to the Charts page (as it does if I manually click on the chartsMenuBtn element.
The DEFAULT_TIMEOUT_INTERVAL is set to 35 seconds in jasmine.js with:
j$.DEFAULT_TIMEOUT_INTERVAL = 35000;
I tried increasing its value, but that didn't make a difference- the test still timed out in the same place, for the same reason, which would indicate to me that there is another reason that this test is failing/ timing out.
Does anyone have any suggestions how I can fix this?
Edit
So I changed my script to add some debug to the test (print statements before and after the call to chartsMenuBtn.click().then(, to see whether or not this line was actually being run, and when I run my test now, I can see both of those print statements displayed in the command line:
Started
...Alarms page test completed
.Start Charts page test
Cursor hovering over chartsMenuBtn
Call to chartsMenuBtn.click() performed
FA Jasmine spec timed out. Resetting the WebDriver Control Flow.
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
Start final Tag Browser page test
Tag Browser menu button clicked
End Tag Browser page test (then call)
.
The two debug lines I added were:
Cursor hovering over chartsMenuBtn
Call to chartsMenuBtn.click() performed
I added these debug lines either side of the call to:
chartsMenuBtn.click().then(
so it's clear that this line is being run, yet for some reason, the click either doesn't seem to be registering, or the result of a click on this element is not actually performing the required & expected action.
Any suggestions for why this is?
Edit
So I've managed to make a bit of progress with this, although it's still not working as I intended/ hoped... I've altered the test script slightly by putting the call to chartsMenuBtn.click() inside a browser.actions() call, chaining multiple promises together:
it('should navigate to the Charts page', function() {
console.log("Start Charts page test ");
browser.waitForAngularEnabled(false);
browser.wait(EC.presenceOf(chartsMenuBtn), 5000).then(
browser.actions().mouseMove(chartsMenuBtn).perform().then(
browser.actions(console.log("Cursor hovering over chartsMenuBtn ")).perform().then(
browser.actions(chartsMenuBtn.click()).perform().then(
browser.actions(console.log("Call to chartsMenuBtn.click() performed ")).perform().then(
function(){
expect(EC.visibilityOf(closeDlgBtn).call()).toBeTruthy();
}
)
)
)
)
)
})
When I now run my script again, I just get a single failure- which seems to be caused by the timing associated with animation that has been set on one of the dialogs opened during the course of one of the tests to run prior to this test.
The error states:
Failed: unknown error: Element ... is not clickable at point (40, 229). Other element would receive the click:
<div tabindex="-1" role="dialog" class="modal fade ng-isolate-scope ult-loading modal-message ng-animate in-remove in-remove-active" ng-class="{in: animate}" ng-style="{'z-index': 1050 + index*10, display: 'block'}" ng-click="close($event)" modal-window="" window-class="ult-loading modal-message" size="sm" index="0" animate="animate" style="z-index: 1050; display: block;; transition-property: opacity;transition-duration: 0.15s;">...</div>
(Session info: chrome=62.0.3202.89)
(Driver info: chromedriver=2.33.506120 (e3e53437346286c0bc2d2dc9aa4915ba81d9023f),platform=Windows NT 10.0.16299 x86_64)
I tried putting the expect clause of my test inside a browser.wait() that would wait for the closeDlgBtn element to be present before running (but given that my expectation is that the button element is visible, this seems a bit redundant...):
function(){
browser.wait(EC.presenceOf(closeDlgBtn), 5000).then(
expect(EC.visibilityOf(closeDlgBtn).call()).toBeTruthy();
)
}
but this gives me a syntax error stating that there's a missing ) on the line:
expect(EC.visibilityOf(closeDlgBtn).call()).toBeTruthy();
I can't see a missing ) anywhere on that line. Can anyone spot what I'm doing wrong here?
Edit
I also tried surrounding the call to browser.actions(chartsMenuBtn.click()).perform().then( with a call to browser.wait(EC.elementToBeClickable()), so that it would wait for the element to be clickable before clicking on it (instead of just waiting for it to be present):
browser.wait(EC.elementToBeClickable(chartsMenuBtn), 5000).then(
browser.actions(chartsMenuBtn.click()).perform().then(
browser.actions(console.log("Call to chartsMenuBtn.click() performed ")).perform().then(
function(){
expect(EC.visibilityOf(closeDlgBtn).call()).toBeTruthy();
}
)
)
)
But for some reason, I still get the same error:
Failed: unknown error: Element ... is not clickable at point (40, 229). Other element would receive the click:
which doesn't make sense- since it should be waiting for the element to be clickable before clicking on it...?
Edit
So, I had a look at actions on the Protract API, and it appears I have been chaining the promises incorrectly. I changed the test script to:
it('should navigate to the Charts page', function() {
console.log("Start Charts page test ");
browser.waitForAngularEnabled(false);
browser.wait(EC.elementToBeClickable(chartsMenuBtn), 5000).then(
browser.actions().
mouseMove(chartsMenuBtn).
//console.log("Cursor hovering over chartsMenuBtn").
chartsMenuBtn.click().
//console.log("Call to chartsMenuBtn.click() performed").
browser.wait(EC.urlIs(VM + '/#/charts'), 5000).
//console.log("browser.wait called- URL should now be VM + /#/charts/ ").
perform()
);
})
and this seems to have resolved the 'element not clickable' issue. However, I now get another error that says:
Failed: Cannot read property 'click' of undefined
but chartsMenuBtn has been defined with:
var chartsMenuBtn = element(by.linkText("Charts"));
Anyone have any suggestions?

browser.get(URL) does not work

I am having an issue with entering text into the address bar nothing happens and I get the error
selenium.common.exceptions.WebDriverException: Message: Can't load the
profile. Profile Dir:
/var/folders/8_/f48lnzrs7r59_h2yb3dkfbh40000gn/T/tmpsGffLD If you
specified a log_file in the FirefoxBinary constructor, check it for
details.
I am able to open the browser but when I uncomment the code browser.get('http://www.google.com') nothing happens and I get the error listed above. I am using Firefox 48, Python 2.7.10 and selenium-2.53.6-py2.7.egg
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('http://www.google.com')
Change that line to
browser.url('http://www.google.com')
OR
browser.open('http://www.google.com')

Non-interactive auto-refresh stale OAuth Token with Googlesheets package

I'm trying to automatically run an r script to download a private Google Sheet every hour. It always works fine when I'm interactively using R. It also works fine during the first hour after I automate the script with launchd.
It stops working an hour after I start automating it with launchd. I think the problem is that after one hour the access token changes, and the non-interactive version isn’t waiting for the auto refreshing of the OAuth token. Here is the error that I get from the error report:
Auto-refreshing stale OAuth token.
Error in gzfile(file, mode) : cannot open the connection
Calls: gs_auth ... -> -> cache_token -> saveRDS -> gzfile
In addition: Warning message:
In gzfile(file, mode) :
cannot open compressed file '.httr-oauth', probable reason 'Permission denied'
Execution halted
I'm using Jenny Bryan's googlesheets package. Here is the code that I initially use to register the sheet, and then save the oAuth token:
gToken <- gs_auth() # Run this the first time to get the oAuth information
saveRDS(gToken, "/Users/…/gToken.rds") # Save the oAuth information for non-interactive use
I then use the following script in the file that I automate with launchd:
gs_auth(token = "/Users/…/gToken.rds")
How can I avoid this error when running the script automatically with launchd?
I don't know about launchd but I had the same problem when I wanted to run a R script automatically from the Windows task planer. Changing the 'cache' attribute value to FALSE did the trick for me [1]: https://i.stack.imgur.com/pprlC.png
You can find the solution here: https://github.com/jennybc/googlesheets/issues/262
To authenticate once in the browser in order to get a token file, I did this:
token_file <- gs_auth(new_user = TRUE, cache = FALSE)
saveRDS(token_file, "googlesheets_token.rds")
Automatic login afterwards via:
gs_auth(token = paste0(path_scripts, "googlesheets_token.rds"),
verbose = TRUE, cache = FALSE)

Change Browser Capabilities through Robot Framework

I do not have privileges to change IE settings locally. I wrote a Java Code to change the capabilities of IEDriver using :
DesiredCapabilities caps = DesiredCapabilities.internetExplorer(); caps.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
caps.setCapability(
InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS,
true);
I want to do the same thing while using the selenium webdriver in Robot Framework. I want to do something like this. But I do not know the right way to do it.
*** Keywords ***
Test Browser
${options}= Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.INTERNETEXPLORER sys,selenium.webdriver
Call Method ${options} add_argument INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS:True
Create WebDriver Internet Explorer ie_options=${options}
Open Browser To Login Page
Open Browser ${LOGIN URL} ${BROWSER}
Maximize Browser Window
Set Selenium Speed ${DELAY}
Login Page Should Be Open
Thanks a lot!
In the Selenium documentation for DesiredCapabilities, the configurable properties are listed. The required property is ignoreProtectedModeSettings which must be set to True
${dc} Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.INTERNETEXPLORER sys, selenium.webdriver
Set To Dictionary ${dc} ignoreProtectedModeSettings ${True}
Open Browser www.google.com ie desired_capabilitie=${dc}
${s2l}= Get Library Instance Selenium2Library
Log Dictionary ${s2l._current_browser().capabilities} # actual capabilities
For anyone that came here looking for a solution to this problem within Robot Framewor:
Set Chrome Desired Capabilities
[Documentation] Create the desired capabilities object with which to instantiate the Chrome browser.
${dc} Evaluate sys.modules['selenium.webdriver'].DesiredCapabilities.CHROME sys, selenium.webdriver
${experimental_options} Create Dictionary useAutomationExtension ${False}
Set To Dictionary ${dc} chromeOptions ${experimental_options}
Set Global Variable ${DESIRED_CAPABILITIES} ${dc}
As Pavol Travnik mentioned, David's answer no longer works. At some point the ignoreProtectedModeSettings key got placed inside the se:ieOptions dictionary within the capabilities dictionary. Here is code that will work with newer versions of the IEDriverServer:
${ie_dc} = Evaluate
... sys.modules['selenium.webdriver'].DesiredCapabilities.INTERNETEXPLORER
... sys, selenium.webdriver
${ieOptions} = Create Dictionary ignoreProtectedModeSettings=${True}
Set To Dictionary ${ie_dc} se:ieOptions ${ieOptions}
Open Browser ${url} ie desired_capabilities=${ie_dc}
You can see this if you debug Selenium's Python library, specifically webdriver/remote/webdriver.py and look at the response in start_session.

Resources