I am using Selenium 2.43.0 with Python 2.7.5. At one point, the test clicks on a button which sends form information to the server. If the request is successful, the server responds with
1) A successful message
2) A PDF with the form information merged in
I don't care to test the PDF, my test is just looking for a successful message. However the PDF is part of the package response from the server that I, as the tester, cannot change.
Until recently, this was never an issue using Chromedriver, since Chrome would automatically download pdfs into its default folder.
However, a few days ago one of my test environments started popping a separate window with a "Print" screen for the pdf, which derails my tests.
I don't want or need this dialog. How do I suppress this dialog programmatically using chromedriver's options? (Something equivalent to FireFox's pdfjs.disable option in about:config).
Here is my current attempt to bypass the dialog, which does not work (by "not work" does not disable or suppress the print pdf dialog window):
dc = DesiredCapabilities.CHROME
dc['loggingPrefs'] = {'browser': 'ALL'}
chrome_profile = webdriver.ChromeOptions()
profile = {"download.default_directory": "C:\\SeleniumTests\\PDF",
"download.prompt_for_download": False,
"download.directory_upgrade": True}
chrome_profile.add_experimental_option("prefs", profile)
chrome_profile.add_argument("--disable-extensions")
chrome_profile.add_argument("--disable-print-preview")
self.driver = webdriver.Chrome(executable_path="C:\\SeleniumTests\\chromedriver.exe",
chrome_options=chrome_profile,
service_args=["--log-path=C:\\SeleniumTests\\chromedriver.log"],
desired_capabilities=dc)
All component versions are the same in both testing environments:
Selenium 2.43.0, Python 2.7.5, Chromedriver 2.12, Chrome (browser) 38.0.02125.122
I had to dig into the source code on this one - I couldn't find any docs listing the full set of Chrome User Preferences.
The key is "plugins.plugins_disabled": ["Chrome PDF Viewer"]}
FULL CODE:
dc = DesiredCapabilities.CHROME
dc['loggingPrefs'] = {'browser': 'ALL'}
chrome_profile = webdriver.ChromeOptions()
profile = {"download.default_directory": "C:\\SeleniumTests\\PDF",
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"plugins.plugins_disabled": ["Chrome PDF Viewer"]}
chrome_profile.add_experimental_option("prefs", profile)
#Helpful command line switches
# http://peter.sh/experiments/chromium-command-line-switches/
chrome_profile.add_argument("--disable-extensions")
self.driver = webdriver.Chrome(executable_path="C:\\SeleniumTests\\chromedriver.exe",
chrome_options=chrome_profile,
service_args=["--log-path=C:\\SeleniumTests\\chromedriver.log"],
desired_capabilities=dc)
Interestingly the blanket command chrome_profile.add_argument("--disable-plugins") switch did not solve this problem. But I prefer the more surgical approach anyways.
Related
After an update in selenium and visual studio I have the following problem. I try to get a url for example
thestore = "http://shop.oki.gr/shop/store/diathesimotita_new.asp" and instead I have a window opened with
http://www.puttop.top/object.php?u=http://shop.oki.gr/shop/store/customerauthenticateform.asp?redirectUrl=http://shop.oki.gr/shop/store/diathesimotita_new.asp&title=Login%20Page
which of course is not working.
options = webdriver.ChromeOptions()
options.add_experimental_option("prefs", {"download.default_directory": downloads_path,
"profile.default_content_settings.popups": 0,
"download.prompt_for_download": False,
"directory_upgrade": True,
"safebrowsing.enabled": True})
browser = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=options)
thestore = "http://shop.oki.gr/shop/store/diathesimotita_new.asp"
browser.get(thestore)
The initial url is opening from other pc normally..
What is happening?
I cant open either of these but it seems like its redirecting you to a login page first
I have a couple programs that do something similar and I keep a function that login for me on hand, then I get the original url again
following many article one can log XHR calls in an automated browser (using selenium) as bellow:
capabilities = DesiredCapabilities.CHROME
capabilities["loggingPrefs"] = {"performance": "ALL"} # newer: goog:loggingPrefs driver = webdriver.Chrome(
desired_capabilities=capabilities, executable_path="./chromedriver" )
...
logs_raw = driver.get_log("performance")
my probleme is the target request is performed by a "WebWorker", so it's not listed in the performance list of the browser main thread.
getting in chrome and manualy selecting the webworkers scope in the dev console "performance.getEntries()" gets me the request i want;
my question is how can someone perform such an action in selenium ? (python preferable).
no where in the doc of python selenium or Devtool Api have i found something similar
i'm so greatful in advance.
Edit: after some deggin i found that it has something to do with execution context of javascrip, i have no clue how to switch that in selenium
I would like to capture network traffic by using Selenium Webdriver on Python. Therefore, I must use a proxy (like BrowserMobProxy)
When I use webdriver.Chrome:
from browsermobproxy import Server
server = Server("~/browsermob-proxy")
server.start()
proxy = server.create_proxy()
from selenium import webdriver
co = webdriver.ChromeOptions()
co.add_argument('--proxy-server={host}:{port}'.format(host='localhost', port=proxy.port))
driver = webdriver.Chrome(executable_path = "~/chromedriver", chrome_options=co)
proxy.new_har
driver.get(url)
proxy.har # returns a HAR
for ent in proxy.har['log']['entries']:
print ent['request']['url']
the webpage is loaded properly and all requests are available and accessible in the HAR file.
But when I use webdriver.Firefox:
# The same as above
# ...
from selenium import webdriver
profile = webdriver.FirefoxProfile()
driver = webdriver.Firefox(firefox_profile=profile, proxy = proxy.selenium_proxy())
proxy.new_har
driver.get(url)
proxy.har # returns a HAR
for ent in proxy.har['log']['entries']:
print ent['request']['url']
The webpage cannot be loaded properly and the number of requests in the HAR file is smaller than the number of requests that should be.
Do you have any idea what the problem of proxy settings in the second code? How should I fix it to use webdriver.Firefox properly for my purpose?
Just stumbled across this project https://github.com/derekargueta/selenium-profiler. Spits out all network data for a URL. Shouldn't be hard to hack and integrate into whatever tests you're running.
Original source: https://www.openhub.net/p/selenium-profiler
For me, following code component works just fine.
profile = webdriver.FirefoxProfile()
profile.set_proxy(proxy.selenium_proxy())
driver = webdriver.Firefox(firefox_profile=profile)
I am sharing my solution, this would not write any logs to any file
but you can collect all sort of messages such as Errors,
Warnings, Logs, Info, Debug , CSS, XHR as well as Requests(traffic)
1. We are going to create Firefox profile so that we can enable option of
"Persist Logs" on Firefox (you can try it to enable on your default browser and see
if it launches with "Persist Logs" without creating firefox profile )
2. we need to modify the Firefox initialize code
where this line will do magic : options.AddArgument("--jsconsole");
so complete Selenium Firefox code would be, this will open Browser Console
everytime you execute your automation :
else if (browser.Equals(Constant.Firefox))
{
var profileManager = new FirefoxProfileManager();
FirefoxProfile profile = profileManager.GetProfile("ConsoleLogs");
FirefoxDriverService service = FirefoxDriverService.CreateDefaultService(DrivePath);
service.FirefoxBinaryPath = DrivePath;
profile.SetPreference("security.sandbox.content.level", 5);
profile.SetPreference("dom.webnotifications.enabled", false);
profile.AcceptUntrustedCertificates = true;
FirefoxOptions options = new FirefoxOptions();
options.AddArgument("--jsconsole");
options.AcceptInsecureCertificates = true;
options.Profile = profile;
options.SetPreference("browser.popups.showPopupBlocker", false);
driver = new FirefoxDriver(service.FirefoxBinaryPath, options, TimeSpan.FromSeconds(100));
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
}
3. Now you can write your logic since you have traffic/ logging window open so don't
go to next execution if test fails. That way Browser Console will keep your errors
messages and help you to troubleshoot further
Browser : Firefox v 61
How can you launch Browser Console for firefox:
1. open firefox (and give any URL )
2. Press Ctrl+Shift+J (or Cmd+Shift+J on a Mac)
Link : https://developer.mozilla.org/en-US/docs/Tools/Browser_Console
I am trying to ZOOM IN and ZOOM OUT the Chrome( selenium webdriver) only using keyboard. I have tried --
from selenium.webdriver.common.keys import Keys
driver.find_element_by_tag_name("body").send_keys(Keys.CONTROL,Keys.SUBTRACT).
but it is not working. Need answer in python.
I was just struggling with this. I managed to find something that works for me, hopefully it works for you:
driver.execute_script("document.body.style.zoom='zoom %'")
Have 'zoom%' = whatever zoom level you want. (e.g. '67%')
Environment:
Selenium 3.6.0
chromedriver 2.33
Chrome version 62.0.3202.75 (Official Build) (64-bit)
macOS Sierra 10.12.6
I tried the ways (without use the CSS) that people suggested in other questions in the past. For example, the answers in this question: Selenium webdriver zoom in/out page content.
Or this: Test zoom levels of page on browsers
without success.
So, I thought: if not with the shortcuts, what could be a different way to do that?
The idea is to use the "chrome://settings/" page in order to change the zoom:
Ok I know, for example from Going through Chrome://settings by Selenium, that every settings should be set in the ChromeOptions.
From this question I noticed that in the list of preferences the only paramater (I think) could be:
// Double that indicates the default zoom level.
const char kPartitionDefaultZoomLevel[] = "partition.default_zoom_level";
I tried, without success.
I want to repeat that I know it isn't the correct approach (and that will be different with different browser versions), but it works and, at least, was useful for me to understand how to go inside a shadow root element with selenium.
The following method return the elements inside a shadow root:
def expand_shadow_element(element):
shadow_root = driver.execute_script('return arguments[0].shadowRoot', element)
return shadow_root
It is useful because in the chrome://settings/ page there are shadow root elements.
In order to do that in my browser, this is the path:
root1=driver.find_element_by_xpath("*//settings-ui")
shadow_root1 = expand_shadow_element(root1)
container= shadow_root1.find_element_by_id("container")
root2= container.find_element_by_css_selector("settings-main")
shadow_root2 = expand_shadow_element(root2)
root3=shadow_root2.find_element_by_css_selector("settings-basic-page")
shadow_root3 = expand_shadow_element(root3)
basic_page = shadow_root3.find_element_by_id("basicPage")
settings_section= basic_page.find_element_by_xpath(".//settings-section[#section='appearance']")
root4= settings_section.find_element_by_css_selector("settings-appearance-page")
shadow_root4=expand_shadow_element(root4)
and finally:
settings_animated_pages= shadow_root4.find_element_by_id("pages")
neon_animatable=settings_animated_pages.find_element_by_css_selector("neon-animatable")
zoomLevel= neon_animatable.find_element_by_xpath(".//select[#id='zoomLevel']/option[#value='0.5']")
zoomLevel.click()
The entire code:
driver = webdriver.Chrome(executable_path=r'/pathTo/chromedriver')
def expand_shadow_element(element):
shadow_root = driver.execute_script('return arguments[0].shadowRoot', element)
return shadow_root
driver.get('chrome://settings/')
root1=driver.find_element_by_xpath("*//settings-ui")
shadow_root1 = expand_shadow_element(root1)
container= shadow_root1.find_element_by_id("container")
root2= container.find_element_by_css_selector("settings-main")
shadow_root2 = expand_shadow_element(root2)
root3=shadow_root2.find_element_by_css_selector("settings-basic-page")
shadow_root3 = expand_shadow_element(root3)
basic_page = shadow_root3.find_element_by_id("basicPage")
settings_section= basic_page.find_element_by_xpath(".//settings-section[#section='appearance']")
root4= settings_section.find_element_by_css_selector("settings-appearance-page")
shadow_root4=expand_shadow_element(root4)
settings_animated_pages= shadow_root4.find_element_by_id("pages")
neon_animatable=settings_animated_pages.find_element_by_css_selector("neon-animatable")
zoomLevel= neon_animatable.find_element_by_xpath(".//select[#id='zoomLevel']/option[#value='0.5']")
zoomLevel.click()
driver.get("https://www.google.co.uk/")
EDIT
As suggested by #Florent B in the comments, we can obtain the same result simple with:
driver.get('chrome://settings/')
driver.execute_script('chrome.settingsPrivate.setDefaultZoom(1.5);')
driver.get("https://www.google.co.uk/")
firefox solution for me,
Zoom body browser
zoom is a non-standard property, use transform instead (demo):
driver.execute_script("document.body.style.transform = 'scale(0.8)'")
https://github.com/SeleniumHQ/selenium/issues/4244
driver.execute_script('document.body.style.MozTransform = "scale(0.50)";')
driver.execute_script('document.body.style.MozTransformOrigin = "0 0";')
Yes, you can invoke the Chrome driver to zoom without having to use CSS. There are methods packaged into the Chrome DevTools Protocol Viewer, one being Input.synthesizePinchGesture aka zoom in/out.
For ease of use, with regards to the DevTools Protocol API, we will use a class called MyChromeDriver with webdriver.Chrome as a metaclass and a new method for sending these commands to Chrome:
# selenium
from selenium import webdriver
# json
import json
class MyChromeDriver(webdriver.Chrome):
def send_cmd(self, cmd, params):
resource = "/session/%s/chromium/send_command_and_get_result" % self.session_id
url = self.command_executor._url + resource
body = json.dumps({'cmd':cmd, 'params': params})
response = self.command_executor._request('POST', url, body)
return response.get('value')
1. Setup our webdriver and get some page:
webdriver = MyChromeDriver()
webdriver.get("https://google.com")
2. Send Chrome the Input.synthesizePinchGesture command along with its parameters via our new method send_cmd:
webdriver.send_cmd('Input.synthesizePinchGesture', {
'x': 0,
'y': 0,
'scaleFactor': 2,
'relativeSpeed': 800, # optional
'gestureSourceType': 'default' # optional
})
3. Walla! Chrome's zoom is invoked:
As a side note, there are tons of other commands you could use with send_cmd. Find them here: https://chromedevtools.github.io/devtools-protocol/
Based off this answer: Take full page screen shot in Chrome with Selenium
As you mentioned that Need it to work in Chrome. The current solutions are only for Firefox, here are a few updates and options :
Zoom the CSS :
driver.execute_script("document.body.style.zoom='150%'")
This option did work for me. But it zooms the CSS, not the Chrome Browser. So probably you are not looking at that.
Zoom In & Zoom Out the Chrome Browser :
After 4131, 4133 and 1621 the fullscreen() mode got supported to Zoom In through Selenium-Java Clients but it's not yet publicly released to PyPI.
I can see it's implemented but not pushed. Selenium 3.7 (Python) will be out soon. The push to sync version numbers will include that.
Configure the webdriver to open the Browser :
If your requirement is to execute the Test Suite in Full Screen mode, you can always use the Options Class and configure the webdriver instance with --kiosk argument as follows:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--kiosk")
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('https://www.google.co.in')
# zoom in firefox browser
driver.get("about:preferences")
driver.execute_script("arguments[0].click();", driver.find_element(By.XPATH, "// [#id='defaultZoom']"))
ActionChains(driver).click(driver.find_element(By.XPATH, "//*[#value='50']")).perform()
I am creating some end-to-end tests for a web app using Selenium.
I am working in Python and using the Firefox driver
driver = webdriver.Firefox()
The problem is that my web app using HTML5 geolocation, and it seems that everytime I run my tests, I have to click the 'Allow Location' popup in Firefox, making my tests less than automated.
Is there a way to force the Selenium Firefox driver to always allow geolocation without prompting?
You can force browser to return some predefined location without permission requests.
Just execute the following JavaScript code:
"navigator.geolocation.getCurrentPosition = function(success) { success({coords: {latitude: 50.455755, longitude: 30.511565}}); }"
Tested in Firefox and Chrome.
This question is almost 7 years old as of time of writing (Apr/20), but still relevant as APIs have changed. I've encountered a similar problem while writing a functional test with Selenium.
As an example, the scenarios that can occur in the canonical Mozilla example :
The browser does not support geolocation (!navigator.geolocation)
With geolocation supported (getCurrentPosition(success, error))
access to geolocation denied (error)
access to geolocation allowed (success)
Here is how these scenarios would translate to the Selenium setup:
from selenium import webdriver
# geolocation API not supported
geoDisabled = webdriver.FirefoxOptions()
geoDisabled.set_preference("geo.enabled", False)
browser = webdriver.Firefox(options=geoDisabled)
In order to go down the path of simulating a "Don't Allow" click in the prompt for geo-enabled browsers (by default enabled, check via about:config):
# geolocation supported but denied
geoBlocked = webdriver.FirefoxOptions()
geoBlocked.set_preference("geo.prompt.testing", True)
geoBlocked.set_preference("geo.prompt.testing.allow", False)
browser = webdriver.Firefox(options=geoBlocked)
And finally, simulating the "Allow Location Access" click
# geolocation supported, allowed and location mocked
geoAllowed = webdriver.FirefoxOptions()
geoAllowed.set_preference('geo.prompt.testing', True)
geoAllowed.set_preference('geo.prompt.testing.allow', True)
geoAllowed.set_preference('geo.provider.network.url',
'data:application/json,{"location": {"lat": 51.47, "lng": 0.0}, "accuracy": 100.0}')
browser = webdriver.Firefox(options=geoAllowed)
The geo.wifi.uri attribute does not seem to exist anymore, but has changed to geo.provider.network.url instead. This solution also prevents "random" Firefox profiles being loaded from disk, or JS code executed at runtime to mock the location. It is largely irrelevant whether the brower configuration is set via "Options" (as it is the case with this solution), via "Profiles", or via "DesiredCapabilities". I found Options to be the simplest.
Because I reached the same problem almost 3 years after this question was asked, and None of above answers were satisfying for me. I like to show solution I use.
So the answer I found on this blog.
And use it on my python code this way:
#classmethod
def setUpClass(cls):
cls.binary = FirefoxBinary(FF_BINARY_PATH)
cls.profile = FirefoxProfile()
cls.profile.set_preference("geo.prompt.testing", True)
cls.profile.set_preference("geo.prompt.testing.allow", True)
cls.profile.set_preference('geo.wifi.uri', GEOLOCATION_PATH)
cls.driver = Firefox(firefox_binary=cls.binary, firefox_profile=cls.profile)
On GEOLOCATION_PATH is my path to JSON file:
{
"status": "OK",
"accuracy": 10.0,
"location": {
"lat": 50.850780,
"lng": 4.358138,
"latitude": 50.850780,
"longitude": 4.358138,
"accuracy": 10.0
}
}
Just stumbled upon this problem today and I knew there should exist a simple and quick way of dealing with this. Here's how I solved it:
Create a new Firefox profile that will be used by Selenium. You can do it by typing about:profiles and then clicking on 'Create new profile'. A step by step instruction can be found in Mozilla's docs.
Head to the site that needs the permissions and wait for it to ask you to grant them. Grant them and check the "Remember this decision" box.
You'll need to know where your profile is stored, so that Selenium can use it. You can find the location in about:profiles. Here I created an "example_profile" and then copied the "Root directory" path:
You can then pass the path as a parameter while instantiating a Firefox browser like this:
root_directory_path = "/.../Firefox/Profiles/loeiok2p.example_profile"
driver = webdriver.Firefox(firefox_profile=root_directory_path)
Selenium should use the profile with granted permissions and the popup should not reappear.
None of the above worked for me but this did:
got answer from: https://security.stackexchange.com/questions/147166/how-can-you-fake-geolocation-in-firefox
from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.set_preference("geo.prompt.testing", True)
profile.set_preference("geo.prompt.testing.allow", True)
profile.set_preference('geo.wifi.uri',
'data:application/json,{"location": {"lat": 40.7590, "lng": -73.9845}, "accuracy": 27000.0}')
driver = webdriver.Firefox(firefox_profile=profile)
driver.get('https://www.where-am-i.net/')
I believe the default is to launch Firefox with a new, anonymous profile. You can launch selenium with -Dwebdriver.firefox.profile=whatever, where "whatever" is the name of a profile when you launch firefox -P.
To make sure there's no weirdness with persistent logins and other cookies:
Launch Firefox with "firefox -P"
Pick the profile you'll launch the tests with
Edit -> Preferences -> Privacy, select Use custom settings for history
Tell Firefox to keep cookies until "I close Firefox"
Here is more refined answer from one of the answers above. This adds some timeout before doing geolocation success callback, as usually JavaScript is written in such a manner that geolocation coordinates are not expected to be available until there has been one cycle back to the event loop.
This allows also tracing the spoofing through Web Console.
SPOOF_LOCATION_JS = """
(function() {
console.log('Preparing geo spoofing');
navigator.geolocation.getCurrentPosition = function(success) {
console.log("getCurrentPosition() called");
setTimeout(function() { console.log("Sending out fake coordinates"); success({coords: {latitude: 50.455755, longitude: 30.511565}}); }, 500);
};
console.log("Finished geospoofing")})();
"""
browser.evaluate_script(SPOOF_LOCATION_JS.replace("\n", " "))
I am using Firefox 74.0 with Selenium/Python 3.141.0 and the following places me in NYC
profile = FirefoxProfile()
profile.set_preference("geo.prompt.testing", True)
profile.set_preference("geo.prompt.testing.allow", True)
profile.set_preference("geo.provider.testing", True)
"geo.provider.network.url", "data:application/json,{"location": {"lat": 40.7590, "lng": -73.9845}, "accuracy": 27000.0}")
Would it be enough to just allow it one time manually and then allow python do to the job?
Because you can easily allow by setting this in the website properties in Firefox: