diff --git a/browser/devtools/inspector/inspector-panel.js b/browser/devtools/inspector/inspector-panel.js index b96b952627b1..1432a3cc7e0a 100644 --- a/browser/devtools/inspector/inspector-panel.js +++ b/browser/devtools/inspector/inspector-panel.js @@ -1113,6 +1113,7 @@ InspectorPanel.prototype = { 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); diff --git a/browser/devtools/markupview/test/browser.ini b/browser/devtools/markupview/test/browser.ini index 01e2a539e1f9..7f128f4bd110 100644 --- a/browser/devtools/markupview/test/browser.ini +++ b/browser/devtools/markupview/test/browser.ini @@ -72,6 +72,8 @@ 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] diff --git a/browser/devtools/markupview/test/browser_markupview_links_01.js b/browser/devtools/markupview/test/browser_markupview_links_01.js index 64ff7ce0696e..ec5f1161cf52 100644 --- a/browser/devtools/markupview/test/browser_markupview_links_01.js +++ b/browser/devtools/markupview/test/browser_markupview_links_01.js @@ -48,7 +48,8 @@ const TEST_DATA = [{ attributeName: "for", links: [ {type: "idref", value: "name"}, - {type: "idref", value: "message"} + {type: "idref", value: "message"}, + {type: "idref", value: "invalid"} ] }] }, { diff --git a/browser/devtools/markupview/test/browser_markupview_links_04.js b/browser/devtools/markupview/test/browser_markupview_links_04.js new file mode 100644 index 000000000000..b1891ea4e099 --- /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"); + } + } +}); diff --git a/browser/devtools/markupview/test/browser_markupview_links_05.js b/browser/devtools/markupview/test/browser_markupview_links_05.js new file mode 100644 index 000000000000..f6ab3ad1ae60 --- /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 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; +} diff --git a/browser/devtools/markupview/test/doc_markup_links.html b/browser/devtools/markupview/test/doc_markup_links.html index c0854735b832..f393319f8d90 100644 --- a/browser/devtools/markupview/test/doc_markup_links.html +++ b/browser/devtools/markupview/test/doc_markup_links.html @@ -8,7 +8,7 @@
-

+

@@ -19,7 +19,7 @@

- Thank you for your message! + Thank you for your message!
Click me, I'm a link