I want to build an automation testing, so I have to know the errors that appear in the console of chrome.
there is an option to get the error lines that appear in the console?
In order to see the console: right click somewhere in the page, click "inspect element" and then go to "console".
I don't know C# but here's Java code that does the job, I hope you can translate it to C#
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class ChromeConsoleLogging {
private WebDriver driver;
#BeforeMethod
public void setUp() {
System.setProperty("webdriver.chrome.driver", "c:\\path\\to\\chromedriver.exe");
DesiredCapabilities caps = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.ALL);
caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
driver = new ChromeDriver(caps);
}
#AfterMethod
public void tearDown() {
driver.quit();
}
public void analyzeLog() {
LogEntries logEntries = driver.manage().logs().get(LogType.BROWSER);
for (LogEntry entry : logEntries) {
System.out.println(new Date(entry.getTimestamp()) + " " + entry.getLevel() + " " + entry.getMessage());
//do something useful with the data
}
}
#Test
public void testMethod() {
driver.get("http://mypage.com");
//do something on page
analyzeLog();
}
}
Pay attention to setUp method in above code. We use LoggingPreferences object to enable logging. There are a few types of logs, but if you want to track console errors then LogType.BROWSER is the one that you should use. Then we pass that object to DesiredCapabilities and further to ChromeDriver constructor and voila - we have an instance of ChromeDriver with logging enabled.
After performing some actions on page we call analyzeLog() method. Here we simply extract the log and iterate through its entries. Here you can put assertions or do any other reporting you want.
My inspiration was this code by Michael Klepikov that explains how to extract performance logs from ChromeDriver.
You can get logs this way:
Driver().Manage().Logs.GetLog();
By specifying what log you are interested in you can get the browser log, that is:
Driver().Manage().Logs.GetLog(LogType.Browser);
Also remember to setup your driver accordingly:
ChromeOptions options = new ChromeOptions();
options.SetLoggingPreference(LogType.Browser, LogLevel.All);
driver = new ChromeDriver("path to driver", options);
This is the c# code for logging the brower log from chrome.
private void CheckLogs()
{
List<LogEntry> logs = Driver.Manage().Logs.GetLog(LogType.Browser).ToList();
foreach (LogEntry log in logs)
{
Log(log.Message);
}
}
here is my code for the actual log:
public void Log(string value, params object[] values)
{
// allow indenting
if (!String.IsNullOrEmpty(value) && value.Length > 0 && value.Substring(0, 1) != "*")
{
value = " " + value;
}
// write the log
Console.WriteLine(String.Format(value, values));
}
As per issue 6832 logging is not implemented yet for C# bindings. So there might not be an easy way to get this working as of now.
Here is a solution to get Chrome logs using the C#, Specflow and Selenium 4.0.0-alpha05.
Pay attention that the same code doesn't work with Selenium 3.141.0.
[AfterScenario]
public void AfterScenario(ScenarioContext context)
{
if (context.TestError != null)
{
GetChromeLogs(context); //Chrome logs are taken only if test fails
}
Driver.Quit();
}
private void GetChromeLogs()
{
var chromeLogs = Driver.Manage().Logs.GetLog(LogType.Browser).ToList();
}
public void Test_DetectMissingFilesToLoadWebpage()
{
try
{
List<LogEntry> logs = driver.Manage().Logs.GetLog(LogType.Browser).ToList();
foreach (LogEntry log in logs)
{
while(logs.Count > 0)
{
String logInfo = log.ToString();
if (log.Message.Contains("Failed to load resource: the server responded with a status of 404 (Not Found)"))
{
Assert.Fail();
}
else
{
Assert.Pass();
}
}
}
}
catch (NoSuchElementException e)
{
test.Fail(e.StackTrace);
}
}
You could do something like this in C#. It is a complete test case. Then print the console output as String i.e logInfo in your report. For some reason, Log(log.Message) from the solution above this one gave me build errors.So, I replaced it.
C# bindings to the Chrome console logs are finally available in Selenium 4.0.0-alpha05. Selenium 3.141.0 and prior do not have support.
Before instantiating a new ChromeDriver object, set the logging preference in a ChromeOptions object and pass that into ChromeDriver:
ChromeOptions options = new ChromeOptions();
options.SetLoggingPreference(LogType.Browser, LogLevel.All);
ChromeDriver driver = new ChromeDriver(options);
Then, to write the Chrome console logs to a flat file:
public void WriteConsoleErrors()
{
string strPath = "C:\\ConsoleErrors.txt";
if (!File.Exists(strPath))
{
File.Create(strPath).Dispose();
}
using (StreamWriter sw = File.AppendText(strPath))
{
var entries = driver.Manage().Logs.GetLog(LogType.Browser);
foreach (var entry in entries)
{
sw.WriteLine(entry.ToString());
}
}
}
driver.manage().logs().get("browser")
Gets all logs printed on the console. I was able to get all logs except Violations. Please have a look here Chrome Console logs not printing Violations
Related
I need to produce a screencast of an IPython session, and to avoid confusing viewers, I want to disable all warnings emitted by warnings.warn calls from different packages. Is there a way to configure the ipythonrc file to automatically disable all such warnings?
Place:
import warnings
warnings.filterwarnings('ignore')
inside ~/.ipython/profile_default/startup/disable-warnings.py.
Quite often it is useful to see a warning once. This can be set by:
warnings.filterwarnings(action='once')
I hide the warnings in the pink boxes by running the following code in a cell:
from IPython.display import HTML
HTML('''<script>
code_show_err=false;
function code_toggle_err() {
if (code_show_err){
$('div.output_stderr').hide();
} else {
$('div.output_stderr').show();
}
code_show_err = !code_show_err
}
$( document ).ready(code_toggle_err);
</script>
To toggle on/off output_stderr, click here.''')
The accepted answer does not work in Jupyter (at least when using some libraries).
The JavaScript solutions here only hide warnings that are already showing but not warnings that would be shown in the future.
To hide/unhide warnings in Jupyter and JupyterLab I wrote the following script that essentially toggles CSS to hide/unhide warnings.
%%javascript
(function(on) {
const e = $("<a>Setup failed</a>");
const ns = "js_jupyter_suppress_warnings";
var cssrules = $("#" + ns);
if(!cssrules.length)
cssrules = $("<style id='" + ns + "' type='text/css'>div.output_stderr { } </style>").appendTo("head");
e.click(function() {
var s = 'Showing';
cssrules.empty()
if(on) {
s = 'Hiding';
cssrules.append("div.output_stderr, div[data-mime-type*='.stderr'] { display:none; }");
}
e.text(s + ' warnings (click to toggle)');
on = !on;
}).click();
$(element).append(e);
})(true);
For JupyterLab, this should work (#Alasja):
from IPython.display import HTML
HTML('''<script>
var code_show_err = false;
var code_toggle_err = function() {
var stderrNodes = document.querySelectorAll('[data-mime-type="application/vnd.jupyter.stderr"]')
var stderr = Array.from(stderrNodes)
if (code_show_err){
stderr.forEach(ele => ele.style.display = 'block');
} else {
stderr.forEach(ele => ele.style.display = 'none');
}
code_show_err = !code_show_err
}
document.addEventListener('DOMContentLoaded', code_toggle_err);
</script>
To toggle on/off output_stderr, click <a onclick="javascript:code_toggle_err()">here</a>.''')
I am Trying to run html page with electron + eel.
I have successfully loaded the webpage + eel.js.
My Problem is whenever I try to use require module in the javascript of the HTML page. it gives me the below:
Uncaught ReferenceError: require is not defined
The sequence is, launching the webapp using runner.py ( eel.start ), then electron start
Also, if I set mainWindow.loadFile('templates/index.html') in main.js file, instead of mainWindow.loadURL('http://localhost:8000/index.html'). the render just work fine and can handle electron window from main html javascript file. but eel is not loaded in this case.
If I tried the steps which in the guide. the electron html page opens normally with eel.js loaded up. but can not handle the electron window from html javascript file
runner.py
import eel
import eel.browsers
eel.init('templates')
eel.browsers.set_path('electron', 'node_modules/electron/dist/electron')
eel.start('index.html', mode='electron' , port=8000 ,host='localhost',disable_cache=True)
main.js:
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
enableRemoteModule: true
}
})
// and load the index.html of the app.
// mainWindow.loadFile('templates/index.html')
mainWindow.loadURL('http://localhost:8000/index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
html javascript:
function login_check(){
var serverIP = document.getElementById('serverIP').value
var Username = document.getElementById('usernameEntry').value
var Password = document.getElementById('passwordEntry').value
var RememberMe = document.getElementById('remember-me-checkbox').checked
if(serverIP != "" && Username != "" && Password != ""){
document.querySelector('.progress-bar-container-div').classList.add('active')
}
else{
const window = require("electron").getCurrentWindow()
alert("Required Fields are empty.")
document.querySelector('.progress-bar-container-div').classList.remove('active')
window.minimize();
}
}
package.json:
{
"name": "electron-quick-start",
"version": "1.0.0",
"description": "A minimal Electron application",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"repository": "https://github.com/electron/electron-quick-start",
"keywords": [
"Electron",
"quick",
"start",
"tutorial",
"demo"
],
"author": "GitHub",
"license": "CC0-1.0",
"devDependencies": {
"electron": "^5.0.0"
}
}
error:
I need to open moz-extension://internal-uuid page after my Selenium script is started to have an access to the extension's storage API, to set some prefs there, that this extension will read later and use to do some actions. But when I use selenium.webdriver.Firefox.add_addon(...) it returns the Extension ID that differs and can't be used to open the moz-extension:// page. Is there any way to get this Internal UUID from my code (not manually by inspecting about:debugging#addons). Or may be some way to pass the data I need from Selenium to Web Extension?
This code is working for me in Linux and Mac:
public static void main(String[] args) throws IOException {
FirefoxOptions options = new FirefoxOptions();
FirefoxDriver driver = new FirefoxDriver(options);
String userPrefsFileContent = readFile(driver.getCapabilities().getCapability("moz:profile") + "/prefs.js");
String extensionUuid = getExtensionUuid(userPrefsFileContent);
driver.quit();
}
private static String getExtensionUuid(String userPrefsFileContent) {
String uuid = null;
String[] usersPrefsList = userPrefsFileContent.split(";");
for (String currentPref : usersPrefsList) {
if (currentPref.contains("extensions.webextensions.uuids")) {
uuid = currentPref.split(":")[1].replaceAll("\"", "").replace("}", "")
.replace(")", "").replace("\\", "");
}
}
if(uuid.contains(",")) {
uuid = uuid.split(",")[0];
}
return uuid;
}
private static String readFile(String pathname) throws IOException {
File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int) file.length());
String lineSeparator = System.getProperty("line.separator");
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
fileContents.append(scanner.nextLine()).append(lineSeparator);
}
}
return fileContents.toString();
}
Don't know how, but I cannot get this approach to work in python, so instead found out another smart approach, instead of trying to get preference that is not provided by Firefox, you can set UUID to something with set-preference API. then just use it.
here is part of my code
if self.webdriver != None:
return self.webdriver
extensionPath = curPath+'/../../packages/firefox.xpi';
cap = DesiredCapabilities().FIREFOX
cap["marionette"]=True;
profile = webdriver.firefox.firefox_profile.FirefoxProfile();
profile.set_preference('extensions.webextensions.uuids',json.dumps({'support#ipburger.com':firefoxUUID}))
self.webdriver = webdriver.Firefox(firefox_binary=firefoxBinary,capabilities=cap,executable_path=curPath+'/../../drivers/geckodriver',firefox_profile=profile);
self.webdriver.install_addon(extensionPath,temporary=True);
return self.webdriver;
firefoxUUID is a string version of random UUID you generate
and you have to replace support#ipburger.com with your addon ID, which you can set inside manifest.json file
the code below is working for me in python on windows :
driver = webdriver.Firefox(service=firefox_service, options=firefox_options)
driver.install_addon(os.path.join(application_path, 'extension_firefox.xpi'), temporary=True)
time.sleep(1)
profile_path = driver.capabilities['moz:profile']
with open('{}/prefs.js'.format(profile_path), 'r') as file_prefs:
lines = file_prefs.readlines()
for line in lines:
if 'extensions.webextensions.uuids' in line:
sublines = line.split(',')
for subline in sublines:
if id_extension_firefox in subline:
internal_uuid = subline.split(':')[1][2:38]
I'm using Selenium to run tests in Chrome via the Python API bindings, and I'm having trouble figuring out how to configure Chrome to make the console.log output from the loaded test available. I see that there are get_log() and log_types() methods on the WebDriver object, and I've seen Get chrome's console log which shows how to do things in Java. But I don't see an equivalent of Java's LoggingPreferences type in the Python API. Is there some way to accomplish what I need?
Ok, finally figured it out:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# enable browser logging
d = DesiredCapabilities.CHROME
d['loggingPrefs'] = { 'browser':'ALL' }
driver = webdriver.Chrome(desired_capabilities=d)
# load the desired webpage
driver.get('http://foo.com')
# print messages
for entry in driver.get_log('browser'):
print(entry)
Entries whose source field equals 'console-api' correspond to console messages, and the message itself is stored in the message field.
Starting from chromedriver, 75.0.3770.8, you have to use goog:loggingPrefs instead of loggingPrefs:
d['goog:loggingPrefs'] = { 'browser':'ALL' }
To complete the answer: starting from chromedriver 75.0.3770.8, you have to use goog:loggingPrefs instead of loggingPrefs.
See Chromedriver changelog: http://chromedriver.chromium.org/downloads or this bug: https://bugs.chromium.org/p/chromedriver/issues/detail?id=2976
if you are using the python logging module (and you should be)... here is a way to add the selenium browser logs to the python logging system..
the get_browser_log_entries() function grabs the logs from eth provded driver, emits them to the python logging module as chrome. (ie chrome.console-api, chrome.network etc..) using the timestamp from the browser.(in case there is a delay before you call get_log)
it could probably do with some better exception handling (like if logging is not turned on ) etc.. but it works most of the time..
hop
import logging
from selenium import webdriver
def get_browser_log_entries(driver):
"""get log entreies from selenium and add to python logger before returning"""
loglevels = { 'NOTSET':0 , 'DEBUG':10 ,'INFO': 20 , 'WARNING':30, 'ERROR':40, 'SEVERE':40, 'CRITICAL':50}
#initialise a logger
browserlog = logging.getLogger("chrome")
#get browser logs
slurped_logs = driver.get_log('browser')
for entry in slurped_logs:
#convert broswer log to python log format
rec = browserlog.makeRecord("%s.%s"%(browserlog.name,entry['source']),loglevels.get(entry['level']),'.',0,entry['message'],None,None)
rec.created = entry['timestamp'] /1000 # log using original timestamp.. us -> ms
try:
#add browser log to python log
browserlog.handle(rec)
except:
print(entry)
#and return logs incase you want them
return slurped_logs
def demo():
caps = webdriver.DesiredCapabilities.CHROME.copy()
caps['goog:loggingPrefs'] = { 'browser':'ALL' }
driver = webdriver.Chrome(desired_capabilities=caps )
driver.get("http://localhost")
consolemsgs = get_browser_log_entries(driver)
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)7s:%(message)s')
logging.info("start")
demo()
logging.info("end")
Note that calling driver.get_log('browser') will cause the next call to return nothing until more logs are written to the console.
I would suggest saving the logs to a variable first. For example below logs_2 will equal [].
If you need something in the console to test you can use:
self.driver.execute_script("""
function myFunction() {
console.log("Window loaded")
}
if(window.attachEvent) {
window.attachEvent('onload', myFunction());
} else {
if(window.onload) {
var curronload = window.onload;
var newonload = function(evt) {
curronload(evt);
myFunction(evt);
};
window.onload = newonload;
} else {
window.onload = myFunction();
}
}
""")
logs_1 = driver.get_log('browser')
print("A::", logs_1 )
logs_2 = driver.get_log('browser')
print("B::", logs_2 )
for entry in logs_1:
print("Aa::",entry)
for entry in logs_2:
print("Bb::",entry)
See the answer from msridhar for what should go above my example code.
I have a list of URL's and would like to scrape the location objects for each of their webpages. The data I am referring to is produced by typing "window.location" into your browser's console. For example, performing this action on www.github.com with Chrome would give you the something like following output:
Location {assign: function, replace: function, reload: function, ancestorOrigins: DOMStringList, origin: "https://github.com"…}
When expanded, you can see more information:
Location {
ancestorOrigins: DOMStringList
assign: function () { [native code] }
hash: ""
host: "github.com"
hostname: "github.com"
href: "https://github.com/"
origin: "https://github.com"
pathname: "/"
port: ""
protocol: "https:"
reload: function () { [native code] }
replace: function () { [native code] }
search: ""
toString: function toString() { [native code] }
valueOf: function valueOf() { [native code] }
__proto__: Location
}
I have used Python and the Mechanize library to scrape in the past, but have never desired this functionality until now and am not sure how to proceed. Any suggestions would be welcomed.
As far as I understand, you want to perform a JavaScript call on desired web page. My suggestion would be to use some headless browsers. I did similar things with Framework called PyQt4. You can also use other headless web browsers like PhantomJS. Or you may also be interesting with tool called Selenium.