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