mirror of
https://github.com/zen-browser/desktop.git
synced 2025-10-03 16:36:35 +00:00
test: Added tests for split view, p=#9667, c=tests
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
|
||||
index 8e839c497bba9de04948ad8759679b6a6f61a65f..877ec60553fc64fea860de297dc0858eb05bae7f 100644
|
||||
index 8e839c497bba9de04948ad8759679b6a6f61a65f..f94a160427b7e465e2c7134fbaf876f589a3fcce 100644
|
||||
--- a/browser/base/content/browser.js
|
||||
+++ b/browser/base/content/browser.js
|
||||
@@ -29,6 +29,7 @@ ChromeUtils.defineESModuleGetters(this, {
|
||||
@@ -10,18 +10,16 @@ index 8e839c497bba9de04948ad8759679b6a6f61a65f..877ec60553fc64fea860de297dc0858e
|
||||
DevToolsSocketStatus:
|
||||
"resource://devtools/shared/security/DevToolsSocketStatus.sys.mjs",
|
||||
DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
|
||||
@@ -2282,6 +2283,10 @@ var XULBrowserWindow = {
|
||||
@@ -2282,6 +2283,8 @@ var XULBrowserWindow = {
|
||||
AboutReaderParent.updateReaderButton(gBrowser.selectedBrowser);
|
||||
TranslationsParent.onLocationChange(gBrowser.selectedBrowser);
|
||||
|
||||
+ gZenViewSplitter.onLocationChange(gBrowser.selectedBrowser);
|
||||
+ gZenWorkspaces.onLocationChange(gBrowser.selectedBrowser);
|
||||
+ gZenPinnedTabManager.onLocationChange(gBrowser.selectedBrowser);
|
||||
+
|
||||
PictureInPicture.updateUrlbarToggle(gBrowser.selectedBrowser);
|
||||
|
||||
if (!gMultiProcessBrowser) {
|
||||
@@ -4617,7 +4622,7 @@ function switchToTabHavingURI(
|
||||
@@ -4617,7 +4620,7 @@ function switchToTabHavingURI(
|
||||
ignoreQueryString || replaceQueryString,
|
||||
ignoreFragmentWhenComparing
|
||||
);
|
||||
@@ -30,7 +28,7 @@ index 8e839c497bba9de04948ad8759679b6a6f61a65f..877ec60553fc64fea860de297dc0858e
|
||||
for (let i = 0; i < browsers.length; i++) {
|
||||
let browser = browsers[i];
|
||||
let browserCompare = cleanURL(
|
||||
@@ -4660,7 +4665,7 @@ function switchToTabHavingURI(
|
||||
@@ -4660,7 +4663,7 @@ function switchToTabHavingURI(
|
||||
}
|
||||
|
||||
if (!doAdopt) {
|
||||
@@ -39,7 +37,7 @@ index 8e839c497bba9de04948ad8759679b6a6f61a65f..877ec60553fc64fea860de297dc0858e
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -5476,6 +5481,9 @@ var ConfirmationHint = {
|
||||
@@ -5476,6 +5479,9 @@ var ConfirmationHint = {
|
||||
MozXULElement.insertFTLIfNeeded("toolkit/branding/brandings.ftl");
|
||||
MozXULElement.insertFTLIfNeeded("browser/confirmationHints.ftl");
|
||||
document.l10n.setAttributes(this._message, messageId, options.l10nArgs);
|
||||
|
60
src/browser/base/content/zen-commands.inc.xhtml
Normal file
60
src/browser/base/content/zen-commands.inc.xhtml
Normal file
@@ -0,0 +1,60 @@
|
||||
# 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/.
|
||||
|
||||
<commandset id="zenCommandSet">
|
||||
<command id="cmd_zenCompactModeToggle" />
|
||||
<command id="cmd_zenCompactModeShowSidebar" />
|
||||
<command id="cmd_zenCompactModeShowToolbar" />
|
||||
<command id="cmd_zenCompactModeHideSidebar" />
|
||||
<command id="cmd_zenCompactModeHideToolbar" />
|
||||
<command id="cmd_zenCompactModeHideBoth" />
|
||||
|
||||
<command id="cmd_zenWorkspaceForward" />
|
||||
<command id="cmd_zenWorkspaceBackward" />
|
||||
|
||||
<command id="cmd_zenSplitViewGrid" />
|
||||
<command id="cmd_zenSplitViewVertical" />
|
||||
<command id="cmd_zenSplitViewHorizontal" />
|
||||
<command id="cmd_zenSplitViewUnsplit" />
|
||||
<command id="cmd_zenSplitViewLinkInNewTab" />
|
||||
<command id="cmd_zenSplitViewContextMenu" />
|
||||
|
||||
<!-- Workspace commands -->
|
||||
<command id="cmd_zenWorkspaceSwitch1" />
|
||||
<command id="cmd_zenWorkspaceSwitch2" />
|
||||
<command id="cmd_zenWorkspaceSwitch3" />
|
||||
<command id="cmd_zenWorkspaceSwitch4" />
|
||||
<command id="cmd_zenWorkspaceSwitch5" />
|
||||
<command id="cmd_zenWorkspaceSwitch6" />
|
||||
<command id="cmd_zenWorkspaceSwitch7" />
|
||||
<command id="cmd_zenWorkspaceSwitch8" />
|
||||
<command id="cmd_zenWorkspaceSwitch9" />
|
||||
<command id="cmd_zenWorkspaceSwitch10" />
|
||||
|
||||
<command id="cmd_zenOpenZenThemePicker" />
|
||||
<command id="cmd_zenChangeWorkspaceTab" />
|
||||
<command id="cmd_zenToggleTabsOnRight" />
|
||||
|
||||
<command id="cmd_zenReplacePinnedUrlWithCurrent" />
|
||||
<command id="cmd_contextZenAddToEssentials" />
|
||||
<command id="cmd_contextZenRemoveFromEssentials" />
|
||||
|
||||
<command id="cmd_zenCtxDeleteWorkspace" />
|
||||
<command id="cmd_zenChangeWorkspaceName" />
|
||||
<command id="cmd_zenChangeWorkspaceIcon" />
|
||||
<command id="cmd_zenReorderWorkspaces" />
|
||||
<command id="cmd_zenOpenWorkspaceCreation" />
|
||||
|
||||
<command id="cmd_zenPinnedTabReset" />
|
||||
<command id="cmd_zenPinnedTabResetNoTab" />
|
||||
|
||||
<command id="cmd_zenToggleSidebar" />
|
||||
|
||||
<command id="cmd_zenCopyCurrentURL" />
|
||||
<command id="cmd_zenCopyCurrentURLMarkdown" />
|
||||
|
||||
<command id="cmd_zenGlanceClose" />
|
||||
<command id="cmd_zenGlanceExpand" />
|
||||
<command id="cmd_zenGlanceSplit" />
|
||||
</commandset>
|
@@ -2,61 +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/.
|
||||
|
||||
<commandset id="zenCommandSet">
|
||||
<command id="cmd_zenCompactModeToggle" />
|
||||
<command id="cmd_zenCompactModeShowSidebar" />
|
||||
<command id="cmd_zenCompactModeShowToolbar" />
|
||||
<command id="cmd_zenCompactModeHideSidebar" />
|
||||
<command id="cmd_zenCompactModeHideToolbar" />
|
||||
<command id="cmd_zenCompactModeHideBoth" />
|
||||
|
||||
<command id="cmd_zenWorkspaceForward" />
|
||||
<command id="cmd_zenWorkspaceBackward" />
|
||||
|
||||
<command id="cmd_zenSplitViewGrid" />
|
||||
<command id="cmd_zenSplitViewVertical" />
|
||||
<command id="cmd_zenSplitViewHorizontal" />
|
||||
<command id="cmd_zenSplitViewUnsplit" />
|
||||
<command id="cmd_zenSplitViewLinkInNewTab" />
|
||||
<command id="cmd_zenSplitViewContextMenu" />
|
||||
|
||||
<!-- Workspace commands -->
|
||||
<command id="cmd_zenWorkspaceSwitch1" />
|
||||
<command id="cmd_zenWorkspaceSwitch2" />
|
||||
<command id="cmd_zenWorkspaceSwitch3" />
|
||||
<command id="cmd_zenWorkspaceSwitch4" />
|
||||
<command id="cmd_zenWorkspaceSwitch5" />
|
||||
<command id="cmd_zenWorkspaceSwitch6" />
|
||||
<command id="cmd_zenWorkspaceSwitch7" />
|
||||
<command id="cmd_zenWorkspaceSwitch8" />
|
||||
<command id="cmd_zenWorkspaceSwitch9" />
|
||||
<command id="cmd_zenWorkspaceSwitch10" />
|
||||
|
||||
<command id="cmd_zenOpenZenThemePicker" />
|
||||
<command id="cmd_zenChangeWorkspaceTab" />
|
||||
<command id="cmd_zenToggleTabsOnRight" />
|
||||
|
||||
<command id="cmd_zenReplacePinnedUrlWithCurrent" />
|
||||
<command id="cmd_contextZenAddToEssentials" />
|
||||
<command id="cmd_contextZenRemoveFromEssentials" />
|
||||
|
||||
<command id="cmd_zenCtxDeleteWorkspace" />
|
||||
<command id="cmd_zenChangeWorkspaceName" />
|
||||
<command id="cmd_zenChangeWorkspaceIcon" />
|
||||
<command id="cmd_zenReorderWorkspaces" />
|
||||
<command id="cmd_zenOpenWorkspaceCreation" />
|
||||
|
||||
<command id="cmd_zenPinnedTabReset" />
|
||||
<command id="cmd_zenPinnedTabResetNoTab" />
|
||||
|
||||
<command id="cmd_zenToggleSidebar" />
|
||||
|
||||
<command id="cmd_zenCopyCurrentURL" />
|
||||
<command id="cmd_zenCopyCurrentURLMarkdown" />
|
||||
|
||||
<command id="cmd_zenGlanceClose" />
|
||||
<command id="cmd_zenGlanceExpand" />
|
||||
<command id="cmd_zenGlanceSplit" />
|
||||
</commandset>
|
||||
#include zen-commands.inc.xhtml
|
||||
|
||||
<keyset id="zenKeyset"></keyset>
|
||||
|
@@ -603,7 +603,13 @@ var gZenVerticalTabsManager = {
|
||||
},
|
||||
|
||||
animateTab(aTab) {
|
||||
if (!gZenUIManager.motion || !aTab || !gZenUIManager._hasLoadedDOM || !aTab.isConnected) {
|
||||
if (
|
||||
!gZenUIManager.motion ||
|
||||
!aTab ||
|
||||
!gZenUIManager._hasLoadedDOM ||
|
||||
!aTab.isConnected ||
|
||||
gZenUIManager.testingEnabled
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// get next visible tab
|
||||
|
@@ -223,6 +223,7 @@
|
||||
this.browserWrapper.setAttribute('has-finished-animation', true);
|
||||
this._animating = false;
|
||||
this.animatingOpen = false;
|
||||
this.#currentTab.dispatchEvent(new Event('GlanceOpen', { bubbles: true }));
|
||||
resolve(this.#currentTab);
|
||||
});
|
||||
});
|
||||
@@ -358,12 +359,12 @@
|
||||
this.overlay.removeAttribute('fade-out');
|
||||
this.browserWrapper.removeAttribute('animate');
|
||||
|
||||
this.lastCurrentTab = this.#currentTab;
|
||||
const lastCurrentTab = this.#currentTab;
|
||||
|
||||
this.overlay.classList.remove('zen-glance-overlay');
|
||||
gBrowser
|
||||
._getSwitcher()
|
||||
.setTabStateNoAction(this.lastCurrentTab, gBrowser.AsyncTabSwitcher.STATE_UNLOADED);
|
||||
.setTabStateNoAction(lastCurrentTab, gBrowser.AsyncTabSwitcher.STATE_UNLOADED);
|
||||
|
||||
if (!onTabClose) {
|
||||
this.#currentParentTab._visuallySelected = false;
|
||||
@@ -381,14 +382,15 @@
|
||||
this.overlay = null;
|
||||
this.contentWrapper = null;
|
||||
|
||||
this.lastCurrentTab.removeAttribute('zen-glance-tab');
|
||||
this.lastCurrentTab._closingGlance = true;
|
||||
lastCurrentTab.removeAttribute('zen-glance-tab');
|
||||
lastCurrentTab._closingGlance = true;
|
||||
|
||||
if (!isDifferent) {
|
||||
gBrowser.selectedTab = this.#currentParentTab;
|
||||
}
|
||||
this._ignoreClose = true;
|
||||
gBrowser.removeTab(this.lastCurrentTab, { animate: true, skipPermitUnload: true });
|
||||
lastCurrentTab.dispatchEvent(new Event('GlanceClose', { bubbles: true }));
|
||||
gBrowser.removeTab(lastCurrentTab, { animate: true, skipPermitUnload: true });
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
|
||||
this.#currentParentTab.removeAttribute('glance-id');
|
||||
@@ -396,7 +398,6 @@
|
||||
this.#glances.delete(this.#currentGlanceID);
|
||||
this.#currentGlanceID = setNewID;
|
||||
|
||||
this.lastCurrentTab = null;
|
||||
this._duringOpening = false;
|
||||
|
||||
this._animating = false;
|
||||
|
@@ -3,8 +3,9 @@
|
||||
# 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/.
|
||||
|
||||
|
||||
FINAL_TARGET_FILES.actors += [
|
||||
"actors/ZenGlanceChild.sys.mjs",
|
||||
"actors/ZenGlanceParent.sys.mjs",
|
||||
]
|
||||
|
||||
TESTING_JS_MODULES += ["tests/GlanceTestUtils.sys.mjs"]
|
||||
|
30
src/zen/glance/tests/GlanceTestUtils.sys.mjs
Normal file
30
src/zen/glance/tests/GlanceTestUtils.sys.mjs
Normal file
@@ -0,0 +1,30 @@
|
||||
/* 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/. */
|
||||
|
||||
export function openGlanceOnTab(window, callback, close = true) {
|
||||
return new Promise(async (resolve) => {
|
||||
window.gZenGlanceManager
|
||||
.openGlance({
|
||||
url: 'https://example.com',
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
})
|
||||
.then(async (glanceTab) => {
|
||||
await callback(glanceTab);
|
||||
if (close) {
|
||||
window.gZenGlanceManager
|
||||
.closeGlance({
|
||||
onTabClose: true,
|
||||
})
|
||||
.then(() => {
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
@@ -177,6 +177,7 @@ class nsZenViewSplitter extends ZenDOMOperatedFeature {
|
||||
if (previousTab && !previousTab.hasAttribute('zen-empty-tab')) {
|
||||
this._lastOpenedTab = previousTab;
|
||||
}
|
||||
this.onLocationChange(event.target.linkedBrowser);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -527,7 +528,6 @@ class nsZenViewSplitter extends ZenDOMOperatedFeature {
|
||||
this._thumnailCanvas.width = 280 * devicePixelRatio;
|
||||
this._thumnailCanvas.height = 140 * devicePixelRatio;
|
||||
}
|
||||
|
||||
const browsers = this._data[this.currentView].tabs.map((t) => t.linkedBrowser);
|
||||
browsers.forEach((b) => {
|
||||
b.style.pointerEvents = 'none';
|
||||
@@ -1108,11 +1108,6 @@ class nsZenViewSplitter extends ZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._sessionRestoring) {
|
||||
return;
|
||||
}
|
||||
this.activateSplitView(splitData);
|
||||
}
|
||||
|
||||
addTabToSplit(tab, splitNode, prepend = true) {
|
||||
@@ -1181,6 +1176,7 @@ class nsZenViewSplitter extends ZenDOMOperatedFeature {
|
||||
this.applyGridLayout(splitData.layoutTree);
|
||||
this.setTabsDocShellState(splitData.tabs, true);
|
||||
this.toggleWrapperDisplay(true);
|
||||
window.dispatchEvent(new CustomEvent('ZenViewSplitter:SplitViewActivated'));
|
||||
}
|
||||
|
||||
calculateLayoutTree(tabs, gridType) {
|
||||
|
@@ -2,33 +2,10 @@
|
||||
* 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 { openGlanceOnTab: internalGlanceHandle } = ChromeUtils.importESModule(
|
||||
'resource://testing-common/GlanceTestUtils.sys.mjs'
|
||||
);
|
||||
|
||||
function openGlanceOnTab(callback, close = true) {
|
||||
return new Promise(async (resolve) => {
|
||||
setTimeout(() => {
|
||||
gZenGlanceManager
|
||||
.openGlance({
|
||||
url: 'https://example.com',
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
})
|
||||
.then(async (glanceTab) => {
|
||||
await callback(glanceTab);
|
||||
if (close) {
|
||||
setTimeout(() => {
|
||||
gZenGlanceManager
|
||||
.closeGlance({
|
||||
onTabClose: true,
|
||||
})
|
||||
.then(() => {
|
||||
resolve();
|
||||
});
|
||||
}, 500); // Give tons of time for the glance to close
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}, 500); // Give tons of time for the glance to open
|
||||
});
|
||||
return internalGlanceHandle(window, callback, close);
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ BROWSER_CHROME_MANIFESTS += [
|
||||
"container_essentials/browser.toml",
|
||||
"glance/browser.toml",
|
||||
"pinned/browser.toml",
|
||||
"split_view/browser.toml",
|
||||
"tabs/browser.toml",
|
||||
"urlbar/browser.toml",
|
||||
"welcome/browser.toml",
|
||||
|
15
src/zen/tests/split_view/browser.toml
Normal file
15
src/zen/tests/split_view/browser.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
# 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/.
|
||||
|
||||
[DEFAULT]
|
||||
support-files = [
|
||||
"head.js",
|
||||
"!/zen/tests/glance/head.js",
|
||||
]
|
||||
|
||||
["browser_basic_split_view.js"]
|
||||
["browser_split_inset_checks.js"]
|
||||
["browser_split_groups.js"]
|
||||
["browser_split_browser_duplication.js"]
|
||||
["browser_split_view_with_glance.js"]
|
31
src/zen/tests/split_view/browser_basic_split_view.js
Normal file
31
src/zen/tests/split_view/browser_basic_split_view.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(async function test_Basic_Split_View() {
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
ok(
|
||||
gBrowser.tabpanels.hasAttribute('zen-split-view'),
|
||||
'The split view should not have crashed with two tabs in it'
|
||||
);
|
||||
});
|
||||
ok(
|
||||
!gBrowser.tabpanels.hasAttribute('zen-split-view'),
|
||||
'Unsplit view should not have crashed with two tabs in it'
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_Browser_Elements_Attributes() {
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
Assert.equal(
|
||||
document.querySelectorAll('.browserSidebarContainer[zen-split="true"]').length,
|
||||
2,
|
||||
'There should be two split browser sidebars'
|
||||
);
|
||||
});
|
||||
ok(
|
||||
!document.querySelector('.browserSidebarContainer[zen-split="true"]'),
|
||||
'There should be no split browser sidebars in unsplit view'
|
||||
);
|
||||
});
|
140
src/zen/tests/split_view/browser_split_browser_duplication.js
Normal file
140
src/zen/tests/split_view/browser_split_browser_duplication.js
Normal file
@@ -0,0 +1,140 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(async function test_Basic_Split_View_Duplication() {
|
||||
const [normal, pinned] = await Promise.all([
|
||||
addTabTo(gBrowser, getUrlForNthTab(1)),
|
||||
addTabTo(gBrowser, getUrlForNthTab(2)),
|
||||
]);
|
||||
const pinEvent = BrowserTestUtils.waitForEvent(pinned, 'TabPinned');
|
||||
gBrowser.pinTab(pinned);
|
||||
await pinEvent;
|
||||
Assert.ok(
|
||||
gBrowser.tabs.length === 4, // empty + initial + 2 split tabs
|
||||
'There should be four tabs after pinning the second tab'
|
||||
);
|
||||
await createSplitView([normal, pinned], 'grid');
|
||||
ok(!pinned.group, 'The pinned tab should not be in a split group after duplication');
|
||||
ok(
|
||||
normal.group.hasAttribute('split-view-group'),
|
||||
'The normal tab should be in a split group after duplication'
|
||||
);
|
||||
const group = normal.group;
|
||||
for (const tab of group.tabs) {
|
||||
Assert.ok(!tab.pinned, 'All tabs in the split group should not be pinned after duplication');
|
||||
Assert.ok(
|
||||
tab.splitView,
|
||||
'All tabs in the split group should be in a split view after duplication'
|
||||
);
|
||||
}
|
||||
Assert.ok(!group.pinned, 'The split group should not be pinned after duplication');
|
||||
for (const tab of [pinned, ...group.tabs]) {
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_Split_View_Duplication_Both_Pinned() {
|
||||
const [tab1, tab2] = await Promise.all([
|
||||
addTabTo(gBrowser, getUrlForNthTab(1)),
|
||||
addTabTo(gBrowser, getUrlForNthTab(2)),
|
||||
]);
|
||||
const pinEvent1 = BrowserTestUtils.waitForEvent(tab1, 'TabPinned');
|
||||
const pinEvent2 = BrowserTestUtils.waitForEvent(tab2, 'TabPinned');
|
||||
gBrowser.pinTab(tab1);
|
||||
gBrowser.pinTab(tab2);
|
||||
await Promise.all([pinEvent1, pinEvent2]);
|
||||
Assert.ok(
|
||||
gBrowser.tabs.length === 4, // empty + initial + 2 split tabs
|
||||
'There should be four tabs after pinning both tabs'
|
||||
);
|
||||
await createSplitView([tab1, tab2], 'grid');
|
||||
ok(tab1.group, 'The first pinned tab should be in a split group after duplication');
|
||||
ok(
|
||||
tab2.group === tab1.group,
|
||||
'The second pinned tab should be in the same split group after duplication'
|
||||
);
|
||||
Assert.equal(
|
||||
gBrowser.tabs.length,
|
||||
4,
|
||||
'There should not be any duplicate tabs after pinning both tabs'
|
||||
);
|
||||
for (const tab of tab1.group.tabs) {
|
||||
Assert.ok(tab.pinned, 'All tabs in the split group should be pinned after duplication');
|
||||
Assert.ok(
|
||||
tab.splitView,
|
||||
'All tabs in the split group should be in a split view after duplication'
|
||||
);
|
||||
}
|
||||
Assert.ok(tab1.group.pinned, 'The split group should be pinned after duplication of both tabs');
|
||||
for (const tab of tab1.group.tabs) {
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
await BrowserTestUtils.removeTab(tab2);
|
||||
await BrowserTestUtils.removeTab(tab1);
|
||||
});
|
||||
|
||||
add_task(async function test_Split_View_Duplication_Pinned_Essential() {
|
||||
const existingTabs = gBrowser.tabs;
|
||||
const [pinned, essential] = await Promise.all([
|
||||
addTabTo(gBrowser, getUrlForNthTab(1)),
|
||||
addTabTo(gBrowser, getUrlForNthTab(2)),
|
||||
]);
|
||||
const pinEvent = BrowserTestUtils.waitForEvent(pinned, 'TabPinned');
|
||||
gBrowser.pinTab(pinned);
|
||||
await pinEvent;
|
||||
gZenPinnedTabManager.addToEssentials(essential);
|
||||
Assert.ok(
|
||||
gBrowser.tabs.length === 4, // empty + initial + 2 split tabs
|
||||
'There should be four tabs after pinning the first tab and adding the second to essentials'
|
||||
);
|
||||
await createSplitView([pinned, essential], 'grid');
|
||||
ok(
|
||||
gBrowser.tabs.length === 4 + 2,
|
||||
'There should be six tabs after creating a split view with the pinned and essential tabs'
|
||||
);
|
||||
ok(
|
||||
!pinned.group,
|
||||
'The pinned tab should not be in a split group after duplication with an essential tab'
|
||||
);
|
||||
ok(
|
||||
!essential.group,
|
||||
'The essential tab should not be in a split group after duplication with a pinned tab'
|
||||
);
|
||||
for (const tab of gBrowser.tabs) {
|
||||
if (existingTabs.includes(tab)) {
|
||||
continue; // Skip if the tab was already present before the test
|
||||
}
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_Split_View_Duplication_Essential() {
|
||||
const existingTabs = gBrowser.tabs;
|
||||
const essentials = await Promise.all(
|
||||
[...Array(2)].map((_, i) => addTabTo(gBrowser, getUrlForNthTab(i + 1)))
|
||||
);
|
||||
essentials.forEach((tab) => {
|
||||
gZenPinnedTabManager.addToEssentials(tab);
|
||||
});
|
||||
ok(
|
||||
gBrowser.tabs.length === 4, // empty + initial + 2 essential tabs
|
||||
'There should be four tabs after adding two essential tabs'
|
||||
);
|
||||
await createSplitView(essentials, 'grid');
|
||||
ok(
|
||||
gBrowser.tabs.length === 4 + 2,
|
||||
'There should be six tabs after creating a split view with two essential tabs'
|
||||
);
|
||||
for (const tab of essentials) {
|
||||
ok(!tab.group, 'Each essential tab should not be in a split group after duplication');
|
||||
ok(!tab.splitView, 'Each essential tab should not be in a split view after duplication');
|
||||
}
|
||||
for (const tab of gBrowser.tabs) {
|
||||
if (existingTabs.includes(tab)) {
|
||||
continue; // Skip if the tab was already present before the test
|
||||
}
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
});
|
43
src/zen/tests/split_view/browser_split_groups.js
Normal file
43
src/zen/tests/split_view/browser_split_groups.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(async function test_Basic_Split_Groups() {
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
ok(tabs[0].group.hasAttribute('split-view-group'), 'The first tab should be in a split group');
|
||||
Assert.equal(tabs[0].group.tabs.length, 2, 'The first split group should contain two tabs');
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_Basic_Split_Groups_Pinning() {
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
const group = tabs[0].group;
|
||||
ok(group.hasAttribute('split-view-group'), 'The first tab should be in a split group');
|
||||
const pinEvent = BrowserTestUtils.waitForEvent(tabs[0], 'TabPinned');
|
||||
gBrowser.pinTab(tabs[0]);
|
||||
await pinEvent;
|
||||
for (const tab of tabs) {
|
||||
ok(tab.pinned, 'All tabs in the split group should be pinned after pinning the first tab');
|
||||
ok(
|
||||
tab.group === group,
|
||||
'All tabs in the split group should remain in the same group after pinning'
|
||||
);
|
||||
}
|
||||
ok(group.pinned, 'The split group should be pinned after pinning a tab');
|
||||
const unpinEvent = BrowserTestUtils.waitForEvent(tabs[0], 'TabUnpinned');
|
||||
gBrowser.unpinTab(tabs[0]);
|
||||
await unpinEvent;
|
||||
for (const tab of tabs) {
|
||||
ok(
|
||||
!tab.pinned,
|
||||
'All tabs in the split group should be unpinned after unpinning the first tab'
|
||||
);
|
||||
ok(
|
||||
tab.group === group,
|
||||
'All tabs in the split group should remain in the same group after unpinning'
|
||||
);
|
||||
}
|
||||
ok(!group.pinned, 'The split group should be unpinned after unpinning a tab');
|
||||
});
|
||||
});
|
68
src/zen/tests/split_view/browser_split_inset_checks.js
Normal file
68
src/zen/tests/split_view/browser_split_inset_checks.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(async function test_Basic_Split_View_Inset() {
|
||||
let viewsToCheck = [];
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
viewsToCheck = document.querySelectorAll('.browserSidebarContainer[zen-split="true"]');
|
||||
ok(viewsToCheck.length, 'There should be split views present');
|
||||
Assert.equal(
|
||||
viewsToCheck[0].style.inset,
|
||||
'0% 50% 0% 0%',
|
||||
'The split view should have correct inset style'
|
||||
);
|
||||
Assert.equal(
|
||||
viewsToCheck[1].style.inset,
|
||||
'0% 0% 0% 50%',
|
||||
'The second split view should have correct inset style'
|
||||
);
|
||||
});
|
||||
for (const view of viewsToCheck) {
|
||||
Assert.equal(view.style.inset, '', 'The unsplit view should not have correct inset style');
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_Horizontal_Split_Inset() {
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
const viewsToCheck = document.querySelectorAll('.browserSidebarContainer[zen-split="true"]');
|
||||
ok(viewsToCheck.length, 'There should be split views present');
|
||||
Assert.equal(
|
||||
viewsToCheck[0].style.inset,
|
||||
'0% 50% 0% 0%',
|
||||
'The horizontal split view should have correct inset style'
|
||||
);
|
||||
Assert.equal(
|
||||
viewsToCheck[1].style.inset,
|
||||
'0% 0% 0% 50%',
|
||||
'The second horizontal split view should have correct inset style'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_3_Splits_Grid_Inset() {
|
||||
await basicSplitNTabs(
|
||||
async (tabs) => {
|
||||
const viewsToCheck = document.querySelectorAll('.browserSidebarContainer[zen-split="true"]');
|
||||
ok(viewsToCheck.length, 'There should be split views present');
|
||||
Assert.equal(
|
||||
viewsToCheck[0].style.inset,
|
||||
'0% 0% 50% 50%',
|
||||
'The first split view should have correct inset style'
|
||||
);
|
||||
Assert.equal(
|
||||
viewsToCheck[1].style.inset,
|
||||
'50% 0% 0% 50%',
|
||||
'The second split view should have correct inset style'
|
||||
);
|
||||
Assert.equal(
|
||||
viewsToCheck[2].style.inset,
|
||||
'0% 50% 0% 0%',
|
||||
'The third split view should have correct inset style'
|
||||
);
|
||||
},
|
||||
'grid',
|
||||
3
|
||||
);
|
||||
});
|
104
src/zen/tests/split_view/browser_split_view_with_glance.js
Normal file
104
src/zen/tests/split_view/browser_split_view_with_glance.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { openGlanceOnTab } = ChromeUtils.importESModule(
|
||||
'resource://testing-common/GlanceTestUtils.sys.mjs'
|
||||
);
|
||||
|
||||
add_task(async function test_Basic_Split_View_Glance() {
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
await openGlanceOnTab(window, async (glanceTab) => {
|
||||
ok(
|
||||
glanceTab.hasAttribute('zen-glance-tab'),
|
||||
'The glance tab should have the zen-glance-tab attribute'
|
||||
);
|
||||
ok(
|
||||
gBrowser.tabpanels.hasAttribute('zen-split-view'),
|
||||
'The split view should not have crashed with two tabs in it'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_Basic_Split_View_Glance_Expand() {
|
||||
await basicSplitNTabs(async (tabs) => {
|
||||
await openGlanceOnTab(
|
||||
window,
|
||||
async (glanceTab) => {
|
||||
await gZenGlanceManager.fullyOpenGlance();
|
||||
ok(
|
||||
!glanceTab.hasAttribute('zen-glance-tab'),
|
||||
'The glance tab should not have the zen-glance-tab attribute after expanding'
|
||||
);
|
||||
ok(!glanceTab.group, 'The glance tab should not be in a split group after expanding');
|
||||
for (const tab of tabs) {
|
||||
ok(
|
||||
tab.group.hasAttribute('split-view-group'),
|
||||
'All tabs in the split view should still be in a split group after expanding glance'
|
||||
);
|
||||
}
|
||||
const selectedBrowser = document.querySelectorAll('.browserSidebarContainer.deck-selected');
|
||||
Assert.equal(
|
||||
selectedBrowser.length,
|
||||
1,
|
||||
'There should be one selected browser sidebar after expanding glance'
|
||||
);
|
||||
BrowserTestUtils.removeTab(glanceTab);
|
||||
},
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_Basic_Split_View_Glance_No_More_Split() {
|
||||
await basicSplitNTabs(
|
||||
async (tabs) => {
|
||||
await openGlanceOnTab(window, async (glanceTab) => {
|
||||
ok(
|
||||
document.getElementById('cmd_zenGlanceSplit').getAttribute('disabled') === 'true',
|
||||
'The split command should be disabled when glance is open'
|
||||
);
|
||||
});
|
||||
},
|
||||
'grid',
|
||||
4
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_Basic_Split_View_Glance_Split() {
|
||||
const tab = await addTabTo(gBrowser, getUrlForNthTab(1));
|
||||
gBrowser.selectedTab = tab;
|
||||
await openGlanceOnTab(
|
||||
window,
|
||||
async (glanceTab) => {
|
||||
const waitForSplitPromise = BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
'ZenViewSplitter:SplitViewActivated'
|
||||
);
|
||||
document.getElementById('cmd_zenGlanceSplit').doCommand();
|
||||
await waitForSplitPromise;
|
||||
ok(
|
||||
!glanceTab.hasAttribute('zen-glance-tab'),
|
||||
'The glance tab should not have the zen-glance-tab attribute after splitting'
|
||||
);
|
||||
ok(
|
||||
gBrowser.tabpanels.hasAttribute('zen-split-view'),
|
||||
'The split view should not have crashed with two tabs in it'
|
||||
);
|
||||
ok(
|
||||
glanceTab.group.hasAttribute('split-view-group'),
|
||||
'The glance tab should be in a split group after splitting'
|
||||
);
|
||||
Assert.equal(
|
||||
tab.group,
|
||||
glanceTab.group,
|
||||
'The original tab should be in the same split group as the glance tab after splitting'
|
||||
);
|
||||
BrowserTestUtils.removeTab(glanceTab);
|
||||
},
|
||||
false
|
||||
);
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
43
src/zen/tests/split_view/head.js
Normal file
43
src/zen/tests/split_view/head.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
async function addTabTo(targetBrowser, url = 'http://mochi.test:8888/', params = {}) {
|
||||
params.skipAnimation = true;
|
||||
const tab = BrowserTestUtils.addTab(targetBrowser, url, params);
|
||||
const browser = targetBrowser.getBrowserForTab(tab);
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
return tab;
|
||||
}
|
||||
|
||||
function getUrlForNthTab(n) {
|
||||
return `data:text/plain,tab${n}`;
|
||||
}
|
||||
|
||||
async function createSplitView(tabs, type = 'grid') {
|
||||
const waitForActivationPromise = BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
'ZenViewSplitter:SplitViewActivated'
|
||||
);
|
||||
gZenViewSplitter.splitTabs(tabs, type);
|
||||
await waitForActivationPromise;
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(async () => {
|
||||
resolve();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
async function basicSplitNTabs(callback, type = 'grid', n = 2) {
|
||||
Assert.greater(n, 1, 'There should be at least two tabs');
|
||||
Assert.less(n, 5, 'There should be at most four tabs');
|
||||
const tabs = await Promise.all(
|
||||
[...Array(n)].map((_, i) => addTabTo(gBrowser, getUrlForNthTab(i + 1)))
|
||||
);
|
||||
await createSplitView(tabs, type);
|
||||
await callback(tabs);
|
||||
for (const tab of tabs) {
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
}
|
||||
}
|
@@ -1,3 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { TabGroupTestUtils } = ChromeUtils.importESModule(
|
||||
'resource://testing-common/TabGroupTestUtils.sys.mjs'
|
||||
);
|
||||
|
24
src/zen/tests/workspaces/browser_change_to_empty.js
Normal file
24
src/zen/tests/workspaces/browser_change_to_empty.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(async function test_Change_To_Empty() {
|
||||
const currentWorkspaceUUID = gZenWorkspaces.activeWorkspace;
|
||||
await gZenWorkspaces.createAndSaveWorkspace('Test Workspace 2');
|
||||
const workspaces = await gZenWorkspaces._workspaces();
|
||||
const secondWorkspace = workspaces.workspaces[1];
|
||||
|
||||
await gZenWorkspaces.changeWorkspace(secondWorkspace.uuid);
|
||||
ok(gBrowser.selectedTab === gZenWorkspaces._emptyTab, 'The empty tab should be selected.');
|
||||
|
||||
await gZenWorkspaces.removeWorkspace(gZenWorkspaces.activeWorkspace);
|
||||
ok(
|
||||
gBrowser.selectedTab !== gZenWorkspaces._emptyTab,
|
||||
'The empty tab should not be selected anymore.'
|
||||
);
|
||||
|
||||
const workspacesAfterRemove = await gZenWorkspaces._workspaces();
|
||||
ok(workspacesAfterRemove.workspaces.length === 1, 'One workspace should exist.');
|
||||
ok(gBrowser.tabs.length === 2, 'There should be two tabs.');
|
||||
});
|
@@ -922,6 +922,7 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
window.addEventListener('TabPinned', tabUpdateListener);
|
||||
window.addEventListener('TabUnpinned', tabUpdateListener);
|
||||
window.addEventListener('aftercustomization', tabUpdateListener);
|
||||
window.addEventListener('TabSelect', this.onLocationChange.bind(this));
|
||||
|
||||
window.addEventListener('TabBrowserInserted', this.onTabBrowserInserted.bind(this));
|
||||
}
|
||||
@@ -1621,7 +1622,9 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
);
|
||||
} else {
|
||||
workspaceElement.style.paddingTop = essentialsHeight + 'px';
|
||||
window.requestAnimationFrame(() => {
|
||||
workspaceElement.style.paddingTop = essentialsHeight + 'px';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2448,7 +2451,8 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
tab.setAttribute('zen-workspace-id', activeWorkspace.uuid);
|
||||
}
|
||||
|
||||
async onLocationChange(browser) {
|
||||
async onLocationChange(event) {
|
||||
let tab = event.target;
|
||||
gZenCompactModeManager.sidebar.toggleAttribute(
|
||||
'zen-has-empty-tab',
|
||||
gBrowser.selectedTab.hasAttribute('zen-empty-tab')
|
||||
@@ -2457,7 +2461,6 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
if (tab.hasAttribute('zen-glance-tab')) {
|
||||
// Extract from parent node so we are not selecting the wrong (current) tab
|
||||
tab = tab.parentNode.closest('.tabbrowser-tab');
|
||||
|
Reference in New Issue
Block a user