Bug 1438463 - Fix click on location in browser console with new frontend; r=bgrins. draft
authorNicolas Chevobbe <nchevobbe@mozilla.com>
Fri, 16 Feb 2018 09:14:02 +0100
changeset 756944 6153a2bebdf734108c891dfc372fb4efa6d7976b
parent 756852 ad133cd410a719c0b67e61b8d3b1c77a32fd80a9
push id99589
push userbmo:nchevobbe@mozilla.com
push dateMon, 19 Feb 2018 11:46:00 +0000
reviewersbgrins
bugs1438463
milestone60.0a1
Bug 1438463 - Fix click on location in browser console with new frontend; r=bgrins. To fix this, we fallback to viewSource when we don't have access to the toolbox, which is what was done in the old frontend. MozReview-Commit-ID: JCcprTlViMi
devtools/client/webconsole/new-console-output/components/Message.js
devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
devtools/client/webconsole/new-console-output/test/components/message-location.test.js
--- a/devtools/client/webconsole/new-console-output/components/Message.js
+++ b/devtools/client/webconsole/new-console-output/components/Message.js
@@ -160,18 +160,20 @@ class Message extends Component {
       attachment = this.props.attachment;
     } else if (stacktrace && open) {
       attachment = dom.div(
         {
           className: "stacktrace devtools-monospace"
         },
         StackTrace({
           stacktrace: stacktrace,
-          onViewSourceInDebugger: serviceContainer.onViewSourceInDebugger,
-          onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad,
+          onViewSourceInDebugger: serviceContainer.onViewSourceInDebugger
+            || serviceContainer.onViewSource,
+          onViewSourceInScratchpad: serviceContainer.onViewSourceInScratchpad
+            || serviceContainer.onViewSource,
           sourceMapService: serviceContainer.sourceMapService,
         })
       );
     }
 
     // If there is an expandable part, make it collapsible.
     let collapse = null;
     if (collapsible) {
@@ -188,17 +190,17 @@ class Message extends Component {
         { className: "message-flex-body error-note" },
         dom.span({ className: "message-body devtools-monospace" },
           "note: " + note.messageBody
         ),
         dom.span({ className: "message-location devtools-monospace" },
           note.frame ? FrameView({
             frame: note.frame,
             onClick: serviceContainer
-              ? serviceContainer.onViewSourceInDebugger
+              ? serviceContainer.onViewSourceInDebugger || serviceContainer.onViewSource
               : undefined,
             showEmptyPathAsHost: true,
             sourceMapService: serviceContainer
               ? serviceContainer.sourceMapService
               : undefined
           }) : null
         )));
     } else {
@@ -208,21 +210,23 @@ class Message extends Component {
     const repeat = this.props.repeat && this.props.repeat > 1 ?
       MessageRepeat({repeat: this.props.repeat}) : null;
 
     let onFrameClick;
     if (serviceContainer && frame) {
       if (source === MESSAGE_SOURCE.CSS) {
         onFrameClick = serviceContainer.onViewSourceInStyleEditor;
       } else if (/^Scratchpad\/\d+$/.test(frame.source)) {
-        onFrameClick = serviceContainer.onViewSourceInScratchpad;
+        onFrameClick = serviceContainer.onViewSourceInScratchpad
+          || serviceContainer.onViewSource;
       } else {
         // Point everything else to debugger, if source not available,
         // it will fall back to view-source.
-        onFrameClick = serviceContainer.onViewSourceInDebugger;
+        onFrameClick = serviceContainer.onViewSourceInDebugger
+          || serviceContainer.onViewSource;
       }
     }
 
     // Configure the location.
     const location = dom.span({ className: "message-location devtools-monospace" },
       frame ? FrameView({
         frame,
         onClick: onFrameClick,
--- a/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
+++ b/devtools/client/webconsole/new-console-output/new-console-output-wrapper.js
@@ -95,16 +95,21 @@ NewConsoleOutputWrapper.prototype = {
           return this.document.createElement(nodename);
         },
         getLongString: (grip) => {
           return hud.proxy.webConsoleClient.getString(grip);
         },
         requestData(id, type) {
           return hud.proxy.networkDataProvider.requestData(id, type);
         },
+        onViewSource(frame) {
+          if (hud && hud.owner && hud.owner.viewSource) {
+            hud.owner.viewSource(frame.url, frame.line);
+          }
+        }
       };
 
       // Set `openContextMenu` this way so, `serviceContainer` variable
       // is available in the current scope and we can pass it into
       // `createContextMenu` method.
       serviceContainer.openContextMenu = (e, message) => {
         let { screenX, screenY, target } = e;
 
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/new-console-output/test/components/message-location.test.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test utils.
+const expect = require("expect");
+const { mount } = require("enzyme");
+const sinon = require("sinon");
+const { createFactory } = require("devtools/client/shared/vendor/react");
+const serviceContainer = require("devtools/client/webconsole/new-console-output/test/fixtures/serviceContainer");
+
+let { MessageContainer } = require("devtools/client/webconsole/new-console-output/components/MessageContainer");
+MessageContainer = createFactory(MessageContainer);
+
+// Test fakes.
+const { stubPreparedMessages } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
+
+describe("Message - location element", () => {
+  it("Calls onViewSourceInDebugger when clicked", () => {
+    const onViewSourceInDebugger = sinon.spy();
+    const onViewSource = sinon.spy();
+
+    const message = stubPreparedMessages.get("console.log('foobar', 'test')");
+    const wrapper = mount(MessageContainer({
+      getMessage: () => message,
+      serviceContainer: Object.assign({}, serviceContainer, {
+        onViewSourceInDebugger,
+        onViewSource,
+      })
+    }));
+
+    // There should be the location
+    const locationLink = wrapper.find(`.message-location a`);
+    expect(locationLink.length).toBe(1);
+    expect(locationLink.text()).toBe("test-console-api.html:1:27");
+
+    locationLink.simulate("click");
+
+    expect(onViewSourceInDebugger.calledOnce).toBe(true);
+    expect(onViewSource.notCalled).toBe(true);
+  });
+
+  it.only("Calls onViewSource when clicked and onViewSourceInDebugger undefined", () => {
+    const onViewSource = sinon.spy();
+
+    const message = stubPreparedMessages.get("console.log('foobar', 'test')");
+
+    const wrapper = mount(MessageContainer({
+      getMessage: () => message,
+      serviceContainer: Object.assign({}, serviceContainer, {
+        onViewSource,
+        onViewSourceInDebugger: undefined,
+      })
+    }));
+
+    // There should be the location
+    const locationLink = wrapper.find(`.message-location a`);
+
+    locationLink.simulate("click");
+    expect(onViewSource.calledOnce).toBe(true);
+  });
+});