Reputation: 315
I'm using Selenium version 2.46.0. In order to debug different issues (for example client issues), I would like to get all the web browser console content (errors, warnings ...)
I tried using:
LogEntries logs1 = DefaultDriver.getWebDriver().manage().logs().get("client");
but got empty log entries...
BTW, I defined the capabilities:
capabilities = DesiredCapabilities.firefox();
LoggingPreferences logs = new LoggingPreferences();
logs.enable( LogType.CLIENT, Level.ALL );
capabilities.setCapability( CapabilityType.LOGGING_PREFS, logs );
webDriver = new FirefoxDriver( capabilities );
I also tried "driver" and "browser" log types but didn't get the web console content.
Any idea how to do it?
The solutions in the following link didn't work... Capturing browser logs with Selenium
Upvotes: 3
Views: 13429
Reputation: 31
I was facing same issue with selenium, in C# and i want to show you my workaround which work for every browser(in C#)
First i redirect all logs which web site produce to array which store all logs. Also i redirrect onerror function to gather all javascript errors
private void BindConsole(IWebDriver webDriver)
{
var script = "if (console.everything === undefined) {
console.everything = [];
console.defaultLog = console.log.bind(console);
console.log = function(){
const args = Array.prototype.slice.call(arguments).join('_');
console.everything.push({ 'Type':'Log', 'Datetime':Date().toLocaleString(), 'Value':args});
console.defaultLog.apply(console, arguments);
}
console.defaultError = console.error.bind(console);
console.error = function(){
const args = Array.prototype.slice.call(arguments).join('_');
console.everything.push({ 'Type':'Error', 'Datetime':Date().toLocaleString(), 'Value':args});
console.defaultError.apply(console, arguments);
}
console.defaultWarn = console.warn.bind(console);
console.warn = function(){
const args = Array.prototype.slice.call(arguments).join('_');
console.everything.push({ 'Type':'Warn', 'Datetime':Date().toLocaleString(), 'Value':args});
console.defaultWarn.apply(console, arguments);
}
console.defaultDebug = console.debug.bind(console);
console.debug = function(){
const args = Array.prototype.slice.call(arguments).join('_');
console.everything.push({ 'Type':'Debug', 'Datetime':Date().toLocaleString(), 'Value':args});
console.defaultDebug.apply(console, arguments);
}
window.onerror = function(message, url, linenumber) {
console.error('JavaScript error: ' + message + ' on line ' +
linenumber + ' for ' + url);
}
}";
((IJavaScriptExecutor)webDriver).ExecuteScript(script);
}
Note: you need run this function before your test, because logs won't be captured, and rerun it every time you refresh or change page (on refresh/change all logs will be lost so save them beforehand)
Then, I have object which match log signature in my function
public class LogEntry
{
public LogType Type { get; set; }
public string Datetime { get; set; }
public string Value { get; set; }
}
public enum LogType
{
Error,
Warn,
Log,
Debug
}
Then I run following function:
/// <summary>
/// Check whether new blogs are in browser console and captures them if any.
/// </summary>
/// <returns>Logs from browser console</returns>
public IEnumerable<LogEntry> GetAllConsoleLogs()
{
SystemTools.Delay();
var jsScript = "return console.everything";
var list = ((IJavaScriptExecutor)_driver.Driver).ExecuteScript(jsScript) as IReadOnlyCollection<object>;
if (list!=null && list.Count > 0) {
var token = JArray.FromObject(list);
ClearConsole();
return token.ToObject<IEnumerable<LogEntry>>();
} else {
return null;
}
}
/// <summary>
/// Delete all previous entrys form browser console, so only new ones will be captured
/// </summary>
private void ClearConsole()
{
var jsScript = "console.everything =[];";
((IJavaScriptExecutor)_driver.Driver).ExecuteScript(jsScript);
}
This function take array with logs (Json) and with help of .NET Json library converts it to C# object. I clear object every time i take logs, because I want to examine only new ones, you may remove call of this function and keep logs for all tests if this behaviour is not suitable for you
Upvotes: 1
Reputation: 65
You can try this:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
def get_logs2(driver):
# enable browser logging
#d = DesiredCapabilities.CHROME
#d['goog:loggingPrefs'] = { 'browser':'ALL' }
#driver = webdriver.Chrome(desired_capabilities=d)
# load the desired webpage
#driver.get('http://34.90.50.21/')
#driver.get(driver.current_url)
a = driver.get_log('browser')
# print messages
for entry in driver.get_log('browser'):
print(entry)
print("finished")
return a
or check this: Robot Frameworkget background call with Robot Framework/selenium
Upvotes: 0
Reputation: 196
I'm not sure whether this will work or not. But you can try opening the console with something like below
Actions builder = new Actions(pbDriver);
builder.keyDown(Keys.CONTROL).sendKeys(Keys.F12).keyUp(Keys.CONTROL).perform();
And then use selenium to interact with the console.
OR,
you can try a less elegant solution by taking the log 'manually' from the user data dir:
Set the user data dir to a fixed place:
options = new ChromeOptions();
capabilities = DesiredCapabilities.chrome();
options.addArguments("user-data-dir=/your_path/");
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
Get the text from the log file chrome_debug.log located in the path you've entered above
Edit:
I actually tried the approach mentioned in the question and it worked for me. The browser I used was Chrome. And as Siking pointed out I have used .enable(LogType.BROWSER) to get the logs. The following code does print all the logs captured during the whole run.
LogEntries logEntries = pbDriver.manage().logs().get("browser");
for (LogEntry entry : logEntries) {
System.out.println(entry.getMessage());
and I just learned that since developer tools is not part of DOM model, selenium can't be used to interact with it. Sikuli can be used to do this job
Upvotes: 0