diff options
Diffstat (limited to 'devtools/client/webconsole/test/browser/browser_webconsole_context_menu_export_console_output.js')
-rw-r--r-- | devtools/client/webconsole/test/browser/browser_webconsole_context_menu_export_console_output.js | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_context_menu_export_console_output.js b/devtools/client/webconsole/test/browser/browser_webconsole_context_menu_export_console_output.js new file mode 100644 index 0000000000..19ae6e2a3f --- /dev/null +++ b/devtools/client/webconsole/test/browser/browser_webconsole_context_menu_export_console_output.js @@ -0,0 +1,197 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const httpServer = createTestHTTPServer(); +httpServer.registerPathHandler(`/`, function (request, response) { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.write(` + <html> + <head> + <meta charset="utf-8"> + <script type="text/javascript" src="test.js"></script> + </head> + <body>Test "Export All" context menu entry</body> + </html>`); +}); + +httpServer.registerPathHandler("/test.js", function (request, response) { + response.setHeader("Content-Type", "application/javascript"); + response.write(` + window.logStuff = function() { + function wrapper() { + console.log("hello"); + console.log("myObject:", {a: 1}, "myArray:", ["b", "c"]); + console.log(new Error("error object")); + console.trace("myConsoleTrace"); + console.info("world", "!"); + /* add enough messages to trigger virtualization */ + for (let i = 0; i < 100; i++) { + console.log("item-"+i); + } + } + wrapper(); + }; + `); +}); + +const TEST_URI = `http://localhost:${httpServer.identity.primaryPort}/`; + +const { MockFilePicker } = SpecialPowers; +MockFilePicker.init(window); +MockFilePicker.returnValue = MockFilePicker.returnOK; + +var FileUtils = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs" +).FileUtils; + +// Test the export visible messages to clipboard of the webconsole copies the expected +// clipboard text for different log messages to find if everything is copied to clipboard. + +add_task(async function testExportToClipboard() { + // Clear clipboard content. + SpecialPowers.clipboardCopyString(""); + // Display timestamp to make sure we export them (there's a container query that would + // hide them in the regular case, which we don't want). + await pushPref("devtools.webconsole.timestampMessages", true); + + const hud = await openNewTabAndConsole(TEST_URI); + await clearOutput(hud); + + info("Call the log function defined in the test page"); + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () { + content.wrappedJSObject.logStuff(); + }); + + info("Test export to clipboard "); + // Let's wait until we have all the logged messages. + const lastMessage = await waitFor(() => + findConsoleAPIMessage(hud, "item-99") + ); + + const clipboardText = await exportAllToClipboard(hud, lastMessage); + ok(true, "Clipboard text was found and saved"); + + checkExportedText(clipboardText); + + info("Test export to file"); + const fileText = await exportAllToFile(hud, lastMessage); + checkExportedText(fileText); +}); + +function checkExportedText(text) { + // Here we should have: + // ----------------------------------------------------- + // hello test.js:4:17 + // ----------------------------------------------------- + // myObject: + // Object { a: 1 } + // myArray: + // Array [ "b", "c"] + // test.js:5:17 + // ----------------------------------------------------- + // Error: error object + // wrapper test.js:5 + // logStuff test.js:14 + // test.js:6:17 + // ----------------------------------------------------- + // console.trace() myConsoleTrace test.js:7:9 + // wrapper test.js:7 + // logStuff test.js:14 + // ----------------------------------------------------- + // world ! test.js:8:17 + // ----------------------------------------------------- + // item-0 test.js:11:19 + // ----------------------------------------------------- + // item-1 test.js:11:19 + // ----------------------------------------------------- + // […] + // ----------------------------------------------------- + // item-99 test.js:11:19 + // ----------------------------------------------------- + info("Check if all messages where exported as expected"); + let lines = text.split("\n").map(line => line.replace(/\r$/, "")); + + is(lines.length, 115, "There's 115 lines of text"); + is(lines.at(-1), "", "Last line is empty"); + + info("Check that timestamp are displayed"); + const timestampRegex = /^\d{2}:\d{2}:\d{2}\.\d{3} /; + // only check the first message + ok(timestampRegex.test(lines[0]), "timestamp are included in the messages"); + lines = lines.map(l => l.replace(timestampRegex, "")); + + info("Check simple text message"); + is(lines[0], "hello test.js:4:17", "Simple log has expected text"); + + info("Check multiple logged items message"); + is(lines[1], `myObject: `); + is(lines[2], `Object { a: 1 }`); + is(lines[3], ` myArray: `); + is(lines[4], `Array [ "b", "c" ]`); + is(lines[5], `test.js:5:17`); + + info("Check logged error object"); + is(lines[6], `Error: error object`); + is(lines[7], ` wrapper ${TEST_URI}test.js:6`); + is(lines[8], ` logStuff ${TEST_URI}test.js:14`); + is(lines[9], `test.js:6:17`); + + info("Check console.trace message"); + is(lines[10], `console.trace() myConsoleTrace test.js:7:17`); + is(lines[11], ` wrapper ${TEST_URI}test.js:7`); + is(lines[12], ` logStuff ${TEST_URI}test.js:14`); + + info("Check console.info message"); + is(lines[13], `world ! test.js:8:17`); + + const numberMessagesStartIndex = 14; + for (let i = 0; i < 100; i++) { + is( + lines[numberMessagesStartIndex + i], + `item-${i} test.js:11:19`, + `Got expected text for line ${numberMessagesStartIndex + i}` + ); + } +} + +async function exportAllToFile(hud, message) { + const menuPopup = await openContextMenu(hud, message); + const exportFile = menuPopup.querySelector("#console-menu-export-file"); + ok(exportFile, "copy menu item is enabled"); + + const nsiFile = FileUtils.getFile("TmpD", [ + `export_console_${Date.now()}.log`, + ]); + MockFilePicker.setFiles([nsiFile]); + exportFile.click(); + info("Exporting to file"); + + menuPopup.hidePopup(); + + // The file may not be ready yet. + await waitFor(() => IOUtils.exists(nsiFile.path)); + const buffer = await IOUtils.read(nsiFile.path); + return new TextDecoder().decode(buffer); +} + +/** + * Simple helper method to open the context menu on a given message, and click on the + * export visible messages to clipboard. + */ +async function exportAllToClipboard(hud, message) { + const menuPopup = await openContextMenu(hud, message); + const exportClipboard = menuPopup.querySelector( + "#console-menu-export-clipboard" + ); + ok(exportClipboard, "copy menu item is enabled"); + + const clipboardText = await waitForClipboardPromise( + () => exportClipboard.click(), + data => data.includes("hello") + ); + + menuPopup.hidePopup(); + return clipboardText; +} |