/* 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); }); });