Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* This test ensures that overriding switch-to-tab correctly loads the page
* rather than switching to it.
*/
"use strict";
const TEST_URL = `${TEST_BASE_URL}dummy_page.html`;
add_task(async function test_switchtab_override() {
info("Opening first tab");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
info("Opening and selecting second tab");
let secondTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
info("Wait for autocomplete");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "dummy_page",
});
info("Select second autocomplete popup entry");
EventUtils.synthesizeKey("KEY_ArrowDown");
let result = await UrlbarTestUtils.getDetailsOfResultAt(
window,
UrlbarTestUtils.getSelectedRowIndex(window)
);
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH);
// Check to see if the switchtab label is visible and
// all other labels are hidden
const allLabels = document.getElementById("urlbar-label-box").children;
for (let label of allLabels) {
if (label.id == "urlbar-label-switchtab") {
Assert.ok(BrowserTestUtils.isVisible(label));
} else {
Assert.ok(BrowserTestUtils.isHidden(label));
}
}
info("Override switch-to-tab");
let deferred = Promise.withResolvers();
// In case of failure this would switch tab.
let onTabSelect = () => {
deferred.reject(new Error("Should have overridden switch to tab"));
};
gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect);
registerCleanupFunction(() => {
gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
});
// Otherwise it would load the page.
BrowserTestUtils.browserLoaded(secondTab.linkedBrowser).then(
deferred.resolve
);
EventUtils.synthesizeKey("KEY_Shift", { type: "keydown" });
// Checks that all labels are hidden when Shift is held down on the SwitchToTab result
for (let label of allLabels) {
Assert.ok(BrowserTestUtils.isHidden(label));
}
let attribute = "action-override";
Assert.ok(
gURLBar.view.panel.hasAttribute(attribute),
"We should be overriding"
);
EventUtils.synthesizeKey("KEY_Enter");
info(`gURLBar.value = ${gURLBar.value}`);
await deferred.promise;
// Blurring the urlbar should have cleared the override.
Assert.ok(
!gURLBar.view.panel.hasAttribute(attribute),
"We should not be overriding anymore"
);
EventUtils.synthesizeKey("KEY_Shift", { type: "keyup" });
await PlacesUtils.history.clear();
gBrowser.removeTab(tab);
gBrowser.removeTab(secondTab);
});
add_task(async function test_switchtab_override_scotch_bonnet() {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.secondaryActions.switchToTab", true]],
});
info("Opening first tab");
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
info("Opening and selecting second tab");
let secondTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
info("Wait for autocomplete");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "dummy_page",
});
info("Select second autocomplete popup entry");
EventUtils.synthesizeKey("KEY_ArrowDown");
let result = await UrlbarTestUtils.getDetailsOfResultAt(
window,
UrlbarTestUtils.getSelectedRowIndex(window)
);
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH);
info("Check the current status");
let actionButton = result.element.row.querySelector(
".urlbarView-action-btn[data-action=tabswitch]"
);
let urlLabel = result.element.url;
Assert.ok(BrowserTestUtils.isVisible(actionButton));
Assert.ok(BrowserTestUtils.isHidden(urlLabel));
info("Enable action-override");
EventUtils.synthesizeKey("KEY_Shift", { type: "keydown" });
Assert.ok(BrowserTestUtils.isHidden(actionButton));
Assert.ok(BrowserTestUtils.isVisible(urlLabel));
info("Disable action-override");
EventUtils.synthesizeKey("KEY_Shift", { type: "keyup" });
Assert.ok(BrowserTestUtils.isVisible(actionButton));
Assert.ok(BrowserTestUtils.isHidden(urlLabel));
info("Cleanup");
gBrowser.removeTab(tab);
gBrowser.removeTab(secondTab);
await SpecialPowers.popPrefEnv();
});
add_task(async function test_switchtab_override_scotch_bonnet_for_split_view() {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.secondaryActions.switchToTab", false]],
});
info("Opening first tab");
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
let tab2 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:opentabs"
);
info("Opening and selecting second tab");
let tab3 = await BrowserTestUtils.openNewForegroundTab(gBrowser);
gBrowser.addTabSplitView([tab2, tab3]);
let tabbrowserTabs = document.getElementById("tabbrowser-tabs");
await BrowserTestUtils.waitForMutationCondition(
tabbrowserTabs,
{ childList: true },
() => tabbrowserTabs.querySelectorAll("tab-split-view-wrapper").length === 1
);
info("Wait for autocomplete");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "dummy_page",
});
info("Select second autocomplete popup entry");
EventUtils.synthesizeKey("KEY_ArrowDown");
let result = await UrlbarTestUtils.getDetailsOfResultAt(
window,
UrlbarTestUtils.getSelectedRowIndex(window)
);
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH);
info("Check the current status");
let actionLabel = result.element.row.querySelector(".urlbarView-action");
Assert.ok(BrowserTestUtils.isVisible(actionLabel));
Assert.ok(actionLabel.textContent, "Move tab to Split View");
info("Cleanup");
gBrowser.removeTab(tab1);
gBrowser.removeTab(tab2);
gBrowser.removeTab(tab3);
await SpecialPowers.popPrefEnv();
});
add_task(async function test_move_tab_to_split_view_from_another_window() {
await SpecialPowers.pushPrefEnv({
set: [["browser.urlbar.secondaryActions.switchToTab", false]],
});
info("Opening first window with a tab");
let win1 = await BrowserTestUtils.openNewBrowserWindow();
await BrowserTestUtils.openNewForegroundTab(win1.gBrowser, TEST_URL);
info("Opening second window with split view");
let win2 = await BrowserTestUtils.openNewBrowserWindow();
let tab2 = await BrowserTestUtils.openNewForegroundTab(
win2.gBrowser,
"about:opentabs"
);
let tab3 = await BrowserTestUtils.openNewForegroundTab(win2.gBrowser);
let tabbrowserTabs = win2.gBrowser.tabContainer;
let splitViewCreated = BrowserTestUtils.waitForEvent(
tabbrowserTabs,
"SplitViewCreated"
);
let splitView = win2.gBrowser.addTabSplitView([tab2, tab3], { id: 1 });
await splitViewCreated;
info("Wait for autocomplete in second window");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window: win2,
value: "dummy_page",
});
info("Select autocomplete entry for tab in first window");
EventUtils.synthesizeKey("KEY_ArrowDown", {}, win2);
let result = await UrlbarTestUtils.getDetailsOfResultAt(
win2,
UrlbarTestUtils.getSelectedRowIndex(win2)
);
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH);
info("Check that action shows 'Move tab to Split View'");
let actionLabel = result.element.row.querySelector(".urlbarView-action");
Assert.ok(BrowserTestUtils.isVisible(actionLabel));
Assert.ok(actionLabel.textContent.includes("Move"));
info("Count tabs in both windows before action");
let win1TabCountBefore = win1.gBrowser.tabs.length;
let win2TabCountBefore = win2.gBrowser.tabs.length;
info("Press Enter to move tab to split view");
EventUtils.synthesizeKey("KEY_Enter", {}, win2);
await BrowserTestUtils.waitForCondition(
() =>
win1.gBrowser.tabs.length === win1TabCountBefore - 1 &&
win2.gBrowser.tabs.length === win2TabCountBefore,
"Wait for tab to be moved from window 1 and replaced in window 2 split view"
);
info("Verify tab was replaced in split view, not added as third tab");
Assert.equal(
win2.gBrowser.tabs.length,
win2TabCountBefore,
"Second window should still have same number of tabs (tab replaced, not added)"
);
info("Verify original tab was moved from first window");
Assert.equal(
win1.gBrowser.tabs.length,
win1TabCountBefore - 1,
"First window should have one fewer tab (tab was moved)"
);
info("Verify the moved tab has the expected URL in split view");
let tabWithTestUrl = splitView.tabs.find(
tab => tab.linkedBrowser.currentURI.spec === TEST_URL
);
Assert.ok(
tabWithTestUrl,
"One of the split view tabs should have the moved tab's URL"
);
info(
"Verify split view panels have correct attributes after cross-window move"
);
const [firstTab, secondTab] = splitView.tabs;
const firstPanel = win2.document.getElementById(firstTab.linkedPanel);
const secondPanel = win2.document.getElementById(secondTab.linkedPanel);
await BrowserTestUtils.waitForMutationCondition(
firstPanel,
{ attributes: true },
() => firstPanel.classList.contains("split-view-panel-active")
);
await BrowserTestUtils.waitForMutationCondition(
secondPanel,
{ attributes: true },
() => secondPanel.classList.contains("split-view-panel-active")
);
Assert.ok(
firstPanel.classList.contains("split-view-panel"),
"First panel has split-view-panel class after cross-window move"
);
Assert.ok(
secondPanel.classList.contains("split-view-panel"),
"Second panel has split-view-panel class after cross-window move"
);
Assert.ok(
firstPanel.classList.contains("split-view-panel-active"),
"First panel has split-view-panel-active class after cross-window move"
);
Assert.ok(
secondPanel.classList.contains("split-view-panel-active"),
"Second panel has split-view-panel-active class after cross-window move"
);
info("Verify panels are displayed at roughly half width");
const tabpanels = win2.document.getElementById("tabbrowser-tabpanels");
const tabpanelsWidth = tabpanels.getBoundingClientRect().width;
const firstPanelWidth = firstPanel.getBoundingClientRect().width;
const secondPanelWidth = secondPanel.getBoundingClientRect().width;
const expectedWidth = tabpanelsWidth / 2;
const tolerance = 50;
Assert.less(
Math.abs(firstPanelWidth - expectedWidth),
tolerance,
`First panel width (${firstPanelWidth}px) is roughly half of tabpanels width (${tabpanelsWidth}px)`
);
Assert.less(
Math.abs(secondPanelWidth - expectedWidth),
tolerance,
`Second panel width (${secondPanelWidth}px) is roughly half of tabpanels width (${tabpanelsWidth}px)`
);
info("Cleanup");
await BrowserTestUtils.closeWindow(win1);
await BrowserTestUtils.closeWindow(win2);
await SpecialPowers.popPrefEnv();
});
add_task(async function test_move_tab_to_split_view_with_collapsed_group() {
info(
"Opening target tab that will be moved to split view AFTER collapsed group"
);
let targetTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_URL
);
info("Create split view");
let splitTab1 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:opentabs"
);
let splitTab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser);
let tabbrowserTabs = gBrowser.tabContainer;
let splitViewCreated = BrowserTestUtils.waitForEvent(
tabbrowserTabs,
"SplitViewCreated"
);
let splitView = gBrowser.addTabSplitView([splitTab1, splitTab2], {
id: 1,
});
await splitViewCreated;
info("Create a tab group, add the split view to it, and collapse the group");
let tabGroup = gBrowser.addTabGroup([splitView], {
color: "blue",
label: "Test Group",
});
tabGroup.collapsed = true;
info("Wait for autocomplete");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "dummy_page",
});
info("Select autocomplete entry for target tab");
EventUtils.synthesizeKey("KEY_ArrowDown");
let result = await UrlbarTestUtils.getDetailsOfResultAt(
window,
UrlbarTestUtils.getSelectedRowIndex(window)
);
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH);
info("Verify result is for the correct tab");
Assert.equal(
result.url,
TEST_URL,
"Autocomplete result should be for the target tab"
);
info("Check that action shows 'Move tab to Split View'");
let actionLabel = result.element.row.querySelector(".urlbarView-action");
Assert.ok(BrowserTestUtils.isVisible(actionLabel));
Assert.ok(actionLabel.textContent.includes("Move"));
info("Verify initial split view state");
Assert.equal(
splitView.tabs.length,
2,
"Should have 2 tabs in split view initially"
);
info("Press Enter to move tab to split view");
EventUtils.synthesizeKey("KEY_Enter");
info("Wait for tab to be moved to split view");
await BrowserTestUtils.waitForCondition(
() =>
splitView.tabs.some(
tab => tab.linkedBrowser.currentURI.spec === TEST_URL
),
"Wait for target tab to be moved and replaced in split view"
);
let tabWithTestUrl = splitView.tabs.find(
tab => tab.linkedBrowser.currentURI.spec === TEST_URL
);
Assert.ok(
tabWithTestUrl,
"One of the split view tabs should have the target URL"
);
info("Cleanup");
splitView.close();
gBrowser.removeTab(targetTab);
});
add_task(async function test_move_tab_from_split_view_to_another_split_view() {
info(
"Test that moving a tab from one split view to another via the urlbar " +
"correctly shows both panels in the destination split view"
);
info("Create source split view tabs (tab1 will be moved, tab2 will be left)");
let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
let tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser);
info("Create destination split view");
let destTab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
let tabbrowserTabs = gBrowser.tabContainer;
let splitViewCreated1 = BrowserTestUtils.waitForEvent(
tabbrowserTabs,
"SplitViewCreated"
);
let sourceSplitView = gBrowser.addTabSplitView([tab1, tab2]);
await splitViewCreated1;
let splitViewCreated2 = BrowserTestUtils.waitForEvent(
tabbrowserTabs,
"SplitViewCreated"
);
TabContextMenu.contextTab = destTab;
TabContextMenu.contextTabs = [destTab];
TabContextMenu.moveTabsToSplitView();
await splitViewCreated2;
let destSplitView = destTab.splitview;
info("Select destTab so destSplitView is active");
gBrowser.selectedTab = destTab;
info("Wait for autocomplete");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "dummy_page",
});
info("Select autocomplete entry for tab1 (in the source split view)");
EventUtils.synthesizeKey("KEY_ArrowDown");
let result = await UrlbarTestUtils.getDetailsOfResultAt(
window,
UrlbarTestUtils.getSelectedRowIndex(window)
);
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH);
info("Check that action shows 'Move tab to Split View'");
let actionLabel = result.element.row.querySelector(".urlbarView-action");
Assert.ok(BrowserTestUtils.isVisible(actionLabel));
Assert.equal(
document.l10n.getAttributes(actionLabel).id,
"urlbar-result-action-move-tab-to-split-view"
);
info(
"Press Enter to move tab1 from source split view to destination split view"
);
EventUtils.synthesizeKey("KEY_Enter");
info("Wait for tab1 to be moved to destSplitView");
await BrowserTestUtils.waitForCondition(
() =>
destSplitView.tabs.some(
tab => tab.linkedBrowser.currentURI.spec === TEST_URL
),
"Wait for tab1 to be in destSplitView"
);
info("Wait for source split view to be unsplit (had only tab2 remaining)");
await BrowserTestUtils.waitForCondition(
() => !sourceSplitView.isConnected,
"Source split view should be removed after tab1 was moved out"
);
let movedTab = destSplitView.tabs.find(
tab => tab.linkedBrowser.currentURI.spec === TEST_URL
);
Assert.ok(movedTab, "tab1 should be in the destination split view");
info("Verify both panels in destSplitView have split-view-panel class");
const [firstTab, secondTab] = destSplitView.tabs;
const firstPanel = document.getElementById(firstTab.linkedPanel);
const secondPanel = document.getElementById(secondTab.linkedPanel);
Assert.ok(
firstPanel.classList.contains("split-view-panel"),
"First panel in destSplitView should have split-view-panel class"
);
Assert.ok(
secondPanel.classList.contains("split-view-panel"),
"Second panel in destSplitView should have split-view-panel class"
);
Assert.ok(
firstPanel.classList.contains("split-view-panel-active") ||
secondPanel.classList.contains("split-view-panel-active"),
"At least one panel in destSplitView should have split-view-panel-active class"
);
info("Cleanup");
destSplitView.close();
gBrowser.removeTab(tab2);
await UrlbarTestUtils.promisePopupClose(window);
});
add_task(async function test_move_tab_to_split_view_same_window_selection() {
info("Test that moving a tab from the same window properly selects it");
info("Create split view with two tabs");
let splitTab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser);
let tabbrowserTabs = gBrowser.tabContainer;
let splitViewCreated = BrowserTestUtils.waitForEvent(
tabbrowserTabs,
"SplitViewCreated"
);
TabContextMenu.contextTab = splitTab1;
TabContextMenu.contextTabs = [splitTab1];
TabContextMenu.moveTabsToSplitView();
await splitViewCreated;
let splitView = splitTab1.splitview;
info("Create target tab that will be moved to split view");
let targetTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
TEST_URL
);
info("Open another regular tab");
let otherTab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"about:blank"
);
info("Select one of the split view tabs to enable 'Move tab to Split View'");
gBrowser.selectedTab = splitTab1;
info("Verify a split view tab is selected");
Assert.ok(
gBrowser.selectedTab.splitview,
"A split view tab should be selected"
);
info("Wait for autocomplete");
await UrlbarTestUtils.promiseAutocompleteResultPopup({
window,
value: "dummy_page",
});
info("Select autocomplete entry for target tab");
EventUtils.synthesizeKey("KEY_ArrowDown");
let result = await UrlbarTestUtils.getDetailsOfResultAt(
window,
UrlbarTestUtils.getSelectedRowIndex(window)
);
Assert.equal(result.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH);
info("Check that action shows 'Move tab to Split View'");
let actionLabel = result.element.row.querySelector(".urlbarView-action");
Assert.ok(BrowserTestUtils.isVisible(actionLabel));
Assert.ok(actionLabel.textContent.includes("Move"));
info("Press Enter to move tab to split view");
EventUtils.synthesizeKey("KEY_Enter");
info("Wait for tab to be moved to split view");
await BrowserTestUtils.waitForCondition(
() =>
splitView.tabs.some(
tab => tab.linkedBrowser.currentURI.spec === TEST_URL
),
"Wait for target tab to be moved and replaced in split view"
);
let movedTab = splitView.tabs.find(
tab => tab.linkedBrowser.currentURI.spec === TEST_URL
);
Assert.ok(movedTab, "Target tab should be in the split view");
info("Verify the moved tab is selected, not the other tab");
Assert.equal(
gBrowser.selectedTab,
movedTab,
"The moved tab should be selected"
);
Assert.notEqual(
gBrowser.selectedTab,
otherTab,
"The other tab should not be selected"
);
info("Verify split view is active");
Assert.ok(
gBrowser.selectedTab.splitview,
"Selected tab should be in a split view"
);
info("Cleanup");
splitView.close();
gBrowser.removeTab(targetTab);
gBrowser.removeTab(otherTab);
await UrlbarTestUtils.promisePopupClose(window);
});