summaryrefslogtreecommitdiffstats
path: root/toolkit/content/tests/browser/head.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /toolkit/content/tests/browser/head.js
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/content/tests/browser/head.js')
-rw-r--r--toolkit/content/tests/browser/head.js338
1 files changed, 338 insertions, 0 deletions
diff --git a/toolkit/content/tests/browser/head.js b/toolkit/content/tests/browser/head.js
new file mode 100644
index 0000000000..8973f1a6b4
--- /dev/null
+++ b/toolkit/content/tests/browser/head.js
@@ -0,0 +1,338 @@
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
+
+/**
+ * A wrapper for the findbar's method "close", which is not synchronous
+ * because of animation.
+ */
+function closeFindbarAndWait(findbar) {
+ return new Promise(resolve => {
+ if (findbar.hidden) {
+ resolve();
+ return;
+ }
+ findbar.addEventListener("transitionend", function cont(aEvent) {
+ if (aEvent.propertyName != "visibility") {
+ return;
+ }
+ findbar.removeEventListener("transitionend", cont);
+ resolve();
+ });
+ let close = findbar.getElement("find-closebutton");
+ close.doCommand();
+ });
+}
+
+function pushPrefs(...aPrefs) {
+ return new Promise(resolve => {
+ SpecialPowers.pushPrefEnv({ set: aPrefs }, resolve);
+ });
+}
+
+/**
+ * Used to check whether the audio unblocking icon is in the tab.
+ */
+async function waitForTabBlockEvent(tab, expectBlocked) {
+ if (tab.activeMediaBlocked == expectBlocked) {
+ ok(true, "The tab should " + (expectBlocked ? "" : "not ") + "be blocked");
+ } else {
+ info("Block state doens't match, wait for attributes changes.");
+ await BrowserTestUtils.waitForEvent(
+ tab,
+ "TabAttrModified",
+ false,
+ event => {
+ if (event.detail.changed.includes("activemedia-blocked")) {
+ is(
+ tab.activeMediaBlocked,
+ expectBlocked,
+ "The tab should " + (expectBlocked ? "" : "not ") + "be blocked"
+ );
+ return true;
+ }
+ return false;
+ }
+ );
+ }
+}
+
+/**
+ * Used to check whether the tab has soundplaying attribute.
+ */
+async function waitForTabPlayingEvent(tab, expectPlaying) {
+ if (tab.soundPlaying == expectPlaying) {
+ ok(true, "The tab should " + (expectPlaying ? "" : "not ") + "be playing");
+ } else {
+ info("Playing state doesn't match, wait for attributes changes.");
+ await BrowserTestUtils.waitForEvent(
+ tab,
+ "TabAttrModified",
+ false,
+ event => {
+ if (event.detail.changed.includes("soundplaying")) {
+ is(
+ tab.soundPlaying,
+ expectPlaying,
+ "The tab should " + (expectPlaying ? "" : "not ") + "be playing"
+ );
+ return true;
+ }
+ return false;
+ }
+ );
+ }
+}
+
+function getTestPlugin(pluginName) {
+ var ph = SpecialPowers.Cc["@mozilla.org/plugin/host;1"].getService(
+ SpecialPowers.Ci.nsIPluginHost
+ );
+ var tags = ph.getPluginTags();
+ var name = pluginName || "Test Plug-in";
+ for (var tag of tags) {
+ if (tag.name == name) {
+ return tag;
+ }
+ }
+
+ ok(false, "Could not find plugin tag with plugin name '" + name + "'");
+ return null;
+}
+
+async function setTestPluginEnabledState(newEnabledState, pluginName) {
+ var oldEnabledState = await SpecialPowers.setTestPluginEnabledState(
+ newEnabledState,
+ pluginName
+ );
+ if (!oldEnabledState) {
+ return;
+ }
+ var plugin = getTestPlugin(pluginName);
+ // Run a nested event loop to wait for the preference change to
+ // propagate to the child. Yuck!
+ SpecialPowers.Services.tm.spinEventLoopUntil(() => {
+ return plugin.enabledState == newEnabledState;
+ });
+ SimpleTest.registerCleanupFunction(function() {
+ return SpecialPowers.setTestPluginEnabledState(oldEnabledState, pluginName);
+ });
+}
+
+function disable_non_test_mouse(disable) {
+ let utils = window.windowUtils;
+ utils.disableNonTestMouseEvents(disable);
+}
+
+function hover_icon(icon, tooltip) {
+ disable_non_test_mouse(true);
+
+ let popupShownPromise = BrowserTestUtils.waitForEvent(tooltip, "popupshown");
+ EventUtils.synthesizeMouse(icon, 1, 1, { type: "mouseover" });
+ EventUtils.synthesizeMouse(icon, 2, 2, { type: "mousemove" });
+ EventUtils.synthesizeMouse(icon, 3, 3, { type: "mousemove" });
+ EventUtils.synthesizeMouse(icon, 4, 4, { type: "mousemove" });
+ return popupShownPromise;
+}
+
+function leave_icon(icon) {
+ EventUtils.synthesizeMouse(icon, 0, 0, { type: "mouseout" });
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mousemove",
+ });
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mousemove",
+ });
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mousemove",
+ });
+
+ disable_non_test_mouse(false);
+}
+
+/**
+ * Helper class for testing datetime input picker widget
+ */
+class DateTimeTestHelper {
+ constructor() {
+ this.panel = gBrowser._getAndMaybeCreateDateTimePickerPanel();
+ this.panel.setAttribute("animate", false);
+ this.tab = null;
+ this.frame = null;
+ }
+
+ /**
+ * Opens a new tab with the URL of the test page, and make sure the picker is
+ * ready for testing.
+ *
+ * @param {String} pageUrl
+ * @param {bool} inFrame true if input is in the first child frame
+ */
+ async openPicker(pageUrl, inFrame) {
+ this.tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
+ let bc = gBrowser.selectedBrowser;
+ if (inFrame) {
+ await SpecialPowers.spawn(bc, [], async function() {
+ const iframe = content.document.querySelector("iframe");
+ // Ensure the iframe's position is correct before doing any
+ // other operations
+ iframe.getBoundingClientRect();
+ });
+ bc = bc.browsingContext.children[0];
+ }
+ await BrowserTestUtils.synthesizeMouseAtCenter("input", {}, bc);
+ this.frame = this.panel.querySelector("#dateTimePopupFrame");
+ await this.waitForPickerReady();
+ }
+
+ promisePickerClosed() {
+ return new Promise(resolve => {
+ this.panel.addEventListener("popuphidden", resolve, { once: true });
+ });
+ }
+
+ async waitForPickerReady() {
+ let readyPromise;
+ let loadPromise = new Promise(resolve => {
+ this.frame.addEventListener(
+ "load",
+ () => {
+ // Add the PickerReady event listener directly inside the load event
+ // listener to avoid missing the event.
+ readyPromise = BrowserTestUtils.waitForEvent(
+ this.frame.contentDocument,
+ "PickerReady"
+ );
+ resolve();
+ },
+ { capture: true, once: true }
+ );
+ });
+
+ await loadPromise;
+ // Wait for picker elements to be ready
+ await readyPromise;
+ }
+
+ /**
+ * Find an element on the picker.
+ *
+ * @param {String} selector
+ * @return {DOMElement}
+ */
+ getElement(selector) {
+ return this.frame.contentDocument.querySelector(selector);
+ }
+
+ /**
+ * Find the children of an element on the picker.
+ *
+ * @param {String} selector
+ * @return {Array<DOMElement>}
+ */
+ getChildren(selector) {
+ return Array.from(this.getElement(selector).children);
+ }
+
+ /**
+ * Click on an element
+ *
+ * @param {DOMElement} element
+ */
+ click(element) {
+ EventUtils.synthesizeMouseAtCenter(element, {}, this.frame.contentWindow);
+ }
+
+ /**
+ * Close the panel and the tab
+ */
+ async tearDown() {
+ if (!this.panel.hidden) {
+ let pickerClosePromise = this.promisePickerClosed();
+ this.panel.hidePopup();
+ await pickerClosePromise;
+ }
+ BrowserTestUtils.removeTab(this.tab);
+ this.tab = null;
+ }
+
+ /**
+ * Clean up after tests. Remove the frame to prevent leak.
+ */
+ cleanup() {
+ this.frame.remove();
+ this.frame = null;
+ this.panel.removeAttribute("animate");
+ this.panel = null;
+ }
+}
+
+/**
+ * Used to listen events if you just need it once
+ */
+function once(target, name) {
+ var p = new Promise(function(resolve, reject) {
+ target.addEventListener(
+ name,
+ function() {
+ resolve();
+ },
+ { once: true }
+ );
+ });
+ return p;
+}
+
+/**
+ * check if current wakelock is equal to expected state, if not, then wait until
+ * the wakelock changes its state to expected state.
+ * @param needLock
+ * the wakolock should be locked or not
+ * @param isForegroundLock
+ * when the lock is on, the wakelock should be in the foreground or not
+ */
+async function waitForExpectedWakeLockState(
+ topic,
+ { needLock, isForegroundLock }
+) {
+ const powerManagerService = Cc["@mozilla.org/power/powermanagerservice;1"];
+ const powerManager = powerManagerService.getService(
+ Ci.nsIPowerManagerService
+ );
+ const wakelockState = powerManager.getWakeLockState(topic);
+ let expectedLockState = "unlocked";
+ if (needLock) {
+ expectedLockState = isForegroundLock
+ ? "locked-foreground"
+ : "locked-background";
+ }
+ if (wakelockState != expectedLockState) {
+ info(`wait until wakelock becomes ${expectedLockState}`);
+ await wakeLockObserved(
+ powerManager,
+ topic,
+ state => state == expectedLockState
+ );
+ }
+ is(
+ powerManager.getWakeLockState(topic),
+ expectedLockState,
+ `the wakelock state for '${topic}' is equal to '${expectedLockState}'`
+ );
+}
+
+function wakeLockObserved(powerManager, observeTopic, checkFn) {
+ return new Promise(resolve => {
+ function wakeLockListener() {}
+ wakeLockListener.prototype = {
+ QueryInterface: ChromeUtils.generateQI(["nsIDOMMozWakeLockListener"]),
+ callback(topic, state) {
+ if (topic == observeTopic && checkFn(state)) {
+ powerManager.removeWakeLockListener(wakeLockListener.prototype);
+ resolve();
+ }
+ },
+ };
+ powerManager.addWakeLockListener(wakeLockListener.prototype);
+ });
+}