summaryrefslogtreecommitdiffstats
path: root/remote/shared/listeners/test/browser/browser_ConsoleAPIListener.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--remote/shared/listeners/test/browser/browser_ConsoleAPIListener.js162
1 files changed, 162 insertions, 0 deletions
diff --git a/remote/shared/listeners/test/browser/browser_ConsoleAPIListener.js b/remote/shared/listeners/test/browser/browser_ConsoleAPIListener.js
new file mode 100644
index 0000000000..ccff78c7a0
--- /dev/null
+++ b/remote/shared/listeners/test/browser/browser_ConsoleAPIListener.js
@@ -0,0 +1,162 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const TESTS = [
+ { method: "log", args: ["log1"] },
+ { method: "log", args: ["log2", "log3"] },
+ { method: "log", args: [[1, 2, 3], { someProperty: "someValue" }] },
+ { method: "warn", args: ["warn1"] },
+ { method: "error", args: ["error1"] },
+ { method: "info", args: ["info1"] },
+ { method: "debug", args: ["debug1"] },
+ { method: "trace", args: ["trace1"] },
+ { method: "assert", args: [false, "assert1"] },
+];
+
+const TEST_PAGE = "https://example.com/document-builder.sjs?html=tab";
+
+add_task(async function test_method_and_arguments() {
+ for (const { method, args } of TESTS) {
+ // Use a dedicated tab for each test to avoid cached messages.
+ gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TEST_PAGE);
+ await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+
+ info(`Test ConsoleApiListener for ${JSON.stringify({ method, args })}`);
+
+ const listenerId = await listenToConsoleAPIMessage();
+ await useConsoleInContent(method, args);
+ const {
+ arguments: msgArguments,
+ level,
+ timeStamp,
+ stacktrace,
+ } = await getConsoleAPIMessage(listenerId);
+
+ if (method == "assert") {
+ // console.assert() consumes first argument.
+ args.shift();
+ }
+
+ is(
+ msgArguments.length,
+ args.length,
+ "Message event has the expected number of arguments"
+ );
+ for (let i = 0; i < args.length; i++) {
+ Assert.deepEqual(
+ msgArguments[i],
+ args[i],
+ `Message event has the expected argument at index ${i}`
+ );
+ }
+ is(level, method, "Message event has the expected level");
+ ok(Number.isInteger(timeStamp), "Message event has a valid timestamp");
+
+ if (["assert", "error", "warn", "trace"].includes(method)) {
+ // Check stacktrace if method is allowed to contain one.
+ if (method === "warn") {
+ todo(
+ Array.isArray(stacktrace),
+ "stacktrace is of expected type Array (Bug 1744705)"
+ );
+ } else {
+ ok(Array.isArray(stacktrace), "stacktrace is of expected type Array");
+ Assert.greaterOrEqual(
+ stacktrace.length,
+ 1,
+ "stack trace contains at least one frame"
+ );
+ }
+ } else {
+ is(typeof stacktrace, "undefined", "stack trace is is not present");
+ }
+
+ gBrowser.removeTab(gBrowser.selectedTab);
+ }
+});
+
+add_task(async function test_stacktrace() {
+ const script = `
+ function foo() { console.error("cheese"); }
+ function bar() { foo(); }
+ bar();
+ `;
+
+ const listenerId = await listenToConsoleAPIMessage();
+ await createScriptNode(script);
+ const { stacktrace } = await getConsoleAPIMessage(listenerId);
+
+ ok(Array.isArray(stacktrace), "stacktrace is of expected type Array");
+
+ // First 3 frames are from the test script.
+ Assert.greaterOrEqual(
+ stacktrace.length,
+ 3,
+ "stack trace contains at least 3 frames"
+ );
+ checkStackFrame(stacktrace[0], "about:blank", "foo", 2, 30);
+ checkStackFrame(stacktrace[1], "about:blank", "bar", 3, 22);
+ checkStackFrame(stacktrace[2], "about:blank", "", 4, 5);
+});
+
+function useConsoleInContent(method, args) {
+ info(`Call console API: console.${method}("${args.join('", "')}");`);
+ return SpecialPowers.spawn(
+ gBrowser.selectedBrowser,
+ [method, args],
+ (_method, _args) => {
+ content.console[_method].apply(content.console, _args);
+ }
+ );
+}
+
+function listenToConsoleAPIMessage() {
+ info("Listen to a console api message in content");
+ return SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
+ const innerWindowId = content.windowGlobalChild.innerWindowId;
+ const { ConsoleAPIListener } = ChromeUtils.importESModule(
+ "chrome://remote/content/shared/listeners/ConsoleAPIListener.sys.mjs"
+ );
+ const consoleAPIListener = new ConsoleAPIListener(innerWindowId);
+ const onMessage = consoleAPIListener.once("message");
+ consoleAPIListener.startListening();
+
+ const listenerId = Math.random();
+ content[listenerId] = { consoleAPIListener, onMessage };
+ return listenerId;
+ });
+}
+
+function getConsoleAPIMessage(listenerId) {
+ info("Retrieve the message event captured for listener: " + listenerId);
+ return SpecialPowers.spawn(
+ gBrowser.selectedBrowser,
+ [listenerId],
+ async _listenerId => {
+ const { consoleAPIListener, onMessage } = content[_listenerId];
+ const message = await onMessage;
+
+ consoleAPIListener.destroy();
+
+ return message;
+ }
+ );
+}
+
+function checkStackFrame(
+ frame,
+ filename,
+ functionName,
+ lineNumber,
+ columnNumber
+) {
+ is(frame.filename, filename, "Received expected filename for frame");
+ is(
+ frame.functionName,
+ functionName,
+ "Received expected function name for frame"
+ );
+ is(frame.lineNumber, lineNumber, "Received expected line for frame");
+ is(frame.columnNumber, columnNumber, "Received expected column for frame");
+}