Bug 1320359 - Make EventRep displays like events were displayed in old console; r=Honza
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Fri, 25 Nov 2016 23:52:06 +0100
changeset 324839 601cde18dfb4dfa8034dd4ad470144b559b80453
parent 324838 30baf39ed89ff9c3efe4ffc1416835e9ed790b50
child 324840 d2c1a3a02f40e4018338678889a6a66a4b6ba86f
push id84525
push userphilringnalda@gmail.com
push dateThu, 01 Dec 2016 03:22:09 +0000
treeherdermozilla-inbound@b1d875f4c673 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersHonza
bugs1320359
milestone53.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 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"
               }
             }
           }
         };
 
     }
   }
 });