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
.get(LogType.BROWSER)not.get("client"). The capabilities part of your code is fine.