C# Selenium access browser log - javascript

Is there a way of capturing browser logs in c# using selenium.
I am looking to capture any JS errors that appear on a particular page. Preferable on Chrome or Firefox.
I have previously done this in Python but can this be done in C#?

To set-up and retrieve the log entries with Selenium / Chrome / C# :
ChromeOptions options = new ChromeOptions();
options.SetLoggingPreference(LogType.Browser, LogLevel.Warning);
var driver = new ChromeDriver(options);
driver.Navigate().GoToUrl("http://stackoverflow.com");
var entries = driver.Manage().Logs.GetLog(LogType.Browser);
foreach (var entry in entries) {
Console.WriteLine(entry.ToString());
}
And with Firefox:
FirefoxOptions options = new FirefoxOptions();
options.SetLoggingPreference(LogType.Browser, LogLevel.Warning);
var driver = new FirefoxDriver(options);
driver.Navigate().GoToUrl("http://stackoverflow.com");
var entries = driver.Manage().Logs.GetLog(LogType.Browser);
foreach (var entry in entries) {
Console.WriteLine(entry.ToString());
}

This library can help you with that: JSErrorCollector.
When you're using it you just have to write one line to get all the errors listed:
List<JavaScriptError> jsErrors = JavaScriptError.ReadErrors(driver);

Related

Selenium/Node.js/Heroku combination no error displayed, but scraping function doesn't print anything

So I've already added the required build packs to my Heroku app. My app.js file has the correct imports (I believe) and I thought I was implementing the function correctly, but I guess I'm not. FYI, I'm calling the scraping function every minute using a cron schedule function.
const webdriver = require('selenium-webdriver');
require('chromedriver');
const chrome = require('selenium-webdriver/chrome');
let options = new chrome.Options();
options.addArguments("--headless");
options.addArguments("--disable-gpu");
options.addArguments("--no-sandbox");
function scrape() {
let driver = new webdriver.Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
driver.get('https://www.selenium.dev/documentation/en/webdriver/web_element/');
let elements = driver.findElements(By.css('p'));
for(let e of elements) {
console.log(e.getText());
}
driver.quit();
};
and in my cron function I just call
scrape()
Cron runs a couple times and then I get this weird error:
https://i.stack.imgur.com/A6t0U.jpg

How do I get selenium-webdriver to ignore SSL errors in Firefox and PhantomJS?

Given these Node dependencies:
{
"chromedriver": "^2.24.1",
"cucumber": "^1.3.0",
"geckodriver": "^1.1.2",
"phantomjs-prebuilt": "^2.1.12",
"selenium-webdriver": "^3.0.0-beta-2"
}
I would like PhantomJS and Firefox to ignore SSL certificates. Here is how my browser.js looks:
require('geckodriver');
// main browser object
var browserHandle;
// load selenium webdriver and some rules
var webdriver = require('selenium-webdriver'),
By = webdriver.By,
until = webdriver.until;
// load phantomjs into webdriver capabilities
var phantomjs_exe = require('phantomjs-prebuilt').path;
var customPhantom = webdriver.Capabilities.phantomjs();
customPhantom.set("phantomjs.binary.path", phantomjs_exe);
webdriver.Builder()
//.forBrowser('firefox')
//.forBrowser('phantomjs')
.withCapabilities(customPhantom)
.build();
Any suggestions with --ignore-ssl-errors=yes? How can I implement it in the code? I want to use only JavaScript, rather than Java.
This is only for Javascript / Node.js Selenium Webdriverjs case, only MacOS solution.
Firefox case:
a. Setup a new Profile using the Profile Manager for Firefox.
Open the Profile Manager with /Applications/Firefox.app/Contents/MacOS/firefox-bin -P (-profilemanager, this works as well)
Click "Create Profile"
In the second Step of creation, the Path to the Profile File is displayed. Copy it!
b. Add the ffprofile File
Go to features/support
Add a new File "ffprofile.json"
add { "ffprofile": "<profilePath>"} to the file, where <profilePath> is the Path you copied in a.
c. Add your local system to the Profile
Open the Profile Manager again with /Applications/Firefox.app/Contents/MacOS/firefox-bin -P
Select your new Profile, click "Start Firefox"
In the Browser, go to your https://.... You should see a Page telling you there is a Problem with the certificate
Click on "Advanced" -> "Add Exception" -> "Confirm Security Exception"
d. Add this into your browser.js or where you call a browser programmatically:
var webdriver = require('selenium-webdriver'),
firefox = require('selenium-webdriver/firefox'),
var ffProfileFile = require('./ffprofile');
var ffProfile = new firefox.Profile(ffProfileFile['ffprofile']);
var ffOptions = new firefox.Options().setProfile(ffProfile);
return browserHandle = new firefox.Driver(ffOptions);
Phantomjs case ( I have got two solutions here, pick up the one which is better for you):
solution 1:
var webdriver = require('selenium-webdriver'),
phantom = require('phantomjs-prebuilt');
var capabilities = webdriver.Capabilities.phantomjs();
capabilities.set(webdriver.Capability.ACCEPT_SSL_CERTS, true);
capabilities.set(webdriver.Capability.SECURE_SSL, false);
capabilities.set("phantomjs.cli.args",
["--web-security=no",
"--ssl-protocol=any",
"--ignore-ssl-errors=yes"]
);
return browserHandle = new webdriver
.Builder()
.withCapabilities(capabilities)
.build();
solution 2:
var webdriver = require('selenium-webdriver'),
phantom = require('phantomjs-prebuilt');
var capabilities = {
'browserName' : 'phantomjs',
'phantomjs.cli.args': ['--ignore-ssl-errors=true',
'--ssl-protocol=any', '--web-security=false']
}
return browserHandle = new webdriver
.Builder()
.withCapabilities(capabilities)
.build();
for this one the 'phantomjs.cli.args': ['--ignore-ssl-errors=true'] did the job for me.
Hope it will be useful for you.
For Firefox, you can use the following code:
var driver = new webdriver.Builder().withCapabilities(Capabilities.firefox()
.set("acceptInsecureCerts", true)).build();
For Chrome browser, just need to set Capability.ACCEPT_INSECURE_TLS_CERTS, true. It is working for me.
const { Builder, By, until, Capabilities, Capability } = require('selenium-webdriver');
const capabilities = Capabilities.chrome();
capabilities.set(Capability.ACCEPT_INSECURE_TLS_CERTS, true);
this.driver = new Builder()
.withCapabilities(capabilities)
.forBrowser('chrome')
.build();

How to access named pipes using JavaScript in Firefox add-on?

I'm trying to access a named pipe in a Firefox add-on. My code, based on solution 2 to this CodeProject question, is:
var file = Components.classes["#mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath("\\\\.\\pipe\\test");
var text = "Some text to be written";
var writer = Components.classes["#mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
// Open file for read/write access, and create it if it does not exist.
writer.init (file, 0x04 | 0x08, -1, 0);
writer.write (text, text.length);
writer.flush ();
writer.close ();
When I run this is Firefox Scratchpad, I get:
/*
Exception: Component returned failure code: 0x80520012 (NS_ERROR_FILE_NOT_FOUND) [nsIFileOutputStream.init]
#6
*/
Line 6 is the line where I call writer.init.
I've played with passing different flags to writer.init, but no luck. I'm able to write to a normal file path with this code, just not the named pipe path.
I've been searching for more information for most of a day. The only other relevant thing I've found is this Bugzilla bug that mentions the same problem, but it's dated 2009.
Thank you in advance for any suggestions.
Edit: Based on the replies I tried the following:
var encoder = new TextEncoder();
var array = encoder.encode("This is some text");
var path = "\\\\.\\pipe\\test";
Task.spawn(function() {
let pfh = yield OS.File.open(path, {write: true});
yield pfh.write(array);
yield pfh.close();
});
which lets me write to a file (if I change the path accordingly) but does not seem to send anything to the pipe.
Here is the (admittedly crude) code I'm using to read the pipe on the .NET side:
let server = new NamedPipeServerStream ("\\\\.\\pipe\\test", PipeDirection.InOut)
let reader = new StreamReader (server)
do
printfn "Listening..."
server.WaitForConnection ()
printfn "Connected."
while true do
while reader.EndOfStream = false do reader.ReadLine () |> printfn "%s"
And the code I threw together to verify that I could at least write to the pipe in .NET:
let client = new NamedPipeClientStream ("\\\\.\\pipe\\test")
do client.Connect ()
let writer = new StreamWriter (client)
do writer.AutoFlush <- true
// Wait for connection
System.Threading.Thread.Sleep (1000)
let message = "hello"
do message |> writer.WriteLine
Try OS.File:
let encoder = new TextEncoder(); // This encoder can be reused for several writes
let array = encoder.encode("This is some text"); // Convert the text to an array
let promise = OS.File.writeAtomic("\\\\.\\pipe\\test", array, // Write the array atomically to "file.txt", using as temporary
{tmpPath: "file.txt.tmp"}); // buffer "file.txt.tmp".

How to save Excel workbook to current user desktop by using javascript?

I create workbook from web page by:
var thisTable = document.getElementById("mytable3").innerHTML;
window.clipboardData.setData("Text", thisTable);
var objExcel = new ActiveXObject ("Excel.Application");
objExcel.visible = true;
var objWorkbook = objExcel.Workbooks.Add();
var objWorksheet = objWorkbook.Worksheets(1);
objWorkbook.Worksheets(1).Activate;
objWorksheet.name = "test";
objWorksheet.Paste;
objWorksheet.columns.autofit;
window.clipboardData.setData("Text","");
objWorkbook.Worksheets(1).SaveAs("%USERPROFILE%\\Desktop\\xxx.xls");
But for objWorkbook.Worksheets(1).SaveAs("%USERPROFILE%\\Desktop\\xxx.xls"); — it doesn't save to desktop and gives this error:
SCRIPT1004: Microsoft Excel cannot access the file 'C:\Users\user\Documents\%USERPROFILE%\Desktop\B612F000'. There are several possible reasons:
• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.
From #PA. Answer
I finally got an answer by
//For Expand environment
var wshShell = new ActiveXObject("WScript.Shell");
var userProfile = wshShell.ExpandEnvironmentStrings("%USERPROFILE%\\Desktop\\test.xls");
//For Save
objWorkbook.Worksheets(1).SaveAs(userProfile);
Thak You #PA.
You assume that javascript expands environment variables inside an string. Unfortunately for you, it does not.
you'll need to expand it in your code. Use the Environment property of the wscript.shell object to access any environment variable.
first, access the wscript.shell object. In WSH, use
var wshell = WScript.CreateObject("wscript.shell");
or in the browser use
var wshell = new ActiveXObject("WScript.Shell");
and then
var userProfile = wshell.Environment("USERPROFILE");
or you can expand the variable inside your string by using ExpandEnvironmentStrings method
objWorkbook.Worksheets(1).SaveAs(
wshell.ExpandEnvironmentStrings("%USERPROFILE%\\Desktop\\xxx.xls")
);

JSON syntax error on Windows 2008

I'm trying to implement a JSON call to simulate AJAX on a certain page where an AJAX panel isn't a viable option.
I want call my .aspx page when a State is selected from a drop down and populate the Counties drop down.
in my State dropdown, I have this call:
onchange="jsonDropDownLoader('COUNTIES', this, 'Content2_DDLCounties')"
That call is on the page and the code is here:
function jsonDropDownLoader(sType, oParent, oChild) {
var lstrChild = document.getElementById(oChild);
var lstrFilter = ""
if (oParent.value > "") {
lstrFilter = oParent.value
}
lstrChild.options.length = 0;
if (oParent.value > "") {
var JSONobject = {};
var http_request = new XMLHttpRequest();
url = "/AltairWeb.NET/RS/jsonDropDownLoader.aspx?TYPE=" + sType + "&FILTER=" + lstrFilter
http_request.open("GET", url, false);
http_request.onreadystatechange = function () {
var done = 4, ok = 200;
if (http_request.readyState == done && http_request.status == ok) {
JSONobject = JSON.parse(http_request.responseText);
}
};
http_request.send(null);
var JSONarray = eval('(' + http_request.responseText + ')').data
for (var i = 0; i < JSONarray.length; ++i) {
var optn = document.createElement("OPTION");
optn.text = JSONarray[i].text;
optn.value = JSONarray[i].value;
lstrChild.options.add(optn);
}
}
}
It returns a string which I then use to populate the County drop down.
I'm getting data back, but it's not rendering on your QA server. Using the developer tools with IE8, I can see that I have a error on this line:
JSONobject = JSON.parse(http_request.responseText);
it says that JSON is not declared.
It says I also have a syntax error on this line:
var JSONarray = eval('(' + http_request.responseText + ')').data
This works perfectly on my development box. However, my development box has WinXP / IIS 5 on it, whereas, our QA server is a Win2008 server with IIS7.5. We have new development boxes coming, but until then, I'm stuck with the XP machine.
Since it works locally, it seems like it must be a security issue with either Windows or IIS on the QA server, possibly with the http_request call, but I can't find anything via google that has helped me figure this out.
I know I've seen posts that JSON.parse is not supported by IE prior to IE9, but this works perfectly in IE8 when I point to my dev server, but not when I point to the QA server, so it doesn't seem to be a browser issue.
Any ideas?
JSON.parse() is a function of your browser, not the server.
Are you sure the difference is the server ... and not your client browser???
You might also wish to consider using something like jQuery (which can both simplify your coding, and help mediate cross-browser issues like this). for example:
Parse JSON in JavaScript?
var json = '{"result":true,"count":1}',
obj = JSON && JSON.parse(json) || $.parseJSON(json);
First, you are using a synchronous call (xhr.open('GET', url, false)) , and you are also using onreadystatechange . This is wrong. Choose one or the other.
https://developer.mozilla.org/en/xmlhttprequest
Next, check your browser support for JSON. See https://stackoverflow.com/a/891306/48082 .
If you are unsure, then use json2.js from json.org.
Finally, do not use eval. Use a proper JSON library.

Categories

Resources