forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			295 lines
		
	
	
	
		
			9.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
	
		
			9.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* 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();
 | |
| });
 | 
