185 lines
6.4 KiB
JavaScript
185 lines
6.4 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
/*
|
|
* Utility module for tests to interact with prompts spawned by nsIPrompt or
|
|
* nsIPromptService.
|
|
*/
|
|
|
|
import { BrowserTestUtils } from "resource://testing-common/BrowserTestUtils.sys.mjs";
|
|
import { TestUtils } from "resource://testing-common/TestUtils.sys.mjs";
|
|
|
|
export let PromptTestUtils = {
|
|
/**
|
|
* Wait for a prompt from nsIPrompt or nsIPromptsService, interact with it and
|
|
* click the specified button to close it.
|
|
* @param {Browser|Window} [parent] - Parent of the prompt. This can be
|
|
* either the parent window or the browser. For tab prompts, if given a
|
|
* window, the currently selected browser in that window will be used.
|
|
* @param {Object} promptOptions - @see waitForPrompt
|
|
* @param {Object} promptActions - @see handlePrompt
|
|
* @returns {Promise} - A promise which resolves once the prompt has been
|
|
* closed.
|
|
*/
|
|
async handleNextPrompt(parent, promptOptions, promptActions) {
|
|
let dialog = await this.waitForPrompt(parent, promptOptions);
|
|
return this.handlePrompt(dialog, promptActions);
|
|
},
|
|
|
|
/**
|
|
* Interact with an existing prompt and close it.
|
|
* @param {Dialog} dialog - The dialog instance associated with the prompt.
|
|
* @param {Object} [actions] - Options on how to interact with the
|
|
* prompt and how to close it.
|
|
* @param {Boolean} [actions.checkboxState] - Set the checkbox state.
|
|
* true = checked, false = unchecked.
|
|
* @param {Number} [actions.buttonNumClick] - Which button to click to close
|
|
* the prompt.
|
|
* @param {String} [actions.loginInput] - Input text for the login text field.
|
|
* This field is also used for text input for the "prompt" type.
|
|
* @param {String} [actions.passwordInput] - Input text for the password text
|
|
* field.
|
|
* @returns {Promise} - A promise which resolves once the prompt has been
|
|
* closed.
|
|
*/
|
|
handlePrompt(
|
|
dialog,
|
|
{
|
|
checkboxState = null,
|
|
buttonNumClick = 0,
|
|
loginInput = null,
|
|
passwordInput = null,
|
|
} = {}
|
|
) {
|
|
let promptClosePromise;
|
|
|
|
// Get parent window to listen for prompt close event
|
|
let win = dialog.ui.prompt?.opener;
|
|
|
|
if (win) {
|
|
promptClosePromise = BrowserTestUtils.waitForEvent(
|
|
win,
|
|
"DOMModalDialogClosed"
|
|
);
|
|
} else {
|
|
// We don't have a parent, wait for window close instead
|
|
promptClosePromise = BrowserTestUtils.windowClosed(dialog.ui.prompt);
|
|
}
|
|
|
|
if (typeof checkboxState == "boolean") {
|
|
dialog.ui.checkbox.checked = checkboxState;
|
|
}
|
|
|
|
if (loginInput != null) {
|
|
dialog.ui.loginTextbox.value = loginInput;
|
|
}
|
|
|
|
if (passwordInput != null) {
|
|
dialog.ui.password1Textbox.value = passwordInput;
|
|
}
|
|
|
|
let button = dialog.ui["button" + buttonNumClick];
|
|
if (!button) {
|
|
throw new Error("Could not find button with index " + buttonNumClick);
|
|
}
|
|
button.click();
|
|
|
|
return promptClosePromise;
|
|
},
|
|
|
|
/**
|
|
* Wait for a prompt from nsIPrompt or nsIPromptsService to open.
|
|
* @param {Browser|Window} [parent] - Parent of the prompt. This can be either
|
|
* the parent window or the browser. For tab prompts, if given a window, the
|
|
* currently selected browser in that window will be used.
|
|
* If not given a parent, the method will return on prompts of any window.
|
|
* @param {Object} attrs - The prompt attributes to filter for.
|
|
* @param {Number} attrs.modalType - Whether the expected prompt is a content, tab or window prompt.
|
|
* nsIPromptService.<MODAL_TYPE_WINDOW|MODAL_TYPE_TAB|MODAL_TYPE_CONTENT>
|
|
* @param {String} [attrs.promptType] - Common dialog type of the prompt to filter for.
|
|
* @see {@link CommonDialog} for possible prompt types.
|
|
* @returns {Promise<CommonDialog>} - A Promise which resolves with a dialog
|
|
* object once the prompt has loaded.
|
|
*/
|
|
async waitForPrompt(parent, { modalType, promptType = null } = {}) {
|
|
if (!modalType) {
|
|
throw new Error("modalType is mandatory");
|
|
}
|
|
|
|
// Get window by browser or browser by window, depending on what is passed
|
|
// via the parent arg. If the caller passes parent=null, both will be null.
|
|
let parentWindow;
|
|
let parentBrowser;
|
|
if (parent) {
|
|
if (Element.isInstance(parent)) {
|
|
// Parent is browser
|
|
parentBrowser = parent;
|
|
parentWindow = parentBrowser.ownerGlobal;
|
|
} else if (parent.isChromeWindow) {
|
|
// Parent is window
|
|
parentWindow = parent;
|
|
parentBrowser = parentWindow.gBrowser?.selectedBrowser;
|
|
} else {
|
|
throw new Error("Invalid parent. Expected browser or dom window");
|
|
}
|
|
}
|
|
|
|
let topic = "common-dialog-loaded";
|
|
|
|
let dialog;
|
|
await TestUtils.topicObserved(topic, subject => {
|
|
// If we are not given a browser, use the currently selected browser of the window
|
|
let browser =
|
|
parentBrowser || subject.ownerGlobal.gBrowser?.selectedBrowser;
|
|
// Is not associated with given parent window, skip
|
|
if (parentWindow && subject.opener !== parentWindow) {
|
|
return false;
|
|
}
|
|
|
|
// For tab prompts, ensure that the associated browser matches.
|
|
if (browser && modalType == Services.prompt.MODAL_TYPE_TAB) {
|
|
let dialogBox = parentWindow.gBrowser.getTabDialogBox(browser);
|
|
let hasMatchingDialog = dialogBox
|
|
.getTabDialogManager()
|
|
._dialogs.some(
|
|
d => d._frame?.browsingContext == subject.browsingContext
|
|
);
|
|
if (!hasMatchingDialog) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (browser && modalType == Services.prompt.MODAL_TYPE_CONTENT) {
|
|
let dialogBox = parentWindow.gBrowser.getTabDialogBox(browser);
|
|
let hasMatchingDialog = dialogBox
|
|
.getContentDialogManager()
|
|
._dialogs.some(
|
|
d => d._frame?.browsingContext == subject.browsingContext
|
|
);
|
|
if (!hasMatchingDialog) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// subject is the window object of the prompt which has a Dialog object
|
|
// attached.
|
|
dialog = subject.Dialog;
|
|
|
|
// Not the modalType we're looking for.
|
|
// For window prompts dialog.args.modalType is undefined.
|
|
if (dialog.args.modalType !== modalType) {
|
|
return false;
|
|
}
|
|
|
|
// Not the promptType we're looking for.
|
|
if (promptType && dialog.args.promptType !== promptType) {
|
|
return false;
|
|
}
|
|
|
|
// Prompt found
|
|
return true;
|
|
});
|
|
|
|
return dialog;
|
|
},
|
|
};
|