Bug 921102 - 4 - Tests for the open/copy links on markup-view attributes; r=bgrins
authorPatrick Brosset <pbrosset@mozilla.com>
Sat, 02 May 2015 23:00:13 +0200
changeset 271997 fd2aa3f10d7f71942179ced6c014acd4273e8ae9
parent 271996 8fe899f2537eab56aa541b79d5f4a0422ff1942c
child 271998 18347201f0351c16e74519044fd0dae4b785434a
push id4830
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:18:48 +0000
treeherdermozilla-beta@4c2175bb0420 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs921102
milestone40.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 921102 - 4 - Tests for the open/copy links on markup-view attributes; r=bgrins
browser/devtools/inspector/inspector-panel.js
browser/devtools/markupview/test/browser.ini
browser/devtools/markupview/test/browser_markupview_links_01.js
browser/devtools/markupview/test/browser_markupview_links_04.js
browser/devtools/markupview/test/browser_markupview_links_05.js
browser/devtools/markupview/test/doc_markup_links.html
browser/devtools/markupview/test/head.js
--- a/browser/devtools/inspector/inspector-panel.js
+++ b/browser/devtools/inspector/inspector-panel.js
@@ -1108,16 +1108,17 @@ InspectorPanel.prototype = {
         let browserWin = this.target.tab.ownerDocument.defaultView;
         browserWin.openUILinkIn(url, "tab");
       }, console.error);
     } else if (type == "idref") {
       // Select the node in the same document.
       this.walker.document(this.selection.nodeFront).then(doc => {
         this.walker.querySelector(doc, "#" + CSS.escape(link)).then(node => {
           if (!node) {
+            this.emit("idref-attribute-link-failed");
             return;
           }
           this.selection.setNodeFront(node);
         }, console.error);
       }, console.error);
     }
   },
 
--- a/browser/devtools/markupview/test/browser.ini
+++ b/browser/devtools/markupview/test/browser.ini
@@ -67,16 +67,18 @@ skip-if = e10s # Bug 1040751 - CodeMirro
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_1.11.1.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_events_jquery_2.1.1.js]
 skip-if = e10s # Bug 1040751 - CodeMirror editor.destroy() isn't e10s compatible
 [browser_markupview_links_01.js]
 [browser_markupview_links_02.js]
 [browser_markupview_links_03.js]
+[browser_markupview_links_04.js]
+[browser_markupview_links_05.js]
 [browser_markupview_load_01.js]
 [browser_markupview_html_edit_01.js]
 [browser_markupview_html_edit_02.js]
 [browser_markupview_html_edit_03.js]
 [browser_markupview_image_tooltip.js]
 [browser_markupview_keybindings_01.js]
 [browser_markupview_keybindings_02.js]
 [browser_markupview_keybindings_03.js]
--- a/browser/devtools/markupview/test/browser_markupview_links_01.js
+++ b/browser/devtools/markupview/test/browser_markupview_links_01.js
@@ -43,17 +43,18 @@ const TEST_DATA = [{
   selector: "output",
   attributes: [{
     attributeName: "form",
     links: [{type: "idref", value: "message-form"}]
   }, {
     attributeName: "for",
     links: [
       {type: "idref", value: "name"},
-      {type: "idref", value: "message"}
+      {type: "idref", value: "message"},
+      {type: "idref", value: "invalid"}
     ]
   }]
 }, {
   selector: "a",
   attributes: [{
     attributeName: "href",
     links: [{type: "uri", value: "/go/somewhere/else"}]
   }, {
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/browser_markupview_links_04.js
@@ -0,0 +1,108 @@
+/* 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";
+
+// Tests that the contextual menu shows the right items when clicking on a link
+// in an attribute.
+
+const TEST_URL = TEST_URL_ROOT + "doc_markup_links.html";
+const STRINGS = Services.strings
+  .createBundle("chrome://browser/locale/devtools/inspector.properties");
+
+// The test case array contains objects with the following properties:
+// - selector: css selector for the node to select in the inspector
+// - attributeName: name of the attribute to test
+// - popupNodeSelector: css selector for the element inside the attribute
+//   element to use as the contextual menu anchor
+// - isLinkFollowItemVisible: is the follow-link item expected to be displayed
+// - isLinkCopyItemVisible: is the copy-link item expected to be displayed
+// - linkFollowItemLabel: the expected label of the follow-link item
+// - linkCopyItemLabel: the expected label of the copy-link item
+const TEST_DATA = [{
+  selector: "link",
+  attributeName: "href",
+  popupNodeSelector: ".link",
+  isLinkFollowItemVisible: true,
+  isLinkCopyItemVisible: true,
+  linkFollowItemLabel: STRINGS.GetStringFromName("inspector.menu.openUrlInNewTab.label"),
+  linkCopyItemLabel: STRINGS.GetStringFromName("inspector.menu.copyUrlToClipboard.label")
+}, {
+  selector: "link[rel=icon]",
+  attributeName: "href",
+  popupNodeSelector: ".link",
+  isLinkFollowItemVisible: true,
+  isLinkCopyItemVisible: true,
+  linkFollowItemLabel: STRINGS.GetStringFromName("inspector.menu.openUrlInNewTab.label"),
+  linkCopyItemLabel: STRINGS.GetStringFromName("inspector.menu.copyUrlToClipboard.label")
+}, {
+  selector: "link",
+  attributeName: "rel",
+  popupNodeSelector: ".attr-value",
+  isLinkFollowItemVisible: false,
+  isLinkCopyItemVisible: false
+}, {
+  selector: "output",
+  attributeName: "for",
+  popupNodeSelector: ".link",
+  isLinkFollowItemVisible: true,
+  isLinkCopyItemVisible: false,
+  linkFollowItemLabel: STRINGS.formatStringFromName(
+    "inspector.menu.selectElement.label", ["name"], 1)
+}, {
+  selector: "script",
+  attributeName: "src",
+  popupNodeSelector: ".link",
+  isLinkFollowItemVisible: true,
+  isLinkCopyItemVisible: true,
+  linkFollowItemLabel: STRINGS.GetStringFromName("inspector.menu.openUrlInNewTab.label"),
+  linkCopyItemLabel: STRINGS.GetStringFromName("inspector.menu.copyUrlToClipboard.label")
+}, {
+  selector: "p[for]",
+  attributeName: "for",
+  popupNodeSelector: ".attr-value",
+  isLinkFollowItemVisible: false,
+  isLinkCopyItemVisible: false
+}];
+
+add_task(function*() {
+  let {inspector} = yield addTab(TEST_URL).then(openInspector);
+
+  let linkFollow = inspector.panelDoc.getElementById("node-menu-link-follow");
+  let linkCopy = inspector.panelDoc.getElementById("node-menu-link-copy");
+
+  for (let test of TEST_DATA) {
+    info("Selecting test node " + test.selector);
+    yield selectNode(test.selector, inspector);
+
+    info("Finding the popupNode to anchor the context-menu to");
+    let {editor} = yield getContainerForSelector(test.selector, inspector);
+    let popupNode = editor.attrElements.get(test.attributeName)
+                    .querySelector(test.popupNodeSelector);
+    ok(popupNode, "Found the popupNode in attribute " + test.attributeName);
+
+    info("Simulating a context click on the popupNode");
+    contextMenuClick(popupNode);
+
+    // The contextual menu setup is async, because it needs to know if the
+    // inspector has the resolveRelativeURL method first. So call actorHasMethod
+    // here too to make sure the first call resolves first and the menu is
+    // properly setup.
+    yield inspector.target.actorHasMethod("inspector", "resolveRelativeURL");
+
+    is(linkFollow.hasAttribute("hidden"), !test.isLinkFollowItemVisible,
+      "The follow-link item display is correct");
+    is(linkCopy.hasAttribute("hidden"), !test.isLinkCopyItemVisible,
+      "The copy-link item display is correct");
+
+    if (test.isLinkFollowItemVisible) {
+      is(linkFollow.getAttribute("label"), test.linkFollowItemLabel,
+        "the follow-link label is correct");
+    }
+    if (test.isLinkCopyItemVisible) {
+      is(linkCopy.getAttribute("label"), test.linkCopyItemLabel,
+        "the copy-link label is correct");
+    }
+  }
+});
new file mode 100644
--- /dev/null
+++ b/browser/devtools/markupview/test/browser_markupview_links_05.js
@@ -0,0 +1,82 @@
+/* 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";
+
+// Tests that the contextual menu items shown when clicking on links in
+// attributes actually do the right things.
+
+const TEST_URL = TEST_URL_ROOT + "doc_markup_links.html";
+
+add_task(function*() {
+  let {inspector} = yield addTab(TEST_URL).then(openInspector);
+
+  let linkFollow = inspector.panelDoc.getElementById("node-menu-link-follow");
+  let linkCopy = inspector.panelDoc.getElementById("node-menu-link-copy");
+
+  info("Select a node with a URI attribute");
+  yield selectNode("video", inspector);
+
+  info("Set the popupNode to the node that contains the uri");
+  let {editor} = yield getContainerForSelector("video", inspector);
+  let popupNode = editor.attrElements.get("poster").querySelector(".link");
+  inspector.panelDoc.popupNode = popupNode;
+
+  info("Follow the link and wait for the new tab to open");
+  let onTabOpened = once(gBrowser.tabContainer, "TabOpen");
+  inspector.followAttributeLink();
+  let {target: tab} = yield onTabOpened;
+  yield waitForTabLoad(tab);
+
+  ok(true, "A new tab opened");
+  is(tab.linkedBrowser.currentURI.spec, TEST_URL_ROOT + "doc_markup_tooltip.png",
+    "The URL for the new tab is correct");
+  gBrowser.removeTab(tab);
+
+  info("Select a node with a IDREF attribute");
+  yield selectNode("label", inspector);
+
+  info("Set the popupNode to the node that contains the ref");
+  ({editor}) = yield getContainerForSelector("label", inspector);
+  popupNode = editor.attrElements.get("for").querySelector(".link");
+  inspector.panelDoc.popupNode = popupNode;
+
+  info("Follow the link and wait for the new node to be selected");
+  let onSelection = inspector.selection.once("new-node-front");
+  inspector.followAttributeLink();
+  yield onSelection;
+
+  ok(true, "A new node was selected");
+  is(inspector.selection.nodeFront.id, "name", "The right node was selected");
+
+  info("Select a node with an invalid IDREF attribute");
+  yield selectNode("output", inspector);
+
+  info("Set the popupNode to the node that contains the ref");
+  ({editor}) = yield getContainerForSelector("output", inspector);
+  popupNode = editor.attrElements.get("for").querySelectorAll(".link")[2];
+  inspector.panelDoc.popupNode = popupNode;
+
+  info("Try to follow the link and check that no new node were selected");
+  let onFailed = inspector.once("idref-attribute-link-failed");
+  inspector.followAttributeLink();
+  yield onFailed;
+
+  ok(true, "The node selection failed");
+  is(inspector.selection.nodeFront.tagName.toLowerCase(), "output",
+    "The <output> node is still selected");
+});
+
+function waitForTabLoad(tab) {
+  let def = promise.defer();
+  tab.addEventListener("load", function onLoad(e) {
+    // Skip load event for about:blank
+    if (tab.linkedBrowser.currentURI.spec === "about:blank") {
+      return;
+    }
+    tab.removeEventListener("load", onLoad);
+    def.resolve();
+  });
+  return def.promise;
+}
--- a/browser/devtools/markupview/test/doc_markup_links.html
+++ b/browser/devtools/markupview/test/doc_markup_links.html
@@ -3,28 +3,28 @@
   <head>
     <meta charset="utf-8">
     <title>Markup-view links</title>
     <link rel="stylesheet" type="text/css" href="style.css">
     <link rel="icon" type="image/png" sizes="196x196" href="/media/img/firefox/favicon-196.223e1bcaf067.png">
   </head>
   <body>
     <form id="message-form" method="post" action="/post_message">
-      <p>
+      <p for="invalid-idref">
         <label for="name">Name</label>
         <input id="name" type="text" />
       </p>
       <p>
         <label for="message">Message</label>
         <input id="message" type="text" />
       </p>
       <p>
         <button>Send message</button>
       </p>
-      <output form="message-form" for="name message">Thank you for your message!</output>
+      <output form="message-form" for="name message invalid">Thank you for your message!</output>
     </form>
     <a href="/go/somewhere/else" ping="/analytics?page=pageA /analytics?user=test">Click me, I'm a link</a>
     <ul>
       <li contextmenu="menu1">Item 1</li>
       <li contextmenu="menu2">Item 2</li>
       <li contextmenu="menu3">Item 3</li>
     </ul>
     <menu type="context" id="menu1">
--- a/browser/devtools/markupview/test/head.js
+++ b/browser/devtools/markupview/test/head.js
@@ -680,8 +680,22 @@ function createTestHTTPServer() {
       destroyed.resolve();
     });
     yield destroyed.promise;
   });
 
   server.start(-1);
   return server;
 }
+
+/**
+ * A helper that simulates a contextmenu event on the given chrome DOM element.
+ */
+function contextMenuClick(element) {
+  let evt = element.ownerDocument.createEvent('MouseEvents');
+  let button = 2;  // right click
+
+  evt.initMouseEvent('contextmenu', true, true,
+       element.ownerDocument.defaultView, 1, 0, 0, 0, 0, false,
+       false, false, false, button, null);
+
+  element.dispatchEvent(evt);
+}