summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/tabdialogs/browser_tabdialogbox_focus.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/tabdialogs/browser_tabdialogbox_focus.js')
-rw-r--r--browser/base/content/test/tabdialogs/browser_tabdialogbox_focus.js212
1 files changed, 212 insertions, 0 deletions
diff --git a/browser/base/content/test/tabdialogs/browser_tabdialogbox_focus.js b/browser/base/content/test/tabdialogs/browser_tabdialogbox_focus.js
new file mode 100644
index 0000000000..08c0e8828d
--- /dev/null
+++ b/browser/base/content/test/tabdialogs/browser_tabdialogbox_focus.js
@@ -0,0 +1,212 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_ROOT_CHROME = getRootDirectory(gTestPath);
+const TEST_DIALOG_PATH = TEST_ROOT_CHROME + "subdialog.xhtml";
+
+/**
+ * Tests that tab dialogs are focused when switching tabs.
+ */
+add_task(async function test_tabdialogbox_tab_switch_focus() {
+ // Open 3 tabs
+ let tabPromises = [];
+ for (let i = 0; i < 3; i += 1) {
+ tabPromises.push(
+ BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ "http://example.com",
+ true
+ )
+ );
+ }
+
+ // Wait for tabs to be ready
+ let tabs = await Promise.all(tabPromises);
+
+ // Open subdialog in first two tabs
+ let dialogs = [];
+ for (let i = 0; i < 2; i += 1) {
+ let dialogBox = gBrowser.getTabDialogBox(tabs[i].linkedBrowser);
+ dialogBox.open(TEST_DIALOG_PATH);
+ dialogs.push(dialogBox.getTabDialogManager()._topDialog);
+ }
+
+ // Wait for dialogs to be ready
+ await Promise.all([dialogs[0]._dialogReady, dialogs[1]._dialogReady]);
+
+ // Switch to first tab which has dialog
+ await BrowserTestUtils.switchTab(gBrowser, tabs[0]);
+
+ // The textbox in the dialogs content window should be focused
+ let dialogTextbox =
+ dialogs[0]._frame.contentDocument.querySelector("#textbox");
+ is(Services.focus.focusedElement, dialogTextbox, "Dialog textbox is focused");
+
+ // Switch to second tab which has dialog
+ await BrowserTestUtils.switchTab(gBrowser, tabs[1]);
+
+ // The textbox in the dialogs content window should be focused
+ let dialogTextbox2 =
+ dialogs[1]._frame.contentDocument.querySelector("#textbox");
+ is(
+ Services.focus.focusedElement,
+ dialogTextbox2,
+ "Dialog2 textbox is focused"
+ );
+
+ // Switch to third tab which does not have a dialog
+ await BrowserTestUtils.switchTab(gBrowser, tabs[2]);
+
+ // Test that content is focused
+ is(
+ Services.focus.focusedElement,
+ tabs[2].linkedBrowser,
+ "Top level browser is focused"
+ );
+
+ // Cleanup
+ tabs.forEach(tab => {
+ BrowserTestUtils.removeTab(tab);
+ });
+});
+
+/**
+ * Tests that if we're showing multiple tab dialogs they are focused in the
+ * correct order and custom focus handlers are called.
+ */
+add_task(async function test_tabdialogbox_multiple_focus() {
+ await BrowserTestUtils.withNewTab(gBrowser, async browser => {
+ let dialogBox = gBrowser.getTabDialogBox(browser);
+ let dialogAClose = dialogBox.open(
+ TEST_DIALOG_PATH,
+ {},
+ {
+ testCustomFocusHandler: true,
+ }
+ ).closedPromise;
+ let dialogBClose = dialogBox.open(TEST_DIALOG_PATH).closedPromise;
+ let dialogCClose = dialogBox.open(
+ TEST_DIALOG_PATH,
+ {},
+ {
+ testCustomFocusHandler: true,
+ }
+ ).closedPromise;
+
+ let dialogs = dialogBox._tabDialogManager._dialogs;
+ let [dialogA, dialogB, dialogC] = dialogs;
+
+ // Wait until all dialogs are ready
+ await Promise.all(dialogs.map(dialog => dialog._dialogReady));
+
+ // Dialog A's custom focus target should be focused
+ let dialogElementA =
+ dialogA._frame.contentDocument.querySelector("#custom-focus-el");
+ is(
+ Services.focus.focusedElement,
+ dialogElementA,
+ "Dialog A custom focus target is focused"
+ );
+
+ // Close top dialog
+ dialogA.close();
+ await dialogAClose;
+
+ // Dialog B's first focus target should be focused
+ let dialogElementB =
+ dialogB._frame.contentDocument.querySelector("#textbox");
+ is(
+ Services.focus.focusedElement,
+ dialogElementB,
+ "Dialog B default focus target is focused"
+ );
+
+ // close top dialog
+ dialogB.close();
+ await dialogBClose;
+
+ // Dialog C's custom focus target should be focused
+ let dialogElementC =
+ dialogC._frame.contentDocument.querySelector("#custom-focus-el");
+ is(
+ Services.focus.focusedElement,
+ dialogElementC,
+ "Dialog C custom focus target is focused"
+ );
+
+ // Close last dialog
+ dialogC.close();
+ await dialogCClose;
+
+ is(
+ dialogBox._tabDialogManager._dialogs.length,
+ 0,
+ "All dialogs should be closed"
+ );
+ is(
+ Services.focus.focusedElement,
+ browser,
+ "Focus should be back on the browser"
+ );
+ });
+});
+
+/**
+ * Tests that other dialogs are still visible if one dialog is hidden.
+ */
+add_task(async function test_tabdialogbox_tab_switch_hidden() {
+ // Open 2 tabs
+ let tabPromises = [];
+ for (let i = 0; i < 2; i += 1) {
+ tabPromises.push(
+ BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ "http://example.com",
+ true
+ )
+ );
+ }
+
+ // Wait for tabs to be ready
+ let tabs = await Promise.all(tabPromises);
+
+ // Open subdialog in tabs
+ let dialogs = [];
+ let dialogBox, dialogBoxManager, browser;
+ for (let i = 0; i < 2; i += 1) {
+ dialogBox = gBrowser.getTabDialogBox(tabs[i].linkedBrowser);
+ browser = tabs[i].linkedBrowser;
+ dialogBox.open(TEST_DIALOG_PATH);
+ dialogBoxManager = dialogBox.getTabDialogManager();
+ dialogs.push(dialogBoxManager._topDialog);
+ }
+
+ // Wait for dialogs to be ready
+ await Promise.all([dialogs[0]._dialogReady, dialogs[1]._dialogReady]);
+
+ // Hide the top dialog
+ dialogBoxManager.hideDialog(browser);
+
+ ok(
+ BrowserTestUtils.is_hidden(dialogBoxManager._dialogStack),
+ "Dialog stack is hidden"
+ );
+
+ // Switch to first tab
+ await BrowserTestUtils.switchTab(gBrowser, tabs[0]);
+
+ // Check the dialog stack is showing in first tab
+ dialogBoxManager = gBrowser
+ .getTabDialogBox(tabs[0].linkedBrowser)
+ .getTabDialogManager();
+ is(dialogBoxManager._dialogStack.hidden, false, "Dialog stack is showing");
+
+ // Cleanup
+ tabs.forEach(tab => {
+ BrowserTestUtils.removeTab(tab);
+ });
+});