Bug 1311426 - Handle Grip with wrapped value in Reps. r=Honza; draft
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Mon, 24 Oct 2016 07:32:32 +0200
changeset 428623 03d01ee1bfcbc0cd303a1a91a585d61ccdeae8c3
parent 428413 a9a41b69f3f9be494ae0653601c08aa388d9afe4
child 534790 77bb2a9e378094547302c666f0d8a58c0291d5a1
push id33371
push userchevobbe.nicolas@gmail.com
push dateMon, 24 Oct 2016 11:43:29 +0000
reviewersHonza
bugs1311426
milestone52.0a1
Bug 1311426 - Handle Grip with wrapped value in Reps. r=Honza; Handle object created from a constructor function, like `new Boolean(true)`, `new Number(42)` or `new String("foo")`. It displays the wrapped value using Rep so the primitives are displayed like expected. MozReview-Commit-ID: JrJVeV0C0wO
devtools/client/shared/components/reps/grip.js
devtools/client/shared/components/test/mochitest/test_reps_grip.html
--- a/devtools/client/shared/components/reps/grip.js
+++ b/devtools/client/shared/components/reps/grip.js
@@ -45,16 +45,26 @@ define(function (require, exports, modul
         return this.propIterator(object, max);
       } catch (err) {
         console.error(err);
       }
       return [];
     },
 
     propIterator: function (object, max) {
+      if (Object.keys(object.preview).includes("wrappedValue")) {
+        const { Rep } = createFactories(require("./rep"));
+
+        return [Rep({
+          object: object.preview.wrappedValue,
+          mode: this.props.mode || "tiny",
+          defaultRep: Grip,
+        })];
+      }
+
       // Property filter. Show only interesting properties to the user.
       let isInterestingProp = this.props.isInterestingProp || ((type, value) => {
         return (
           type == "boolean" ||
           type == "number" ||
           (type == "string" && value.length != 0)
         );
       });
--- a/devtools/client/shared/components/test/mochitest/test_reps_grip.html
+++ b/devtools/client/shared/components/test/mochitest/test_reps_grip.html
@@ -17,16 +17,19 @@ Test grip rep
 window.onload = Task.async(function* () {
   let { Rep } = browserRequire("devtools/client/shared/components/reps/rep");
   let { Grip } = browserRequire("devtools/client/shared/components/reps/grip");
 
   const componentUnderTest = Grip;
 
   try {
     yield testBasic();
+    yield testBooleanObject();
+    yield testNumberObject();
+    yield testStringObject();
 
     // Test property iterator
     yield testMaxProps();
     yield testMoreThanMaxProps();
     yield testUninterestingProps();
     yield testNonEnumerableProps();
 
     // Test that properties are rendered as expected by PropRep
@@ -70,16 +73,118 @@ window.onload = Task.async(function* () 
         mode: "long",
         expectedOutput: defaultOutput,
       }
     ];
 
     testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
   }
 
+  function testBooleanObject() {
+    // Test object: `new Boolean(true)`
+    const testName = "testBooleanObject";
+
+    // Test that correct rep is chosen
+    const gripStub = getGripStub(testName);
+    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
+    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
+
+    // Test rendering
+    const defaultOutput = `Boolean { true }`;
+
+    const modeTests = [
+      {
+        mode: undefined,
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "tiny",
+        expectedOutput: `Boolean`,
+      },
+      {
+        mode: "short",
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "long",
+        expectedOutput: defaultOutput,
+      }
+    ];
+
+    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
+  }
+
+  function testNumberObject() {
+    // Test object: `new Number(42)`
+    const testName = "testNumberObject";
+
+    // Test that correct rep is chosen
+    const gripStub = getGripStub(testName);
+    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
+    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
+
+    // Test rendering
+    const defaultOutput = `Number { 42 }`;
+
+    const modeTests = [
+      {
+        mode: undefined,
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "tiny",
+        expectedOutput: `Number`,
+      },
+      {
+        mode: "short",
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "long",
+        expectedOutput: defaultOutput,
+      }
+    ];
+
+    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
+  }
+
+  function testStringObject() {
+    // Test object: `new String("foo")`
+    const testName = "testStringObject";
+
+    // Test that correct rep is chosen
+    const gripStub = getGripStub(testName);
+    const renderedRep = shallowRenderComponent(Rep, { object: gripStub });
+    is(renderedRep.type, Grip.rep, `Rep correctly selects ${Grip.rep.displayName}`);
+
+    // Test rendering
+    const defaultOutput = `String { "foo" }`;
+
+    const modeTests = [
+      {
+        mode: undefined,
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "tiny",
+        expectedOutput: `String`,
+      },
+      {
+        mode: "short",
+        expectedOutput: defaultOutput,
+      },
+      {
+        mode: "long",
+        expectedOutput: defaultOutput,
+      }
+    ];
+
+    testRepRenderModes(modeTests, testName, componentUnderTest, getGripStub(testName));
+  }
+
   function testMaxProps() {
     // Test object: `{a: "a", b: "b", c: "c"}`;
     const testName = "testMaxProps";
 
     const defaultOutput = `Object { a: "a", b: "b", c: "c" }`;
 
     const modeTests = [
       {
@@ -525,16 +630,57 @@ window.onload = Task.async(function* () 
                 "writable": true,
                 "value": 3
               }
             },
             "ownPropertiesLength": 4,
             "safeGetterValues": {}
           }
         };
-
+      case "testBooleanObject":
+        return {
+          "type": "object",
+          "actor": "server1.conn1.child1/obj57",
+          "class": "Boolean",
+          "ownPropertyLength": 0,
+          "preview": {
+            "kind": "Object",
+            "ownProperties": {},
+            "ownPropertiesLength": 0,
+            "safeGetterValues": {},
+            "wrappedValue": true
+          }
+        };
+      case "testNumberObject":
+        return {
+          "type": "object",
+          "actor": "server1.conn1.child1/obj59",
+          "class": "Number",
+          "ownPropertyLength": 0,
+          "preview": {
+            "kind": "Object",
+            "ownProperties": {},
+            "ownPropertiesLength": 0,
+            "safeGetterValues": {},
+            "wrappedValue": 42
+          }
+        };
+      case "testStringObject":
+        return {
+          "type": "object",
+          "actor": "server1.conn1.child1/obj61",
+          "class": "String",
+          "ownPropertyLength": 4,
+          "preview": {
+            "kind": "Object",
+            "ownProperties": {},
+            "ownPropertiesLength": 4,
+            "safeGetterValues": {},
+            "wrappedValue": "foo"
+          }
+        };
     }
   }
 });
 </script>
 </pre>
 </body>
 </html>