michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: let doc = null, toolbox = null, panelWin = null, modifiedPrefs = []; michael@0: michael@0: function test() { michael@0: waitForExplicitFinish(); michael@0: michael@0: const URL = "data:text/html;charset=utf8,test for dynamically registering and unregistering tools"; michael@0: Task.spawn(function* () { michael@0: let { target } = yield addTab(URL); michael@0: let toolbox = yield gDevTools.showToolbox(target); michael@0: yield testSelectTool(toolbox); michael@0: yield testOptionsShortcut(); michael@0: yield testOptions(); michael@0: yield testToggleTools(); michael@0: }).then(cleanup, errorHandler); michael@0: } michael@0: michael@0: function testSelectTool(aToolbox) { michael@0: let deferred = promise.defer(); michael@0: michael@0: toolbox = aToolbox; michael@0: doc = toolbox.doc; michael@0: toolbox.once("options-selected", () => { michael@0: ok(true, "Toolbox selected via selectTool method"); michael@0: deferred.resolve(); michael@0: }); michael@0: toolbox.selectTool("options"); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function testOptionsShortcut() { michael@0: let deferred = promise.defer(); michael@0: michael@0: toolbox.selectTool("webconsole") michael@0: .then(() => synthesizeKeyFromKeyTag("toolbox-options-key", doc)) michael@0: .then(() => { michael@0: ok(true, "Toolbox selected via shortcut key"); michael@0: deferred.resolve(); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function testOptions() { michael@0: let tool = toolbox.getPanel("options"); michael@0: panelWin = tool.panelWin; michael@0: let prefNodes = tool.panelDoc.querySelectorAll("checkbox[data-pref]"); michael@0: michael@0: // Store modified pref names so that they can be cleared on error. michael@0: for (let node of prefNodes) { michael@0: let pref = node.getAttribute("data-pref"); michael@0: modifiedPrefs.push(pref); michael@0: } michael@0: michael@0: // Test each options pref michael@0: let p = promise.resolve(); michael@0: for (let node of prefNodes) { michael@0: let prefValue = Services.prefs.getBoolPref(node.getAttribute("data-pref")); michael@0: p = p.then(testMouseClick.bind(null, node, prefValue)); michael@0: } michael@0: // Do again with opposite values to reset prefs michael@0: for (let node of prefNodes) { michael@0: let prefValue = !Services.prefs.getBoolPref(node.getAttribute("data-pref")); michael@0: p = p.then(testMouseClick.bind(null, node, prefValue)); michael@0: } michael@0: michael@0: return p; michael@0: } michael@0: michael@0: function testMouseClick(node, prefValue) { michael@0: let deferred = promise.defer(); michael@0: michael@0: let pref = node.getAttribute("data-pref"); michael@0: gDevTools.once("pref-changed", (event, data) => { michael@0: if (data.pref == pref) { michael@0: ok(true, "Correct pref was changed"); michael@0: is(data.oldValue, prefValue, "Previous value is correct"); michael@0: is(data.newValue, !prefValue, "New value is correct"); michael@0: } else { michael@0: ok(false, "Pref " + pref + " was not changed correctly"); michael@0: } michael@0: deferred.resolve(); michael@0: }); michael@0: michael@0: node.scrollIntoView(); michael@0: michael@0: // We use executeSoon here to ensure that the element is in view and michael@0: // clickable. michael@0: executeSoon(function() { michael@0: info("Click event synthesized for pref " + pref); michael@0: EventUtils.synthesizeMouseAtCenter(node, {}, panelWin); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function testToggleTools() { michael@0: let toolNodes = panelWin.document.querySelectorAll("#default-tools-box > checkbox:not([unsupported])"); michael@0: let enabledTools = Array.prototype.filter.call(toolNodes, node => node.checked); michael@0: michael@0: let toggleableTools = gDevTools.getDefaultTools().filter(tool => tool.visibilityswitch); michael@0: for (let node of toolNodes) { michael@0: let id = node.getAttribute("id"); michael@0: ok (toggleableTools.some(tool => tool.id === id), michael@0: "There should be a toggle checkbox for: " + id); michael@0: } michael@0: michael@0: // Store modified pref names so that they can be cleared on error. michael@0: for (let tool of toggleableTools) { michael@0: let pref = tool.visibilityswitch; michael@0: modifiedPrefs.push(pref); michael@0: } michael@0: michael@0: // Toggle each tool michael@0: let p = promise.resolve(); michael@0: for (let node of toolNodes) { michael@0: p = p.then(toggleTool.bind(null, node)); michael@0: } michael@0: // Toggle again to reset tool enablement state michael@0: for (let node of toolNodes) { michael@0: p = p.then(toggleTool.bind(null, node)); michael@0: } michael@0: michael@0: // Test that a tool can still be added when no tabs are present: michael@0: // Disable all tools michael@0: for (let node of enabledTools) { michael@0: p = p.then(toggleTool.bind(null, node)); michael@0: } michael@0: // Re-enable the tools which are enabled by default michael@0: for (let node of enabledTools) { michael@0: p = p.then(toggleTool.bind(null, node)); michael@0: } michael@0: michael@0: // Toggle first, middle, and last tools to ensure that toolbox tabs are michael@0: // inserted in order michael@0: let firstTool = toolNodes[0], michael@0: middleTool = toolNodes[(toolNodes.length / 2) | 0], michael@0: lastTool = toolNodes[toolNodes.length - 1]; michael@0: michael@0: p = p.then(toggleTool.bind(null, firstTool)) michael@0: .then(toggleTool.bind(null, firstTool)) michael@0: .then(toggleTool.bind(null, middleTool)) michael@0: .then(toggleTool.bind(null, middleTool)) michael@0: .then(toggleTool.bind(null, lastTool)) michael@0: .then(toggleTool.bind(null, lastTool)); michael@0: michael@0: return p; michael@0: } michael@0: michael@0: function toggleTool(node) { michael@0: let deferred = promise.defer(); michael@0: michael@0: let toolId = node.getAttribute("id"); michael@0: if (node.checked) { michael@0: gDevTools.once("tool-unregistered", checkUnregistered.bind(null, toolId, deferred)); michael@0: } else { michael@0: gDevTools.once("tool-registered", checkRegistered.bind(null, toolId, deferred)); michael@0: } michael@0: node.scrollIntoView(); michael@0: EventUtils.synthesizeMouseAtCenter(node, {}, panelWin); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function checkUnregistered(toolId, deferred, event, data) { michael@0: if (data.id == toolId) { michael@0: ok(true, "Correct tool removed"); michael@0: // checking tab on the toolbox michael@0: ok(!doc.getElementById("toolbox-tab-" + toolId), "Tab removed for " + toolId); michael@0: } else { michael@0: ok(false, "Something went wrong, " + toolId + " was not unregistered"); michael@0: } michael@0: deferred.resolve(); michael@0: } michael@0: michael@0: function checkRegistered(toolId, deferred, event, data) { michael@0: if (data == toolId) { michael@0: ok(true, "Correct tool added back"); michael@0: // checking tab on the toolbox michael@0: let radio = doc.getElementById("toolbox-tab-" + toolId); michael@0: ok(radio, "Tab added back for " + toolId); michael@0: if (radio.previousSibling) { michael@0: ok(+radio.getAttribute("ordinal") >= michael@0: +radio.previousSibling.getAttribute("ordinal"), michael@0: "Inserted tab's ordinal is greater than equal to its previous tab." + michael@0: "Expected " + radio.getAttribute("ordinal") + " >= " + michael@0: radio.previousSibling.getAttribute("ordinal")); michael@0: } michael@0: if (radio.nextSibling) { michael@0: ok(+radio.getAttribute("ordinal") < michael@0: +radio.nextSibling.getAttribute("ordinal"), michael@0: "Inserted tab's ordinal is less than its next tab. Expected " + michael@0: radio.getAttribute("ordinal") + " < " + michael@0: radio.nextSibling.getAttribute("ordinal")); michael@0: } michael@0: } else { michael@0: ok(false, "Something went wrong, " + toolId + " was not registered"); michael@0: } michael@0: deferred.resolve(); michael@0: } michael@0: michael@0: function cleanup() { michael@0: toolbox.destroy().then(function() { michael@0: gBrowser.removeCurrentTab(); michael@0: for (let pref of modifiedPrefs) { michael@0: Services.prefs.clearUserPref(pref); michael@0: } michael@0: toolbox = doc = panelWin = modifiedPrefs = null; michael@0: finish(); michael@0: }); michael@0: } michael@0: michael@0: function errorHandler(error) { michael@0: ok(false, "Unexpected error: " + error); michael@0: cleanup(); michael@0: }