Selenium WebDriver — Start Chrome with DevTools open to Console panel - javascript

I know how to start Chrome with the DevTools open so please don't tell me it is a duplicate of How to open Chrome Developer console in Selenium WebDriver using JAVA
I'm trying to have the DevTools open to a specific panel. By default it opens on the Elements panel but I want it to open on the Console panel instead:
I've seen this command line switch --devtools-flags but I haven't found any example usage of it. Essentially what I'm trying to achieve is something similar to that. Obviously that doesn't work but you get the gist:
const { Options } = require('selenium-webdriver/chrome');
// …
const options = new Options().addArguments([
'auto-open-devtools-for-tabs',
'devtools-flags="panel=console"' /* <- That doesn't work. What else would? */
]);
// …

I figured out how to do this for my Ruby on Rails app that uses RSpec and Capybara. Here's the code that I use to configure my Capybara driver to select the Console tab and dock the devtools to the bottom:
options = Selenium::WebDriver::Chrome::Options.new
options.add_preference(
'devtools',
'preferences' => {
'currentDockState' => '"bottom"', # Or '"undocked"', '"right"', etc.
'panel-selectedTab' => '"console"',
}
)
...
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
options: options,
desired_capabilities: capabilities,
You should be able to call the setUserPreferences function to set user preferences: https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/chrome_exports_Options.html#setUserPreferences
const { Options } = require('selenium-webdriver/chrome');
// …
const options = new Options().addArguments([
"auto-open-devtools-for-tabs"
]).setUserPreferences({
"devtools": {
"preferences": {
"panel-selectedTab": "\"console\""
// "currentDockState": "\"bottom\"" // Or "\"undocked\"", "\"right\"", etc.
}
}
});
(I haven't tested this for JS, so please try it out and let me know if it works.)
I figured out how to set these preferences by looking at ~/Library/Application Support/Google/Chrome/Default/Preferences. This is where my main Google Chrome installation stores my user preferences, and it's JSON data.
You can view all of the possible settings under devtools => preferences. Note that all the values are strings that are parsed as JSON, so you need to "double-wrap" any strings in your code, e.g. "\"console\"".
You can open your main Google Chrome browser and change the settings in the UI, and then re-open your Preferences file to see what JSON you need to set.

Related

Selenium chrome browser won't launch in background using Electron

i've been trying for hours launching a selenium web browser and now it's done, i can't put it in headless mode ( want it to perform tasks in background ). My electron app is a simple quick start with a button launching a Selenium webdriver. Here's my code :
document.getElementById("test").onclick = function () {
require('chromedriver');
var webdriver = require('selenium-webdriver');
var chromeCapabilities = webdriver.Capabilities.chrome();
//setting chrome options
var chromeOptions = {
'args': ['--headless']
};
chromeCapabilities.set('chromeOptions', chromeOptions);
var driver = new webdriver.Builder().withCapabilities(chromeCapabilities).build();
driver.get('http://www.google.com/');
};
What it makes : When you press the test button, selenium browser is launched and appears in my screen instead of being headless or in background :(
It seems like it doens't take in consideration the args of the chromeOption variable. I tried to put many different flags with many different syntaxes but noone of them worked. Does anyone have a solution please ?

Is there a way to get a webpage's Network activity (which you can see on Chrome Dev Tools) on load via Python?

I want to listen to the Network events (basically all of the activity that you can see when you go to the Network tab on Chrome's Developer Tools / Inspect) and record specific events when a page is loaded via Python.
Is this possible? Thanks!
Specifically:
go to webpage.com
open Chrome Dev Tools and go to the Network tab
add api.webpage.com as a filter
refresh page [scroll]
I want to be able to capture the names of these events because there are specific IDs that aren't available via the UI.
Update 2021
I had to make few changes to Zach answer to make it work. Comments with ### are my comments
def get_perf_log_on_load(url, headless=True, filter=None):
# init Chrome driver (Selenium)
options = Options()
options.add_experimental_option('w3c', False) ### added this line
options.headless = headless
cap = DesiredCapabilities.CHROME
cap["loggingPrefs"] = {"performance": "ALL"}
### installed chromedriver.exe and identify path
driver = webdriver.Chrome(r"C:\Users\asiddiqui\Downloads\chromedriver_win32\chromedriver.exe", desired_capabilities=cap, options=options) ### installed
# record and parse performance log
driver.get(url)
if filter:
log = [item for item in driver.get_log("performance") if filter in str(item)]
else:
log = driver.get_log("performance")
driver.close()
return log
Although it didn't completely answer the question, #mihai-andrei's answer got me the closest.
If anyone is looking for a Python solution than the following code should do the trick:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.chrome.options import Options
def get_perf_log_on_load(self, url, headless = True, filter = None):
# init Chrome driver (Selenium)
options = Options()
options.headless = headless
cap = DesiredCapabilities.CHROME
cap['loggingPrefs'] = {'performance': 'ALL'}
driver = webdriver.Chrome(desired_capabilities = cap, options = options)
# record and parse performance log
driver.get(url)
if filter: log = [item for item in driver.get_log('performance')
if filter in str(item)]
else: log = driver.get_log('performance')
driver.close()
return log
You could side step chrome and use a scriptable proxy like mitmproxy.
https://mitmproxy.org/
Another ideea is to use selenium to drive the browser and get the events from perf logs
https://sites.google.com/a/chromium.org/chromedriver/logging/performance-log

Disable Chrome clipboard popups WebdriverIO

I'm trying to disable the chrome clipboard popup/notification using webdriverIO (Selenium) for automation. I tried setting chrome options but still it doesn't disable it. I want to click a web element that is behind this popup, so I don't want this popup to appear in automation. I tried disabling the clipboard settings manually but selenium opens a new session every time which refreshes the settings. Also, it is not possible to inspect using developer tools. It is not an alert so accepting/dismissing alert does not work either.
browser.alertAccept();
or
browser.alertDismiss();
chromeOptions: {
args: [
'disable-infobars',
'disable-popup-blocking',
'disable-notifications'
],
prefs: {
'profile.default_content_settings.popups' : 2,
'profile.default_content_settings.notifications' : 2,
}
}
Please help me with this issue, any help would be really appreciated.
A workaround might be to switch to the popup and dismiss it.
driver.switchTo().alert().dismiss();
or
driver.switchTo().activeElement().dismiss();
EDIT: I found an interesting Website. Try the code at the end of this site: http://blog.amolchavan.space/block-push-notification-on-chrome-in-selenium-webdriver/
I see many people also suggest to use profile.default_content_settings so it may be depend on chrome version. Current chrome version will work with this code as follows
chromeOptions: {
prefs: {
'profile.managed_default_content_settings.popups' : 2,
'profile.managed_default_content_settings.notifications' : 2,
}
}
After hours of trying, this worked for me with version 103 of Chrome (Jul 2022):
chrome_options = webdriver.ChromeOptions()
prefs = {"profile.content_settings.exceptions.clipboard": {
'*': {'setting': 1}
}}
chrome_options.add_experimental_option('prefs', prefs)
...
currentDriver = webdriver.Remote(command_executor=SELENIUM_URL, options=chrome_options)
with currentDriver as driver:
...

Capture browser console logs with capybara

I need to capture the console logs (category: info) of a browser using Ruby & Capybara. Until now I have tried using driver.manage.logs.get(:browser) or (:client) but, using this, the result is not what I want. It gives out the interaction results between selenium and browser where I can see my javascript statements sent for execution, but the resulting output fails to get captured.
Whether or not logs are available when using selenium depends on what browser you are using with Selenium. If you were using Firefox you'd be out of luck since it doesn't support the log retrieval API, however since you're using Chrome they are accessible. The issue you're having is that, by default, only WARN or ERROR level logs are captured. You can change this in the driver registration through the loggingPrefs capability
Selenium 3
Capybara.register_driver :logging_selenium_chrome do |app|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs:{browser: 'ALL'})
browser_options = ::Selenium::WebDriver::Chrome::Options.new()
# browser_options.args << '--some_option' # add whatever browser args and other options you need (--headless, etc)
Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options, desired_capabilities: caps)
end
Selenium 4
Capybara.register_driver :logging_selenium_chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new
options.add_option("goog:loggingPrefs", {browser: 'ALL'})
browser_options = ::Selenium::WebDriver::Chrome::Options.new()
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(app,
capabilities: options,
browser: :chrome)
end
end
and then specify to use :logging_selenium_chrome as your driver
Capybara.javascript_driver = :logging_selenium_chrome # or however else you're specifying which driver to use
which should then allow you to get the logs in your tests with
page.driver.browser.manage.logs.get(:browser)
Thomas Walpole answer is correct but it seems that nowadays if you are using chrome as your driver you should use
Selenium::WebDriver::Remote::Capabilities.chrome( "goog:loggingPrefs": { browser: 'ALL' } )
Notice goog:loggingPrefs instead of loggingPrefs only with this solution i was able to get console.log printed in the log.
Took me a while and got it from here https://intellipaat.com/community/5478/getting-console-log-output-from-chrome-with-selenium-python-api-bindings after several frustrating attempts.
November 2022 update, use:
page.driver.browser.logs.get(:browser)
Not sure that this is what you want, but take a look at https://github.com/dbalatero/capybara-chromedriver-logger.
It helps me identify the problem with dynamic modules import(''). Works both locally and in Github Actions / Circle CI by displaying failed loads of assets (which i believe outputs as console.error).

ReferenceError while using sdk/tabs in firefox webextension

This is my first time learning to build a firefox addon. I want store all the open tabs in a window and for that I require sdk/tabs.
Here is my js file:
/*
Given the name of a beast, get the URL to the corresponding image.
*/
debugger;
var tabs = require("sdk/tabs");
function beastNameToURL(beastName) {
switch (beastName) {
case "Save Session":
debugger;
for (let tab of tabs)
console.log(tab.url);
return;
case "Load Session":
debugger;
return chrome.extension.getURL("beasts/snake.jpg");
case "Turtle":
return chrome.extension.getURL("beasts/turtle.jpg");
}
}
/*
Listen for clicks in the popup.
If the click is not on one of the beasts, return early.
Otherwise, the text content of the node is the name of the beast we want.
Inject the "beastify.js" content script in the active tab.
Then get the active tab and send "beastify.js" a message
containing the URL to the chosen beast's image.
*/
document.addEventListener("click", function(e) {
if (!e.target.classList.contains("btn")) {
return;
}
var chosenBeast = e.target.textContent;
var chosenBeastURL = beastNameToURL(chosenBeast);
chrome.tabs.executeScript(null, {
file: "/content_scripts/beastify.js"
});
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {beastURL: chosenBeastURL});
});
});
When I reach the var tabs = require("sdk/tabs") line I get a Reference error.
Github : https://github.com/sagar-shah/Session-manifest
Kindly let me know how do I resolve this error. This being my first time with add-ons I am completely lost.
Thanks in advance.
Update:
Tried to declare it globally in the js file. Now I am getting undefined error for tabs.
Update2:
I was mixing up development using sdk and webextensions as pointed out by #matagus. I have decided to go with development using the webextensions. Link to the new repository has been updated.
The error is on package.json line 6: you're telling to the addon sdk that the main file of your addon is manage.json. According to [the docs] the value of main should be:
A string representing the name of a program module that is located in one of the top-level module directories specified by lib. Defaults to "index.js".
So you need to change its value to index.js.
Besides that, I think you're missing a difference between Firefox addon built using the addon-sdk (which do not have a ´manifest.json´ and that you build using jpm tool) and the new WebExtensions which do require you to write a ´manifest.json´ like the one already have.
UPDATE:
Again: you're missing the difference between WebExtensions and SDK-based addons. Now you made a WebExtension but you're trying to use the SDK. It isn't possible. Just use chrome.tabs directly instead of trying to import it from the sdk (var tabs = require("sdk/tabs");).

Categories