339 lines
9.1 KiB
JavaScript
339 lines
9.1 KiB
JavaScript
"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);
|
|
});
|
|
}
|