Bug 1310630 - Add Rep for LongString. r=Honza; draft
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Mon, 24 Oct 2016 19:53:13 +0200
changeset 429321 6c9c494de0d8c9f51a9d79589eef968e05ef7e69
parent 428736 c845bfd0accb7e0c29b41713255963b08006e701
child 534950 086193be68b9a56e4e40265d69b86646f74889e2
push id33543
push userchevobbe.nicolas@gmail.com
push dateTue, 25 Oct 2016 18:21:19 +0000
reviewersHonza
bugs1310630
milestone52.0a1
Bug 1310630 - Add Rep for LongString. r=Honza; MozReview-Commit-ID: MWYWaYp8zG
devtools/client/shared/components/reps/long-string.js
devtools/client/shared/components/reps/moz.build
devtools/client/shared/components/reps/rep.js
devtools/client/shared/components/test/mochitest/chrome.ini
devtools/client/shared/components/test/mochitest/test_reps_long-string.html
new file mode 100644
--- /dev/null
+++ b/devtools/client/shared/components/reps/long-string.js
@@ -0,0 +1,73 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* 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";
+
+// Make this available to both AMD and CJS environments
+define(function (require, exports, module) {
+  // Dependencies
+  const React = require("devtools/client/shared/vendor/react");
+  const { isGrip } = require("./rep-utils");
+  // Shortcuts
+  const { span } = React.DOM;
+
+  /**
+   * Renders a long string grip.
+   */
+  const LongStringRep = React.createClass({
+    displayName: "LongStringRep",
+
+    propTypes: {
+      useQuotes: React.PropTypes.bool,
+      style: React.PropTypes.object,
+    },
+
+    getDefaultProps: function () {
+      return {
+        useQuotes: true,
+      };
+    },
+
+    render: function () {
+      let {
+        cropLimit,
+        member,
+        object,
+        style,
+        useQuotes
+      } = this.props;
+      let {initial, length} = object;
+
+      let config = {className: "objectBox objectBox-string"};
+      if (style) {
+        config.style = style;
+      }
+
+      let croppedString = cropLimit && !(member && member.open)
+        ? initial.substring(0, cropLimit)
+        : initial;
+
+      if (croppedString.length < length) {
+        croppedString += "\u2026";
+      }
+      let formattedString = useQuotes ? `"${croppedString}"` : croppedString;
+      return span(config, formattedString);
+    },
+  });
+
+  function supportsObject(object, type) {
+    if (!isGrip(object)) {
+      return false;
+    }
+    return object.type === "longString";
+  }
+
+  // Exports from this module
+  exports.LongStringRep = {
+    rep: LongStringRep,
+    supportsObject: supportsObject,
+  };
+});
--- a/devtools/client/shared/components/reps/moz.build
+++ b/devtools/client/shared/components/reps/moz.build
@@ -12,16 +12,17 @@ DevToolsModules(
     'date-time.js',
     'document.js',
     'event.js',
     'function.js',
     'grip-array.js',
     'grip-map.js',
     'grip.js',
     'infinity.js',
+    'long-string.js',
     'nan.js',
     'null.js',
     'number.js',
     'object-with-text.js',
     'object-with-url.js',
     'object.js',
     'prop-rep.js',
     'regexp.js',
--- a/devtools/client/shared/components/reps/rep.js
+++ b/devtools/client/shared/components/reps/rep.js
@@ -12,16 +12,17 @@ define(function (require, exports, modul
   const React = require("devtools/client/shared/vendor/react");
 
   const { isGrip } = require("./rep-utils");
 
   // Load all existing rep templates
   const { Undefined } = require("./undefined");
   const { Null } = require("./null");
   const { StringRep } = require("./string");
+  const { LongStringRep } = require("./long-string");
   const { Number } = require("./number");
   const { ArrayRep } = require("./array");
   const { Obj } = require("./object");
   const { SymbolRep } = require("./symbol");
   const { InfinityRep } = require("./infinity");
   const { NaNRep } = require("./nan");
 
   // DOM types (grips)
@@ -47,16 +48,17 @@ define(function (require, exports, modul
   let reps = [
     RegExp,
     StyleSheet,
     Event,
     DateTime,
     CommentNode,
     TextNode,
     Attribute,
+    LongStringRep,
     Func,
     ArrayRep,
     Document,
     Window,
     ObjectWithText,
     ObjectWithURL,
     GripArray,
     GripMap,
--- a/devtools/client/shared/components/test/mochitest/chrome.ini
+++ b/devtools/client/shared/components/test/mochitest/chrome.ini
@@ -13,16 +13,17 @@ support-files =
 [test_reps_date-time.html]
 [test_reps_document.html]
 [test_reps_event.html]
 [test_reps_function.html]
 [test_reps_grip.html]
 [test_reps_grip-array.html]
 [test_reps_grip-map.html]
 [test_reps_infinity.html]
+[test_reps_long-string.html]
 [test_reps_nan.html]
 [test_reps_null.html]
 [test_reps_number.html]
 [test_reps_object.html]
 [test_reps_object-with-text.html]
 [test_reps_object-with-url.html]
 [test_reps_regexp.html]
 [test_reps_string.html]
new file mode 100644
--- /dev/null
+++ b/devtools/client/shared/components/test/mochitest/test_reps_long-string.html
@@ -0,0 +1,92 @@
+
+<!DOCTYPE HTML>
+<html>
+<!--
+Test LongString rep
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Rep test - String</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
+</head>
+<body>
+<pre id="test">
+<script src="head.js" type="application/javascript;version=1.8"></script>
+<script type="application/javascript;version=1.8">
+window.onload = Task.async(function* () {
+  let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
+  let { LongStringRep } = browserRequire("devtools/client/shared/components/reps/long-string");
+
+  try {
+    // Test that correct rep is chosen
+    const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testMultiline") });
+    is(renderedRep.type, LongStringRep.rep,
+      `Rep correctly selects ${LongStringRep.rep.displayName}`);
+
+    // Test rendering
+    yield testMultiline();
+    yield testMultilineOpen();
+    yield testMultilineLimit();
+    yield testUseQuotes();
+  } catch (e) {
+    ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
+  } finally {
+    SimpleTest.finish();
+  }
+
+  function testMultiline() {
+    const stub = getGripStub("testMultiline");
+    const renderedComponent = renderComponent(
+      LongStringRep.rep, { object: stub });
+
+    is(renderedComponent.textContent, `"${stub.initial}…"`,
+      "LongString rep has expected text content for multiline string");
+  }
+
+  function testMultilineLimit() {
+    const renderedComponent = renderComponent(
+      LongStringRep.rep, { object: getGripStub("testMultiline"), cropLimit: 20 });
+
+    is(
+      renderedComponent.textContent,
+      `"a\naaaaaaaaaaaaaaaaaa…"`,
+      "LongString rep has expected text content for multiline string " +
+      "with specified number of characters");
+  }
+
+  function testMultilineOpen() {
+    const stub = getGripStub("testMultiline");
+    const renderedComponent = renderComponent(
+      LongStringRep.rep, { object: stub, member: {open: true}, cropLimit: 20 });
+
+    is(renderedComponent.textContent, `"${stub.initial}…"`,
+      "LongString rep has expected text content for multiline string when open");
+  }
+
+  function testUseQuotes() {
+    const renderedComponent = renderComponent(LongStringRep.rep,
+      { object: getGripStub("testMultiline"), cropLimit: 20, useQuotes: false });
+
+    is(renderedComponent.textContent,
+      "a\naaaaaaaaaaaaaaaaaa…",
+      "LongString rep was expected to omit quotes");
+  }
+
+  function getGripStub(name) {
+    switch (name) {
+      case "testMultiline":
+        return {
+          "type": "longString",
+          "initial": "a\n" + Array(9998).fill("a").join(""),
+          "length": 10002,
+          "actor": "server1.conn1.child1/longString58"
+        };
+    }
+    return null;
+  }
+});
+</script>
+</pre>
+</body>
+</html>