Bug 659625 - part2: implement console.clear in devtools webconsole;r=bgrins
☠☠ backed out by 3d003731a97b ☠ ☠
authorJulian Descottes <jdescottes@mozilla.com>
Tue, 12 Apr 2016 08:09:41 +0200
changeset 330828 671011b82100a598dd8368205bd625227bfdc060
parent 330827 89cfa8c724e1fcb0909e1414b6051dbd62b40105
child 330829 0b2c8e57a6ebe93e58bb598ece22faaa7da9f591
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs659625
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 659625 - part2: implement console.clear in devtools webconsole;r=bgrins When receiving a console clear message, the webconsole should clear the UI: remove all messages until the clear() message and close the variables view sidebar if opened. Add one integration tests to test console.clear calls from the content page. MozReview-Commit-ID: GnBCBSmN1rk
devtools/client/locales/en-US/webconsole.properties
devtools/client/webconsole/console-output.js
devtools/client/webconsole/test/browser.ini
devtools/client/webconsole/test/browser_console_clear_method.js
devtools/client/webconsole/test/test-console-clear.html
devtools/client/webconsole/webconsole.js
--- a/devtools/client/locales/en-US/webconsole.properties
+++ b/devtools/client/locales/en-US/webconsole.properties
@@ -102,16 +102,21 @@ stacktrace.asyncStack=(Async: %S)
 # of the console.time() call. Parameters: %S is the name of the timer.
 timerStarted=%S: timer started
 
 # LOCALIZATION NOTE (timeEnd): this string is used to display the result of
 # the console.timeEnd() call. Parameters: %1$S is the name of the timer, %2$S
 # is the number of milliseconds.
 timeEnd=%1$S: %2$Sms
 
+# LOCALIZATION NOTE (consoleCleared): this string is displayed when receiving a
+# call to console.clear() to let the user know the previous messages of the
+# console have been removed programmatically.
+consoleCleared=Console was cleared.
+
 # LOCALIZATION NOTE (noCounterLabel): this string is used to display
 # count-messages with no label provided.
 noCounterLabel=<no label>
 
 # LOCALIZATION NOTE (Autocomplete.blank): this string is used when inputnode
 # string containing anchor doesn't matches to any property in the content.
 Autocomplete.blank=  <- no result
 
--- a/devtools/client/webconsole/console-output.js
+++ b/devtools/client/webconsole/console-output.js
@@ -88,16 +88,17 @@ const COMPAT = {
 // A map from the console API call levels to the Web Console severities.
 const CONSOLE_API_LEVELS_TO_SEVERITIES = {
   error: "error",
   exception: "error",
   assert: "error",
   warn: "warning",
   info: "info",
   log: "log",
+  clear: "log",
   trace: "log",
   table: "log",
   debug: "log",
   dir: "log",
   dirxml: "log",
   group: "log",
   groupCollapsed: "log",
   groupEnd: "log",
--- a/devtools/client/webconsole/test/browser.ini
+++ b/devtools/client/webconsole/test/browser.ini
@@ -64,16 +64,17 @@ support-files =
   test-bug-782653-css-errors.html
   test-bug-837351-security-errors.html
   test-bug-859170-longstring-hang.html
   test-bug-869003-iframe.html
   test-bug-869003-top-window.html
   test-closure-optimized-out.html
   test-closures.html
   test-console-assert.html
+  test-console-clear.html
   test-console-count.html
   test-console-count-external-file.js
   test-console-extras.html
   test-console-replaced-api.html
   test-console-server-logging.sjs
   test-console-server-logging-array.sjs
   test-console.html
   test-console-workers.html
@@ -152,16 +153,17 @@ skip-if = (e10s && debug) || (e10s && os
 skip-if = (e10s && (os == 'win' || os == 'mac')) # Bug 1243976
 [browser_bug_865288_repeat_different_objects.js]
 [browser_bug_865871_variables_view_close_on_esc_key.js]
 [browser_bug_869003_inspect_cross_domain_object.js]
 [browser_bug_871156_ctrlw_close_tab.js]
 [browser_cached_messages.js]
 [browser_console.js]
 [browser_console_addonsdk_loader_exception.js]
+[browser_console_clear_method.js]
 [browser_console_clear_on_reload.js]
 [browser_console_click_focus.js]
 [browser_console_consolejsm_output.js]
 [browser_console_copy_command.js]
 [browser_console_dead_objects.js]
 skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
 [browser_console_copy_entire_message_context_menu.js]
 [browser_console_error_source_click.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/browser_console_clear_method.js
@@ -0,0 +1,131 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Check that calls to console.clear from a script delete the messages
+// previously logged.
+
+"use strict";
+
+add_task(function* () {
+  const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
+                   "test/test-console-clear.html";
+
+  yield loadTab(TEST_URI);
+  let hud = yield openConsole();
+  ok(hud, "Web Console opened");
+
+  info("Check the console.clear() done on page load has been processed.");
+  yield waitForLog("Console was cleared", hud);
+  ok(hud.outputNode.textContent.includes("Console was cleared"),
+    "console.clear() message is displayed");
+  ok(!hud.outputNode.textContent.includes("log1"), "log1 not displayed");
+  ok(!hud.outputNode.textContent.includes("log2"), "log2 not displayed");
+
+  info("Logging two messages log3, log4");
+  ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
+    content.wrappedJSObject.console.log("log3");
+    content.wrappedJSObject.console.log("log4");
+  });
+
+  yield waitForLog("log3", hud);
+  yield waitForLog("log4", hud);
+
+  ok(hud.outputNode.textContent.includes("Console was cleared"),
+    "console.clear() message is still displayed");
+  ok(hud.outputNode.textContent.includes("log3"), "log3 is displayed");
+  ok(hud.outputNode.textContent.includes("log4"), "log4 is displayed");
+
+  info("Open the variables view sidebar for 'objFromPage'");
+  yield openSidebar("objFromPage", { a: 1 }, hud);
+  let sidebarClosed = hud.jsterm.once("sidebar-closed");
+
+  info("Call console.clear from the page");
+  ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
+    content.wrappedJSObject.console.clear();
+  });
+
+  // Cannot wait for "Console was cleared" here because such a message is
+  // already present and would yield immediately.
+  info("Wait for variables view sidebar to be closed after console.clear()");
+  yield sidebarClosed;
+
+  ok(!hud.outputNode.textContent.includes("log3"), "log3 not displayed");
+  ok(!hud.outputNode.textContent.includes("log4"), "log4 not displayed");
+  ok(hud.outputNode.textContent.includes("Console was cleared"),
+    "console.clear() message is still displayed");
+  is(hud.outputNode.textContent.split("Console was cleared").length, 2,
+    "console.clear() message is only displayed once");
+
+  info("Logging one messages log5");
+  ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
+    content.wrappedJSObject.console.log("log5");
+  });
+  yield waitForLog("log5", hud);
+
+  info("Close and reopen the webconsole.");
+  yield closeConsole(gBrowser.selectedTab);
+  hud = yield openConsole();
+  yield waitForLog("Console was cleared", hud);
+
+  ok(hud.outputNode.textContent.includes("Console was cleared"),
+    "console.clear() message is still displayed");
+  ok(!hud.outputNode.textContent.includes("log1"), "log1 not displayed");
+  ok(!hud.outputNode.textContent.includes("log2"), "log1 not displayed");
+  ok(!hud.outputNode.textContent.includes("log3"), "log3 not displayed");
+  ok(!hud.outputNode.textContent.includes("log4"), "log4 not displayed");
+  ok(hud.outputNode.textContent.includes("log5"), "log5 still displayed");
+});
+
+/**
+ * Wait for a single message to be logged in the provided webconsole instance
+ * with the category CATEGORY_WEBDEV and the SEVERITY_LOG severity.
+ *
+ * @param {String} message
+ *        The expected messaged.
+ * @param {WebConsole} webconsole
+ *        WebConsole instance in which the message should be logged.
+ */
+function* waitForLog(message, webconsole, options) {
+  yield waitForMessages({
+    webconsole: webconsole,
+    messages: [{
+      text: message,
+      category: CATEGORY_WEBDEV,
+      severity: SEVERITY_LOG,
+    }],
+  });
+}
+
+/**
+ * Open the variables view sidebar for the object with the provided name objName
+ * and wait for the expected object is displayed in the variables view.
+ *
+ * @param {String} objName
+ *        The name of the object to open in the sidebar.
+ * @param {Object} expectedObj
+ *        The properties that should be displayed in the variables view.
+ * @param {WebConsole} webconsole
+ *        WebConsole instance in which the message should be logged.
+ *
+ */
+function* openSidebar(objName, expectedObj, webconsole) {
+  let msg = yield webconsole.jsterm.execute(objName);
+  ok(msg, "output message found");
+
+  let anchor = msg.querySelector("a");
+  let body = msg.querySelector(".message-body");
+  ok(anchor, "object anchor");
+  ok(body, "message body");
+
+  yield EventUtils.synthesizeMouse(anchor, 2, 2, {}, webconsole.iframeWindow);
+
+  let vviewVar = yield webconsole.jsterm.once("variablesview-fetched");
+  let vview = vviewVar._variablesView;
+  ok(vview, "variables view object exists");
+
+  yield findVariableViewProperties(vviewVar, [
+    expectedObj,
+  ], { webconsole: webconsole });
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/test-console-clear.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html dir="ltr" xml:lang="en-US" lang="en-US"><head>
+    <meta charset="utf-8">
+    <title>Console.clear() tests</title>
+    <script type="text/javascript">
+      console.log("log1");
+      console.log("log2");
+      console.clear();
+
+      window.objFromPage = { a: 1 };
+    </script>
+  </head>
+  <body>
+    <h1 id="header">Clear Demo</h1>
+  </body>
+</html>
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -137,16 +137,17 @@ const MESSAGE_PREFERENCE_KEYS = [
 // severities.
 const LEVELS = {
   error: SEVERITY_ERROR,
   exception: SEVERITY_ERROR,
   assert: SEVERITY_ERROR,
   warn: SEVERITY_WARNING,
   info: SEVERITY_INFO,
   log: SEVERITY_LOG,
+  clear: SEVERITY_LOG,
   trace: SEVERITY_LOG,
   table: SEVERITY_LOG,
   debug: SEVERITY_LOG,
   dir: SEVERITY_LOG,
   dirxml: SEVERITY_LOG,
   group: SEVERITY_LOG,
   groupCollapsed: SEVERITY_LOG,
   groupEnd: SEVERITY_LOG,
@@ -1280,16 +1281,21 @@ WebConsoleFrame.prototype = {
         node = msg.init(this.output).render().element;
         break;
       }
       case "trace": {
         let msg = new Messages.ConsoleTrace(message);
         node = msg.init(this.output).render().element;
         break;
       }
+      case "clear": {
+        body = l10n.getStr("consoleCleared");
+        clipboardText = body;
+        break;
+      }
       case "dir": {
         body = { arguments: args };
         let clipboardArray = [];
         args.forEach((value) => {
           clipboardArray.push(VariablesView.getString(value));
         });
         clipboardText = clipboardArray.join(" ");
         break;
@@ -2198,16 +2204,24 @@ WebConsoleFrame.prototype = {
     if (!node) {
       return null;
     }
 
     let isFiltered = this.filterMessageNode(node);
 
     let isRepeated = this._filterRepeatedMessage(node);
 
+    // If a clear message is processed while the webconsole is opened, the UI
+    // should be cleared.
+    if (message && message.level == "clear") {
+      // Do not clear the consoleStorage here as it has been cleared already
+      // by the clear method, only clear the UI.
+      this.jsterm.clearOutput(false);
+    }
+
     let visible = !isRepeated && !isFiltered;
     if (!isRepeated) {
       this.outputNode.appendChild(node);
       this._pruneCategoriesQueue[node.category] = true;
 
       let nodeID = node.getAttribute("id");
       Services.obs.notifyObservers(hudIdSupportsString,
                                    "web-console-message-created", nodeID);