diff --git a/devtools/client/shared/components/frame.js b/devtools/client/shared/components/frame.js index d673ccc053a9..7070994b61fe 100644 --- a/devtools/client/shared/components/frame.js +++ b/devtools/client/shared/components/frame.js @@ -176,7 +176,8 @@ module.exports = createClass({ if (functionDisplayName) { elements.push( dom.span({ className: "frame-link-function-display-name" }, - functionDisplayName) + functionDisplayName), + " " ); } } @@ -236,7 +237,7 @@ module.exports = createClass({ elements.push(sourceEl); if (showHost && host) { - elements.push(dom.span({ className: "frame-link-host" }, host)); + elements.push(" ", dom.span({ className: "frame-link-host" }, host)); } return dom.span(attributes, ...elements); diff --git a/devtools/client/shared/components/stack-trace.js b/devtools/client/shared/components/stack-trace.js index 9818d36d106e..511b4762618d 100644 --- a/devtools/client/shared/components/stack-trace.js +++ b/devtools/client/shared/components/stack-trace.js @@ -42,12 +42,12 @@ const StackTrace = createClass({ let frames = []; stacktrace.forEach(s => { if (s.asyncCause) { - frames.push(AsyncFrame({ + frames.push("\t", AsyncFrame({ asyncCause: s.asyncCause - })); + }), "\n"); } - frames.push(Frame({ + frames.push("\t", Frame({ frame: { functionDisplayName: s.functionName, source: s.filename.split(" -> ").pop(), @@ -58,7 +58,7 @@ const StackTrace = createClass({ showAnonymousFunctionName: true, showFullSourceUrl: true, onClick: onViewSourceInDebugger - })); + }), "\n"); }); return dom.div({ className: "stack-trace" }, frames); diff --git a/devtools/client/webconsole/console-output.js b/devtools/client/webconsole/console-output.js index 46bc29650bb1..56ef65f956dd 100644 --- a/devtools/client/webconsole/console-output.js +++ b/devtools/client/webconsole/console-output.js @@ -935,8 +935,6 @@ Messages.Simple.prototype = extend(Messages.BaseMessage.prototype, { this.element.appendChild(body); - this.element.appendChild(this.document.createTextNode("\n")); - this.element.clipboardText = this.element.textContent; if (this.private) { @@ -993,12 +991,16 @@ Messages.Simple.prototype = extend(Messages.BaseMessage.prototype, { let location = this._renderLocation(); if (repeatNode) { + bodyFlex.appendChild(this.document.createTextNode(" ")); bodyFlex.appendChild(repeatNode); } if (location) { + bodyFlex.appendChild(this.document.createTextNode(" ")); bodyFlex.appendChild(location); } + bodyFlex.appendChild(this.document.createTextNode("\n")); + if (this.stack) { this._attachment = new Widgets.Stacktrace(this, this.stack).render().element; } diff --git a/devtools/client/webconsole/test/browser_console_copy_entire_message_context_menu.js b/devtools/client/webconsole/test/browser_console_copy_entire_message_context_menu.js index 966f4308afff..bdd4f71793f2 100644 --- a/devtools/client/webconsole/test/browser_console_copy_entire_message_context_menu.js +++ b/devtools/client/webconsole/test/browser_console_copy_entire_message_context_menu.js @@ -3,67 +3,95 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +/* globals goDoCommand */ + "use strict"; // Test copying of the entire console message when right-clicked // with no other text selected. See Bug 1100562. -function test() { +add_task(function* () { let hud; let outputNode; let contextMenu; - const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + - "test/test-console.html"; + const TEST_URI = "http://example.com/browser/devtools/client/webconsole/test/test-console.html"; - Task.spawn(runner).then(finishTest); + const { tab, browser } = yield loadTab(TEST_URI); + hud = yield openConsole(tab); + outputNode = hud.outputNode; + contextMenu = hud.iframeWindow.document.getElementById("output-contextmenu"); - function* runner() { - const {tab} = yield loadTab(TEST_URI); - hud = yield openConsole(tab); - outputNode = hud.outputNode; - contextMenu = hud.iframeWindow.document.getElementById("output-contextmenu"); + registerCleanupFunction(() => { + hud = outputNode = contextMenu = null; + }); - registerCleanupFunction(() => { - hud = outputNode = contextMenu = null; - }); + hud.jsterm.clearOutput(); - hud.jsterm.clearOutput(); - content.console.log("bug 1100562"); + yield ContentTask.spawn(browser, {}, function* () { + let button = content.document.getElementById("testTrace"); + button.click(); + }); - let [results] = yield waitForMessages({ - webconsole: hud, - messages: [{ + let results = yield waitForMessages({ + webconsole: hud, + messages: [ + { text: "bug 1100562", category: CATEGORY_WEBDEV, severity: SEVERITY_LOG, - }] - }); + lines: 1, + }, + { + name: "console.trace output", + consoleTrace: true, + lines: 3, + }, + ] + }); - outputNode.focus(); - let message = [...results.matched][0]; + outputNode.focus(); - yield waitForContextMenu(contextMenu, message, copyFromPopup, - testContextMenuCopy); + for (let result of results) { + let message = [...result.matched][0]; - function copyFromPopup() { + yield waitForContextMenu(contextMenu, message, () => { let copyItem = contextMenu.querySelector("#cMenu_copy"); copyItem.doCommand(); let controller = top.document.commandDispatcher .getControllerForCommand("cmd_copy"); is(controller.isCommandEnabled("cmd_copy"), true, "cmd_copy is enabled"); - } + }); - function testContextMenuCopy() { - waitForClipboard((str) => { - return message.textContent.trim() == str.trim(); - }, () => { - goDoCommand("cmd_copy"); - }, () => {}, () => {} - ); - } + let clipboardText; - yield closeConsole(tab); + yield waitForClipboardPromise( + () => goDoCommand("cmd_copy"), + (str) => { + clipboardText = str; + return message.textContent == clipboardText; + } + ); + + ok(clipboardText, "Clipboard text was found and saved"); + + let lines = clipboardText.split("\n"); + ok(lines.length > 0, "There is at least one newline in the message"); + is(lines.pop(), "", "There is a newline at the end"); + is(lines.length, result.lines, `There are ${result.lines} lines in the message`); + + // Test the first line for "timestamp message repeat file:line" + let firstLine = lines.shift(); + ok(/^[\d:.]+ .+ \d+ .+:\d+$/.test(firstLine), + "The message's first line has the right format"); + + // Test the remaining lines (stack trace) for "TABfunctionName sourceURL:line:col" + for (let line of lines) { + ok(/^\t.+ .+:\d+:\d+$/.test(line), "The stack trace line has the right format"); + } } -} + + yield closeConsole(tab); + yield finishTest(); +}); diff --git a/devtools/client/webconsole/test/test-console.html b/devtools/client/webconsole/test/test-console.html index 9731c86a9fd5..b294a3ba1cfd 100644 --- a/devtools/client/webconsole/test/test-console.html +++ b/devtools/client/webconsole/test/test-console.html @@ -13,6 +13,12 @@ console.log(str); } } + + function testTrace() { + console.log("bug 1100562"); + console.trace(); + } + console.info("INLINE SCRIPT:"); test(); console.warn("I'm warning you, he will eat up all yr bacon."); @@ -22,6 +28,7 @@