michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: function test() { michael@0: waitForExplicitFinish(); michael@0: requestLongerTimeout(2); michael@0: newWindowWithTabView(onTabViewWindowLoaded); michael@0: } michael@0: michael@0: function onTabViewWindowLoaded(win) { michael@0: ok(win.TabView.isVisible(), "Tab View is visible"); michael@0: michael@0: let contentWindow = win.document.getElementById("tab-view").contentWindow; michael@0: let [originalTab] = win.gBrowser.visibleTabs; michael@0: let currentGroup = contentWindow.GroupItems.getActiveGroupItem(); michael@0: michael@0: // let's create a group small enough to get stacked michael@0: let group = new contentWindow.GroupItem([], { michael@0: immediately: true, michael@0: bounds: {left: 20, top: 300, width: 400, height: 400} michael@0: }); michael@0: michael@0: let expander = contentWindow.iQ(group.container).find(".stackExpander"); michael@0: ok("length" in expander && expander.length == 1, "The group has an expander."); michael@0: michael@0: // procreate! michael@0: contentWindow.UI.setActive(group); michael@0: for (var i=0; i<7; i++) { michael@0: win.gBrowser.loadOneTab('http://example.com#' + i, {inBackground: true}); michael@0: } michael@0: let children = group.getChildren(); michael@0: michael@0: // Wait until they all update because, once updated, they will notice that they michael@0: // don't have favicons and this will change their styling at some unknown time. michael@0: afterAllTabItemsUpdated(function() { michael@0: ok(!group.shouldStack(group._children.length), "The group should not stack."); michael@0: is(expander[0].style.display, "none", "The expander is hidden."); michael@0: michael@0: // now resize the group down. michael@0: group.setSize(100, 100, true); michael@0: michael@0: ok(group.shouldStack(group._children.length), "The group should stack."); michael@0: isnot(expander[0].style.display, "none", "The expander is now visible!"); michael@0: let expanderBounds = expander.bounds(); michael@0: ok(group.getBounds().contains(expanderBounds), "The expander lies in the group."); michael@0: let stackCenter = children[0].getBounds().center(); michael@0: ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack."); michael@0: michael@0: // STAGE 1: michael@0: // Here, we just expand the group, click elsewhere, and make sure michael@0: // it collapsed. michael@0: let stage1expanded = function() { michael@0: group.removeSubscriber("expanded", stage1expanded); michael@0: michael@0: ok(group.expanded, "The group is now expanded."); michael@0: is(expander[0].style.display, "none", "The expander is hidden!"); michael@0: michael@0: let overlay = contentWindow.document.getElementById("expandedTray"); michael@0: ok(overlay, "The expanded tray exists."); michael@0: let $overlay = contentWindow.iQ(overlay); michael@0: michael@0: group.addSubscriber("collapsed", stage1collapsed); michael@0: // null type means "click", for some reason... michael@0: EventUtils.synthesizeMouse(contentWindow.document.body, 10, $overlay.bounds().bottom + 5, michael@0: {type: null}, contentWindow); michael@0: }; michael@0: michael@0: let stage1collapsed = function() { michael@0: group.removeSubscriber("collapsed", stage1collapsed); michael@0: ok(!group.expanded, "The group is no longer expanded."); michael@0: isnot(expander[0].style.display, "none", "The expander is visible!"); michael@0: let expanderBounds = expander.bounds(); michael@0: ok(group.getBounds().contains(expanderBounds), "The expander still lies in the group."); michael@0: let stackCenter = children[0].getBounds().center(); michael@0: ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack."); michael@0: michael@0: // now, try opening it up again. michael@0: group.addSubscriber("expanded", stage2expanded); michael@0: EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow); michael@0: }; michael@0: michael@0: // STAGE 2: michael@0: // Now make sure every child of the group shows up within this "tray", and michael@0: // click on one of them and make sure we go into the tab and the tray collapses. michael@0: let stage2expanded = function() { michael@0: group.removeSubscriber("expanded", stage2expanded); michael@0: michael@0: ok(group.expanded, "The group is now expanded."); michael@0: is(expander[0].style.display, "none", "The expander is hidden!"); michael@0: michael@0: let overlay = contentWindow.document.getElementById("expandedTray"); michael@0: ok(overlay, "The expanded tray exists."); michael@0: let $overlay = contentWindow.iQ(overlay); michael@0: let overlayBounds = $overlay.bounds(); michael@0: michael@0: children.forEach(function(child, i) { michael@0: ok(overlayBounds.contains(child.getBounds()), "Child " + i + " is in the overlay"); michael@0: }); michael@0: michael@0: win.addEventListener("tabviewhidden", stage2hidden, false); michael@0: // again, null type means "click", for some reason... michael@0: EventUtils.synthesizeMouse(children[1].container, 2, 2, {type: null}, contentWindow); michael@0: }; michael@0: michael@0: let stage2hidden = function() { michael@0: win.removeEventListener("tabviewhidden", stage2hidden, false); michael@0: michael@0: is(win.gBrowser.selectedTab, children[1].tab, "We clicked on the second child."); michael@0: michael@0: win.addEventListener("tabviewshown", stage2shown, false); michael@0: win.TabView.toggle(); michael@0: }; michael@0: michael@0: let stage2shown = function() { michael@0: win.removeEventListener("tabviewshown", stage2shown, false); michael@0: ok(!group.expanded, "The group is not expanded."); michael@0: isnot(expander[0].style.display, "none", "The expander is visible!"); michael@0: let expanderBounds = expander.bounds(); michael@0: ok(group.getBounds().contains(expanderBounds), "The expander still lies in the group."); michael@0: let stackCenter = children[0].getBounds().center(); michael@0: ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack."); michael@0: michael@0: is(group.getTopChild(), children[1], "The top child in the stack is the second tab item"); michael@0: let topChildzIndex = children[1].zIndex; michael@0: // the second tab item should have the largest z-index. michael@0: // only check the first 6 tabs as the stack only contains 6 tab items. michael@0: for (let i = 0; i < 6; i++) { michael@0: if (i != 1) michael@0: ok(children[i].zIndex < topChildzIndex, michael@0: "The child[" + i + "] has smaller zIndex than second child"); michael@0: } michael@0: michael@0: // okay, expand this group one last time michael@0: group.addSubscriber("expanded", stage3expanded); michael@0: EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow); michael@0: } michael@0: michael@0: // STAGE 3: michael@0: // Ensure that stack still shows the same top item after a expand and a collapse. michael@0: let stage3expanded = function() { michael@0: group.removeSubscriber("expanded", stage3expanded); michael@0: michael@0: ok(group.expanded, "The group is now expanded."); michael@0: let overlay = contentWindow.document.getElementById("expandedTray"); michael@0: let $overlay = contentWindow.iQ(overlay); michael@0: michael@0: group.addSubscriber("collapsed", stage3collapsed); michael@0: // null type means "click", for some reason... michael@0: EventUtils.synthesizeMouse(contentWindow.document.body, 10, $overlay.bounds().bottom + 5, michael@0: {type: null}, contentWindow); michael@0: }; michael@0: michael@0: let stage3collapsed = function() { michael@0: group.removeSubscriber("collapsed", stage3collapsed); michael@0: michael@0: ok(!group.expanded, "The group is no longer expanded."); michael@0: isnot(expander[0].style.display, "none", "The expander is visible!"); michael@0: michael@0: let stackCenter = children[0].getBounds().center(); michael@0: ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack."); michael@0: michael@0: is(group.getTopChild(), children[1], michael@0: "The top child in the stack is still the second tab item"); michael@0: let topChildzIndex = children[1].zIndex; michael@0: // the second tab item should have the largest z-index. michael@0: // only check the first 6 tabs as the stack only contains 6 tab items. michael@0: for (let i = 0; i < 6; i++) { michael@0: if (i != 1) michael@0: ok(children[i].zIndex < topChildzIndex, michael@0: "The child[" + i + "] has smaller zIndex than second dhild after a collapse."); michael@0: } michael@0: michael@0: // In preparation for Stage 4, find that original tab and make it the active tab. michael@0: let originalTabItem = originalTab._tabViewTabItem; michael@0: contentWindow.UI.setActive(originalTabItem); michael@0: michael@0: // now, try opening it up again. michael@0: group.addSubscriber("expanded", stage4expanded); michael@0: EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow); michael@0: }; michael@0: michael@0: // STAGE 4: michael@0: // Activate another tab not in this group, expand our stacked group, but then michael@0: // enter Panorama (i.e., zoom into this other group), and make sure we can go to michael@0: // it and that the tray gets collapsed. michael@0: let stage4expanded = function() { michael@0: group.removeSubscriber("expanded", stage4expanded); michael@0: michael@0: ok(group.expanded, "The group is now expanded."); michael@0: is(expander[0].style.display, "none", "The expander is hidden!"); michael@0: let overlay = contentWindow.document.getElementById("expandedTray"); michael@0: ok(overlay, "The expanded tray exists."); michael@0: michael@0: let activeTab = contentWindow.UI.getActiveTab(); michael@0: ok(activeTab, "There is an active tab."); michael@0: let originalTabItem = originalTab._tabViewTabItem; michael@0: michael@0: isnot(activeTab, originalTabItem, "But it's not what it was a moment ago."); michael@0: let someChildIsActive = group.getChildren().some(function(child) michael@0: child == activeTab); michael@0: ok(someChildIsActive, "Now one of the children in the group is active."); michael@0: michael@0: // now activate Panorama... michael@0: win.addEventListener("tabviewhidden", stage4hidden, false); michael@0: win.TabView.toggle(); michael@0: }; michael@0: michael@0: let stage4hidden = function() { michael@0: win.removeEventListener("tabviewhidden", stage4hidden, false); michael@0: michael@0: isnot(win.gBrowser.selectedTab, originalTab, "We did not enter the original tab."); michael@0: michael@0: let someChildIsSelected = group.getChildren().some(function(child) michael@0: child.tab == win.gBrowser.selectedTab); michael@0: ok(someChildIsSelected, "Instead we're in one of the stack's children."); michael@0: michael@0: win.addEventListener("tabviewshown", stage4shown, false); michael@0: win.TabView.toggle(); michael@0: }; michael@0: michael@0: let stage4shown = function() { michael@0: win.removeEventListener("tabviewshown", stage4shown, false); michael@0: michael@0: let overlay = contentWindow.document.getElementById("expandedTray"); michael@0: ok(!group.expanded, "The group is no longer expanded."); michael@0: isnot(expander[0].style.display, "none", "The expander is visible!"); michael@0: michael@0: win.close(); michael@0: finish(); michael@0: } michael@0: michael@0: // get the ball rolling michael@0: group.addSubscriber("expanded", stage1expanded); michael@0: EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow); michael@0: }, win); michael@0: }