mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-10-31 16:28:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			339 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			339 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| ChromeUtils.defineESModuleGetters(this, {
 | |
|   AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs",
 | |
|   PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs",
 | |
|   PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
 | |
|   TabCrashHandler: "resource:///modules/ContentCrashHandlers.sys.mjs",
 | |
| });
 | |
| 
 | |
| /**
 | |
|  * Wait for a <notification> to be closed then call the specified callback.
 | |
|  */
 | |
| function waitForNotificationClose(notification, cb) {
 | |
|   let observer = new MutationObserver(function onMutatations(mutations) {
 | |
|     for (let mutation of mutations) {
 | |
|       for (let i = 0; i < mutation.removedNodes.length; i++) {
 | |
|         let node = mutation.removedNodes.item(i);
 | |
|         if (node != notification) {
 | |
|           continue;
 | |
|         }
 | |
|         observer.disconnect();
 | |
|         cb();
 | |
|       }
 | |
|     }
 | |
|   });
 | |
|   observer.observe(notification.control.stack, { childList: true });
 | |
| }
 | |
| 
 | |
| function closeAllNotifications() {
 | |
|   if (!gNotificationBox.currentNotification) {
 | |
|     return Promise.resolve();
 | |
|   }
 | |
| 
 | |
|   return new Promise(resolve => {
 | |
|     for (let notification of gNotificationBox.allNotifications) {
 | |
|       waitForNotificationClose(notification, function () {
 | |
|         if (gNotificationBox.allNotifications.length === 0) {
 | |
|           resolve();
 | |
|         }
 | |
|       });
 | |
|       notification.close();
 | |
|     }
 | |
|   });
 | |
| }
 | |
| 
 | |
| function whenDelayedStartupFinished(aWindow, aCallback) {
 | |
|   Services.obs.addObserver(function observer(aSubject, aTopic) {
 | |
|     if (aWindow == aSubject) {
 | |
|       Services.obs.removeObserver(observer, aTopic);
 | |
|       executeSoon(aCallback);
 | |
|     }
 | |
|   }, "browser-delayed-startup-finished");
 | |
| }
 | |
| 
 | |
| function openToolbarCustomizationUI(aCallback, aBrowserWin) {
 | |
|   if (!aBrowserWin) {
 | |
|     aBrowserWin = window;
 | |
|   }
 | |
| 
 | |
|   aBrowserWin.gCustomizeMode.enter();
 | |
| 
 | |
|   aBrowserWin.gNavToolbox.addEventListener(
 | |
|     "customizationready",
 | |
|     function () {
 | |
|       executeSoon(function () {
 | |
|         aCallback(aBrowserWin);
 | |
|       });
 | |
|     },
 | |
|     { once: true }
 | |
|   );
 | |
| }
 | |
| 
 | |
| function closeToolbarCustomizationUI(aCallback, aBrowserWin) {
 | |
|   aBrowserWin.gNavToolbox.addEventListener(
 | |
|     "aftercustomization",
 | |
|     function () {
 | |
|       executeSoon(aCallback);
 | |
|     },
 | |
|     { once: true }
 | |
|   );
 | |
| 
 | |
|   aBrowserWin.gCustomizeMode.exit();
 | |
| }
 | |
| 
 | |
| function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
 | |
|   retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30;
 | |
|   var tries = 0;
 | |
|   var interval = setInterval(function () {
 | |
|     if (tries >= retryTimes) {
 | |
|       ok(false, errorMsg);
 | |
|       moveOn();
 | |
|     }
 | |
|     var conditionPassed;
 | |
|     try {
 | |
|       conditionPassed = condition();
 | |
|     } catch (e) {
 | |
|       ok(false, e + "\n" + e.stack);
 | |
|       conditionPassed = false;
 | |
|     }
 | |
|     if (conditionPassed) {
 | |
|       moveOn();
 | |
|     }
 | |
|     tries++;
 | |
|   }, 100);
 | |
|   var moveOn = function () {
 | |
|     clearInterval(interval);
 | |
|     nextTest();
 | |
|   };
 | |
| }
 | |
| 
 | |
| function promiseWaitForCondition(aConditionFn) {
 | |
|   return new Promise(resolve => {
 | |
|     waitForCondition(aConditionFn, resolve, "Condition didn't pass.");
 | |
|   });
 | |
| }
 | |
| 
 | |
| function promiseWaitForEvent(
 | |
|   object,
 | |
|   eventName,
 | |
|   capturing = false,
 | |
|   chrome = false
 | |
| ) {
 | |
|   return new Promise(resolve => {
 | |
|     function listener(event) {
 | |
|       info("Saw " + eventName);
 | |
|       object.removeEventListener(eventName, listener, capturing, chrome);
 | |
|       resolve(event);
 | |
|     }
 | |
| 
 | |
|     info("Waiting for " + eventName);
 | |
|     object.addEventListener(eventName, listener, capturing, chrome);
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Allows setting focus on a window, and waiting for that window to achieve
 | |
|  * focus.
 | |
|  *
 | |
|  * @param aWindow
 | |
|  *        The window to focus and wait for.
 | |
|  *
 | |
|  * @return {Promise}
 | |
|  * @resolves When the window is focused.
 | |
|  * @rejects Never.
 | |
|  */
 | |
| function promiseWaitForFocus(aWindow) {
 | |
|   return new Promise(resolve => {
 | |
|     waitForFocus(resolve, aWindow);
 | |
|   });
 | |
| }
 | |
| 
 | |
| function pushPrefs(...aPrefs) {
 | |
|   return SpecialPowers.pushPrefEnv({ set: aPrefs });
 | |
| }
 | |
| 
 | |
| function popPrefs() {
 | |
|   return SpecialPowers.popPrefEnv();
 | |
| }
 | |
| 
 | |
| function promiseWindowClosed(win) {
 | |
|   let promise = BrowserTestUtils.domWindowClosed(win);
 | |
|   win.close();
 | |
|   return promise;
 | |
| }
 | |
| 
 | |
| function promiseOpenAndLoadWindow(aOptions, aWaitForDelayedStartup = false) {
 | |
|   return new Promise(resolve => {
 | |
|     let win = OpenBrowserWindow(aOptions);
 | |
|     if (aWaitForDelayedStartup) {
 | |
|       Services.obs.addObserver(function onDS(aSubject) {
 | |
|         if (aSubject != win) {
 | |
|           return;
 | |
|         }
 | |
|         Services.obs.removeObserver(onDS, "browser-delayed-startup-finished");
 | |
|         resolve(win);
 | |
|       }, "browser-delayed-startup-finished");
 | |
|     } else {
 | |
|       win.addEventListener(
 | |
|         "load",
 | |
|         function () {
 | |
|           resolve(win);
 | |
|         },
 | |
|         { once: true }
 | |
|       );
 | |
|     }
 | |
|   });
 | |
| }
 | |
| 
 | |
| async function whenNewTabLoaded(aWindow, aCallback) {
 | |
|   aWindow.BrowserCommands.openTab();
 | |
| 
 | |
|   let expectedURL = AboutNewTab.newTabURL;
 | |
|   let browser = aWindow.gBrowser.selectedBrowser;
 | |
|   let loadPromise = BrowserTestUtils.browserLoaded(browser, false, expectedURL);
 | |
|   let alreadyLoaded = await SpecialPowers.spawn(browser, [expectedURL], url => {
 | |
|     let doc = content.document;
 | |
|     return doc && doc.readyState === "complete" && doc.location.href == url;
 | |
|   });
 | |
|   if (!alreadyLoaded) {
 | |
|     await loadPromise;
 | |
|   }
 | |
|   aCallback();
 | |
| }
 | |
| 
 | |
| function whenTabLoaded(aTab, aCallback) {
 | |
|   promiseTabLoadEvent(aTab).then(aCallback);
 | |
| }
 | |
| 
 | |
| function promiseTabLoaded(aTab) {
 | |
|   return new Promise(resolve => {
 | |
|     whenTabLoaded(aTab, resolve);
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Waits for a load (or custom) event to finish in a given tab. If provided
 | |
|  * load an uri into the tab.
 | |
|  *
 | |
|  * @param tab
 | |
|  *        The tab to load into.
 | |
|  * @param [optional] url
 | |
|  *        The url to load, or the current url.
 | |
|  * @return {Promise} resolved when the event is handled.
 | |
|  * @resolves to the received event
 | |
|  * @rejects if a valid load event is not received within a meaningful interval
 | |
|  */
 | |
| function promiseTabLoadEvent(tab, url) {
 | |
|   info("Wait tab event: load");
 | |
| 
 | |
|   function handle(loadedUrl) {
 | |
|     if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) {
 | |
|       info(`Skipping spurious load event for ${loadedUrl}`);
 | |
|       return false;
 | |
|     }
 | |
| 
 | |
|     info("Tab event received: load");
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle);
 | |
| 
 | |
|   if (url) {
 | |
|     BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, url);
 | |
|   }
 | |
| 
 | |
|   return loaded;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Returns a Promise that resolves once a new tab has been opened in
 | |
|  * a xul:tabbrowser.
 | |
|  *
 | |
|  * @param aTabBrowser
 | |
|  *        The xul:tabbrowser to monitor for a new tab.
 | |
|  * @return {Promise}
 | |
|  *        Resolved when the new tab has been opened.
 | |
|  * @resolves to the TabOpen event that was fired.
 | |
|  * @rejects Never.
 | |
|  */
 | |
| function waitForNewTabEvent(aTabBrowser) {
 | |
|   return BrowserTestUtils.waitForEvent(aTabBrowser.tabContainer, "TabOpen");
 | |
| }
 | |
| 
 | |
| function is_hidden(element) {
 | |
|   var style = element.ownerGlobal.getComputedStyle(element);
 | |
|   if (style.display == "none") {
 | |
|     return true;
 | |
|   }
 | |
|   if (style.visibility != "visible") {
 | |
|     return true;
 | |
|   }
 | |
|   if (XULPopupElement.isInstance(element)) {
 | |
|     return ["hiding", "closed"].includes(element.state);
 | |
|   }
 | |
| 
 | |
|   // Hiding a parent element will hide all its children
 | |
|   if (element.parentNode != element.ownerDocument) {
 | |
|     return is_hidden(element.parentNode);
 | |
|   }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| function is_element_visible(element, msg) {
 | |
|   isnot(element, null, "Element should not be null, when checking visibility");
 | |
|   ok(BrowserTestUtils.isVisible(element), msg || "Element should be visible");
 | |
| }
 | |
| 
 | |
| function is_element_hidden(element, msg) {
 | |
|   isnot(element, null, "Element should not be null, when checking visibility");
 | |
|   ok(is_hidden(element), msg || "Element should be hidden");
 | |
| }
 | |
| 
 | |
| function promisePopupShown(popup) {
 | |
|   return BrowserTestUtils.waitForPopupEvent(popup, "shown");
 | |
| }
 | |
| 
 | |
| function promisePopupHidden(popup) {
 | |
|   return BrowserTestUtils.waitForPopupEvent(popup, "hidden");
 | |
| }
 | |
| 
 | |
| function promiseNotificationShown(notification) {
 | |
|   let win = notification.browser.ownerGlobal;
 | |
|   if (win.PopupNotifications.panel.state == "open") {
 | |
|     return Promise.resolve();
 | |
|   }
 | |
|   let panelPromise = promisePopupShown(win.PopupNotifications.panel);
 | |
|   notification.reshow();
 | |
|   return panelPromise;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Resolves when a bookmark with the given uri is added.
 | |
|  */
 | |
| function promiseOnBookmarkItemAdded(aExpectedURI) {
 | |
|   return new Promise((resolve, reject) => {
 | |
|     let listener = events => {
 | |
|       is(events.length, 1, "Should only receive one event.");
 | |
|       info("Added a bookmark to " + events[0].url);
 | |
|       PlacesUtils.observers.removeListener(["bookmark-added"], listener);
 | |
|       if (events[0].url == aExpectedURI.spec) {
 | |
|         resolve();
 | |
|       } else {
 | |
|         reject(new Error("Added an unexpected bookmark"));
 | |
|       }
 | |
|     };
 | |
|     info("Waiting for a bookmark to be added");
 | |
|     PlacesUtils.observers.addListener(["bookmark-added"], listener);
 | |
|   });
 | |
| }
 | |
| 
 | |
| async function loadBadCertPage(url) {
 | |
|   let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
 | |
|   BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
 | |
|   await loaded;
 | |
| 
 | |
|   await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
 | |
|     content.document.getElementById("exceptionDialogButton").click();
 | |
|   });
 | |
|   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 | |
| }
 | 
