Bug 1273323 - Add integration tests for namespaced elements. r=jdescottes
authorNicolas Chevobbe <chevobbe.nicolas@gmail.com>
Sun, 22 May 2016 00:03:42 +0200
changeset 338080 5040cc90f9fc18505d3c9822ca33453ee16f610b
parent 338079 c80d58a15cff0cecf948168917c45c50dbf473b1
child 338081 6a39cf939f60fff5e45c961ca5fe50769984d4a9
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1273323
milestone49.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 1273323 - Add integration tests for namespaced elements. r=jdescottes Add tests for : - markup display - add rule - breadcrumb - highlighter info bar - markup search - webconsole element output Move webconsole dom output test to head.js as similar things are done in several tests. MozReview-Commit-ID: 6gclZhzd7sD
devtools/client/inspector/markup/test/browser.ini
devtools/client/inspector/markup/test/browser_markup_node_names_namespaced.js
devtools/client/inspector/rules/test/browser.ini
devtools/client/inspector/rules/test/browser_rules_add-rule_06.js
devtools/client/inspector/test/browser.ini
devtools/client/inspector/test/browser_inspector_breadcrumbs_namespaced.js
devtools/client/inspector/test/browser_inspector_infobar_02.js
devtools/client/inspector/test/browser_inspector_search-08.js
devtools/client/webconsole/test/browser.ini
devtools/client/webconsole/test/browser_webconsole_output_dom_elements_02.js
devtools/client/webconsole/test/browser_webconsole_output_dom_elements_05.js
devtools/client/webconsole/test/head.js
--- a/devtools/client/inspector/markup/test/browser.ini
+++ b/devtools/client/inspector/markup/test/browser.ini
@@ -104,18 +104,19 @@ subsuite = clipboard
 [browser_markup_keybindings_01.js]
 [browser_markup_keybindings_02.js]
 [browser_markup_keybindings_03.js]
 [browser_markup_keybindings_04.js]
 [browser_markup_keybindings_delete_attributes.js]
 [browser_markup_keybindings_scrolltonode.js]
 [browser_markup_mutation_01.js]
 [browser_markup_mutation_02.js]
+[browser_markup_navigation.js]
 [browser_markup_node_names.js]
-[browser_markup_navigation.js]
+[browser_markup_node_names_namespaced.js]
 [browser_markup_node_not_displayed_01.js]
 [browser_markup_node_not_displayed_02.js]
 [browser_markup_pagesize_01.js]
 [browser_markup_pagesize_02.js]
 [browser_markup_remove_xul_attributes.js]
 skip-if = e10s # Bug 1036409 - The last selected node isn't reselected
 [browser_markup_search_01.js]
 [browser_markup_tag_edit_01.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/test/browser_markup_node_names_namespaced.js
@@ -0,0 +1,43 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test namespaced element node names in the markupview.
+
+const XHTML = `
+  <!DOCTYPE html>
+  <html xmlns="http://www.w3.org/1999/xhtml"
+        xmlns:svg="http://www.w3.org/2000/svg">
+    <body>
+      <svg:svg width="100" height="100">
+        <svg:clipPath id="clip">
+          <svg:rect id="rectangle" x="0" y="0" width="10" height="5"></svg:rect>
+        </svg:clipPath>
+        <svg:circle cx="0" cy="0" r="5"></svg:circle>
+      </svg:svg>
+    </body>
+  </html>
+`;
+
+const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
+
+add_task(function* () {
+  let {inspector} = yield openInspectorForURL(TEST_URI);
+
+  // Get and open the svg element to show its children.
+  let svgNodeFront = yield getNodeFront("svg", inspector);
+  yield inspector.markup.expandNode(svgNodeFront);
+  yield waitForMultipleChildrenUpdates(inspector);
+
+  let clipPathContainer = yield getContainerForSelector("clipPath", inspector);
+  info("Checking the clipPath element");
+  ok(clipPathContainer.editor.tag.textContent === "svg:clipPath",
+     "svg:clipPath node is correctly displayed");
+
+  let circlePathContainer = yield getContainerForSelector("circle", inspector);
+  info("Checking the circle element");
+  ok(circlePathContainer.editor.tag.textContent === "svg:circle",
+     "svg:circle node is correctly displayed");
+});
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -47,16 +47,17 @@ support-files =
 [browser_rules_add-property_01.js]
 [browser_rules_add-property_02.js]
 [browser_rules_add-property-svg.js]
 [browser_rules_add-rule_01.js]
 [browser_rules_add-rule_02.js]
 [browser_rules_add-rule_03.js]
 [browser_rules_add-rule_04.js]
 [browser_rules_add-rule_05.js]
+[browser_rules_add-rule_06.js]
 [browser_rules_add-rule_pseudo_class.js]
 [browser_rules_add-rule_iframes.js]
 [browser_rules_authored.js]
 [browser_rules_authored_color.js]
 [browser_rules_authored_override.js]
 [browser_rules_blob_stylesheet.js]
 [browser_rules_colorpicker-and-image-tooltip_01.js]
 [browser_rules_colorpicker-and-image-tooltip_02.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_add-rule_06.js
@@ -0,0 +1,49 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests the behaviour of adding a new rule using the add rule button
+// on namespaced elements.
+
+const XHTML = `
+  <!DOCTYPE html>
+  <html xmlns="http://www.w3.org/1999/xhtml"
+        xmlns:svg="http://www.w3.org/2000/svg">
+    <body>
+      <svg:svg width="100" height="100">
+        <svg:clipPath>
+          <svg:rect x="0" y="0" width="10" height="5"></svg:rect>
+        </svg:clipPath>
+        <svg:circle cx="0" cy="0" r="5"></svg:circle>
+      </svg:svg>
+    </body>
+  </html>
+`;
+const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
+
+const TEST_DATA = [
+  { node: "clipPath", expected: "clipPath" },
+  { node: "rect", expected: "rect" },
+  { node: "circle", expected: "circle" }
+];
+
+add_task(function* () {
+  yield addTab(TEST_URI);
+  let {inspector, view} = yield openRuleView();
+
+  for (let data of TEST_DATA) {
+    let {node, expected} = data;
+    yield selectNode(node, inspector);
+    yield addNewRule(inspector, view);
+    yield testNewRule(view, expected, 1);
+  }
+});
+
+function* testNewRule(view, expected, index) {
+  let idRuleEditor = getRuleViewRuleEditor(view, index);
+  let editor = idRuleEditor.selectorText.ownerDocument.activeElement;
+  is(editor.value, expected,
+      "Selector editor value is as expected: " + expected);
+}
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -41,16 +41,17 @@ support-files =
 [browser_inspector_addNode_02.js]
 [browser_inspector_addNode_03.js]
 [browser_inspector_breadcrumbs.js]
 [browser_inspector_breadcrumbs_highlight_hover.js]
 [browser_inspector_breadcrumbs_keybinding.js]
 [browser_inspector_breadcrumbs_keyboard_trap.js]
 skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard Preferences
 [browser_inspector_breadcrumbs_mutations.js]
+[browser_inspector_breadcrumbs_namespaced.js]
 [browser_inspector_delete-selected-node-01.js]
 [browser_inspector_delete-selected-node-02.js]
 [browser_inspector_delete-selected-node-03.js]
 [browser_inspector_destroy-after-navigation.js]
 [browser_inspector_destroy-before-ready.js]
 [browser_inspector_expand-collapse.js]
 [browser_inspector_gcli-inspect-command.js]
 [browser_inspector_highlighter-01.js]
@@ -86,16 +87,17 @@ skip-if = os == "mac" # Full keyboard na
 [browser_inspector_highlighter-rulers_01.js]
 [browser_inspector_highlighter-rulers_02.js]
 [browser_inspector_highlighter-selector_01.js]
 [browser_inspector_highlighter-selector_02.js]
 [browser_inspector_highlighter-xbl.js]
 [browser_inspector_highlighter-zoom.js]
 [browser_inspector_iframe-navigation.js]
 [browser_inspector_infobar_01.js]
+[browser_inspector_infobar_02.js]
 [browser_inspector_initialization.js]
 skip-if = (e10s && debug) # Bug 1250058 - Docshell leak on debug e10s
 [browser_inspector_inspect-object-element.js]
 [browser_inspector_invalidate.js]
 [browser_inspector_keyboard-shortcuts-copy-outerhtml.js]
 subsuite = clipboard
 [browser_inspector_keyboard-shortcuts.js]
 [browser_inspector_menu-01-sensitivity.js]
@@ -121,16 +123,17 @@ subsuite = clipboard
 [browser_inspector_remove-iframe-during-load.js]
 [browser_inspector_search-01.js]
 [browser_inspector_search-02.js]
 [browser_inspector_search-03.js]
 [browser_inspector_search-04.js]
 [browser_inspector_search-05.js]
 [browser_inspector_search-06.js]
 [browser_inspector_search-07.js]
+[browser_inspector_search-08.js]
 [browser_inspector_search_keyboard_trap.js]
 [browser_inspector_search-reserved.js]
 [browser_inspector_search-selection.js]
 [browser_inspector_select-docshell.js]
 [browser_inspector_select-last-selected.js]
 [browser_inspector_search-navigation.js]
 [browser_inspector_sidebarstate.js]
 [browser_inspector_switch-to-inspector-on-pick.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_namespaced.js
@@ -0,0 +1,55 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test that the breadcrumbs widget content for namespaced elements is correct.
+
+const XHTML = `
+  <!DOCTYPE html>
+  <html xmlns="http://www.w3.org/1999/xhtml"
+        xmlns:svg="http://www.w3.org/2000/svg">
+    <body>
+      <svg:svg width="100" height="100">
+        <svg:clipPath id="clip">
+          <svg:rect id="rectangle" x="0" y="0" width="10" height="5"></svg:rect>
+        </svg:clipPath>
+        <svg:circle cx="0" cy="0" r="5"></svg:circle>
+      </svg:svg>
+    </body>
+  </html>
+`;
+
+const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
+
+const NODES = [
+  {selector: "clipPath", nodes: ["svg:svg", "svg:clipPath"],
+    nodeName: "svg:clipPath", title: "svg:clipPath#clip"},
+  {selector: "circle", nodes: ["svg:svg", "svg:circle"],
+    nodeName: "svg:circle", title: "svg:circle"},
+];
+
+add_task(function* () {
+  let { inspector } = yield openInspectorForURL(TEST_URI);
+  let container = inspector.panelDoc.getElementById("inspector-breadcrumbs");
+
+  for (let node of NODES) {
+    info("Testing node " + node.selector);
+
+    info("Selecting node and waiting for breadcrumbs to update");
+    let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
+    yield selectNode(node.selector, inspector);
+    yield breadcrumbsUpdated;
+
+    info("Performing checks for node " + node.selector);
+
+    let checkedButton = container.querySelector("button[checked]");
+
+    let labelTag = checkedButton.querySelector(".breadcrumbs-widget-item-tag");
+    is(labelTag.textContent, node.nodeName,
+      "Node " + node.selector + " has the expected tag name");
+
+    is(checkedButton.getAttribute("tooltiptext"), node.title,
+      "Node " + node.selector + " has the expected tooltip");
+  }
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_infobar_02.js
@@ -0,0 +1,50 @@
+/* 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";
+
+// Check the text content of the highlighter info bar for namespaced elements.
+
+const XHTML = `
+  <!DOCTYPE html>
+  <html xmlns="http://www.w3.org/1999/xhtml"
+        xmlns:svg="http://www.w3.org/2000/svg">
+    <body>
+      <svg:svg width="100" height="100">
+        <svg:circle cx="0" cy="0" r="5"></svg:circle>
+      </svg:svg>
+    </body>
+  </html>
+`;
+
+const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
+
+add_task(function* () {
+  let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
+
+  let testData = [
+    {
+      selector: "svg",
+      tag: "svg:svg"
+    },
+    {
+      selector: "circle",
+      tag: "svg:circle"
+    },
+  ];
+
+  for (let currTest of testData) {
+    yield testNode(currTest, inspector, testActor);
+  }
+});
+
+function* testNode(test, inspector, testActor) {
+  info("Testing " + test.selector);
+
+  yield selectAndHighlightNode(test.selector, inspector);
+
+  let tag = yield testActor.getHighlighterNodeTextContent(
+    "box-model-nodeinfobar-tagname");
+  is(tag, test.tag, "node " + test.selector + ": tagName matches.");
+}
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/test/browser_inspector_search-08.js
@@ -0,0 +1,64 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+// Test that searching for namespaced elements does work.
+
+const XHTML = `
+  <!DOCTYPE html>
+  <html xmlns="http://www.w3.org/1999/xhtml"
+        xmlns:svg="http://www.w3.org/2000/svg">
+    <body>
+      <svg:svg width="100" height="100">
+        <svg:clipPath>
+          <svg:rect x="0" y="0" width="10" height="5"></svg:rect>
+        </svg:clipPath>
+        <svg:circle cx="0" cy="0" r="5"></svg:circle>
+      </svg:svg>
+    </body>
+  </html>
+`;
+
+const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
+
+// An array of (key, suggestions) pairs where key is a key to press and
+// suggestions is an array of suggestions that should be shown in the popup.
+const TEST_DATA = [{
+  key: "c",
+  suggestions: ["circle", "clipPath"]
+}, {
+  key: "VK_BACK_SPACE",
+  suggestions: []
+}, {
+  key: "s",
+  suggestions: ["svg"]
+}];
+
+add_task(function* () {
+  let {inspector} = yield openInspectorForURL(TEST_URI);
+  let {searchBox} = inspector;
+  let popup = inspector.searchSuggestions.searchPopup;
+
+  yield focusSearchBoxUsingShortcut(inspector.panelWin);
+
+  for (let {key, suggestions} of TEST_DATA) {
+    info("Pressing " + key + " to get " + suggestions.join(", "));
+
+    let command = once(searchBox, "command");
+    EventUtils.synthesizeKey(key, {}, inspector.panelWin);
+    yield command;
+
+    info("Waiting for search query to complete and getting the suggestions");
+    yield inspector.searchSuggestions._lastQuery;
+    let actualSuggestions = popup.getItems().reverse();
+
+    is(popup.isOpen ? actualSuggestions.length : 0, suggestions.length,
+       "There are expected number of suggestions.");
+
+    for (let i = 0; i < suggestions.length; i++) {
+      is(actualSuggestions[i].label, suggestions[i],
+         "The suggestion at " + i + "th index is correct.");
+    }
+  }
+});
--- a/devtools/client/webconsole/test/browser.ini
+++ b/devtools/client/webconsole/test/browser.ini
@@ -361,16 +361,17 @@ tags = trackingprotection
 [browser_webconsole_output_05.js]
 [browser_webconsole_output_06.js]
 [browser_webconsole_output_dom_elements_01.js]
 [browser_webconsole_output_dom_elements_02.js]
 skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
 [browser_webconsole_output_dom_elements_03.js]
 [browser_webconsole_output_dom_elements_04.js]
 skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
+[browser_webconsole_output_dom_elements_05.js]
 [browser_webconsole_output_events.js]
 [browser_webconsole_output_regexp.js]
 [browser_webconsole_output_table.js]
 [browser_console_variables_view_highlighter.js]
 [browser_webconsole_start_netmon_first.js]
 [browser_webconsole_console_trace_duplicates.js]
 [browser_webconsole_cd_iframe.js]
 [browser_webconsole_autocomplete_crossdomain_iframe.js]
--- a/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_02.js
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_02.js
@@ -1,54 +1,54 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test the inspector links in the webconsole output for DOM Nodes actually
-// open the inspector and select the right node
+// open the inspector and select the right node.
 
 "use strict";
 
 const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
                  "test/test-console-output-dom-elements.html";
 
 const TEST_DATA = [
   {
     // The first test shouldn't be returning the body element as this is the
     // default selected node, so re-selecting it won't fire the
     // inspector-updated event
     input: "testNode()",
     output: '<p some-attribute="some-value">',
-    tagName: "P",
+    displayName: "p",
     attrs: [{name: "some-attribute", value: "some-value"}]
   },
   {
     input: "testBodyNode()",
     output: '<body class="body-class" id="body-id">',
-    tagName: "BODY",
+    displayName: "body",
     attrs: [
       {
         name: "class", value: "body-class"
       },
       {
         name: "id", value: "body-id"
       }
     ]
   },
   {
     input: "testNodeInIframe()",
     output: "<p>",
-    tagName: "P",
+    displayName: "p",
     attrs: []
   },
   {
     input: "testDocumentElement()",
     output: '<html dir="ltr" lang="en-US">',
-    tagName: "HTML",
+    displayName: "html",
     attrs: [
       {
         name: "dir",
         value: "ltr"
       },
       {
         name: "lang",
         value: "en-US"
@@ -56,87 +56,11 @@ const TEST_DATA = [
     ]
   }
 ];
 
 function test() {
   Task.spawn(function* () {
     let {tab} = yield loadTab(TEST_URI);
     let hud = yield openConsole(tab);
-    let toolbox = gDevTools.getToolbox(hud.target);
-
-    // Loading the inspector panel at first, to make it possible to listen for
-    // new node selections
-    yield toolbox.selectTool("inspector");
-    let inspector = toolbox.getCurrentPanel();
-    yield toolbox.selectTool("webconsole");
-
-    info("Iterating over the test data");
-    for (let data of TEST_DATA) {
-      let [result] = yield jsEval(data.input, hud, {text: data.output});
-      let {msg} = yield getWidgetAndMessage(result);
-
-      let inspectorIcon = msg.querySelector(".open-inspector");
-      ok(inspectorIcon, "Inspector icon found in the ElementNode widget");
-
-      info("Clicking on the inspector icon and waiting for the " +
-           "inspector to be selected");
-      let onInspectorSelected = toolbox.once("inspector-selected");
-      let onInspectorUpdated = inspector.once("inspector-updated");
-      let onNewNode = toolbox.selection.once("new-node-front");
-      let onNodeHighlight = toolbox.once("node-highlight");
-
-      EventUtils.synthesizeMouseAtCenter(inspectorIcon, {},
-        inspectorIcon.ownerDocument.defaultView);
-      yield onInspectorSelected;
-      yield onInspectorUpdated;
-      yield onNodeHighlight;
-      let nodeFront = yield onNewNode;
-
-      ok(true, "Inspector selected and new node got selected");
-
-      is(nodeFront.tagName, data.tagName, "The correct node was highlighted");
-
-      let attrs = nodeFront.attributes;
-      for (let i in data.attrs) {
-        is(attrs[i].name, data.attrs[i].name,
-           "The correct node was highlighted");
-        is(attrs[i].value, data.attrs[i].value,
-           "The correct node was highlighted");
-      }
-
-      info("Unhighlight the node by moving away from the markup view");
-      let onNodeUnhighlight = toolbox.once("node-unhighlight");
-      let btn = inspector.toolbox.doc.querySelector(".toolbox-dock-button");
-      EventUtils.synthesizeMouseAtCenter(btn, {type: "mousemove"},
-        inspector.toolbox.win);
-      yield onNodeUnhighlight;
-
-      info("Switching back to the console");
-      yield toolbox.selectTool("webconsole");
-    }
+    yield checkDomElementHighlightingForInputs(hud, TEST_DATA);
   }).then(finishTest);
 }
-
-function jsEval(input, hud, message) {
-  info("Executing '" + input + "' in the web console");
-
-  hud.jsterm.clearOutput();
-  hud.jsterm.execute(input);
-
-  return waitForMessages({
-    webconsole: hud,
-    messages: [message]
-  });
-}
-
-function* getWidgetAndMessage(result) {
-  info("Getting the output ElementNode widget");
-
-  let msg = [...result.matched][0];
-  let widget = [...msg._messageObject.widgets][0];
-  ok(widget, "ElementNode widget found in the output");
-
-  info("Waiting for the ElementNode widget to be linked to the inspector");
-  yield widget.linkToInspector();
-
-  return {widget: widget, msg: msg};
-}
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/browser_webconsole_output_dom_elements_05.js
@@ -0,0 +1,47 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the inspector links in the webconsole output for namespaced elements
+// actually open the inspector and select the right node.
+
+const XHTML = `
+  <!DOCTYPE html>
+  <html xmlns="http://www.w3.org/1999/xhtml"
+        xmlns:svg="http://www.w3.org/2000/svg">
+    <body>
+      <svg:svg width="100" height="100">
+        <svg:clipPath id="clip">
+          <svg:rect id="rectangle" x="0" y="0" width="10" height="5"></svg:rect>
+        </svg:clipPath>
+        <svg:circle cx="0" cy="0" r="5"></svg:circle>
+      </svg:svg>
+    </body>
+  </html>
+`;
+
+const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
+
+const TEST_DATA = [
+  {
+    input: 'document.querySelector("clipPath")',
+    output: '<svg:clipPath id="clip">',
+    displayName: "svg:clipPath"
+  },
+  {
+    input: 'document.querySelector("circle")',
+    output: '<svg:circle cx="0" cy="0" r="5">',
+    displayName: "svg:circle"
+  },
+];
+
+function test() {
+  Task.spawn(function* () {
+    let {tab} = yield loadTab(TEST_URI);
+    let hud = yield openConsole(tab);
+    yield checkDomElementHighlightingForInputs(hud, TEST_DATA);
+  }).then(finishTest);
+}
--- a/devtools/client/webconsole/test/head.js
+++ b/devtools/client/webconsole/test/head.js
@@ -1579,16 +1579,124 @@ function checkOutputForInputs(hud, input
          "opened tab '" + uri + "', expected tab '" + entry.expectedTab + "'");
       yield closeTab(tab);
     }).then(resolve, reject);
   }
 
   return Task.spawn(runner);
 }
 
+/**
+ * Check the web console DOM element output for the given inputs.
+ * Each input is checked for the expected JS eval result. The JS eval result is
+ * also checked if it opens the inspector with the correct node selected on
+ * inspector icon click
+ *
+ * @param object hud
+ *        The web console instance to work with.
+ * @param array inputTests
+ *        An array of input tests. An input test element is an object. Each
+ *        object has the following properties:
+ *        - input: string, JS input value to execute.
+ *
+ *        - output: string, expected JS eval result.
+ *
+ *        - displayName: string, expected NodeFront's displayName.
+ *
+ *        - attr: Array, expected NodeFront's attributes
+ */
+function checkDomElementHighlightingForInputs(hud, inputs) {
+  function* runner() {
+    let toolbox = gDevTools.getToolbox(hud.target);
+
+    // Loading the inspector panel at first, to make it possible to listen for
+    // new node selections
+    yield toolbox.selectTool("inspector");
+    let inspector = toolbox.getCurrentPanel();
+    yield toolbox.selectTool("webconsole");
+
+    info("Iterating over the test data");
+    for (let data of inputs) {
+      let [result] = yield jsEval(data.input, {text: data.output});
+      let {msg} = yield checkWidgetAndMessage(result);
+      yield checkNodeHighlight(toolbox, inspector, msg, data);
+    }
+  }
+
+  function jsEval(input, message) {
+    info("Executing '" + input + "' in the web console");
+
+    hud.jsterm.clearOutput();
+    hud.jsterm.execute(input);
+
+    return waitForMessages({
+      webconsole: hud,
+      messages: [message]
+    });
+  }
+
+  function* checkWidgetAndMessage(result) {
+    info("Getting the output ElementNode widget");
+
+    let msg = [...result.matched][0];
+    let widget = [...msg._messageObject.widgets][0];
+    ok(widget, "ElementNode widget found in the output");
+
+    info("Waiting for the ElementNode widget to be linked to the inspector");
+    yield widget.linkToInspector();
+
+    return {widget, msg};
+  }
+
+  function* checkNodeHighlight(toolbox, inspector, msg, testData) {
+    let inspectorIcon = msg.querySelector(".open-inspector");
+    ok(inspectorIcon, "Inspector icon found in the ElementNode widget");
+
+    info("Clicking on the inspector icon and waiting for the " +
+         "inspector to be selected");
+    let onInspectorSelected = toolbox.once("inspector-selected");
+    let onInspectorUpdated = inspector.once("inspector-updated");
+    let onNewNode = toolbox.selection.once("new-node-front");
+    let onNodeHighlight = toolbox.once("node-highlight");
+
+    EventUtils.synthesizeMouseAtCenter(inspectorIcon, {},
+      inspectorIcon.ownerDocument.defaultView);
+    yield onInspectorSelected;
+    yield onInspectorUpdated;
+    yield onNodeHighlight;
+    let nodeFront = yield onNewNode;
+
+    ok(true, "Inspector selected and new node got selected");
+
+    is(nodeFront.displayName, testData.displayName,
+      "The correct node was highlighted");
+
+    if (testData.attrs) {
+      let attrs = nodeFront.attributes;
+      for (let i in testData.attrs) {
+        is(attrs[i].name, testData.attrs[i].name,
+           "Expected attribute's name is present");
+        is(attrs[i].value, testData.attrs[i].value,
+           "Expected attribute's value is present");
+      }
+    }
+
+    info("Unhighlight the node by moving away from the markup view");
+    let onNodeUnhighlight = toolbox.once("node-unhighlight");
+    let btn = inspector.toolbox.doc.querySelector(".toolbox-dock-button");
+    EventUtils.synthesizeMouseAtCenter(btn, {type: "mousemove"},
+      inspector.toolbox.win);
+    yield onNodeUnhighlight;
+
+    info("Switching back to the console");
+    yield toolbox.selectTool("webconsole");
+  }
+
+  return Task.spawn(runner);
+}
 
 /**
  * Finish the request and resolve with the request object.
  *
  * @param {Function} predicate A predicate function that takes the request
  * object as an argument and returns true if the request was the expected one,
  * false otherwise. The returned promise is resolved ONLY if the predicate
  * matches a request. Defaults to accepting any request.