summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/tabs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/base/content/test/tabs')
-rw-r--r--browser/base/content/test/tabs/browser.toml4
-rw-r--r--browser/base/content/test/tabs/browser_blank_tab_label.js49
-rw-r--r--browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js178
-rw-r--r--browser/base/content/test/tabs/browser_tab_preview.js94
-rw-r--r--browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js19
5 files changed, 333 insertions, 11 deletions
diff --git a/browser/base/content/test/tabs/browser.toml b/browser/base/content/test/tabs/browser.toml
index fa77a8b1a4..8a95c87a6e 100644
--- a/browser/base/content/test/tabs/browser.toml
+++ b/browser/base/content/test/tabs/browser.toml
@@ -30,6 +30,8 @@ skip-if = [
["browser_bfcache_exemption_about_pages.js"]
skip-if = ["!fission"]
+["browser_blank_tab_label.js"]
+
["browser_bug580956.js"]
["browser_bug_1387976_restore_lazy_tab_browser_muted_state.js"]
@@ -140,6 +142,8 @@ support-files = [
["browser_multiselect_tabs_close.js"]
+["browser_multiselect_tabs_close_duplicate_tabs.js"]
+
["browser_multiselect_tabs_close_other_tabs.js"]
["browser_multiselect_tabs_close_tabs_to_the_left.js"]
diff --git a/browser/base/content/test/tabs/browser_blank_tab_label.js b/browser/base/content/test/tabs/browser_blank_tab_label.js
new file mode 100644
index 0000000000..9fe5f6b1b0
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_blank_tab_label.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Ensure that we don't use an entirely-blank (non-printable) document title
+ * as the tab label.
+ */
+add_task(async function test_ensure_printable_label() {
+ const TEST_DOC = `
+ <!DOCTYPE html>
+ <meta charset="utf-8">
+ <!-- Title is NO-BREAK SPACE, COMBINING ACUTE ACCENT, ARABIC LETTER MARK -->
+ <title>&nbsp;&%23x0301;&%23x061C;</title>
+ Is my title blank?`;
+
+ let newTab;
+ function tabLabelChecker() {
+ Assert.stringMatches(
+ newTab.label,
+ /\p{L}|\p{N}|\p{P}|\p{S}/u,
+ "Tab label should contain printable character."
+ );
+ }
+ let mutationObserver = new MutationObserver(tabLabelChecker);
+ registerCleanupFunction(() => mutationObserver.disconnect());
+
+ gBrowser.tabContainer.addEventListener(
+ "TabOpen",
+ event => {
+ newTab = event.target;
+ tabLabelChecker();
+ mutationObserver.observe(newTab, {
+ attributeFilter: ["label"],
+ });
+ },
+ { once: true }
+ );
+
+ await BrowserTestUtils.withNewTab("data:text/html," + TEST_DOC, async () => {
+ // Wait another longer-than-tick to ensure more mutation observer things have
+ // come in.
+ await new Promise(executeSoon);
+
+ // Check one last time for good measure, for the final label:
+ tabLabelChecker();
+ });
+});
diff --git a/browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js b/browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js
new file mode 100644
index 0000000000..d18795447f
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_close_duplicate_tabs.js
@@ -0,0 +1,178 @@
+const PREF_WARN_ON_CLOSE = "browser.tabs.warnOnCloseOtherTabs";
+const PREF_SHOWN_DUPE_DIALOG =
+ "browser.tabs.haveShownCloseAllDuplicateTabsWarning";
+
+add_task(async function setPref() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [PREF_WARN_ON_CLOSE, false],
+ [PREF_SHOWN_DUPE_DIALOG, true],
+ ],
+ });
+});
+
+add_task(async function withAMultiSelectedTab() {
+ let initialTab = gBrowser.selectedTab;
+ let tab1 = await addTab();
+ let tab2 = await addTab();
+ let tab3 = await addTab();
+ let tab4 = await addTab();
+
+ is(gBrowser.multiSelectedTabsCount, 0, "Zero multiselected tabs");
+
+ await triggerClickOn(tab1, { ctrlKey: true });
+
+ let tab4Pinned = BrowserTestUtils.waitForEvent(tab4, "TabPinned");
+ gBrowser.pinTab(tab4);
+ await tab4Pinned;
+
+ ok(initialTab.multiselected, "InitialTab is multiselected");
+ ok(tab1.multiselected, "Tab1 is multiselected");
+ ok(!tab2.multiselected, "Tab2 is not multiselected");
+ ok(!tab3.multiselected, "Tab3 is not multiselected");
+ ok(!tab4.multiselected, "Tab4 is not multiselected");
+ ok(tab4.pinned, "Tab4 is pinned");
+ is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs");
+ is(gBrowser.selectedTab, initialTab, "InitialTab is the active tab");
+
+ let closingTabs = [tab2, tab3];
+ let tabClosingPromises = [];
+ for (let tab of closingTabs) {
+ tabClosingPromises.push(BrowserTestUtils.waitForTabClosing(tab));
+ }
+
+ gBrowser.removeDuplicateTabs(tab1);
+
+ await Promise.all(tabClosingPromises);
+
+ ok(!initialTab.closing, "InitialTab is not closing");
+ ok(!tab1.closing, "Tab1 is not closing");
+ ok(tab2.closing, "Tab2 is closing");
+ ok(tab3.closing, "Tab3 is closing");
+ ok(!tab4.closing, "Tab4 is not closing");
+ is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs");
+ is(gBrowser.selectedTab, initialTab, "InitialTab is still the active tab");
+
+ gBrowser.clearMultiSelectedTabs();
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab4);
+});
+
+add_task(async function withNotAMultiSelectedTab() {
+ let initialTab = gBrowser.selectedTab;
+ let tab1 = await addTab("http://mochi.test:8888/");
+ let tab2 = await addTab("http://mochi.test:8888/");
+ let tab3 = await addTab("http://mochi.test:8888/");
+ let tab4 = await addTab("http://mochi.test:8888/");
+ let tab5 = await addTab("http://mochi.test:8888/");
+ let tab6 = await addTab("http://mochi.test:8888/", { userContextId: 1 });
+
+ is(gBrowser.multiSelectedTabsCount, 0, "Zero multiselected tabs");
+
+ await BrowserTestUtils.switchTab(gBrowser, tab1);
+ await triggerClickOn(tab2, { ctrlKey: true });
+ await triggerClickOn(tab5, { ctrlKey: true });
+
+ let tab4Pinned = BrowserTestUtils.waitForEvent(tab4, "TabPinned");
+ gBrowser.pinTab(tab4);
+ await tab4Pinned;
+
+ let tab5Pinned = BrowserTestUtils.waitForEvent(tab5, "TabPinned");
+ gBrowser.pinTab(tab5);
+ await tab5Pinned;
+
+ ok(!initialTab.multiselected, "InitialTab is not multiselected");
+ ok(tab1.multiselected, "Tab1 is multiselected");
+ ok(tab2.multiselected, "Tab2 is multiselected");
+ ok(!tab3.multiselected, "Tab3 is not multiselected");
+ ok(!tab4.multiselected, "Tab4 is not multiselected");
+ ok(tab4.pinned, "Tab4 is pinned");
+ ok(tab5.multiselected, "Tab5 is multiselected");
+ ok(tab5.pinned, "Tab5 is pinned");
+ ok(!tab6.multiselected, "Tab6 is not multiselected");
+ ok(!tab6.pinned, "Tab6 is not pinned");
+ is(gBrowser.multiSelectedTabsCount, 3, "Three multiselected tabs");
+ is(gBrowser.selectedTab, tab1, "Tab1 is the active tab");
+
+ let closingTabs = [tab1, tab2];
+ let tabClosingPromises = [];
+ for (let tab of closingTabs) {
+ tabClosingPromises.push(BrowserTestUtils.waitForTabClosing(tab));
+ }
+
+ await BrowserTestUtils.switchTab(
+ gBrowser,
+ gBrowser.removeDuplicateTabs(tab3)
+ );
+
+ await Promise.all(tabClosingPromises);
+
+ ok(!initialTab.closing, "InitialTab is not closing");
+ ok(tab1.closing, "Tab1 is closing");
+ ok(tab2.closing, "Tab2 is closing");
+ ok(!tab3.closing, "Tab3 is not closing");
+ ok(!tab4.closing, "Tab4 is not closing");
+ ok(!tab5.closing, "Tab5 is not closing");
+ ok(!tab6.closing, "Tab6 is not closing");
+ is(
+ gBrowser.multiSelectedTabsCount,
+ 0,
+ "Zero multiselected tabs, selection is cleared"
+ );
+ is(gBrowser.selectedTab, tab3, "tab3 is the active tab now");
+
+ for (let tab of [tab3, tab4, tab5, tab6]) {
+ BrowserTestUtils.removeTab(tab);
+ }
+});
+
+add_task(async function closeAllDuplicateTabs() {
+ let initialTab = gBrowser.selectedTab;
+ let tab1 = await addTab("http://mochi.test:8888/one");
+ let tab2 = await addTab("http://mochi.test:8888/two", { userContextId: 1 });
+ let tab3 = await addTab("http://mochi.test:8888/one");
+ let tab4 = await addTab("http://mochi.test:8888/two");
+ let tab5 = await addTab("http://mochi.test:8888/one");
+ let tab6 = await addTab("http://mochi.test:8888/two");
+
+ let tab1Pinned = BrowserTestUtils.waitForEvent(tab1, "TabPinned");
+ gBrowser.pinTab(tab1);
+ await tab1Pinned;
+
+ // So we have 1p,2c,1,2,1,2
+ // We expect 1p,2c,X,2,X,X because the pinned 1 will dupe the other two 1,
+ // but the 2c's userContextId makes it unique against the other two 2,
+ // but one of the other two 2 will close.
+
+ // Ensure tab4 remains by making it active more recently than tab6.
+ tab4._lastSeenActive = Date.now(); // as recent as it gets.
+
+ // Assert some preconditions:
+ ok(tab1.pinned, "Tab1 is pinned");
+ Assert.greater(tab4.lastSeenActive, tab6.lastSeenActive);
+
+ let closingTabs = [tab3, tab5, tab6];
+ let tabClosingPromises = [];
+ for (let tab of closingTabs) {
+ tabClosingPromises.push(BrowserTestUtils.waitForTabClosing(tab));
+ }
+
+ await BrowserTestUtils.switchTab(
+ gBrowser,
+ gBrowser.removeAllDuplicateTabs(initialTab)
+ );
+
+ await Promise.all(tabClosingPromises);
+
+ ok(!initialTab.closing, "InitialTab is not closing");
+ ok(!tab1.closing, "Tab1 is not closing");
+ ok(!tab2.closing, "Tab2 is not closing");
+ ok(tab3.closing, "Tab3 is closing");
+ ok(!tab4.closing, "Tab4 is not closing");
+ ok(tab5.closing, "Tab5 is closing");
+ ok(tab6.closing, "Tab6 is closing");
+
+ for (let tab of [tab1, tab2, tab4]) {
+ BrowserTestUtils.removeTab(tab);
+ }
+});
diff --git a/browser/base/content/test/tabs/browser_tab_preview.js b/browser/base/content/test/tabs/browser_tab_preview.js
index 0f83b1e28c..19ba85b9f8 100644
--- a/browser/base/content/test/tabs/browser_tab_preview.js
+++ b/browser/base/content/test/tabs/browser_tab_preview.js
@@ -34,6 +34,7 @@ add_setup(async function () {
set: [
["browser.tabs.cardPreview.enabled", true],
["browser.tabs.cardPreview.showThumbnails", false],
+ ["browser.tabs.tooltipsShowPidAndActiveness", false],
["ui.tooltip.delay_ms", 0],
],
});
@@ -82,6 +83,99 @@ add_task(async function hoverTests() {
});
/**
+ * Verify that the pid and activeness statuses are not shown
+ * when the flag is not enabled.
+ */
+add_task(async function pidAndActivenessHiddenByDefaultTests() {
+ const tabUrl1 =
+ "data:text/html,<html><head><title>First New Tab</title></head><body>Hello</body></html>";
+ const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl1);
+ const previewContainer = document.getElementById("tab-preview-panel");
+
+ await openPreview(tab1);
+ Assert.equal(
+ previewContainer.querySelector(".tab-preview-pid").innerText,
+ "",
+ "Tab PID is not shown"
+ );
+ Assert.equal(
+ previewContainer.querySelector(".tab-preview-activeness").innerText,
+ "",
+ "Tab activeness is not shown"
+ );
+
+ await closePreviews();
+
+ BrowserTestUtils.removeTab(tab1);
+
+ // Move the mouse outside of the tab strip.
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mouseover",
+ });
+});
+
+add_task(async function pidAndActivenessTests() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.tabs.tooltipsShowPidAndActiveness", true]],
+ });
+
+ const tabUrl1 =
+ "data:text/html,<html><head><title>Single process tab</title></head><body>Hello</body></html>";
+ const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl1);
+ const tabUrl2 = `data:text/html,<html>
+ <head>
+ <title>Multi-process tab</title>
+ </head>
+ <body>
+ <iframe
+ id="inlineFrameExample"
+ title="Inline Frame Example"
+ width="300"
+ height="200"
+ src="https://example.com">
+ </iframe>
+ </body>
+ </html>`;
+ const tab2 = await BrowserTestUtils.openNewForegroundTab(gBrowser, tabUrl2);
+ const previewContainer = document.getElementById("tab-preview-panel");
+
+ await openPreview(tab1);
+ Assert.stringMatches(
+ previewContainer.querySelector(".tab-preview-pid").innerText,
+ /^pid: \d+$/,
+ "Tab PID is shown on single process tab"
+ );
+ Assert.equal(
+ previewContainer.querySelector(".tab-preview-activeness").innerText,
+ "",
+ "Tab activeness is not shown on inactive tab"
+ );
+ await closePreviews();
+
+ await openPreview(tab2);
+ Assert.stringMatches(
+ previewContainer.querySelector(".tab-preview-pid").innerText,
+ /^pids: \d+, \d+$/,
+ "Tab PIDs are shown on multi-process tab"
+ );
+ Assert.equal(
+ previewContainer.querySelector(".tab-preview-activeness").innerText,
+ "[A]",
+ "Tab activeness is shown on active tab"
+ );
+ await closePreviews();
+
+ BrowserTestUtils.removeTab(tab1);
+ BrowserTestUtils.removeTab(tab2);
+ await SpecialPowers.popPrefEnv();
+
+ // Move the mouse outside of the tab strip.
+ EventUtils.synthesizeMouseAtCenter(document.documentElement, {
+ type: "mouseover",
+ });
+});
+
+/**
* Verify that non-selected tabs display a thumbnail in their preview
* when browser.tabs.cardPreview.showThumbnails is set to true,
* while the currently selected tab never displays a thumbnail in its preview.
diff --git a/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js b/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js
index 202c43ce47..06fdd27d9c 100644
--- a/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js
+++ b/browser/base/content/test/tabs/browser_visibleTabs_contextMenu.js
@@ -2,11 +2,6 @@
* 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/. */
-const remoteClientsFixture = [
- { id: 1, name: "Foo" },
- { id: 2, name: "Bar" },
-];
-
add_task(async function test() {
// There should be one tab when we start the test
let [origTab] = gBrowser.visibleTabs;
@@ -16,9 +11,8 @@ add_task(async function test() {
// Check the context menu with two tabs
updateTabContextMenu(origTab);
- is(
- document.getElementById("context_closeTab").disabled,
- false,
+ ok(
+ !document.getElementById("context_closeTab").disabled,
"Close Tab is enabled"
);
@@ -29,11 +23,14 @@ add_task(async function test() {
// Check the context menu with one tab.
updateTabContextMenu(testTab);
- is(
- document.getElementById("context_closeTab").disabled,
- false,
+ ok(
+ !document.getElementById("context_closeTab").disabled,
"Close Tab is enabled when more than one tab exists"
);
+ ok(
+ !document.getElementById("context_closeDuplicateTabs").disabled,
+ "Close duplicate tabs is enabled when more than one tab with the same URL exists"
+ );
// Add a tab that will get pinned
// So now there's one pinned tab, one visible unpinned tab, and one hidden tab