diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /browser/components/preferences/tests/head.js | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/preferences/tests/head.js')
-rw-r--r-- | browser/components/preferences/tests/head.js | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/browser/components/preferences/tests/head.js b/browser/components/preferences/tests/head.js new file mode 100644 index 0000000000..69d174d534 --- /dev/null +++ b/browser/components/preferences/tests/head.js @@ -0,0 +1,264 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +ChromeUtils.import("resource://gre/modules/Promise.jsm", this); +const { PermissionTestUtils } = ChromeUtils.import( + "resource://testing-common/PermissionTestUtils.jsm" +); + +const kDefaultWait = 2000; + +function is_element_visible(aElement, aMsg) { + isnot(aElement, null, "Element should not be null, when checking visibility"); + ok(!BrowserTestUtils.is_hidden(aElement), aMsg); +} + +function is_element_hidden(aElement, aMsg) { + isnot(aElement, null, "Element should not be null, when checking visibility"); + ok(BrowserTestUtils.is_hidden(aElement), aMsg); +} + +function open_preferences(aCallback) { + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:preferences"); + let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab); + newTabBrowser.addEventListener( + "Initialized", + function() { + aCallback(gBrowser.contentWindow); + }, + { capture: true, once: true } + ); +} + +function openAndLoadSubDialog( + aURL, + aFeatures = null, + aParams = null, + aClosingCallback = null +) { + let promise = promiseLoadSubDialog(aURL); + content.gSubDialog.open( + aURL, + { features: aFeatures, closingCallback: aClosingCallback }, + aParams + ); + return promise; +} + +function promiseLoadSubDialog(aURL) { + return new Promise((resolve, reject) => { + content.gSubDialog._dialogStack.addEventListener( + "dialogopen", + function dialogopen(aEvent) { + if ( + aEvent.detail.dialog._frame.contentWindow.location == "about:blank" + ) { + return; + } + content.gSubDialog._dialogStack.removeEventListener( + "dialogopen", + dialogopen + ); + + is( + aEvent.detail.dialog._frame.contentWindow.location.toString(), + aURL, + "Check the proper URL is loaded" + ); + + // Check visibility + is_element_visible(aEvent.detail.dialog._overlay, "Overlay is visible"); + + // Check that stylesheets were injected + let expectedStyleSheetURLs = aEvent.detail.dialog._injectedStyleSheets.slice( + 0 + ); + for (let styleSheet of aEvent.detail.dialog._frame.contentDocument + .styleSheets) { + let i = expectedStyleSheetURLs.indexOf(styleSheet.href); + if (i >= 0) { + info("found " + styleSheet.href); + expectedStyleSheetURLs.splice(i, 1); + } + } + is( + expectedStyleSheetURLs.length, + 0, + "All expectedStyleSheetURLs should have been found" + ); + + // Wait for the next event tick to make sure the remaining part of the + // testcase runs after the dialog gets ready for input. + executeSoon(() => resolve(aEvent.detail.dialog._frame.contentWindow)); + } + ); + }); +} + +/** + * Waits a specified number of miliseconds for a specified event to be + * fired on a specified element. + * + * Usage: + * let receivedEvent = waitForEvent(element, "eventName"); + * // Do some processing here that will cause the event to be fired + * // ... + * // Now yield until the Promise is fulfilled + * yield receivedEvent; + * if (receivedEvent && !(receivedEvent instanceof Error)) { + * receivedEvent.msg == "eventName"; + * // ... + * } + * + * @param aSubject the element that should receive the event + * @param aEventName the event to wait for + * @param aTimeoutMs the number of miliseconds to wait before giving up + * @returns a Promise that resolves to the received event, or to an Error + */ +function waitForEvent(aSubject, aEventName, aTimeoutMs, aTarget) { + let eventDeferred = Promise.defer(); + let timeoutMs = aTimeoutMs || kDefaultWait; + let stack = new Error().stack; + let timerID = setTimeout(function wfe_canceller() { + aSubject.removeEventListener(aEventName, listener); + eventDeferred.reject(new Error(aEventName + " event timeout at " + stack)); + }, timeoutMs); + + var listener = function(aEvent) { + if (aTarget && aTarget !== aEvent.target) { + return; + } + + // stop the timeout clock and resume + clearTimeout(timerID); + eventDeferred.resolve(aEvent); + }; + + function cleanup(aEventOrError) { + // unhook listener in case of success or failure + aSubject.removeEventListener(aEventName, listener); + return aEventOrError; + } + aSubject.addEventListener(aEventName, listener); + return eventDeferred.promise.then(cleanup, cleanup); +} + +async function openPreferencesViaOpenPreferencesAPI(aPane, aOptions) { + let finalPaneEvent = Services.prefs.getBoolPref("identity.fxaccounts.enabled") + ? "sync-pane-loaded" + : "privacy-pane-loaded"; + let finalPrefPaneLoaded = TestUtils.topicObserved(finalPaneEvent, () => true); + gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank"); + openPreferences(aPane, aOptions); + let newTabBrowser = gBrowser.selectedBrowser; + + if (!newTabBrowser.contentWindow) { + await BrowserTestUtils.waitForEvent(newTabBrowser, "Initialized", true); + await BrowserTestUtils.waitForEvent(newTabBrowser.contentWindow, "load"); + await finalPrefPaneLoaded; + } + + let win = gBrowser.contentWindow; + let selectedPane = win.history.state; + if (!aOptions || !aOptions.leaveOpen) { + gBrowser.removeCurrentTab(); + } + return { selectedPane }; +} + +async function evaluateSearchResults( + keyword, + searchReults, + includeExperiments = false +) { + searchReults = Array.isArray(searchReults) ? searchReults : [searchReults]; + searchReults.push("header-searchResults"); + + let searchInput = gBrowser.contentDocument.getElementById("searchInput"); + searchInput.focus(); + let searchCompletedPromise = BrowserTestUtils.waitForEvent( + gBrowser.contentWindow, + "PreferencesSearchCompleted", + evt => evt.detail == keyword + ); + EventUtils.sendString(keyword); + await searchCompletedPromise; + + let mainPrefTag = gBrowser.contentDocument.getElementById("mainPrefPane"); + for (let i = 0; i < mainPrefTag.childElementCount; i++) { + let child = mainPrefTag.children[i]; + if (!includeExperiments && child.id?.startsWith("pane-experimental")) { + continue; + } + if (searchReults.includes(child.id)) { + is_element_visible(child, `${child.id} should be in search results`); + } else if (child.id) { + is_element_hidden(child, `${child.id} should not be in search results`); + } + } +} + +function waitForMutation(target, opts, cb) { + return new Promise(resolve => { + let observer = new MutationObserver(() => { + if (!cb || cb(target)) { + observer.disconnect(); + resolve(); + } + }); + observer.observe(target, opts); + }); +} + +// Used to add sample experimental features for testing. To use, create +// a DefinitionServer, then call addDefinition as needed. +class DefinitionServer { + constructor(definitionOverrides = []) { + let { HttpServer } = ChromeUtils.import( + "resource://testing-common/httpd.js" + ); + + this.server = new HttpServer(); + this.server.registerPathHandler("/definitions.json", this); + this.definitions = {}; + + for (const override of definitionOverrides) { + this.addDefinition(override); + } + + this.server.start(); + registerCleanupFunction( + () => new Promise(resolve => this.server.stop(resolve)) + ); + } + + // for nsIHttpRequestHandler + handle(request, response) { + response.write(JSON.stringify(this.definitions)); + } + + get definitionsUrl() { + const { primaryScheme, primaryHost, primaryPort } = this.server.identity; + return `${primaryScheme}://${primaryHost}:${primaryPort}/definitions.json`; + } + + addDefinition(overrides = {}) { + const definition = { + id: "test-feature", + // These l10n IDs are just random so we have some text to display + title: "experimental-features-media-avif", + description: "pane-experimental-description", + restartRequired: false, + type: "boolean", + preference: "test.feature", + defaultValue: false, + isPublic: false, + ...overrides, + }; + // convert targeted values, used by fromId + definition.isPublic = { default: definition.isPublic }; + definition.defaultValue = { default: definition.defaultValue }; + this.definitions[definition.id] = definition; + return definition; + } +} |