Avi Rosenfeld
Avi Rosenfeld

Reputation: 315

How to read the Web Browser Console in Selenium?

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

Answers (3)

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

Anna Ramolini
Anna Ramolini

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

Amit G
Amit G

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:

  1. 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);

  2. 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

Related Questions