/* * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.user.client.ui; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.junit.DoNotRunWith; import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; /** * Tests for {@link PopupPanel}. */ public class PopupTest extends GWTTestCase { /** * The Widget adder used to set the widget in a {@link PopupPanel}. */ private static class Adder implements HasWidgetsTester.WidgetAdder { public void addChild(HasWidgets container, Widget child) { ((PopupPanel) container).setWidget(child); } } /** * Expose otherwise private or protected methods. */ private static class TestablePopupPanel extends PopupPanel { private int onLoadCount; public void assertOnLoadCount(int expected) { assertEquals(expected, onLoadCount); } @Override public com.google.gwt.user.client.Element getContainerElement() { return super.getContainerElement(); } @Override public void onLoad() { super.onLoad(); onLoadCount++; } } @Override public String getModuleName() { return "com.google.gwt.user.User"; } /** * Test the basic accessors. */ public void testAccessors() { PopupPanel popup = createPopupPanel(); // Animation enabled assertFalse(popup.isAnimationEnabled()); popup.setAnimationEnabled(true); assertTrue(popup.isAnimationEnabled()); // Modal popup.setModal(true); assertTrue(popup.isModal()); popup.setModal(false); assertFalse(popup.isModal()); // AutoHide enabled popup.setAutoHideEnabled(true); assertTrue(popup.isAutoHideEnabled()); popup.setAutoHideEnabled(false); assertFalse(popup.isAutoHideEnabled()); // PreviewAllNativeEvents enabled popup.setPreviewingAllNativeEvents(true); assertTrue(popup.isPreviewingAllNativeEvents()); popup.setPreviewingAllNativeEvents(false); assertFalse(popup.isPreviewingAllNativeEvents()); // setVisible assertTrue(popup.isVisible()); popup.setVisible(false); assertFalse(popup.isVisible()); popup.setVisible(true); assertTrue(popup.isVisible()); // isShowing assertFalse(popup.isShowing()); popup.show(); assertTrue(popup.isShowing()); popup.hide(); assertFalse(popup.isShowing()); } public void testAttachDetachOrder() { HasWidgetsTester.testAll(createPopupPanel(), new Adder(), false); } public void testAutoHidePartner() { final PopupPanel popup = new PopupPanel(); // Add a partner DivElement partner0 = Document.get().createDivElement(); popup.addAutoHidePartner(partner0); popup.addAutoHidePartner(Document.get().createDivElement()); // Remove a partner popup.removeAutoHidePartner(partner0); } public void testAutoHideOnHistoryEvent() { PopupPanel popup = createPopupPanel(); popup.show(); assertTrue(popup.isShowing()); // When autoHideOnHistoryEvent is disabled, the popup remains visible. History.newItem("popupToken0"); assertTrue(popup.isShowing()); // When autoHideOnHistoryEvent is enabled, the popup is hidden. popup.setAutoHideOnHistoryEventsEnabled(true); History.newItem("popupToken1"); assertFalse(popup.isShowing()); } /** * Tests that a large PopupPanel is not positioned off the top or left edges * of the browser window, making part of the panel unreachable. */ public void testCenterLargePopup() { PopupPanel popup = new PopupPanel(); popup.setHeight("4096px"); popup.setWidth("4096px"); popup.setWidget(new Label("foo")); popup.center(); assertEquals(0, popup.getAbsoluteTop()); assertEquals(0, popup.getAbsoluteLeft()); } /** * Issue 2463: If a {@link PopupPanel} contains a dependent {@link PopupPanel} * that is hidden or shown in the onDetach or onAttach method, we could run * into conflicts with the animations. The {@link MenuBar} exhibits this * behavior because, when we detach a {@link MenuBar} from the page, it closes * all of its sub menus, each located in a different {@link PopupPanel}. */ @DoNotRunWith(Platform.HtmlUnitUnknown) public void testDependantPopupPanel() { // Create the dependent popup final PopupPanel dependantPopup = createPopupPanel(); dependantPopup.setAnimationEnabled(true); // Create the primary popup final PopupPanel primaryPopup = new PopupPanel(false, false) { @Override protected void onAttach() { dependantPopup.show(); super.onAttach(); } @Override protected void onDetach() { dependantPopup.hide(); super.onDetach(); } }; primaryPopup.setAnimationEnabled(true); testDependantPopupPanel(primaryPopup); } public void testGlassPanelDisabled() { // Verify that the glass is disabled by default PopupPanel popup = createPopupPanel(); assertFalse(popup.isGlassEnabled()); assertNull(popup.getGlassElement()); // Verify the glass panel is never created popup.show(); assertNull(popup.getGlassElement()); popup.hide(); } public void testGlassDisabledWhileShowing() { // Show the popup and glass panel PopupPanel popup = createPopupPanel(); popup.setGlassEnabled(true); Element glass = popup.getGlassElement(); popup.show(); // Disable the glass panel and hide the popup popup.setGlassEnabled(false); assertTrue(isAttached(glass)); popup.hide(); assertFalse(isAttached(glass)); // Show the popup and verify that glass is no longer used popup.show(); assertFalse(isAttached(glass)); popup.hide(); } public void testGlassEnabled() { // Verify that the glass is disabled by default PopupPanel popup = createPopupPanel(); assertFalse(popup.isGlassEnabled()); assertNull(popup.getGlassElement()); // Enable the glass panel and verify it is created popup.setGlassEnabled(true); Element glass = popup.getGlassElement(); assertNotNull(glass); assertFalse(isAttached(glass)); // Show the popup and verify the glass panel is added popup.show(); assertTrue(isAttached(glass)); // Hide the popup and verify the glass panel is removed popup.hide(); assertFalse(isAttached(glass)); } public void testGlassEnabledWhileShowing() { // Verify that the glass is disabled by default PopupPanel popup = createPopupPanel(); assertFalse(popup.isGlassEnabled()); assertNull(popup.getGlassElement()); // Show the popup and enable the glass panel popup.show(); popup.setGlassEnabled(true); Element glass = popup.getGlassElement(); assertNotNull(glass); assertFalse(isAttached(glass)); // Hide the popup and verify the glass panel is removed popup.hide(); assertFalse(isAttached(glass)); // Show the popup and verify the glas is now used popup.show(); assertTrue(isAttached(glass)); popup.hide(); } /** * Test the hiding a popup while it is showing will not result in an illegal * state. */ public void testHideWhileShowing() { PopupPanel popup = createPopupPanel(); // Start showing the popup. popup.setAnimationEnabled(true); popup.show(); assertTrue(popup.isShowing()); // Hide the popup while its showing. popup.hide(); assertFalse(popup.isShowing()); } /** * Test that the onLoad method is only called once when showing the popup. */ public void testOnLoad() { TestablePopupPanel popup = new TestablePopupPanel(); // show() without animation { popup.setAnimationEnabled(false); popup.show(); popup.assertOnLoadCount(1); popup.hide(); } // show() with animation { popup.setAnimationEnabled(true); popup.show(); popup.assertOnLoadCount(2); popup.hide(); } // center() without animation { popup.setAnimationEnabled(false); popup.center(); popup.assertOnLoadCount(3); popup.hide(); } // center() with animation { popup.setAnimationEnabled(true); popup.center(); popup.assertOnLoadCount(4); popup.hide(); } } public void testPopup() { // Get rid of window margins so we can test absolute position. Window.setMargin("0px"); PopupPanel popup = createPopupPanel(); popup.setAnimationEnabled(false); Label lbl = new Label("foo"); // Make sure that setting the popup's size & position works _before_ // setting its widget. popup.setSize("384px", "128px"); popup.setPopupPosition(128, 64); popup.setWidget(lbl); popup.show(); // DecoratorPanel adds width and height because it wraps the content in a // 3x3 table. assertTrue("Expected >= 384, got " + popup.getOffsetWidth(), popup.getOffsetWidth() >= 384); assertTrue("Expected >= 128, got " + popup.getOffsetHeight(), popup.getOffsetHeight() >= 128); assertEquals(128, popup.getPopupLeft()); assertEquals(64, popup.getPopupTop()); // Make sure that the popup returns to the correct position // after hiding and showing it. popup.hide(); popup.show(); assertEquals(128, popup.getPopupLeft()); assertEquals(64, popup.getPopupTop()); // Make sure that setting the popup's size & position works _after_ // setting its widget (and that clearing its size properly resizes it to // its widget's size). popup.setSize("", ""); popup.setPopupPosition(16, 16); // DecoratorPanel adds width and height because it wraps the content in a // 3x3 table. assertTrue(popup.getOffsetWidth() >= lbl.getOffsetWidth()); assertTrue(popup.getOffsetWidth() >= lbl.getOffsetHeight()); assertEquals(16, popup.getAbsoluteLeft()); assertEquals(16, popup.getAbsoluteTop()); // Ensure that hiding the popup fires the appropriate events. delayTestFinish(1000); popup.addCloseHandler(new CloseHandler<PopupPanel>() { public void onClose(CloseEvent<PopupPanel> event) { finishTest(); } }); popup.hide(); } /** * Issue 4720: Glass is not removed when removeFromParent is called. */ public void testRemoveFromParent() { PopupPanel popup = createPopupPanel(); popup.setGlassEnabled(true); assertNull(popup.getGlassElement().getParentElement()); popup.show(); assertNotNull(popup.getGlassElement().getParentElement()); popup.removeFromParent(); assertNull(popup.getGlassElement().getParentElement()); } public void testSeparateContainers() { TestablePopupPanel p1 = new TestablePopupPanel(); TestablePopupPanel p2 = new TestablePopupPanel(); assertTrue(p1.getContainerElement() != null); assertTrue(p2.getContainerElement() != null); assertFalse(p1.getContainerElement() == p2.getContainerElement()); } /** * Issue 2481: Try to set the contents of the popup while the popup is * attached. When we hide the popup, this should not leave the popup in an * invalid attach state. */ public void testSetWidgetWhileAttached() { PopupPanel popup = createPopupPanel(); popup.show(); popup.setWidget(new Label("test")); popup.hide(); } public void testSetVisibleWithGlass() { PopupPanel popup = createPopupPanel(); popup.setGlassEnabled(true); popup.show(); Element glass = popup.getGlassElement(); assertTrue(popup.isVisible()); assertFalse("hidden".equalsIgnoreCase(glass.getStyle().getVisibility())); popup.setVisible(false); assertFalse(popup.isVisible()); assertTrue("hidden".equalsIgnoreCase(glass.getStyle().getVisibility())); popup.setVisible(true); assertTrue(popup.isVisible()); assertFalse("hidden".equalsIgnoreCase(glass.getStyle().getVisibility())); popup.hide(); } /** * Test that showing a popup while it is attached does not put it in an * invalid state. */ public void testShowWhileAttached() { PopupPanel popup = createPopupPanel(); RootPanel.get().add(popup); popup.show(); assertTrue(popup.isAttached()); assertTrue(popup.isShowing()); popup.hide(); assertFalse(popup.isAttached()); assertFalse(popup.isShowing()); } /** * Test that showing a popup while it is hiding will not result in an illegal * state. */ public void testShowWhileHiding() { PopupPanel popup = createPopupPanel(); // Show the popup popup.setAnimationEnabled(false); popup.show(); assertTrue(popup.isShowing()); // Start hiding the popup popup.setAnimationEnabled(true); popup.hide(); assertFalse(popup.isShowing()); // Show the popup while its hiding popup.show(); assertTrue(popup.isShowing()); } /** * Create a new PopupPanel. */ protected PopupPanel createPopupPanel() { return new PopupPanel(); } @Override protected void gwtTearDown() { RootPanel.get().clear(); } /** * @see #testDependantPopupPanel() */ protected void testDependantPopupPanel(final PopupPanel primaryPopup) { // Show the popup primaryPopup.show(); // Hide the popup new Timer() { @Override public void run() { primaryPopup.hide(); } }.schedule(1000); delayTestFinish(5000); // Give time for any errors to occur new Timer() { @Override public void run() { finishTest(); } }.schedule(2000); } private boolean isAttached(Element elem) { return Document.get().getBody().isOrHasChild(elem); } }