Retrieving console log from Firefox 43 with Selenium without Firefox extensions - javascript

Is it possible to retrieve the browsers console.log with Selenium and Firefox 43? If so, how?
Here are my settings:
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
LoggingPreferences logs = new LoggingPreferences();
logs.enable(LogType.BROWSER, Level.ALL);
logs.enable(LogType.DRIVER, Level.ALL);
logs.enable(LogType.CLIENT, Level.ALL);
logs.enable(LogType.PERFORMANCE, Level.ALL);
logs.enable(LogType.PROFILER, Level.ALL);
logs.enable(LogType.SERVER, Level.ALL);
capabilities.setCapability(CapabilityType.LOGGING_PREFS, logs);
FirefoxBinary binary = new FirefoxBinary(new File(...));
FirefoxProfile profile = new FirefoxProfile();
WebDriver driver = new FirefoxDriver(binary, profile, capabilities);
//...doing things with the driver ...
driver.manage().logs().get(LogType.BROWSER) // already tried every LogType
The only output i get from this is something like:
1450878255029 addons.xpi DEBUG startup
...
Error in parsing value for 'display'. Declaration dropped.
But not the output which is written in the browsers javascript console log.
I already tried several FF profile settings like:
profile.setPreference("extensions.sdk.console.logLevel", "all");
profile.setPreference("webdriver.log.file",tempfile.getAbsolutePath());
profile.setPreference("webdriver.firefox.logfile", othertempfile.getAbsolutePath());
profile.setPreference("webdriver.log.driver", "ALL");
Nothing helped so far.
In Chrome this is working flawlessly.
Selenium version: 2.48.2
Firefox version: 43.0.2

I had the same issue. I only got all that log noise about css, security, network and what not, but not what was actually logged by the app through console.log. I am using the same version for webdriver and firefox you do. For other browsers this was not a problem.
I ended up extending my client code with custom log recording. Speaking in wire protocol terms:
use execute to put something like the following into the client
window.recordedLogs = [];
console.log = function (message) {
if (typeof message === 'object') {
message = JSON.stringify(message);
}
window.recordedLogs.push(message);
};
use execute to retrieve window.recordedLogs
Warning: the above code is very simplistic, it does not take care of multiple messages passed to the log method, nor does it handle other log methods like info, error, etc.
However it can be a good multi-browser-compliant alternative to the wire protocol log method.

Related

WebDriverError: Unknown error, while opening second edge window using Selenium(Javsacript)

I am creating automation tool for Edge Browser using selenium, where I need to open three edge window with three different URLs parallelly.
First Edge browser window launch successfully, but when calling function openEdgeBrowser for second url, it throws Exception: WebDriverError: Unknown error.
const webdriver = require('selenium-webdriver');
const edgedriver = require('edgedriver');
const edge = require('selenium-webdriver/edge');
var openEdgeBrowser = async function(url){
try {
let edgeService = await new edge.ServiceBuilder(edgedriver.path);
let browser = await new webdriver.Builder().forBrowser('MicrosoftEdge').setEdgeService(edgeService).build();
await browser.get(url);
console.log('Browser launched successfully with url: ' + url);
} catch(e) {
console.log.end(`Error in launching edge browser, Exception: ${e}`);
}
};
I expect to run three instances of Edge together.
The problem is that Edge does not support multiple instances:
Hi, This is a known issue.
I just checked the Feedback Hub and I only
see a Microsoft internal posting for this issue. Will you add this to
the Feedback Hub? Open the Feedback Hub app by using the Search Bar
(Win + s) and typing “feedback hub”
The only workaround I am aware of
is to use Selenium grid with multiple Windows Clients. The Clients
can be Hyper-V instances.
Appreciate you reporting this issue and wish
I had a better answer for you. :-/ Steve
https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/17754737/
The same has also been noted on twitter.
https://twitter.com/instylevii/status/783480823445987329
I can't find any indication that this bug has been fixed, so I'm going to assume it's still outstanding. It was definitely still outstanding in version 41.16299.15.0 and I can't find anything in the release notes mentioning a fix In version 42.

Reloading and debugging JavaScript in TVOS simulator

I have started looking at tutorials for making TVML/TVJS based apps for the new Apple TV, and I have two problems that makes the development process very tedious and impractical.
First thing I am having trouble understanding is how I am supposed to debug code that happens on startup of the application. I have connected the Safari debugger, and I do manage to hit some breakpoints, but only for code that is triggered by some user input. On startup I am loading an xml document from a remote location, and I will use this to dynamically generate the tvml template, but I cannot get the debugger to stop anywhere in the code that is running before the template is done rendering.
The other anti-productive problem I have is that I cannot seem to reload the JavaScript files in any other way than completely shutting down the application in the simulator (double-click the home button, and swipe the app away). This also makes the debugger quit, so I have to restart that one as well. This surely cannot be the way you are supposed to do continuous development and testing?
You can make the debugger stop at the first line when you choose the Auto Pause and Auto Show options from the Safari menu "Develop/Simulator".
You are correct about the exit issue.
One thing you can also try is to run App.reload() from the Safari Debugger console.
This also restarts the app, maybe in the future they can make it work so the debugger will not be gone.
But at the moment this also does not solve the issue.
For manual debugger output (aka console.log()), you could redirect the logging to the Xcode debugger.
(somewhere on the web) I found a way to actually do that, in short it looks like...
AppDelegate.Swift
func appController(appController: TVApplicationController, evaluateAppJavaScriptInContext jsContext: JSContext) {
let jsInterface: cJsInterface = cJsInterface();
jsContext.setObject(jsInterface, forKeyedSubscript: "swiftInterface")
}
App.js
// re-route console.log() to XCode debug window
var console = {
log: function() {
var message = '';
for(var i = 0; i < arguments.length; i++) {
message += arguments[i] + ' '
};
swiftInterface.log(message)
}
};
JsInterface.Swift
#objc protocol jsInterfaceProtocol : JSExport {
func log(message: String) -> Void
}
...
class cJsInterface: NSObject, jsInterfaceProtocol {
func log(message: String) -> Void {
print("JS: \(message)")
}
}
Complete sources in github: https://github.com/iBaa/PlexConnectApp/tree/f512dfd9c1cb2fbfed2da43c4e3837435b0b22af
I don't have any solution for the dying debugger myself...

Inspecting WebSocket frames in an undetectable way

How I can read WebSocket frames of a web page in a Chrome extension or Firefox add-on, in a way that cannot be detected by the page?
Inspect WebSockets frames from a Chrome Dev Tools extension formulates a similar question, but developing a NPAPI plugin no longer makes sense because it will soon be removed.
Intercepting the WebSocket data is easy. Simply execute the following script before the page constructs the WebSocket. This snippet monkey-patches the WebSocket constructor: When a new WebSocket constructor is created, the snippet subscribes to the message event, from where you can do whatever you want with the data.
This snippet is designed to be indistinguishable from native code so the modification cannot easily be detected by the page (however, see the remarks at the end of this post).
(function() {
var OrigWebSocket = window.WebSocket;
var callWebSocket = OrigWebSocket.apply.bind(OrigWebSocket);
var wsAddListener = OrigWebSocket.prototype.addEventListener;
wsAddListener = wsAddListener.call.bind(wsAddListener);
window.WebSocket = function WebSocket(url, protocols) {
var ws;
if (!(this instanceof WebSocket)) {
// Called without 'new' (browsers will throw an error).
ws = callWebSocket(this, arguments);
} else if (arguments.length === 1) {
ws = new OrigWebSocket(url);
} else if (arguments.length >= 2) {
ws = new OrigWebSocket(url, protocols);
} else { // No arguments (browsers will throw an error)
ws = new OrigWebSocket();
}
wsAddListener(ws, 'message', function(event) {
// TODO: Do something with event.data (received data) if you wish.
});
return ws;
}.bind();
window.WebSocket.prototype = OrigWebSocket.prototype;
window.WebSocket.prototype.constructor = window.WebSocket;
var wsSend = OrigWebSocket.prototype.send;
wsSend = wsSend.apply.bind(wsSend);
OrigWebSocket.prototype.send = function(data) {
// TODO: Do something with the sent data if you wish.
return wsSend(this, arguments);
};
})();
In a Chrome extension, the snippet can be run via a content script with run_at:'document_start', see Insert code into the page context using a content script.
Firefox also supports content scripts, the same logic applies (with contentScriptWhen:'start').
Note: The previous snippet is designed to be indistinguishable from native code when executed before the rest of the page. The only (unusual and fragile) ways to detect these modifications are:
Pass invalid parameters to the WebSocket constructor, catch the error and inspecting the implementation-dependent (browser-specific) stack trace. If there is one more stack frame than usual, then the constructor might be tampered (seen from the page's perspective).
Serialize the constructor. Unmodified constructors become function WebSocket() { [native code] }, whereas a patched constructor looks like function () { [native code] } (this issue is only present in Chrome; in Firefox, the serialization is identical).
Serialize the WebSocket.prototype.send method. Since the function is not bound, serializing it (WebSocket.prototype.send.toString()) reveals the non-native implementation. This could be mitigated by overriding the .toString method of .send, which in turn can be detected by the page by a strict comparison with Function.prototype.toString. If you don't need the sent data, do not override OrigWebSocket.prototype.send.
There is an alternative to Rob W's method that completely masks any interaction with the page (for Chrome)
Namely, you can take out some heavy artillery and use chrome.debugger.
Note that using it will stop you from opening Dev Tools for the page in question (or, more precisely, opening the Dev Tools will make it stop working, since only one debugger client can connect). This has been improved since: multiple debuggers can be attached.
This is a pretty low-level API; you'll need to construct your queries using the debugger protocol yourself. Also, the corresponding events are not in the 1.1 documentation, you'll need to look at the development version.
You should be able to receive WebSocket events like those and examine their payloadData:
{"method":"Network.webSocketFrameSent","params":{"requestId":"3080.31","timestamp":18090.353684,"response":{"opcode":1,"mask":true,"payloadData":"Rock it with HTML5 WebSocket"}}}
{"method":"Network.webSocketFrameReceived","params":{"requestId":"3080.31","timestamp":18090.454617,"response":{"opcode":1,"mask":false,"payloadData":"Rock it with HTML5 WebSocket"}}}
This extension sample should provide a starting point.
In fact, here's a starting point, assuming tabId is the tab you're interested in:
chrome.debugger.attach({tabId:tab.id}, "1.1", function() {
chrome.debugger.sendCommand({tabId:tabId}, "Network.enable");
chrome.debugger.onEvent.addListener(onEvent);
});
function onEvent(debuggeeId, message, params) {
if (tabId != debuggeeId.tabId)
return;
if (message == "Network.webSocketFrameSent") {
// do something with params.response.payloadData,
// it contains the data SENT
} else if (message == "Network.webSocketFrameReceived") {
// do something with params.response.payloadData,
// it contains the data RECEIVED
}
}
I have tested this approach (with the linked sample modified as above) and it works.
Just to add an exception to #Xan answer (I don't have enough rep to post a comment on his answer so I add it here cause I believe it can save some time to someone else).
That example won't work if the WebSocket connection is established in a context that was loaded via about:, data: and blob: schemes.
See here for the related bugs: Attach debugger to worker from chrome devtools extension

javascript. formatting console.log

I´m working on a big angular.js project.
Now, I´ve to profile some pages about the performance.
With the console.log of the project I´m looking for the performance problems.
I miss if console.log can output the current time (yes, I know in Chrome you can set up).
Is there a way (like in log4java) to format the output?
Thanks in advance,
Be careful, the console object should not be activated in production mainly because it can breaks the code for some users (for example IE8 or less users).
But if you want to test on a tool that you know, you can use the Web API interface which provides some useful method on this object:
https://developer.mozilla.org/en-US/docs/Web/API/Console
(This doc is from the Mozilla Developer Network (MDN) and therefore mainly applies to Firefox, but at the end of that page you can find links to the corresponding docs for the IE, Chrome and Safari DevTools as well as Firebug).
For example, you can use the time() method for your use case:
console.time("answer time");
// ... some other code
console.timeEnd("answer time");
Outputs something like this:
You could try something like this:
console = window.console ? console : {};
native_log = console.log;
window.console.log = function myConsole() {
// Cannot log if console.log is not present natively,
// so fail silently (in IE without debugger opened)
if (!native_log)
return;
var args = Array.prototype.slice.call(arguments);
args.unshift(new Date());
native_log.apply(console, args);
}
console.log('hello'); // Date 2014-12-02T14:14:50.138Z "hello"
Of course, you would not let the new Date() as is, but it gives you the idea.

Parallel.js have problems with Blob in IE

I need to execute functions in "parallel" and I use parallel.js:
var p = new Parallel(items);
var fn1 = function (item) {
doSomething(item);
};
p.map(fn1).then(function () {
otherFunction();
});
But IE shows the following error:
[Q] Unhandled rejection reasons (should be empty): (no stack) SecurityError
HTML7007: One or more blob URLs were revoked by closing the blob
for which they were created. These URLs will no longer resolve as
the data backing the URL has been freed.
How to fix this error?
I had review parallel.js page in IE and all examples work fine.
I use Durandal, Breeze and Knockout.
In Firefox shows the following error:
[Q] Unhandled rejection reasons (should be empty):
["(no stack) [Exception..... location: "<unknown>"]"]
and in Google Chrome no shows error, but parallel.js no work.
In case you're still having trouble with this, to make Parallel.js work in Internet Explorer you have to include the evalPath option, as mentioned on the website:
evalPath (optional): This is the path to the file eval.js. This is
required when running in node, and required when requiring files in
browser environments (to work around cross-domain restrictions for web
workers in IE 10).
This also applies to IE 11.
So your code will become:
var p = new Parallel(items, {evalPath: [PATH_TO_EVAL_JS]});
Where [PATH_TO_EVAL_JS] points to eval.js.

Categories

Resources