Bug 1320359 - Make EventRep displays like events were displayed in old console; r=Honza draft
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Fri, 25 Nov 2016 23:52:06 +0100
changeset 445545 29ad4d398ad7518d752b323a6e6393cd30b18a0a
parent 444725 8387a4ada9a5c4cab059d8fafe0f8c933e83c149
child 538553 41605a44e045a3caa099c84686579471f64d0418
push id37546
push userchevobbe.nicolas@gmail.com
push dateTue, 29 Nov 2016 22:23:53 +0000
reviewersHonza
bugs1320359
milestone53.0a1
Bug 1320359 - Make EventRep displays like events were displayed in old console; r=Honza Add a target property and show the event name (and modifiers if any) in the title. Minor edit in GripRep to allow to pass a title as a prop. Edit tests accordingly, and add some to test node highlighting. MozReview-Commit-ID: JmMidejKS6m
devtools/client/shared/components/reps/event.js
devtools/client/shared/components/reps/grip.js
devtools/client/shared/components/test/mochitest/test_reps_event.html
--- a/devtools/client/shared/components/reps/event.js
+++ b/devtools/client/shared/components/reps/event.js
@@ -19,51 +19,71 @@ define(function (require, exports, modul
    */
   let Event = React.createClass({
     displayName: "event",
 
     propTypes: {
       object: React.PropTypes.object.isRequired
     },
 
+    getTitle: function (props) {
+      let preview = props.object.preview;
+      let title = preview.type;
+
+      if (preview.eventKind == "key" && preview.modifiers && preview.modifiers.length) {
+        title = `${title} ${preview.modifiers.join("-")}`;
+      }
+      return title;
+    },
+
     render: function () {
       // Use `Object.assign` to keep `this.props` without changes because:
       // 1. JSON.stringify/JSON.parse is slow.
       // 2. Immutable.js is planned for the future.
-      let props = Object.assign({}, this.props);
+      let props = Object.assign({
+        title: this.getTitle(this.props)
+      }, this.props);
       props.object = Object.assign({}, this.props.object);
       props.object.preview = Object.assign({}, this.props.object.preview);
-      props.object.preview.ownProperties = props.object.preview.properties;
+
+      props.object.preview.ownProperties = {};
+      if (props.object.preview.target) {
+        Object.assign(props.object.preview.ownProperties, {
+          target: props.object.preview.target
+        });
+      }
+      Object.assign(props.object.preview.ownProperties, props.object.preview.properties);
+
       delete props.object.preview.properties;
       props.object.ownPropertyLength =
         Object.keys(props.object.preview.ownProperties).length;
 
       switch (props.object.class) {
         case "MouseEvent":
           props.isInterestingProp = (type, value, name) => {
-            return (name == "clientX" ||
-                    name == "clientY" ||
-                    name == "layerX" ||
-                    name == "layerY");
+            return ["target", "clientX", "clientY", "layerX", "layerY"].includes(name);
           };
           break;
         case "KeyboardEvent":
           props.isInterestingProp = (type, value, name) => {
-            return (name == "key" ||
-                    name == "charCode" ||
-                    name == "keyCode");
+            return ["target", "key", "charCode", "keyCode"].includes(name);
           };
           break;
         case "MessageEvent":
           props.isInterestingProp = (type, value, name) => {
-            return (name == "isTrusted" ||
-                    name == "data");
+            return ["target", "isTrusted", "data"].includes(name);
           };
           break;
+        default:
+          props.isInterestingProp = (type, value, name) => {
+            // We want to show the properties in the order they are declared.
+            return Object.keys(props.object.preview.ownProperties).includes(name);
+          };
       }
+
       return rep(props);
     }
   });
 
   // Registration
 
   function supportsObject(grip, type) {
     if (!isGrip(grip)) {
--- a/devtools/client/shared/components/reps/grip.js
+++ b/devtools/client/shared/components/reps/grip.js
@@ -24,26 +24,28 @@ define(function (require, exports, modul
    */
   const GripRep = React.createClass({
     displayName: "Grip",
 
     propTypes: {
       object: React.PropTypes.object.isRequired,
       // @TODO Change this to Object.values once it's supported in Node's version of V8
       mode: React.PropTypes.oneOf(Object.keys(MODE).map(key => MODE[key])),
-      isInterestingProp: React.PropTypes.func
+      isInterestingProp: React.PropTypes.func,
+      title: React.PropTypes.string,
     },
 
     getTitle: function (object) {
+      let title = this.props.title || object.class || "Object";
       if (this.props.objectLink) {
         return this.props.objectLink({
           object: object
-        }, object.class);
+        }, title);
       }
-      return object.class || "Object";
+      return title;
     },
 
     safePropIterator: function (object, max) {
       max = (typeof max === "undefined") ? 3 : max;
       try {
         return this.propIterator(object, max);
       } catch (err) {
         console.error(err);
--- a/devtools/client/shared/components/test/mochitest/test_reps_event.html
+++ b/devtools/client/shared/components/test/mochitest/test_reps_event.html
@@ -14,58 +14,148 @@ Test Event rep
 </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 { Event } = browserRequire("devtools/client/shared/components/reps/event");
+  const { MODE } = browserRequire("devtools/client/shared/components/reps/constants");
 
   try {
     // Test that correct rep is chosen
     const renderedRep = shallowRenderComponent(Rep, { object: getGripStub("testEvent") });
     is(renderedRep.type, Event.rep, `Rep correctly selects ${Event.rep.displayName}`);
 
     yield testEvent();
     yield testMouseEvent();
     yield testKeyboardEvent();
+    yield testKeyboardEventWithModifiers();
     yield testMessageEvent();
+
+    yield testOnMouseOver();
+    yield testOnMouseOut();
   } catch(e) {
     ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
   } finally {
     SimpleTest.finish();
   }
 
   function testEvent() {
-    const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testEvent") });
+    const renderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testEvent"),
+    });
     is(renderedComponent.textContent,
-       "Event { isTrusted: true, eventPhase: 2, bubbles: false, 7 more… }",
-       "Event rep has expected text content for an event");
+      "beforeprint { target: http://example.com, isTrusted: true, " +
+      "currentTarget: http://example.com, 8 more… }",
+      "Event rep has expected text content for an event");
   }
 
   function testMouseEvent() {
-    const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testMouseEvent") });
+    const renderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testMouseEvent")
+    });
     is(renderedComponent.textContent,
-       "MouseEvent { clientX: 62, clientY: 18, layerX: 0, 2 more… }",
-       "Event rep has expected text content for a mouse event");
+      "click { target: div#test, clientX: 62, clientY: 18, 3 more… }",
+      "Event rep has expected text content for a mouse event");
+
+    const longRenderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testMouseEvent"),
+      mode: MODE.LONG,
+    });
+    is(longRenderedComponent.textContent,
+      "click { target: div#test, buttons: 0, clientX: 62, clientY: 18, layerX: 0, " +
+      "layerY: 0 }",
+      "Event rep has expected text content for a mouse event in long mode");
   }
 
   function testKeyboardEvent() {
-    const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testKeyboardEvent") });
+    const renderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testKeyboardEvent")
+    });
     is(renderedComponent.textContent,
-       "KeyboardEvent { key: \"Control\", charCode: 0, keyCode: 17 }",
+       "keyup { target: body, key: \"Control\", charCode: 0, 1 more… }",
        "Event rep has expected text content for a keyboard event");
+
+    const longRenderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testKeyboardEvent"),
+      mode: MODE.LONG,
+    });
+    is(longRenderedComponent.textContent,
+       `keyup { target: body, key: "Control", charCode: 0, keyCode: 17 }`,
+       "Event rep has expected text content for a keyboard event in long mode");
+  }
+
+  function testKeyboardEventWithModifiers() {
+    const renderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testKeyboardEventWithModifiers"),
+      mode: MODE.LONG,
+    });
+
+    is(renderedComponent.textContent,
+       `keyup Meta-Shift { target: body, key: "M", charCode: 0, keyCode: 77 }`,
+       "Event rep has expected text content for a keyboard event with modifiers " +
+       "in long mode");
   }
 
   function testMessageEvent() {
-    const renderedComponent = renderComponent(Event.rep, { object: getGripStub("testMessageEvent") });
+    const renderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testMessageEvent")
+    });
     is(renderedComponent.textContent,
-       "MessageEvent { isTrusted: false, data: \"test data\", origin: \"null\", 7 more… }",
+       `message { target: http://example.com, isTrusted: false, data: "test data", ` +
+       "8 more… }",
        "Event rep has expected text content for a message event");
+
+    const longRenderedComponent = renderComponent(Event.rep, {
+      object: getGripStub("testMessageEvent"),
+      mode: MODE.LONG,
+    });
+    is(longRenderedComponent.textContent,
+       `message { target: http://example.com, isTrusted: false, data: "test data", ` +
+       `origin: "null", lastEventId: "", source: , ports: message, currentTarget: , ` +
+       `eventPhase: 2, bubbles: false, 1 more… }`,
+       "Event rep has expected text content for a message event in long mode");
+  }
+
+  function testOnMouseOver() {
+    const stub = getGripStub("testMouseEvent");
+
+    let mouseOverValue;
+    let onDOMNodeMouseOver = (object) => {
+      mouseOverValue = object;
+    };
+    const renderedComponent = renderComponent(Event.rep, {
+      object: stub, onDOMNodeMouseOver
+    });
+
+    const node = renderedComponent.querySelector(".objectBox-node");
+    TestUtils.Simulate.mouseOver(node);
+
+    is(mouseOverValue, stub.preview.target, "onDOMNodeMouseOver is called with " +
+      "the expected argument when mouseover is fired on the Rep");
+  }
+
+  function testOnMouseOut() {
+    const stub = getGripStub("testMouseEvent");
+
+    let called = false;
+    let onDOMNodeMouseOut = (object) => {
+      called = true;
+    };
+    const renderedComponent = renderComponent(Event.rep, {
+      object: stub,
+      onDOMNodeMouseOut
+    });
+
+    const node = renderedComponent.querySelector(".objectBox-node");
+    TestUtils.Simulate.mouseOut(node);
+
+    is(called, true, "onDOMNodeMouseOut is called when mouseout is fired on the Rep");
   }
 
   function getGripStub(name) {
     switch (name) {
       case "testEvent":
         return {
           "type": "object",
           "class": "Event",
@@ -214,16 +304,54 @@ window.onload = Task.async(function* () 
                 "attributesLength": 0
               }
             },
             "eventKind": "key",
             "modifiers": []
           }
         };
 
+      case "testKeyboardEventWithModifiers":
+        return {
+          "type": "object",
+          "class": "KeyboardEvent",
+          "actor": "server1.conn21.obj49",
+          "extensible": true,
+          "frozen": false,
+          "sealed": false,
+          "ownPropertyLength": 1,
+          "preview": {
+            "kind": "DOMEvent",
+            "type": "keyup",
+            "properties": {
+              "key": "M",
+              "charCode": 0,
+              "keyCode": 77
+            },
+            "target": {
+              "type": "object",
+              "class": "HTMLBodyElement",
+              "actor": "server1.conn21.obj50",
+              "extensible": true,
+              "frozen": false,
+              "sealed": false,
+              "ownPropertyLength": 0,
+              "preview": {
+                "kind": "DOMNode",
+                "nodeType": 1,
+                "nodeName": "body",
+                "attributes": {},
+                "attributesLength": 0
+              }
+            },
+            "eventKind": "key",
+            "modifiers": ["Meta", "Shift"]
+          }
+        };
+
       case "testMessageEvent":
         return {
           "type": "object",
           "class": "MessageEvent",
           "actor": "server1.conn3.obj34",
           "extensible": true,
           "frozen": false,
           "sealed": false,
@@ -280,17 +408,17 @@ window.onload = Task.async(function* () 
               "class": "Window",
               "actor": "server1.conn3.obj35",
               "extensible": true,
               "frozen": false,
               "sealed": false,
               "ownPropertyLength": 760,
               "preview": {
                 "kind": "ObjectWithURL",
-                "url": ""
+                "url": "http://example.com"
               }
             }
           }
         };
 
     }
   }
 });