diff --git a/browser/components/downloads/test/browser/Makefile.in b/browser/components/downloads/test/browser/Makefile.in index 39e02866717..71dc291f6c3 100644 --- a/browser/components/downloads/test/browser/Makefile.in +++ b/browser/components/downloads/test/browser/Makefile.in @@ -4,5 +4,6 @@ MOCHITEST_BROWSER_FILES = \ browser_basic_functionality.js \ browser_first_download_panel.js \ + browser_overflow_anchor.js \ head.js \ $(NULL) diff --git a/browser/components/downloads/test/browser/browser_overflow_anchor.js b/browser/components/downloads/test/browser/browser_overflow_anchor.js new file mode 100644 index 00000000000..682c39ffd96 --- /dev/null +++ b/browser/components/downloads/test/browser/browser_overflow_anchor.js @@ -0,0 +1,115 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Make sure the downloads button and indicator overflows into the nav-bar + * chevron properly, and then when those buttons are clicked in the overflow + * panel that the downloads panel anchors to the chevron. + */ +function test_task() { + try { + // Ensure that state is reset in case previous tests didn't finish. + yield task_resetState(); + + // Record the original width of the window so we can put it back when + // this test finishes. + let oldWidth = window.outerWidth; + + // The downloads button should not be overflowed to begin with. + let button = CustomizableUI.getWidget("downloads-button") + .forWindow(window); + ok(!button.overflowed, "Downloads button should not be overflowed."); + + // Hack - we lock the size of the default flex-y items in the nav-bar, + // namely, the URL and search inputs. That way we can resize the + // window without worrying about them flexing. + const kFlexyItems = ["urlbar-container", "search-container"]; + registerCleanupFunction(() => unlockWidth(kFlexyItems)); + lockWidth(kFlexyItems); + + // Resize the window to half of its original size. That should + // be enough to overflow the downloads button. + window.resizeTo(oldWidth / 2, window.outerHeight); + yield waitForOverflowed(button, true); + + let promise = promisePanelOpened(); + button.node.doCommand(); + yield promise; + + let panel = DownloadsPanel.panel; + let chevron = document.getElementById("nav-bar-overflow-button"); + is(panel.anchorNode, chevron, "Panel should be anchored to the chevron."); + + DownloadsPanel.hidePanel(); + + // Unlock the widths on the flex-y items. + unlockWidth(kFlexyItems); + + // Put the window back to its original dimensions. + window.resizeTo(oldWidth, window.outerHeight); + + // The downloads button should eventually be un-overflowed. + yield waitForOverflowed(button, false); + + // Now try opening the panel again. + promise = promisePanelOpened(); + button.node.doCommand(); + yield promise; + + is(panel.anchorNode.id, "downloads-indicator-anchor"); + + DownloadsPanel.hidePanel(); + } finally { + // Clean up when the test finishes. + yield task_resetState(); + } +} + +/** + * For some node IDs, finds the nodes and sets their min-width's to their + * current width, preventing them from flex-shrinking. + * + * @param aItemIDs an array of item IDs to set min-width on. + */ +function lockWidth(aItemIDs) { + for (let itemID of aItemIDs) { + let item = document.getElementById(itemID); + let curWidth = item.getBoundingClientRect().width + "px"; + item.style.minWidth = curWidth; + } +} + +/** + * Clears the min-width's set on a set of IDs by lockWidth. + * + * @param aItemIDs an array of ItemIDs to remove min-width on. + */ +function unlockWidth(aItemIDs) { + for (let itemID of aItemIDs) { + let item = document.getElementById(itemID); + item.style.minWidth = ""; + } +} + +/** + * Waits for a node to enter or exit the overflowed state. + * + * @param aItem the node to wait for. + * @param aIsOverflowed if we're waiting for the item to be overflowed. + */ +function waitForOverflowed(aItem, aIsOverflowed) { + let deferOverflow = Promise.defer(); + if (aItem.overflowed == aIsOverflowed) { + return deferOverflow.resolve(); + } + + let observer = new MutationObserver(function(aMutations) { + if (aItem.overflowed == aIsOverflowed) { + observer.disconnect(); + deferOverflow.resolve(); + } + }); + observer.observe(aItem.node, {attributes: true}); + + return deferOverflow.promise; +}