|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 "use strict"; |
|
6 |
|
7 const kXULWidgetId = "sync-button"; |
|
8 const kAPIWidgetId = "feed-button"; |
|
9 const kPanel = CustomizableUI.AREA_PANEL; |
|
10 const kToolbar = CustomizableUI.AREA_NAVBAR; |
|
11 const kVisiblePalette = "customization-palette"; |
|
12 const kPlaceholderClass = "panel-customization-placeholder"; |
|
13 |
|
14 function checkWrapper(id) { |
|
15 is(document.querySelectorAll("#wrapper-" + id).length, 1, "There should be exactly 1 wrapper for " + id + " in the customizing window."); |
|
16 } |
|
17 |
|
18 let move = { |
|
19 "drag": function(id, target) { |
|
20 let targetNode = document.getElementById(target); |
|
21 if (targetNode.customizationTarget) { |
|
22 targetNode = targetNode.customizationTarget; |
|
23 } |
|
24 simulateItemDrag(document.getElementById(id), targetNode); |
|
25 }, |
|
26 "dragToItem": function(id, target) { |
|
27 let targetNode = document.getElementById(target); |
|
28 if (targetNode.customizationTarget) { |
|
29 targetNode = targetNode.customizationTarget; |
|
30 } |
|
31 let items = targetNode.querySelectorAll("toolbarpaletteitem:not(." + kPlaceholderClass + ")"); |
|
32 if (target == kPanel) { |
|
33 targetNode = items[items.length - 1]; |
|
34 } else { |
|
35 targetNode = items[0]; |
|
36 } |
|
37 simulateItemDrag(document.getElementById(id), targetNode); |
|
38 }, |
|
39 "API": function(id, target) { |
|
40 if (target == kVisiblePalette) { |
|
41 return CustomizableUI.removeWidgetFromArea(id); |
|
42 } |
|
43 return CustomizableUI.addWidgetToArea(id, target, null); |
|
44 } |
|
45 }; |
|
46 |
|
47 function isLast(containerId, defaultPlacements, id) { |
|
48 assertAreaPlacements(containerId, defaultPlacements.concat([id])); |
|
49 is(document.getElementById(containerId).customizationTarget.lastChild.firstChild.id, id, |
|
50 "Widget " + id + " should be in " + containerId + " in customizing window."); |
|
51 is(otherWin.document.getElementById(containerId).customizationTarget.lastChild.id, id, |
|
52 "Widget " + id + " should be in " + containerId + " in other window."); |
|
53 } |
|
54 |
|
55 function getLastVisibleNodeInToolbar(containerId, win=window) { |
|
56 let container = win.document.getElementById(containerId).customizationTarget; |
|
57 let rv = container.lastChild; |
|
58 while (rv && (rv.getAttribute('hidden') == 'true' || (rv.firstChild && rv.firstChild.getAttribute('hidden') == 'true'))) { |
|
59 rv = rv.previousSibling; |
|
60 } |
|
61 return rv; |
|
62 } |
|
63 |
|
64 function isLastVisibleInToolbar(containerId, defaultPlacements, id) { |
|
65 let newPlacements; |
|
66 for (let i = defaultPlacements.length - 1; i >= 0; i--) { |
|
67 let el = document.getElementById(defaultPlacements[i]); |
|
68 if (el && el.getAttribute('hidden') != 'true') { |
|
69 newPlacements = [...defaultPlacements]; |
|
70 newPlacements.splice(i + 1, 0, id); |
|
71 break; |
|
72 } |
|
73 } |
|
74 if (!newPlacements) { |
|
75 assertAreaPlacements(containerId, defaultPlacements.concat([id])); |
|
76 } else { |
|
77 assertAreaPlacements(containerId, newPlacements); |
|
78 } |
|
79 is(getLastVisibleNodeInToolbar(containerId).firstChild.id, id, |
|
80 "Widget " + id + " should be in " + containerId + " in customizing window."); |
|
81 is(getLastVisibleNodeInToolbar(containerId, otherWin).id, id, |
|
82 "Widget " + id + " should be in " + containerId + " in other window."); |
|
83 } |
|
84 |
|
85 function isFirst(containerId, defaultPlacements, id) { |
|
86 assertAreaPlacements(containerId, [id].concat(defaultPlacements)); |
|
87 is(document.getElementById(containerId).customizationTarget.firstChild.firstChild.id, id, |
|
88 "Widget " + id + " should be in " + containerId + " in customizing window."); |
|
89 is(otherWin.document.getElementById(containerId).customizationTarget.firstChild.id, id, |
|
90 "Widget " + id + " should be in " + containerId + " in other window."); |
|
91 } |
|
92 |
|
93 function checkToolbar(id, method) { |
|
94 // Place at start of the toolbar: |
|
95 let toolbarPlacements = getAreaWidgetIds(kToolbar); |
|
96 move[method](id, kToolbar); |
|
97 if (method == "dragToItem") { |
|
98 isFirst(kToolbar, toolbarPlacements, id); |
|
99 } else if (method == "drag") { |
|
100 isLastVisibleInToolbar(kToolbar, toolbarPlacements, id); |
|
101 } else { |
|
102 isLast(kToolbar, toolbarPlacements, id); |
|
103 } |
|
104 checkWrapper(id); |
|
105 } |
|
106 |
|
107 function checkPanel(id, method) { |
|
108 let panelPlacements = getAreaWidgetIds(kPanel); |
|
109 move[method](id, kPanel); |
|
110 let children = document.getElementById(kPanel).querySelectorAll("toolbarpaletteitem:not(." + kPlaceholderClass + ")"); |
|
111 let otherChildren = otherWin.document.getElementById(kPanel).children; |
|
112 let newPlacements = panelPlacements.concat([id]); |
|
113 // Relative position of the new item from the end: |
|
114 let position = -1; |
|
115 // For the drag to item case, we drag to the last item, making the dragged item the |
|
116 // penultimate item. We can't well use the first item because the panel has complicated |
|
117 // rules about rearranging wide items (which, by default, the first two items are). |
|
118 if (method == "dragToItem") { |
|
119 newPlacements.pop(); |
|
120 newPlacements.splice(panelPlacements.length - 1, 0, id); |
|
121 position = -2; |
|
122 } |
|
123 assertAreaPlacements(kPanel, newPlacements); |
|
124 is(children[children.length + position].firstChild.id, id, |
|
125 "Widget " + id + " should be in " + kPanel + " in customizing window."); |
|
126 is(otherChildren[otherChildren.length + position].id, id, |
|
127 "Widget " + id + " should be in " + kPanel + " in other window."); |
|
128 checkWrapper(id); |
|
129 } |
|
130 |
|
131 function checkPalette(id, method) { |
|
132 // Move back to palette: |
|
133 move[method](id, kVisiblePalette); |
|
134 ok(CustomizableUI.inDefaultState, "Should end in default state"); |
|
135 let visibleChildren = gCustomizeMode.visiblePalette.children; |
|
136 let expectedChild = method == "dragToItem" ? visibleChildren[0] : visibleChildren[visibleChildren.length - 1]; |
|
137 is(expectedChild.firstChild.id, id, "Widget " + id + " was moved using " + method + " and should now be wrapped in palette in customizing window."); |
|
138 if (id == kXULWidgetId) { |
|
139 ok(otherWin.gNavToolbox.palette.querySelector("#" + id), "Widget " + id + " should be in invisible palette in other window."); |
|
140 } |
|
141 checkWrapper(id); |
|
142 } |
|
143 |
|
144 let otherWin; |
|
145 |
|
146 // Moving widgets in two windows, one with customize mode and one without, should work. |
|
147 add_task(function MoveWidgetsInTwoWindows() { |
|
148 yield startCustomizing(); |
|
149 otherWin = yield openAndLoadWindow(null, true); |
|
150 yield otherWin.PanelUI.ensureReady(); |
|
151 ok(CustomizableUI.inDefaultState, "Should start in default state"); |
|
152 |
|
153 for (let widgetId of [kXULWidgetId, kAPIWidgetId]) { |
|
154 for (let method of ["API", "drag", "dragToItem"]) { |
|
155 info("Moving widget " + widgetId + " using " + method); |
|
156 checkToolbar(widgetId, method); |
|
157 checkPanel(widgetId, method); |
|
158 checkPalette(widgetId, method); |
|
159 checkPanel(widgetId, method); |
|
160 checkToolbar(widgetId, method); |
|
161 checkPalette(widgetId, method); |
|
162 } |
|
163 } |
|
164 yield promiseWindowClosed(otherWin); |
|
165 otherWin = null; |
|
166 yield endCustomizing(); |
|
167 }); |
|
168 |
|
169 add_task(function asyncCleanup() { |
|
170 yield resetCustomization(); |
|
171 }); |