/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * This file tests the code that integrates the Style Inspector's rule view * with the MDN docs tooltip. * * If you display the context click on a property name in the rule view, you * should see a menu item "Show MDN Docs". If you click that item, the MDN * docs tooltip should be shown, containing docs from MDN for that property. * * This file tests that the context menu item is shown when it should be * shown and hidden when it should be hidden. */ "use strict"; /** * The test document tries to confuse the context menu * code by having a tag called "padding" and a property * value called "margin". */ const { PrefObserver } = require("devtools/client/shared/prefs"); const PREF_ENABLE_MDN_DOCS_TOOLTIP = "devtools.inspector.mdnDocsTooltip.enabled"; const TEST_URI = ` MDN tooltip testing `; add_task(function* () { info("Ensure the pref is true to begin with"); let initial = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP); if (initial != true) { yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true); } yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_URI)); let {inspector, view} = yield openRuleView(); yield selectNode("padding", inspector); yield testMdnContextMenuItemVisibility(view); info("Ensure the pref is reset to its initial value"); let eventual = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP); if (eventual != initial) { yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, initial); } }); /** * Set a boolean pref, and wait for the pref observer to * trigger, so that code listening for the pref change * has had a chance to update itself. * * @param pref {string} Name of the pref to change * @param state {boolean} Desired value of the pref. * * Note that if the pref already has the value in `state`, * then the prefObserver will not trigger. So you should only * call this function if you know the pref's current value is * not `state`. */ function* setBooleanPref(pref, state) { let oncePrefChanged = defer(); let prefObserver = new PrefObserver("devtools."); prefObserver.on(pref, oncePrefChanged.resolve); info("Set the pref " + pref + " to: " + state); Services.prefs.setBoolPref(pref, state); info("Wait for prefObserver to call back so the UI can update"); yield oncePrefChanged.promise; prefObserver.off(pref, oncePrefChanged.resolve); } /** * Tests that the MDN context menu item is shown when it should be, * and hidden when it should be. * - iterate through every node in the rule view * - set that node as popupNode (the node that the context menu * is shown for) * - update the context menu's state * - test that the MDN context menu item is hidden, or not, * depending on popupNode */ function* testMdnContextMenuItemVisibility(view) { info("Test that MDN context menu item is shown only when it should be."); let root = rootElement(view); for (let node of iterateNodes(root)) { info("Setting " + node + " as popupNode"); info("Creating context menu with " + node + " as popupNode"); let allMenuItems = openStyleContextMenuAndGetAllItems(view, node); let menuitemShowMdnDocs = allMenuItems.find(item => item.label === STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs")); let isVisible = menuitemShowMdnDocs.visible; let shouldBeVisible = isPropertyNameNode(node); let message = shouldBeVisible ? "shown" : "hidden"; is(isVisible, shouldBeVisible, "The MDN context menu item is " + message + " ; content : " + node.textContent + " ; type : " + node.nodeType); } } /** * Check if a node is a property name. */ function isPropertyNameNode(node) { return node.textContent === "font-family"; } /** * A generator that iterates recursively through all child nodes of baseNode. */ function* iterateNodes(baseNode) { yield baseNode; for (let child of baseNode.childNodes) { yield* iterateNodes(child); } } /** * Returns the root element for the rule view. */ var rootElement = view => (view.element) ? view.element : view.styleDocument;