diff options
Diffstat (limited to 'browser/components/uitour/test/head.js')
-rw-r--r-- | browser/components/uitour/test/head.js | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/browser/components/uitour/test/head.js b/browser/components/uitour/test/head.js deleted file mode 100644 index 2b5b994ae..000000000 --- a/browser/components/uitour/test/head.js +++ /dev/null @@ -1,449 +0,0 @@ -"use strict"; - -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "UITour", - "resource:///modules/UITour.jsm"); - - -const SINGLE_TRY_TIMEOUT = 100; -const NUMBER_OF_TRIES = 30; - -function waitForConditionPromise(condition, timeoutMsg, tryCount=NUMBER_OF_TRIES) { - let defer = Promise.defer(); - let tries = 0; - function checkCondition() { - if (tries >= tryCount) { - defer.reject(timeoutMsg); - } - var conditionPassed; - try { - conditionPassed = condition(); - } catch (e) { - return defer.reject(e); - } - if (conditionPassed) { - return defer.resolve(); - } - tries++; - setTimeout(checkCondition, SINGLE_TRY_TIMEOUT); - return undefined; - } - setTimeout(checkCondition, SINGLE_TRY_TIMEOUT); - return defer.promise; -} - -function waitForCondition(condition, nextTest, errorMsg) { - waitForConditionPromise(condition, errorMsg).then(nextTest, (reason) => { - ok(false, reason + (reason.stack ? "\n" + reason.stack : "")); - }); -} - -/** - * Wrapper to partially transition tests to Task. Use `add_UITour_task` instead for new tests. - */ -function taskify(fun) { - return (done) => { - // Output the inner function name otherwise no name will be output. - info("\t" + fun.name); - return Task.spawn(fun).then(done, (reason) => { - ok(false, reason); - done(); - }); - }; -} - -function is_hidden(element) { - var style = element.ownerGlobal.getComputedStyle(element); - if (style.display == "none") - return true; - if (style.visibility != "visible") - return true; - if (style.display == "-moz-popup") - return ["hiding", "closed"].indexOf(element.state) != -1; - - // Hiding a parent element will hide all its children - if (element.parentNode != element.ownerDocument) - return is_hidden(element.parentNode); - - return false; -} - -function is_visible(element) { - var style = element.ownerGlobal.getComputedStyle(element); - if (style.display == "none") - return false; - if (style.visibility != "visible") - return false; - if (style.display == "-moz-popup" && element.state != "open") - return false; - - // Hiding a parent element will hide all its children - if (element.parentNode != element.ownerDocument) - return is_visible(element.parentNode); - - return true; -} - -function is_element_visible(element, msg) { - isnot(element, null, "Element should not be null, when checking visibility"); - ok(is_visible(element), msg); -} - -function waitForElementToBeVisible(element, nextTest, msg) { - waitForCondition(() => is_visible(element), - () => { - ok(true, msg); - nextTest(); - }, - "Timeout waiting for visibility: " + msg); -} - -function waitForElementToBeHidden(element, nextTest, msg) { - waitForCondition(() => is_hidden(element), - () => { - ok(true, msg); - nextTest(); - }, - "Timeout waiting for invisibility: " + msg); -} - -function elementVisiblePromise(element, msg) { - return waitForConditionPromise(() => is_visible(element), "Timeout waiting for visibility: " + msg); -} - -function elementHiddenPromise(element, msg) { - return waitForConditionPromise(() => is_hidden(element), "Timeout waiting for invisibility: " + msg); -} - -function waitForPopupAtAnchor(popup, anchorNode, nextTest, msg) { - waitForCondition(() => is_visible(popup) && popup.popupBoxObject.anchorNode == anchorNode, - () => { - ok(true, msg); - is_element_visible(popup, "Popup should be visible"); - nextTest(); - }, - "Timeout waiting for popup at anchor: " + msg); -} - -function getConfigurationPromise(configName) { - return ContentTask.spawn(gTestTab.linkedBrowser, configName, configName => { - return new Promise((resolve) => { - let contentWin = Components.utils.waiveXrays(content); - contentWin.Mozilla.UITour.getConfiguration(configName, resolve); - }); - }); -} - -function hideInfoPromise(...args) { - let popup = document.getElementById("UITourTooltip"); - gContentAPI.hideInfo.apply(gContentAPI, args); - return promisePanelElementHidden(window, popup); -} - -/** - * `buttons` and `options` require functions from the content scope so we take a - * function name to call to generate the buttons/options instead of the - * buttons/options themselves. This makes the signature differ from the content one. - */ -function showInfoPromise(target, title, text, icon, buttonsFunctionName, optionsFunctionName) { - let popup = document.getElementById("UITourTooltip"); - let shownPromise = promisePanelElementShown(window, popup); - return ContentTask.spawn(gTestTab.linkedBrowser, [...arguments], args => { - let contentWin = Components.utils.waiveXrays(content); - let [target, title, text, icon, buttonsFunctionName, optionsFunctionName] = args; - let buttons = buttonsFunctionName ? contentWin[buttonsFunctionName]() : null; - let options = optionsFunctionName ? contentWin[optionsFunctionName]() : null; - contentWin.Mozilla.UITour.showInfo(target, title, text, icon, buttons, options); - }).then(() => shownPromise); -} - -function showHighlightPromise(...args) { - let popup = document.getElementById("UITourHighlightContainer"); - gContentAPI.showHighlight.apply(gContentAPI, args); - return promisePanelElementShown(window, popup); -} - -function showMenuPromise(name) { - return ContentTask.spawn(gTestTab.linkedBrowser, name, name => { - return new Promise((resolve) => { - let contentWin = Components.utils.waiveXrays(content); - contentWin.Mozilla.UITour.showMenu(name, resolve); - }); - }); -} - -function waitForCallbackResultPromise() { - return ContentTask.spawn(gTestTab.linkedBrowser, null, function*() { - let contentWin = Components.utils.waiveXrays(content); - yield ContentTaskUtils.waitForCondition(() => { - return contentWin.callbackResult; - }, "callback should be called"); - return { - data: contentWin.callbackData, - result: contentWin.callbackResult, - }; - }); -} - -function promisePanelShown(win) { - let panelEl = win.PanelUI.panel; - return promisePanelElementShown(win, panelEl); -} - -function promisePanelElementEvent(win, aPanel, aEvent) { - return new Promise((resolve, reject) => { - let timeoutId = win.setTimeout(() => { - aPanel.removeEventListener(aEvent, onPanelEvent); - reject(aEvent + " event did not happen within 5 seconds."); - }, 5000); - - function onPanelEvent(e) { - aPanel.removeEventListener(aEvent, onPanelEvent); - win.clearTimeout(timeoutId); - // Wait one tick to let UITour.jsm process the event as well. - executeSoon(resolve); - } - - aPanel.addEventListener(aEvent, onPanelEvent); - }); -} - -function promisePanelElementShown(win, aPanel) { - return promisePanelElementEvent(win, aPanel, "popupshown"); -} - -function promisePanelElementHidden(win, aPanel) { - return promisePanelElementEvent(win, aPanel, "popuphidden"); -} - -function is_element_hidden(element, msg) { - isnot(element, null, "Element should not be null, when checking visibility"); - ok(is_hidden(element), msg); -} - -function isTourBrowser(aBrowser) { - let chromeWindow = aBrowser.ownerGlobal; - return UITour.tourBrowsersByWindow.has(chromeWindow) && - UITour.tourBrowsersByWindow.get(chromeWindow).has(aBrowser); -} - -function promisePageEvent() { - return new Promise((resolve) => { - Services.mm.addMessageListener("UITour:onPageEvent", function onPageEvent(aMessage) { - Services.mm.removeMessageListener("UITour:onPageEvent", onPageEvent); - SimpleTest.executeSoon(resolve); - }); - }); -} - -function loadUITourTestPage(callback, host = "https://example.org/") { - if (gTestTab) - gBrowser.removeTab(gTestTab); - - let url = getRootDirectory(gTestPath) + "uitour.html"; - url = url.replace("chrome://mochitests/content/", host); - - gTestTab = gBrowser.addTab(url); - gBrowser.selectedTab = gTestTab; - - gTestTab.linkedBrowser.addEventListener("load", function onLoad() { - gTestTab.linkedBrowser.removeEventListener("load", onLoad, true); - - if (gMultiProcessBrowser) { - // When e10s is enabled, make gContentAPI and gContentWindow proxies which has every property - // return a function which calls the method of the same name on - // contentWin.Mozilla.UITour/contentWin in a ContentTask. - let contentWinHandler = { - get(target, prop, receiver) { - return (...args) => { - let taskArgs = { - methodName: prop, - args, - }; - return ContentTask.spawn(gTestTab.linkedBrowser, taskArgs, args => { - let contentWin = Components.utils.waiveXrays(content); - return contentWin[args.methodName].apply(contentWin, args.args); - }); - }; - }, - }; - gContentWindow = new Proxy({}, contentWinHandler); - - let UITourHandler = { - get(target, prop, receiver) { - return (...args) => { - let browser = gTestTab.linkedBrowser; - const proxyFunctionName = "UITourHandler:proxiedfunction-"; - // We need to proxy any callback functions using messages: - let callbackMap = new Map(); - let fnIndices = []; - args = args.map((arg, index) => { - // Replace function arguments with "", and add them to the list of - // forwarded functions. We'll construct a function on the content-side - // that forwards all its arguments to a message, and we'll listen for - // those messages on our side and call the corresponding function with - // the arguments we got from the content side. - if (typeof arg == "function") { - callbackMap.set(index, arg); - fnIndices.push(index); - let handler = function(msg) { - // Please note that this handler assumes that the callback is used only once. - // That means that a single gContentAPI.observer() call can't be used to observe - // multiple events. - browser.messageManager.removeMessageListener(proxyFunctionName + index, handler); - callbackMap.get(index).apply(null, msg.data); - }; - browser.messageManager.addMessageListener(proxyFunctionName + index, handler); - return ""; - } - return arg; - }); - let taskArgs = { - methodName: prop, - args, - fnIndices, - }; - return ContentTask.spawn(browser, taskArgs, function*(args) { - let contentWin = Components.utils.waiveXrays(content); - let callbacksCalled = 0; - let resolveCallbackPromise; - let allCallbacksCalledPromise = new Promise(resolve => resolveCallbackPromise = resolve); - let argumentsWithFunctions = args.args.map((arg, index) => { - if (arg === "" && args.fnIndices.includes(index)) { - return function() { - callbacksCalled++; - sendAsyncMessage("UITourHandler:proxiedfunction-" + index, Array.from(arguments)); - if (callbacksCalled >= args.fnIndices.length) { - resolveCallbackPromise(); - } - }; - } - return arg; - }); - let rv = contentWin.Mozilla.UITour[args.methodName].apply(contentWin.Mozilla.UITour, - argumentsWithFunctions); - if (args.fnIndices.length) { - yield allCallbacksCalledPromise; - } - return rv; - }); - }; - }, - }; - gContentAPI = new Proxy({}, UITourHandler); - } else { - gContentWindow = Components.utils.waiveXrays(gTestTab.linkedBrowser.contentDocument.defaultView); - gContentAPI = gContentWindow.Mozilla.UITour; - } - - waitForFocus(callback, gTestTab.linkedBrowser); - }, true); -} - -// Wrapper for UITourTest to be used by add_task tests. -function* setup_UITourTest() { - return UITourTest(true); -} - -// Use `add_task(setup_UITourTest);` instead as we will fold this into `setup_UITourTest` once all tests are using `add_UITour_task`. -function UITourTest(usingAddTask = false) { - Services.prefs.setBoolPref("browser.uitour.enabled", true); - let testHttpsUri = Services.io.newURI("https://example.org", null, null); - let testHttpUri = Services.io.newURI("http://example.org", null, null); - Services.perms.add(testHttpsUri, "uitour", Services.perms.ALLOW_ACTION); - Services.perms.add(testHttpUri, "uitour", Services.perms.ALLOW_ACTION); - - // If a test file is using add_task, we don't need to have a test function or - // call `waitForExplicitFinish`. - if (!usingAddTask) { - waitForExplicitFinish(); - } - - registerCleanupFunction(function() { - delete window.gContentWindow; - delete window.gContentAPI; - if (gTestTab) - gBrowser.removeTab(gTestTab); - delete window.gTestTab; - Services.prefs.clearUserPref("browser.uitour.enabled"); - Services.perms.remove(testHttpsUri, "uitour"); - Services.perms.remove(testHttpUri, "uitour"); - }); - - // When using tasks, the harness will call the next added task for us. - if (!usingAddTask) { - nextTest(); - } -} - -function done(usingAddTask = false) { - info("== Done test, doing shared checks before teardown =="); - return new Promise((resolve) => { - executeSoon(() => { - if (gTestTab) - gBrowser.removeTab(gTestTab); - gTestTab = null; - - let highlight = document.getElementById("UITourHighlightContainer"); - is_element_hidden(highlight, "Highlight should be closed/hidden after UITour tab is closed"); - - let tooltip = document.getElementById("UITourTooltip"); - is_element_hidden(tooltip, "Tooltip should be closed/hidden after UITour tab is closed"); - - ok(!PanelUI.panel.hasAttribute("noautohide"), "@noautohide on the menu panel should have been cleaned up"); - ok(!PanelUI.panel.hasAttribute("panelopen"), "The panel shouldn't have @panelopen"); - isnot(PanelUI.panel.state, "open", "The panel shouldn't be open"); - is(document.getElementById("PanelUI-menu-button").hasAttribute("open"), false, "Menu button should know that the menu is closed"); - - info("Done shared checks"); - if (usingAddTask) { - executeSoon(resolve); - } else { - executeSoon(nextTest); - } - }); - }); -} - -function nextTest() { - if (tests.length == 0) { - info("finished tests in this file"); - finish(); - return; - } - let test = tests.shift(); - info("Starting " + test.name); - waitForFocus(function() { - loadUITourTestPage(function() { - test(done); - }); - }); -} - -/** - * All new tests that need the help of `loadUITourTestPage` should use this - * wrapper around their test's generator function to reduce boilerplate. - */ -function add_UITour_task(func) { - let genFun = function*() { - yield new Promise((resolve) => { - waitForFocus(function() { - loadUITourTestPage(function() { - let funcPromise = Task.spawn(func) - .then(() => done(true), - (reason) => { - ok(false, reason); - return done(true); - }); - resolve(funcPromise); - }); - }); - }); - }; - Object.defineProperty(genFun, "name", { - configurable: true, - value: func.name, - }); - add_task(genFun); -} |