summaryrefslogtreecommitdiffstats
path: root/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js')
-rw-r--r--browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js295
1 files changed, 295 insertions, 0 deletions
diff --git a/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js b/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
new file mode 100644
index 0000000000..cf73326e53
--- /dev/null
+++ b/browser/components/customizableui/test/browser_876926_customize_mode_wrapping.js
@@ -0,0 +1,295 @@
+/* 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/. */
+
+"use strict";
+
+const kXULWidgetId = "a-test-button"; // we'll create a button with this ID.
+const kAPIWidgetId = "save-page-button";
+const kPanel = CustomizableUI.AREA_FIXED_OVERFLOW_PANEL;
+const kToolbar = CustomizableUI.AREA_NAVBAR;
+const kVisiblePalette = "customization-palette";
+
+function checkWrapper(id) {
+ is(
+ document.querySelectorAll("#wrapper-" + id).length,
+ 1,
+ "There should be exactly 1 wrapper for " +
+ id +
+ " in the customizing window."
+ );
+}
+
+async function ensureVisible(node) {
+ let isInPalette = node.parentNode.parentNode == gNavToolbox.palette;
+ if (isInPalette) {
+ node.scrollIntoView();
+ }
+ let dwu = window.windowUtils;
+ await BrowserTestUtils.waitForCondition(() => {
+ let nodeBounds = dwu.getBoundsWithoutFlushing(node);
+ if (isInPalette) {
+ let paletteBounds = dwu.getBoundsWithoutFlushing(gNavToolbox.palette);
+ if (
+ !(
+ nodeBounds.top >= paletteBounds.top &&
+ nodeBounds.bottom <= paletteBounds.bottom
+ )
+ ) {
+ return false;
+ }
+ }
+ return nodeBounds.height && nodeBounds.width;
+ });
+}
+
+var move = {
+ async drag(id, target) {
+ let targetNode = document.getElementById(target);
+ if (CustomizableUI.getCustomizationTarget(targetNode)) {
+ targetNode = CustomizableUI.getCustomizationTarget(targetNode);
+ }
+ let nodeToMove = document.getElementById(id);
+ await ensureVisible(nodeToMove);
+
+ simulateItemDrag(nodeToMove, targetNode, "end");
+ },
+ async dragToItem(id, target) {
+ let targetNode = document.getElementById(target);
+ if (CustomizableUI.getCustomizationTarget(targetNode)) {
+ targetNode = CustomizableUI.getCustomizationTarget(targetNode);
+ }
+ let items = targetNode.querySelectorAll("toolbarpaletteitem");
+ if (target == kPanel) {
+ targetNode = items[items.length - 1];
+ } else {
+ targetNode = items[0];
+ }
+ let nodeToMove = document.getElementById(id);
+ await ensureVisible(nodeToMove);
+ simulateItemDrag(nodeToMove, targetNode, "start");
+ },
+ API(id, target) {
+ if (target == kVisiblePalette) {
+ return CustomizableUI.removeWidgetFromArea(id);
+ }
+ return CustomizableUI.addWidgetToArea(id, target, null);
+ },
+};
+
+function isLast(containerId, defaultPlacements, id) {
+ assertAreaPlacements(containerId, defaultPlacements.concat([id]));
+ let thisTarget = CustomizableUI.getCustomizationTarget(
+ document.getElementById(containerId)
+ );
+ is(
+ thisTarget.lastElementChild.firstElementChild.id,
+ id,
+ "Widget " + id + " should be in " + containerId + " in customizing window."
+ );
+ let otherTarget = CustomizableUI.getCustomizationTarget(
+ otherWin.document.getElementById(containerId)
+ );
+ is(
+ otherTarget.lastElementChild.id,
+ id,
+ "Widget " + id + " should be in " + containerId + " in other window."
+ );
+}
+
+function getLastVisibleNodeInToolbar(containerId, win = window) {
+ let container = CustomizableUI.getCustomizationTarget(
+ win.document.getElementById(containerId)
+ );
+ let rv = container.lastElementChild;
+ while (rv?.hidden || rv?.firstElementChild?.hidden) {
+ rv = rv.previousElementSibling;
+ }
+ return rv;
+}
+
+function isLastVisibleInToolbar(containerId, defaultPlacements, id) {
+ let newPlacements;
+ for (let i = defaultPlacements.length - 1; i >= 0; i--) {
+ let el = document.getElementById(defaultPlacements[i]);
+ if (el && !el.hidden) {
+ newPlacements = [...defaultPlacements];
+ newPlacements.splice(i + 1, 0, id);
+ break;
+ }
+ }
+ if (!newPlacements) {
+ assertAreaPlacements(containerId, defaultPlacements.concat([id]));
+ } else {
+ assertAreaPlacements(containerId, newPlacements);
+ }
+ is(
+ getLastVisibleNodeInToolbar(containerId).firstElementChild.id,
+ id,
+ "Widget " + id + " should be in " + containerId + " in customizing window."
+ );
+ is(
+ getLastVisibleNodeInToolbar(containerId, otherWin).id,
+ id,
+ "Widget " + id + " should be in " + containerId + " in other window."
+ );
+}
+
+function isFirst(containerId, defaultPlacements, id) {
+ assertAreaPlacements(containerId, [id].concat(defaultPlacements));
+ let thisTarget = CustomizableUI.getCustomizationTarget(
+ document.getElementById(containerId)
+ );
+ is(
+ thisTarget.firstElementChild.firstElementChild.id,
+ id,
+ "Widget " + id + " should be in " + containerId + " in customizing window."
+ );
+ let otherTarget = CustomizableUI.getCustomizationTarget(
+ otherWin.document.getElementById(containerId)
+ );
+ is(
+ otherTarget.firstElementChild.id,
+ id,
+ "Widget " + id + " should be in " + containerId + " in other window."
+ );
+}
+
+async function checkToolbar(id, method) {
+ // Place at start of the toolbar:
+ let toolbarPlacements = getAreaWidgetIds(kToolbar);
+ await move[method](id, kToolbar);
+ if (method == "dragToItem") {
+ isFirst(kToolbar, toolbarPlacements, id);
+ } else if (method == "drag") {
+ isLastVisibleInToolbar(kToolbar, toolbarPlacements, id);
+ } else {
+ isLast(kToolbar, toolbarPlacements, id);
+ }
+ checkWrapper(id);
+}
+
+async function checkPanel(id, method) {
+ let panelPlacements = getAreaWidgetIds(kPanel);
+ await move[method](id, kPanel);
+ let children = document
+ .getElementById(kPanel)
+ .querySelectorAll("toolbarpaletteitem");
+ let otherChildren = otherWin.document.getElementById(kPanel).children;
+ let newPlacements = panelPlacements.concat([id]);
+ // Relative position of the new item from the end:
+ let position = -1;
+ // For the drag to item case, we drag to the last item, making the dragged item the
+ // penultimate item. We can't well use the first item because the panel has complicated
+ // rules about rearranging wide items (which, by default, the first two items are).
+ if (method == "dragToItem") {
+ newPlacements.pop();
+ newPlacements.splice(panelPlacements.length - 1, 0, id);
+ position = -2;
+ }
+ assertAreaPlacements(kPanel, newPlacements);
+ is(
+ children[children.length + position].firstElementChild.id,
+ id,
+ "Widget " + id + " should be in " + kPanel + " in customizing window."
+ );
+ is(
+ otherChildren[otherChildren.length + position].id,
+ id,
+ "Widget " + id + " should be in " + kPanel + " in other window."
+ );
+ checkWrapper(id);
+}
+
+async function checkPalette(id, method) {
+ // Move back to palette:
+ await move[method](id, kVisiblePalette);
+ ok(CustomizableUI.inDefaultState, "Should end in default state");
+ let visibleChildren = gCustomizeMode.visiblePalette.children;
+ let expectedChild =
+ method == "dragToItem"
+ ? visibleChildren[0]
+ : visibleChildren[visibleChildren.length - 1];
+ // Items dragged to the end of the palette should be the final item. That they're the penultimate
+ // item when dragged is tracked in bug 1395950. Once that's fixed, this hack can be removed.
+ if (method == "drag") {
+ expectedChild = expectedChild.previousElementSibling;
+ }
+ is(
+ expectedChild.firstElementChild.id,
+ id,
+ "Widget " +
+ id +
+ " was moved using " +
+ method +
+ " and should now be wrapped in palette in customizing window."
+ );
+ if (id == kXULWidgetId) {
+ ok(
+ otherWin.gNavToolbox.palette.querySelector("#" + id),
+ "Widget " + id + " should be in invisible palette in other window."
+ );
+ }
+ checkWrapper(id);
+}
+
+// This test needs a XUL button that's in the palette by default. No such
+// button currently exists, so we create a simple one.
+function createXULButtonForWindow(win) {
+ createDummyXULButton(kXULWidgetId, "test-button", win);
+}
+
+function removeXULButtonForWindow(win) {
+ win.gNavToolbox.palette.querySelector(`#${kXULWidgetId}`).remove();
+}
+
+var otherWin;
+
+// Moving widgets in two windows, one with customize mode and one without, should work.
+add_task(async function MoveWidgetsInTwoWindows() {
+ CustomizableUI.createWidget({
+ id: "cui-mode-wrapping-some-panel-item",
+ label: "Test panel wrapping",
+ });
+ await startCustomizing();
+ otherWin = await openAndLoadWindow(null, true);
+ await otherWin.PanelUI.ensureReady();
+ // Create the XUL button to use in the test in both windows.
+ createXULButtonForWindow(window);
+ createXULButtonForWindow(otherWin);
+ ok(CustomizableUI.inDefaultState, "Should start in default state");
+
+ for (let widgetId of [kXULWidgetId, kAPIWidgetId]) {
+ for (let method of ["API", "drag", "dragToItem"]) {
+ info("Moving widget " + widgetId + " using " + method);
+ await checkToolbar(widgetId, method);
+ // We add an item to the panel because otherwise we can't test dragging
+ // to items that are already there. We remove it because
+ // 'checkPalette' checks that we leave the browser in the default state.
+ CustomizableUI.addWidgetToArea(
+ "cui-mode-wrapping-some-panel-item",
+ CustomizableUI.AREA_FIXED_OVERFLOW_PANEL
+ );
+ await checkPanel(widgetId, method);
+ CustomizableUI.removeWidgetFromArea("cui-mode-wrapping-some-panel-item");
+ await checkPalette(widgetId, method);
+ CustomizableUI.addWidgetToArea(
+ "cui-mode-wrapping-some-panel-item",
+ CustomizableUI.AREA_FIXED_OVERFLOW_PANEL
+ );
+ await checkPanel(widgetId, method);
+ await checkToolbar(widgetId, method);
+ CustomizableUI.removeWidgetFromArea("cui-mode-wrapping-some-panel-item");
+ await checkPalette(widgetId, method);
+ }
+ }
+ await promiseWindowClosed(otherWin);
+ otherWin = null;
+ await endCustomizing();
+ removeXULButtonForWindow(window);
+});
+
+add_task(async function asyncCleanup() {
+ CustomizableUI.destroyWidget("cui-mode-wrapping-some-panel-item");
+ await resetCustomization();
+});