aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java89
-rw-r--r--client/src/com/vaadin/client/Util.java55
-rw-r--r--client/src/com/vaadin/client/ui/VPanel.java44
-rw-r--r--client/src/com/vaadin/client/ui/VTabsheet.java3
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java32
-rw-r--r--client/src/com/vaadin/client/ui/ui/UIConnector.java25
-rw-r--r--liferay/build.xml6
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltip.java60
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltipTest.java81
-rw-r--r--uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindow.java66
-rw-r--r--uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java57
-rw-r--r--uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java56
-rw-r--r--uitest/tb3test.xml9
-rw-r--r--uitest/test.xml10
14 files changed, 472 insertions, 121 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 08c755ef79..da41543894 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Logger;
import com.google.gwt.aria.client.LiveValue;
import com.google.gwt.aria.client.RelevantValue;
@@ -64,6 +65,7 @@ import com.google.gwt.user.client.Window.ClosingHandler;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ApplicationConfiguration.ErrorMessage;
+import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent;
import com.vaadin.client.ResourceLoader.ResourceLoadEvent;
import com.vaadin.client.ResourceLoader.ResourceLoadListener;
import com.vaadin.client.communication.HasJavaScriptConnectorHelper;
@@ -290,7 +292,7 @@ public class ApplicationConnection {
}
@Override
- public com.google.gwt.event.shared.GwtEvent.Type<CommunicationHandler> getAssociatedType() {
+ public Type<CommunicationHandler> getAssociatedType() {
return TYPE;
}
@@ -310,7 +312,7 @@ public class ApplicationConnection {
}
@Override
- public com.google.gwt.event.shared.GwtEvent.Type<CommunicationHandler> getAssociatedType() {
+ public Type<CommunicationHandler> getAssociatedType() {
return TYPE;
}
@@ -345,7 +347,7 @@ public class ApplicationConnection {
public static Type<CommunicationHandler> TYPE = new Type<CommunicationHandler>();
@Override
- public com.google.gwt.event.shared.GwtEvent.Type<CommunicationHandler> getAssociatedType() {
+ public Type<CommunicationHandler> getAssociatedType() {
return TYPE;
}
@@ -356,6 +358,34 @@ public class ApplicationConnection {
}
/**
+ * Event triggered when a application is stopped by calling
+ * {@link ApplicationConnection#setApplicationRunning(false)}.
+ *
+ * To listen for the event add a {@link ApplicationStoppedHandler} by
+ * invoking
+ * {@link ApplicationConnection#addHandler(ApplicationStoppedEvent.Type, ApplicationStoppedHandler)}
+ * to the {@link ApplicationConnection}
+ *
+ * @since 7.1.8
+ * @author Vaadin Ltd
+ */
+ public static class ApplicationStoppedEvent extends
+ GwtEvent<ApplicationStoppedHandler> {
+
+ public static Type<ApplicationStoppedHandler> TYPE = new Type<ApplicationStoppedHandler>();
+
+ @Override
+ public Type<ApplicationStoppedHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ @Override
+ protected void dispatch(ApplicationStoppedHandler listener) {
+ listener.onApplicationStopped(this);
+ }
+ }
+
+ /**
* Allows custom handling of communication errors.
*/
public interface CommunicationErrorHandler {
@@ -373,6 +403,27 @@ public class ApplicationConnection {
public boolean onError(String details, int statusCode);
}
+ /**
+ * A listener for listening to application stopped events. The listener can
+ * be added to a {@link ApplicationConnection} by invoking
+ * {@link ApplicationConnection#addHandler(ApplicationStoppedEvent.Type, ApplicationStoppedHandler)}
+ *
+ * @since 7.1.8
+ * @author Vaadin Ltd
+ */
+ public interface ApplicationStoppedHandler extends EventHandler {
+
+ /**
+ * Triggered when the {@link ApplicationConnection} marks a previously
+ * running application as stopped by invoking
+ * {@link ApplicationConnection#setApplicationRunning(false)}
+ *
+ * @param event
+ * the event triggered by the {@link ApplicationConnection}
+ */
+ void onApplicationStopped(ApplicationStoppedEvent event);
+ }
+
private CommunicationErrorHandler communicationErrorDelegate = null;
private VLoadingIndicator loadingIndicator;
@@ -756,6 +807,10 @@ public class ApplicationConnection {
showCommunicationError(details, statusCode);
}
endRequest();
+
+ // Consider application not running any more and prevent all
+ // future requests
+ setApplicationRunning(false);
}
@Override
@@ -887,10 +942,10 @@ public class ApplicationConnection {
VConsole.log("JSON parsing took "
+ (new Date().getTime() - start.getTime()) + "ms");
- if (applicationRunning) {
+ if (isApplicationRunning()) {
handleReceivedJSONMessage(start, jsonText, json);
} else {
- applicationRunning = true;
+ setApplicationRunning(true);
handleWhenCSSLoaded(jsonText, json);
}
}
@@ -1149,7 +1204,7 @@ public class ApplicationConnection {
retryCanceledActiveRequest = false;
webkitMaybeIgnoringRequests = false;
- if (applicationRunning) {
+ if (isApplicationRunning()) {
checkForPendingVariableBursts();
runPostRequestHooks(configuration.getRootPanelId());
}
@@ -1499,7 +1554,7 @@ public class ApplicationConnection {
error.getString("message"),
error.getString("url"));
- applicationRunning = false;
+ setApplicationRunning(false);
}
Profiler.leave("Error handling");
}
@@ -2422,6 +2477,12 @@ public class ApplicationConnection {
*/
public void addMethodInvocationToQueue(MethodInvocation invocation,
boolean delayed, boolean lastOnly) {
+ if (!isApplicationRunning()) {
+ getLogger()
+ .warning(
+ "Trying to invoke method on not yet started or stopped application");
+ return;
+ }
String tag;
if (lastOnly) {
tag = invocation.getLastOnlyTag();
@@ -2480,7 +2541,7 @@ public class ApplicationConnection {
private boolean deferedSendPending = false;
private void doSendPendingVariableChanges() {
- if (applicationRunning) {
+ if (isApplicationRunning()) {
if (hasActiveRequest() || (push != null && !push.isActive())) {
// skip empty queues if there are pending bursts to be sent
if (pendingInvocations.size() > 0 || pendingBursts.size() == 0) {
@@ -2492,6 +2553,11 @@ public class ApplicationConnection {
} else {
buildAndSendVariableBurst(pendingInvocations);
}
+ } else {
+ getLogger()
+ .warning(
+ "Trying to send variable changes from not yet started or stopped application");
+ return;
}
}
@@ -3393,6 +3459,9 @@ public class ApplicationConnection {
}
public void setApplicationRunning(boolean running) {
+ if (applicationRunning && !running) {
+ eventBus.fireEvent(new ApplicationStoppedEvent());
+ }
applicationRunning = running;
}
@@ -3495,4 +3564,8 @@ public class ApplicationConnection {
}
}
+ private static Logger getLogger() {
+ return Logger.getLogger(ApplicationConnection.class.getName());
+ }
+
}
diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java
index 8972670232..8a5712215d 100644
--- a/client/src/com/vaadin/client/Util.java
+++ b/client/src/com/vaadin/client/Util.java
@@ -32,6 +32,7 @@ import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
+import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
@@ -518,6 +519,60 @@ public class Util {
}
/**
+ * Prevents some browsers from adding scroll bars to a component (such as a
+ * Window) whose contents fit in the component.
+ * <p>
+ * See: bugs #11994 and #12736.
+ *
+ * @param contentNode
+ * an element that contains a scrollable element as its first
+ * child
+ *
+ * @since 7.1.8
+ */
+ public static void removeUnneededScrollbars(final Element contentNode) {
+ if (BrowserInfo.get().isWebkit()) {
+
+ /*
+ * Shake up the DOM a bit to make the window shed unnecessary
+ * scrollbars and resize correctly afterwards. This resulting code
+ * took over a week to summon forth, and involved some pretty hairy
+ * black magic. Don't touch it unless you know what you're doing!
+ * Fixes ticket #11994. Later modified to fix ticket #12736.
+ */
+ Scheduler.get().scheduleFinally(new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ final com.google.gwt.dom.client.Element scrollable = contentNode
+ .getFirstChildElement();
+
+ // Adjusting the width or height may change the scroll
+ // position, so store the current position
+ int horizontalScrollPosition = scrollable.getScrollLeft();
+ int verticalScrollPosition = scrollable.getScrollTop();
+
+ final String oldWidth = scrollable.getStyle().getWidth();
+ final String oldHeight = scrollable.getStyle().getHeight();
+
+ scrollable.getStyle().setWidth(110, Unit.PCT);
+ scrollable.getStyle().setHeight(110, Unit.PCT);
+ scrollable.getOffsetWidth();
+ scrollable.getOffsetHeight();
+ scrollable.getStyle().setProperty("width", oldWidth);
+ scrollable.getStyle().setProperty("height", oldHeight);
+
+ // Restore the scroll position
+ scrollable.setScrollLeft(horizontalScrollPosition);
+ scrollable.setScrollTop(verticalScrollPosition);
+
+ }
+ });
+
+ }
+ }
+
+ /**
* Parses shared state and fetches the relative size of the component. If a
* dimension is not specified as relative it will return -1. If the shared
* state does not contain width or height specifications this will return
diff --git a/client/src/com/vaadin/client/ui/VPanel.java b/client/src/com/vaadin/client/ui/VPanel.java
index 15c3883b11..307a2e4a91 100644
--- a/client/src/com/vaadin/client/ui/VPanel.java
+++ b/client/src/com/vaadin/client/ui/VPanel.java
@@ -16,18 +16,15 @@
package com.vaadin.client.ui;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
-import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.SimplePanel;
import com.vaadin.client.ApplicationConnection;
-import com.vaadin.client.BrowserInfo;
import com.vaadin.client.Focusable;
+import com.vaadin.client.Util;
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
@@ -210,43 +207,6 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
}
touchScrollHandler.addElement(contentNode);
-
- /*
- * Shake up the DOM a bit to make the window shed unnecessary scroll
- * bars and resize correctly afterwards. This resulting code took over a
- * week to summon forth, and involved some pretty hairy black magic.
- * Don't touch it unless you know what you're doing! Fixes ticket
- * #12727.
- *
- * This solution comes from the ticket #11994: Windows get unnecessary
- * scroll bars in WebKit when content is 100% wide.
- */
- if (BrowserInfo.get().isWebkit()) {
- Scheduler.get().scheduleFinally(new ScheduledCommand() {
- @Override
- public void execute() {
- final com.google.gwt.dom.client.Element scrollable = contentNode
- .getFirstChildElement();
-
- int contentNodeScrollTop = contentNode.getScrollTop();
- int contentNodeScrollLeft = contentNode.getScrollLeft();
-
- final String oldWidth = scrollable.getStyle().getWidth();
- final String oldHeight = scrollable.getStyle().getHeight();
-
- scrollable.getStyle().setWidth(110, Unit.PCT);
- scrollable.getOffsetWidth();
- scrollable.getStyle().setProperty("width", oldWidth);
-
- scrollable.getStyle().setHeight(110, Unit.PCT);
- scrollable.getOffsetHeight();
- scrollable.getStyle().setProperty("height", oldHeight);
-
- // Recovering scroll position:
- contentNode.setScrollTop(contentNodeScrollTop);
- contentNode.setScrollLeft(contentNodeScrollLeft);
- }
- });
- }
+ Util.removeUnneededScrollbars(contentNode);
}
}
diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java
index 04cd9c09ba..9ad518b85b 100644
--- a/client/src/com/vaadin/client/ui/VTabsheet.java
+++ b/client/src/com/vaadin/client/ui/VTabsheet.java
@@ -324,7 +324,8 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
public boolean updateCaption(UIDL uidl) {
- if (uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION)) {
+ if (uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION)
+ || uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE)) {
setTooltipInfo(new TooltipInfo(
uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION),
uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE)));
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index 03ad8d03c8..6a1a2e547b 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -536,36 +536,10 @@ public class VWindow extends VWindowOverlay implements
if (!visibilityChangesDisabled) {
super.setVisible(visible);
}
-
if (visible && BrowserInfo.get().isWebkit()) {
-
- /*
- * Shake up the DOM a bit to make the window shed unnecessary
- * scrollbars and resize correctly afterwards. This resulting code
- * took over a week to summon forth, and involved some pretty hairy
- * black magic. Don't touch it unless you know what you're doing!
- * Fixes ticket #11994
- */
- Scheduler.get().scheduleFinally(new ScheduledCommand() {
- @Override
- public void execute() {
- final com.google.gwt.dom.client.Element scrollable = contents
- .getFirstChildElement();
- final String oldWidth = scrollable.getStyle().getWidth();
- final String oldHeight = scrollable.getStyle().getHeight();
-
- scrollable.getStyle().setWidth(110, Unit.PCT);
- scrollable.getOffsetWidth();
- scrollable.getStyle().setProperty("width", oldWidth);
-
- scrollable.getStyle().setHeight(110, Unit.PCT);
- scrollable.getOffsetHeight();
- scrollable.getStyle().setProperty("height", oldHeight);
-
- updateContentsSize();
- positionOrSizeUpdated();
- }
- });
+ Util.removeUnneededScrollbars(contents);
+ updateContentsSize();
+ positionOrSizeUpdated();
}
}
diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java
index 903a2cc3fb..2a4a9824d8 100644
--- a/client/src/com/vaadin/client/ui/ui/UIConnector.java
+++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java
@@ -45,6 +45,7 @@ import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.HandlerRegistration;
import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent;
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
@@ -316,7 +317,8 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
.getPaintableAttribute("focused", getConnection());
if (paintable == null) {
- // Do not try to focus invisible components which not present in UIDL
+ // Do not try to focus invisible components which not
+ // present in UIDL
return;
}
@@ -463,6 +465,21 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
// side-effects from focusing (scrollIntoView).
getWidget().getElement().focus();
}
+
+ applicationConnection.addHandler(
+ ApplicationConnection.ApplicationStoppedEvent.TYPE,
+ new ApplicationConnection.ApplicationStoppedHandler() {
+
+ @Override
+ public void onApplicationStopped(
+ ApplicationStoppedEvent event) {
+ // Stop any polling
+ if (pollTimer != null) {
+ pollTimer.cancel();
+ pollTimer = null;
+ }
+ }
+ });
}
private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
@@ -687,6 +704,12 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
pollTimer = new Timer() {
@Override
public void run() {
+ if (getState().pollInterval < 0) {
+ // Polling has been cancelled server side
+ pollTimer.cancel();
+ pollTimer = null;
+ return;
+ }
getRpcProxy(UIServerRpc.class).poll();
// Send changes even though poll is @Delayed
getConnection().sendPendingVariableChanges();
diff --git a/liferay/build.xml b/liferay/build.xml
index a13cb37366..fc1d748e55 100644
--- a/liferay/build.xml
+++ b/liferay/build.xml
@@ -69,4 +69,8 @@
<antcall target="common.clean" />
</target>
-</project> \ No newline at end of file
+ <target name="checkstyle" />
+
+ <target name="test" depends="checkstyle" />
+
+</project>
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltip.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltip.java
new file mode 100644
index 0000000000..02482b7049
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltip.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.tabsheet;
+
+import com.vaadin.server.UserError;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.TabSheet.Tab;
+
+public class TabSheetErrorTooltip extends AbstractTestUI {
+
+ private TabSheet tabSheet = new TabSheet();
+ private int tabCount = 0;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ addTab();
+ addTab().setComponentError(new UserError("Error!"));
+ addTab().setDescription("This is a tab");
+
+ Tab t = addTab();
+ t.setComponentError(new UserError("Error!"));
+ t.setDescription("This tab has both an error and a description");
+
+ setContent(tabSheet);
+ }
+
+ private Tab addTab() {
+ tabCount++;
+ Label contents = new Label("Contents for tab " + tabCount);
+ return tabSheet.addTab(contents, "Tab " + tabCount);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "TabSheet Tabs should display component error tooltips when expected";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 12802;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltipTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltipTest.java
new file mode 100644
index 0000000000..88bc23d12b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetErrorTooltipTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.tabsheet;
+
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TabSheetErrorTooltipTest extends MultiBrowserTest {
+
+ @Test
+ public void checkTooltips() throws IOException {
+ openTestURL();
+
+ testBenchElement(getTab(0)).showTooltip();
+ assertNoTooltip();
+
+ testBenchElement(getTab(1)).showTooltip();
+ assertErrorMessage("Error!");
+ assertTooltip("");
+
+ testBenchElement(getTab(2)).showTooltip();
+ assertErrorMessage("");
+ assertTooltip("This is a tab");
+
+ testBenchElement(getTab(3)).showTooltip();
+ assertErrorMessage("Error!");
+ assertTooltip("This tab has both an error and a description");
+ }
+
+ private WebElement getTab(int index) {
+ return vaadinElement("/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild["
+ + index + "]/domChild[0]");
+ }
+
+ private WebElement getTooltip() {
+ return getDriver().findElement(
+ By.xpath("//div[@class='v-tooltip-text']"));
+ }
+
+ private WebElement getErrorMessage() {
+ return getDriver().findElement(
+ By.xpath("//div[@class='v-errormessage']"));
+ }
+
+ private void assertTooltip(String tooltip) {
+ Assert.assertEquals(tooltip, getTooltip().getText());
+ }
+
+ private void assertErrorMessage(String message) {
+ Assert.assertEquals(message, getErrorMessage().getText());
+ }
+
+ private void assertNoTooltip() {
+ try {
+ getTooltip();
+ } catch (NoSuchElementException e) {
+ return;
+ }
+ Assert.fail("Tooltip exists");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindow.java b/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindow.java
new file mode 100644
index 0000000000..6347ff9a76
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindow.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.window;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+/**
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class ComboboxScrollableWindow extends AbstractTestUI {
+
+ static final String WINDOW_ID = "window";
+ static final String COMBOBOX_ID = "combobox";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ Window w = new Window();
+ w.setId(WINDOW_ID);
+ w.setWidth("300px");
+ w.setHeight("300px");
+ w.center();
+
+ VerticalLayout content = new VerticalLayout();
+ w.setContent(content);
+ content.setHeight("1000px");
+ ComboBox cb = new ComboBox();
+ cb.setId(COMBOBOX_ID);
+ content.addComponent(cb);
+ content.setComponentAlignment(cb, Alignment.BOTTOM_CENTER);
+
+ addWindow(w);
+
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "The combo box in the bottom of the scrollable window should remain visible when it is clicked.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 12736;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java b/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java
new file mode 100644
index 0000000000..665e175f2c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/ComboboxScrollableWindowTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * 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.vaadin.tests.components.window;
+
+import static com.vaadin.tests.components.window.ComboboxScrollableWindow.COMBOBOX_ID;
+import static com.vaadin.tests.components.window.ComboboxScrollableWindow.WINDOW_ID;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.commands.TestBenchElementCommands;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class ComboboxScrollableWindowTest extends MultiBrowserTest {
+
+ @Test
+ public void testWindowScrollbars() throws Exception {
+ openTestURL();
+ com.vaadin.testbench.Parameters
+ .setScreenshotComparisonCursorDetection(true);
+
+ WebElement window = driver.findElement(By.id(WINDOW_ID));
+ WebElement scrollableElement = window.findElement(By
+ .className("v-scrollable"));
+ TestBenchElementCommands scrollable = testBenchElement(scrollableElement);
+ scrollable.scroll(1000);
+ WebElement comboBox = driver.findElement(By.id(COMBOBOX_ID));
+ WebElement selectButton = driver.findElement(By
+ .className("v-filterselect-button"));
+ selectButton.click();
+
+ // Wait for the browser before taking a screenshot
+ Thread.sleep(1000);
+ compareScreen(getScreenshotBaseName());
+
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java
index cbdae1a6c1..a51421d3d5 100644
--- a/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java
+++ b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java
@@ -31,7 +31,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.remote.DesiredCapabilities;
@@ -62,18 +61,7 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
String className = testClass.getSimpleName();
screenshotBaseName = className + "-" + testMethod;
- }
-
- @Override
- protected void failed(Throwable e, Description description) {
-
- // Notify Teamcity of failed test
- if (!System.getProperty("teamcity.version", "").equals("")) {
- System.out.print("##teamcity[publishArtifacts '");
- System.out.println(getScreenshotErrorBaseName()
- + "* => screenshot-errors']");
- }
- }
+ };
};
/**
@@ -129,9 +117,28 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
// Matched one comparison but not all, remove all error images +
// HTML files
} else {
- // All comparisons failed, keep the main error image + HTML
- screenshotFailures.add(mainReference.getName());
- referenceToKeep = mainReference;
+ // Ensure we use the correct browser version (e.g. if running IE11
+ // and only an IE 10 reference was available, then mainReference
+ // will be for IE 10, not 11)
+ String originalName = getScreenshotReferenceName(identifier);
+ File exactVersionFile = new File(originalName);
+
+ if (!exactVersionFile.equals(mainReference)) {
+ // Rename png+html to have the correct version
+ File correctPng = getErrorFileFromReference(exactVersionFile);
+ File producedPng = getErrorFileFromReference(mainReference);
+ File correctHtml = htmlFromPng(correctPng);
+ File producedHtml = htmlFromPng(producedPng);
+
+ producedPng.renameTo(correctPng);
+ producedHtml.renameTo(correctHtml);
+ referenceToKeep = exactVersionFile;
+ screenshotFailures.add(exactVersionFile.getName());
+ } else {
+ // All comparisons failed, keep the main error image + HTML
+ screenshotFailures.add(mainReference.getName());
+ referenceToKeep = mainReference;
+ }
}
// Remove all PNG/HTML files we no longer need (failed alternative
@@ -140,10 +147,7 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
File failurePng = getErrorFileFromReference(failedAlternative);
if (failedAlternative != referenceToKeep) {
// Delete png + HTML
- String htmlFileName = failurePng.getName().replace(".png",
- ".html");
- File failureHtml = new File(failurePng.getParentFile(),
- htmlFileName);
+ File failureHtml = htmlFromPng(failurePng);
failurePng.delete();
failureHtml.delete();
@@ -152,6 +156,18 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
}
/**
+ * Returns a new File which points to a .html file instead of the given .png
+ * file
+ *
+ * @param png
+ * @return
+ */
+ private static File htmlFromPng(File png) {
+ return new File(png.getParentFile(), png.getName().replaceAll(
+ "\\.png$", ".png.html"));
+ }
+
+ /**
*
* @param referenceFile
* The reference image file (in the directory defined by
diff --git a/uitest/tb3test.xml b/uitest/tb3test.xml
index 5285280608..dd0c12db91 100644
--- a/uitest/tb3test.xml
+++ b/uitest/tb3test.xml
@@ -19,21 +19,12 @@
<target name="run-tb3-suite">
<fail unless="junit.test.suite" message="Define suite to run using junit.test.suite" />
<fail unless="com.vaadin.testbench.screenshot.directory" message="Define screenshot directory using -Dcom.vaadin.testbench.screenshot.directory" />
-
- <!-- Ensure teamcity.version is set to something -->
- <condition property="teamcity.version" value="">
- <not>
- <isset property="teamcity.version" />
- </not>
- </condition>
-
<junit printsummary="withOutAndErr" fork="yes">
<formatter usefile="false" type="plain" />
<classpath refid="classpath.tb3" />
<jvmarg value="-Dcom.vaadin.testbench.screenshot.directory=${com.vaadin.testbench.screenshot.directory}" />
<jvmarg value="-Djava.awt.headless=true" />
- <jvmarg value="-Dteamcity.version=${teamcity.version}" />
<test name="${junit.test.suite}" />
</junit>
diff --git a/uitest/test.xml b/uitest/test.xml
index 3bfeb66c05..b0db8d47f4 100644
--- a/uitest/test.xml
+++ b/uitest/test.xml
@@ -134,18 +134,8 @@
</batchtest>
</junit>
- <antcall target="notify-teamcity-of-build-artifact">
- <param name="file" value="${target}" />
- </antcall>
-
</target>
- <!-- Have teamcity publish each test error artifact immediatly if there are any -->
- <target name="notify-teamcity-of-build-artifact" if="teamcity.version">
- <basename property="basename" file="${file}" suffix="java" />
- <echo>##teamcity[publishArtifacts '${com.vaadin.testbench.screenshot.directory}/errors/${basename}* => screenshot-errors']</echo>
- </target>
-
<!-- Remove temporary source and compiled java files -->
<target name="remove-temp-testclasses">
<delete failonerror="false">