Bug 1408454 - Move error.pprint to format.pprint. r=whimboo
authorAndreas Tolfsen <ato@sny.no>
Fri, 13 Oct 2017 17:59:30 +0100
changeset 386194 68ccc9cb5de00d3e357b3736142d106e6bce11b3
parent 386193 83ae3528255f77bbd5681fa8f94147417281a4d4
child 386195 35866a88d5673db6c760658f3e3cd159cc50f36b
push id32678
push userarchaeopteryx@coole-files.de
push dateSat, 14 Oct 2017 09:40:07 +0000
treeherdermozilla-central@0dd64d5842e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswhimboo
bugs1408454
milestone58.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 1408454 - Move error.pprint to format.pprint. r=whimboo Pretty-printing an object belongs more naturally to the new format module. MozReview-Commit-ID: AfXLMPAT5ar
testing/marionette/action.js
testing/marionette/assert.js
testing/marionette/cookie.js
testing/marionette/element.js
testing/marionette/error.js
testing/marionette/format.js
testing/marionette/interaction.js
testing/marionette/test_error.js
testing/marionette/test_format.js
--- a/testing/marionette/action.js
+++ b/testing/marionette/action.js
@@ -6,22 +6,22 @@
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("chrome://marionette/content/assert.js");
 Cu.import("chrome://marionette/content/element.js");
 const {
-  pprint,
   InvalidArgumentError,
   MoveTargetOutOfBoundsError,
   UnsupportedOperationError,
 } = Cu.import("chrome://marionette/content/error.js", {});
 Cu.import("chrome://marionette/content/event.js");
+const {pprint} = Cu.import("chrome://marionette/content/format.js", {});
 Cu.import("chrome://marionette/content/interaction.js");
 
 this.EXPORTED_SYMBOLS = ["action"];
 
 // TODO? With ES 2016 and Symbol you can make a safer approximation
 // to an enum e.g. https://gist.github.com/xmlking/e86e4f15ec32b12c4689
 /**
  * Implements WebDriver Actions API: a low-level interface for providing
--- a/testing/marionette/assert.js
+++ b/testing/marionette/assert.js
@@ -9,20 +9,20 @@ const {utils: Cu} = Components;
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 const {
   InvalidArgumentError,
   InvalidSessionIDError,
   NoSuchWindowError,
-  pprint,
   UnexpectedAlertOpenError,
   UnsupportedOperationError,
 } = Cu.import("chrome://marionette/content/error.js", {});
+const {pprint} = Cu.import("chrome://marionette/content/format.js", {});
 
 this.EXPORTED_SYMBOLS = ["assert"];
 
 const isFennec = () => AppConstants.platform == "android";
 const isFirefox = () =>
     Services.appinfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
 
 /**
--- a/testing/marionette/cookie.js
+++ b/testing/marionette/cookie.js
@@ -4,20 +4,18 @@
 
 "use strict";
 
 const {interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 
 Cu.import("chrome://marionette/content/assert.js");
-const {
-  InvalidCookieDomainError,
-  pprint,
-} = Cu.import("chrome://marionette/content/error.js", {});
+const {InvalidCookieDomainError} = Cu.import("chrome://marionette/content/error.js", {});
+const {pprint} = Cu.import("chrome://marionette/content/format.js", {});
 
 this.EXPORTED_SYMBOLS = ["cookie"];
 
 const IPV4_PORT_EXPR = /:\d+$/;
 
 /** @namespace */
 this.cookie = {
   manager: Services.cookies,
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -7,19 +7,19 @@
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("chrome://marionette/content/assert.js");
 Cu.import("chrome://marionette/content/atom.js");
 const {
   InvalidSelectorError,
   NoSuchElementError,
-  pprint,
   StaleElementReferenceError,
 } = Cu.import("chrome://marionette/content/error.js", {});
+const {pprint} = Cu.import("chrome://marionette/content/format.js", {});
 const {PollPromise} = Cu.import("chrome://marionette/content/sync.js", {});
 
 this.EXPORTED_SYMBOLS = ["element"];
 
 const XMLNS = "http://www.w3.org/1999/xhtml";
 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 /** XUL elements that support checked property. */
--- a/testing/marionette/error.js
+++ b/testing/marionette/error.js
@@ -1,16 +1,18 @@
 /* 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/. */
 
 "use strict";
 
 const {interfaces: Ci, utils: Cu} = Components;
 
+const {pprint} = Cu.import("chrome://marionette/content/format.js", {});
+
 const ERRORS = new Set([
   "ElementClickInterceptedError",
   "ElementNotAccessibleError",
   "ElementNotInteractableError",
   "InsecureCertificateError",
   "InvalidArgumentError",
   "InvalidCookieDomainError",
   "InvalidElementStateError",
@@ -42,17 +44,16 @@ const BUILTIN_ERRORS = new Set([
   "ReferenceError",
   "SyntaxError",
   "TypeError",
   "URIError",
 ]);
 
 this.EXPORTED_SYMBOLS = [
   "error",
-  "pprint",
   "stack",
 ].concat(Array.from(ERRORS));
 
 /** @namespace */
 this.error = {};
 
 /**
  * Check if |val| is an instance of the |Error| prototype.
@@ -143,84 +144,16 @@ error.stringify = function(err) {
       s += "\n" + err.stack;
     }
     return s;
   } catch (e) {
     return "<unprintable error>";
   }
 };
 
-/**
- * Pretty-print values passed to template strings.
- *
- * Usage:
- *
- *     const {pprint} = Cu.import("chrome://marionette/content/error.js", {});
- *     let bool = {value: true};
- *     pprint`Expected boolean, got ${bool}`;
- *     => 'Expected boolean, got [object Object] {"value": true}'
- *
- *     let htmlElement = document.querySelector("input#foo");
- *     pprint`Expected element ${htmlElement}`;
- *     => 'Expected element <input id="foo" class="bar baz">'
- */
-this.pprint = function(ss, ...values) {
-  function prettyObject(obj) {
-    let proto = Object.prototype.toString.call(obj);
-    let s = "";
-    try {
-      s = JSON.stringify(obj);
-    } catch (e) {
-      if (e instanceof TypeError) {
-        s = `<${e.message}>`;
-      } else {
-        throw e;
-      }
-    }
-    return proto + " " + s;
-  }
-
-  function prettyElement(el) {
-    let ident = [];
-    if (el.id) {
-      ident.push(`id="${el.id}"`);
-    }
-    if (el.classList.length > 0) {
-      ident.push(`class="${el.className}"`);
-    }
-
-    let idents = "";
-    if (ident.length > 0) {
-      idents = " " + ident.join(" ");
-    }
-
-    return `<${el.localName}${idents}>`;
-  }
-
-  let res = [];
-  for (let i = 0; i < ss.length; i++) {
-    res.push(ss[i]);
-    if (i < values.length) {
-      let val = values[i];
-      let s;
-      try {
-        if (val && val.nodeType === 1) {
-          s = prettyElement(val);
-        } else {
-          s = prettyObject(val);
-        }
-      } catch (e) {
-        s = typeof val;
-      }
-      res.push(s);
-    }
-  }
-  return res.join("");
-};
-
 /** Create a stacktrace to the current line in the program. */
 this.stack = function() {
   let trace = new Error().stack;
   let sa = trace.split("\n");
   sa = sa.slice(1);
   return "stacktrace:\n" + sa.join("\n");
 };
 
--- a/testing/marionette/format.js
+++ b/testing/marionette/format.js
@@ -1,19 +1,90 @@
 /* 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/. */
 
 "use strict";
 
-this.EXPORTED_SYMBOLS = ["truncate"];
+this.EXPORTED_SYMBOLS = ["pprint", "truncate"];
 
 const MAX_STRING_LENGTH = 250;
 
 /**
+ * Pretty-print values passed to template strings.
+ *
+ * Usage:
+ *
+ * <pre><code>
+ *     const {pprint} = Cu.import("chrome://marionette/content/error.js", {});
+ *     let bool = {value: true};
+ *     pprint`Expected boolean, got ${bool}`;
+ *     => 'Expected boolean, got [object Object] {"value": true}'
+ *
+ *     let htmlElement = document.querySelector("input#foo");
+ *     pprint`Expected element ${htmlElement}`;
+ *     => 'Expected element <input id="foo" class="bar baz">'
+ * </code></pre>
+ */
+function pprint(ss, ...values) {
+  function prettyObject(obj) {
+    let proto = Object.prototype.toString.call(obj);
+    let s = "";
+    try {
+      s = JSON.stringify(obj);
+    } catch (e) {
+      if (e instanceof TypeError) {
+        s = `<${e.message}>`;
+      } else {
+        throw e;
+      }
+    }
+    return proto + " " + s;
+  }
+
+  function prettyElement(el) {
+    let ident = [];
+    if (el.id) {
+      ident.push(`id="${el.id}"`);
+    }
+    if (el.classList.length > 0) {
+      ident.push(`class="${el.className}"`);
+    }
+
+    let idents = "";
+    if (ident.length > 0) {
+      idents = " " + ident.join(" ");
+    }
+
+    return `<${el.localName}${idents}>`;
+  }
+
+  let res = [];
+  for (let i = 0; i < ss.length; i++) {
+    res.push(ss[i]);
+    if (i < values.length) {
+      let val = values[i];
+      let s;
+      try {
+        if (val && val.nodeType === 1) {
+          s = prettyElement(val);
+        } else {
+          s = prettyObject(val);
+        }
+      } catch (e) {
+        s = typeof val;
+      }
+      res.push(s);
+    }
+  }
+  return res.join("");
+}
+this.pprint = pprint;
+
+/**
  * Template literal that truncates string values in arbitrary objects.
  *
  * Given any object, the template will walk the object and truncate
  * any strings it comes across to a reasonable limit.  This is suitable
  * when you have arbitrary data and data integrity is not important.
  *
  * The strings are truncated in the middle so that the beginning and
  * the end is preserved.  This will make a long, truncated string look
--- a/testing/marionette/interaction.js
+++ b/testing/marionette/interaction.js
@@ -8,19 +8,19 @@ const {utils: Cu} = Components;
 
 Cu.import("chrome://marionette/content/accessibility.js");
 Cu.import("chrome://marionette/content/atom.js");
 const {
   ElementClickInterceptedError,
   ElementNotInteractableError,
   InvalidArgumentError,
   InvalidElementStateError,
-  pprint,
 } = Cu.import("chrome://marionette/content/error.js", {});
 Cu.import("chrome://marionette/content/element.js");
+const {pprint} = Cu.import("chrome://marionette/content/format.js", {});
 Cu.import("chrome://marionette/content/event.js");
 
 Cu.importGlobalProperties(["File"]);
 
 this.EXPORTED_SYMBOLS = ["interaction"];
 
 /** XUL elements that support disabled attribute. */
 const DISABLED_ATTRIBUTE_SUPPORTED_XUL = new Set([
--- a/testing/marionette/test_error.js
+++ b/testing/marionette/test_error.js
@@ -16,17 +16,16 @@ const {
   InvalidSelectorError,
   InvalidSessionIDError,
   JavaScriptError,
   MoveTargetOutOfBoundsError,
   NoAlertOpenError,
   NoSuchElementError,
   NoSuchFrameError,
   NoSuchWindowError,
-  pprint,
   ScriptTimeoutError,
   SessionNotCreatedError,
   stack,
   StaleElementReferenceError,
   TimeoutError,
   UnableToSetCookieError,
   UnexpectedAlertOpenError,
   UnknownCommandError,
@@ -113,43 +112,16 @@ add_test(function test_stringify() {
   equal("WebDriverError: foo",
       error.stringify(new WebDriverError("foo")).split("\n")[0]);
   equal("InvalidArgumentError: foo",
       error.stringify(new InvalidArgumentError("foo")).split("\n")[0]);
 
   run_next_test();
 });
 
-add_test(function test_pprint() {
-  equal('[object Object] {"foo":"bar"}', pprint`${{foo: "bar"}}`);
-
-  equal("[object Number] 42", pprint`${42}`);
-  equal("[object Boolean] true", pprint`${true}`);
-  equal("[object Undefined] undefined", pprint`${undefined}`);
-  equal("[object Null] null", pprint`${null}`);
-
-  let complexObj = {toJSON: () => "foo"};
-  equal('[object Object] "foo"', pprint`${complexObj}`);
-
-  let cyclic = {};
-  cyclic.me = cyclic;
-  equal("[object Object] <cyclic object value>", pprint`${cyclic}`);
-
-  let el = {
-    nodeType: 1,
-    localName: "input",
-    id: "foo",
-    classList: {length: 1},
-    className: "bar baz",
-  };
-  equal('<input id="foo" class="bar baz">', pprint`${el}`);
-
-  run_next_test();
-});
-
 add_test(function test_stack() {
   equal("string", typeof stack());
   ok(stack().includes("test_stack"));
   ok(!stack().includes("add_test"));
 
   run_next_test();
 });
 
--- a/testing/marionette/test_format.js
+++ b/testing/marionette/test_format.js
@@ -1,19 +1,46 @@
 /* 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 {utils: Cu} = Components;
 
-const {truncate} = Cu.import("chrome://marionette/content/format.js", {});
+const {pprint, truncate} = Cu.import("chrome://marionette/content/format.js", {});
 
 const MAX_STRING_LENGTH = 250;
 const HALF = "x".repeat(MAX_STRING_LENGTH / 2);
 
+add_test(function test_pprint() {
+  equal('[object Object] {"foo":"bar"}', pprint`${{foo: "bar"}}`);
+
+  equal("[object Number] 42", pprint`${42}`);
+  equal("[object Boolean] true", pprint`${true}`);
+  equal("[object Undefined] undefined", pprint`${undefined}`);
+  equal("[object Null] null", pprint`${null}`);
+
+  let complexObj = {toJSON: () => "foo"};
+  equal('[object Object] "foo"', pprint`${complexObj}`);
+
+  let cyclic = {};
+  cyclic.me = cyclic;
+  equal("[object Object] <cyclic object value>", pprint`${cyclic}`);
+
+  let el = {
+    nodeType: 1,
+    localName: "input",
+    id: "foo",
+    classList: {length: 1},
+    className: "bar baz",
+  };
+  equal('<input id="foo" class="bar baz">', pprint`${el}`);
+
+  run_next_test();
+});
+
 add_test(function test_truncate_empty() {
   equal(truncate``, "");
   run_next_test();
 });
 
 add_test(function test_truncate_noFields() {
   equal(truncate`foo bar`, "foo bar");
   run_next_test();