|
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 let gNavBar = document.getElementById(CustomizableUI.AREA_NAVBAR); |
|
8 let gOverflowList = document.getElementById(gNavBar.getAttribute("overflowtarget")); |
|
9 |
|
10 const kBookmarksButton = "bookmarks-menu-button"; |
|
11 const kBookmarksItems = "personal-bookmarks"; |
|
12 const kOriginalWindowWidth = window.outerWidth; |
|
13 const kSmallWidth = 400; |
|
14 |
|
15 /** |
|
16 * Helper function that opens the bookmarks menu, and returns a Promise that |
|
17 * resolves as soon as the menu is ready for interaction. |
|
18 */ |
|
19 function bookmarksMenuPanelShown() { |
|
20 let deferred = Promise.defer(); |
|
21 let bookmarksMenuPopup = document.getElementById("BMB_bookmarksPopup"); |
|
22 let onTransitionEnd = (e) => { |
|
23 if (e.target == bookmarksMenuPopup) { |
|
24 bookmarksMenuPopup.removeEventListener("transitionend", onTransitionEnd); |
|
25 deferred.resolve(); |
|
26 } |
|
27 } |
|
28 bookmarksMenuPopup.addEventListener("transitionend", onTransitionEnd); |
|
29 return deferred.promise; |
|
30 } |
|
31 |
|
32 /** |
|
33 * Checks that the placesContext menu is correctly attached to the |
|
34 * controller of some view. Returns a Promise that resolves as soon |
|
35 * as the context menu is closed. |
|
36 * |
|
37 * @param aItemWithContextMenu the item that we need to synthesize hte |
|
38 * right click on in order to open the context menu. |
|
39 */ |
|
40 function checkPlacesContextMenu(aItemWithContextMenu) { |
|
41 return Task.spawn(function* () { |
|
42 let contextMenu = document.getElementById("placesContext"); |
|
43 let newBookmarkItem = document.getElementById("placesContext_new:bookmark"); |
|
44 let shownPromise = popupShown(contextMenu); |
|
45 EventUtils.synthesizeMouseAtCenter(aItemWithContextMenu, |
|
46 {type: "contextmenu", button: 2}); |
|
47 yield shownPromise; |
|
48 |
|
49 ok(!newBookmarkItem.hasAttribute("disabled"), |
|
50 "New bookmark item shouldn't be disabled"); |
|
51 |
|
52 yield closePopup(contextMenu); |
|
53 }); |
|
54 } |
|
55 |
|
56 /** |
|
57 * Opens the bookmarks menu panel, and then opens each of the "special" |
|
58 * submenus in that list. Then it checks that those submenu's context menus |
|
59 * are properly hooked up to a controller. |
|
60 */ |
|
61 function checkSpecialContextMenus() { |
|
62 return Task.spawn(function* () { |
|
63 let contextMenu = document.getElementById("placesContext"); |
|
64 let bookmarksMenuButton = document.getElementById(kBookmarksButton); |
|
65 let bookmarksMenuPopup = document.getElementById("BMB_bookmarksPopup"); |
|
66 |
|
67 const kSpecialItemIDs = { |
|
68 "BMB_bookmarksToolbar": "BMB_bookmarksToolbarPopup", |
|
69 "BMB_unsortedBookmarks": "BMB_unsortedBookmarksPopup", |
|
70 }; |
|
71 |
|
72 // Open the bookmarks menu button context menus and ensure that |
|
73 // they have the proper views attached. |
|
74 let shownPromise = bookmarksMenuPanelShown(); |
|
75 let dropmarker = document.getAnonymousElementByAttribute(bookmarksMenuButton, |
|
76 "anonid", "dropmarker"); |
|
77 EventUtils.synthesizeMouseAtCenter(dropmarker, {}); |
|
78 info("Waiting for bookmarks menu popup to show after clicking dropmarker.") |
|
79 yield shownPromise; |
|
80 |
|
81 for (let menuID in kSpecialItemIDs) { |
|
82 let menuItem = document.getElementById(menuID); |
|
83 let menuPopup = document.getElementById(kSpecialItemIDs[menuID]); |
|
84 let shownPromise = popupShown(menuPopup); |
|
85 menuPopup.openPopup(menuItem, null, 0, 0, false, false, null); |
|
86 |
|
87 yield shownPromise; |
|
88 |
|
89 yield checkPlacesContextMenu(menuPopup); |
|
90 yield closePopup(menuPopup); |
|
91 } |
|
92 |
|
93 yield closePopup(bookmarksMenuPopup); |
|
94 }); |
|
95 } |
|
96 |
|
97 /** |
|
98 * Closes a focused popup by simulating pressing the Escape key, |
|
99 * and returns a Promise that resolves as soon as the popup is closed. |
|
100 * |
|
101 * @param aPopup the popup node to close. |
|
102 */ |
|
103 function closePopup(aPopup) { |
|
104 let hiddenPromise = popupHidden(aPopup); |
|
105 EventUtils.synthesizeKey("VK_ESCAPE", {}); |
|
106 return hiddenPromise; |
|
107 } |
|
108 |
|
109 /** |
|
110 * Helper function that checks that the context menu of the |
|
111 * bookmark toolbar items chevron popup is correctly hooked up |
|
112 * to the controller of a view. |
|
113 */ |
|
114 function checkBookmarksItemsChevronContextMenu() { |
|
115 return Task.spawn(function*() { |
|
116 let chevronPopup = document.getElementById("PlacesChevronPopup"); |
|
117 let shownPromise = popupShown(chevronPopup); |
|
118 let chevron = document.getElementById("PlacesChevron"); |
|
119 EventUtils.synthesizeMouseAtCenter(chevron, {}); |
|
120 yield shownPromise; |
|
121 yield waitForCondition(() => { |
|
122 for (let child of chevronPopup.children) { |
|
123 if (child.style.visibility != "hidden") |
|
124 return true; |
|
125 } |
|
126 }); |
|
127 yield checkPlacesContextMenu(chevronPopup); |
|
128 yield closePopup(chevronPopup); |
|
129 }); |
|
130 } |
|
131 |
|
132 /** |
|
133 * Forces the window to a width that causes the nav-bar to overflow |
|
134 * its contents. Returns a Promise that resolves as soon as the |
|
135 * overflowable nav-bar is showing its chevron. |
|
136 */ |
|
137 function overflowEverything() { |
|
138 window.resizeTo(kSmallWidth, window.outerHeight); |
|
139 return waitForCondition(() => gNavBar.hasAttribute("overflowing")); |
|
140 } |
|
141 |
|
142 /** |
|
143 * Returns the window to its original size from the start of the test, |
|
144 * and returns a Promise that resolves when the nav-bar is no longer |
|
145 * overflowing. |
|
146 */ |
|
147 function stopOverflowing() { |
|
148 window.resizeTo(kOriginalWindowWidth, window.outerHeight); |
|
149 return waitForCondition(() => !gNavBar.hasAttribute("overflowing")); |
|
150 } |
|
151 |
|
152 /** |
|
153 * Checks that an item with ID aID is overflowing in the nav-bar. |
|
154 * |
|
155 * @param aID the ID of the node to check for overflowingness. |
|
156 */ |
|
157 function checkOverflowing(aID) { |
|
158 ok(!gNavBar.querySelector("#" + aID), |
|
159 "Item with ID " + aID + " should no longer be in the gNavBar"); |
|
160 let item = gOverflowList.querySelector("#" + aID); |
|
161 ok(item, "Item with ID " + aID + " should be overflowing"); |
|
162 is(item.getAttribute("overflowedItem"), "true", |
|
163 "Item with ID " + aID + " should have overflowedItem attribute"); |
|
164 } |
|
165 |
|
166 /** |
|
167 * Checks that an item with ID aID is not overflowing in the nav-bar. |
|
168 * |
|
169 * @param aID the ID of hte node to check for non-overflowingness. |
|
170 */ |
|
171 function checkNotOverflowing(aID) { |
|
172 ok(!gOverflowList.querySelector("#" + aID), |
|
173 "Item with ID " + aID + " should no longer be overflowing"); |
|
174 let item = gNavBar.querySelector("#" + aID); |
|
175 ok(item, "Item with ID " + aID + " should be in the nav bar"); |
|
176 ok(!item.hasAttribute("overflowedItem"), |
|
177 "Item with ID " + aID + " should not have overflowedItem attribute"); |
|
178 } |
|
179 |
|
180 /** |
|
181 * Test that overflowing the bookmarks menu button doesn't break the |
|
182 * context menus for the Unsorted and Bookmarks Toolbar menu items. |
|
183 */ |
|
184 add_task(function* testOverflowingBookmarksButtonContextMenu() { |
|
185 ok(!gNavBar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar."); |
|
186 ok(CustomizableUI.inDefaultState, "Should start in default state."); |
|
187 |
|
188 // Open the Unsorted and Bookmarks Toolbar context menus and ensure |
|
189 // that they have views attached. |
|
190 yield checkSpecialContextMenus(); |
|
191 |
|
192 yield overflowEverything(); |
|
193 checkOverflowing(kBookmarksButton); |
|
194 |
|
195 yield stopOverflowing(); |
|
196 checkNotOverflowing(kBookmarksButton); |
|
197 |
|
198 yield checkSpecialContextMenus(); |
|
199 }); |
|
200 |
|
201 /** |
|
202 * Test that the bookmarks toolbar items context menu still works if moved |
|
203 * to the menu from the overflow panel, and then back to the toolbar. |
|
204 */ |
|
205 add_task(function* testOverflowingBookmarksItemsContextMenu() { |
|
206 yield PanelUI.ensureReady(); |
|
207 |
|
208 let bookmarksToolbarItems = document.getElementById(kBookmarksItems); |
|
209 gCustomizeMode.addToToolbar(bookmarksToolbarItems); |
|
210 yield checkPlacesContextMenu(bookmarksToolbarItems); |
|
211 |
|
212 yield overflowEverything(); |
|
213 checkOverflowing(kBookmarksItems) |
|
214 |
|
215 gCustomizeMode.addToPanel(bookmarksToolbarItems); |
|
216 |
|
217 yield stopOverflowing(); |
|
218 |
|
219 gCustomizeMode.addToToolbar(bookmarksToolbarItems); |
|
220 yield checkPlacesContextMenu(bookmarksToolbarItems); |
|
221 }); |
|
222 |
|
223 /** |
|
224 * Test that overflowing the bookmarks toolbar items doesn't cause the |
|
225 * context menu in the bookmarks toolbar items chevron to stop working. |
|
226 */ |
|
227 add_task(function* testOverflowingBookmarksItemsChevronContextMenu() { |
|
228 // If it's not already there, let's move the bookmarks toolbar items to |
|
229 // the nav-bar. |
|
230 let bookmarksToolbarItems = document.getElementById(kBookmarksItems); |
|
231 gCustomizeMode.addToToolbar(bookmarksToolbarItems); |
|
232 |
|
233 // We make the PlacesToolbarItems element be super tiny in order to force |
|
234 // the bookmarks toolbar items into overflowing and making the chevron |
|
235 // show itself. |
|
236 let placesToolbarItems = document.getElementById("PlacesToolbarItems"); |
|
237 let placesChevron = document.getElementById("PlacesChevron"); |
|
238 placesToolbarItems.style.maxWidth = "10px"; |
|
239 yield waitForCondition(() => !placesChevron.collapsed); |
|
240 |
|
241 yield checkBookmarksItemsChevronContextMenu(); |
|
242 |
|
243 yield overflowEverything(); |
|
244 checkOverflowing(kBookmarksItems); |
|
245 |
|
246 yield stopOverflowing(); |
|
247 checkNotOverflowing(kBookmarksItems); |
|
248 |
|
249 yield checkBookmarksItemsChevronContextMenu(); |
|
250 |
|
251 placesToolbarItems.style.removeProperty("max-width"); |
|
252 }); |
|
253 |
|
254 add_task(function* asyncCleanup() { |
|
255 window.resizeTo(kOriginalWindowWidth, window.outerHeight); |
|
256 yield resetCustomization(); |
|
257 }); |