summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonatan Kronqvist <jonatan@vaadin.com>2014-02-07 15:46:30 +0200
committerJonatan Kronqvist <jonatan@vaadin.com>2014-02-07 15:46:30 +0200
commit0e8500a5af0c4924d4a164bbd548128cf474b203 (patch)
tree8453e88b1c777d0a4ac28e6cad9a61de16aed785
parent2659a54ebed8af66dce22b27d3ea285d1c8eb221 (diff)
parent407bdb39f7d87acaf15c399e46baf6d6a858fa6d (diff)
downloadvaadin-framework-0e8500a5af0c4924d4a164bbd548128cf474b203.tar.gz
vaadin-framework-0e8500a5af0c4924d4a164bbd548128cf474b203.zip
Merge changes from origin/7.1
8245079 Decrease the websocket buffer size due to a Jetty 9.1 issue (#13087) ea8f381 Show the widgetset name to more easily spot misconfigurations 797ebdf Allow user to override Atmosphere init params set by Vaadin (#13088) 65c2f2b Properly remove shadow event listeners to prevent IE8 memory leak (#13129) e9a547a Fixed spelling mistake in log message. 0b95f8d Moved selection of selected rows in TableConnector to occur after the new rows are created (#13008) 0579fba Upload control with empty selection (#9602) db4dba4 Ensure event listener is a widget before casting #13130 5e8e866 Changes padding for Textfields with Chameleon theme. (#12974) 171e68d Only use ClientRcp and ServerRpc types that are interfaces (#13056) e41a2ce Add helper for adding multiple components to AbstractTestUI 407bdb3 Ignores scroll events while update from server is in progress (#11454) Change-Id: I5d21b4071165b02da0f53bd055fb1c64e90cae5b
-rw-r--r--WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss7
-rw-r--r--client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java8
-rw-r--r--client/src/com/vaadin/client/Util.java2
-rw-r--r--client/src/com/vaadin/client/ui/UnknownComponentConnector.java6
-rw-r--r--client/src/com/vaadin/client/ui/VOverlay.java4
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java38
-rw-r--r--client/src/com/vaadin/client/ui/VUpload.java7
-rw-r--r--client/src/com/vaadin/client/ui/table/TableConnector.java6
-rw-r--r--client/src/com/vaadin/client/ui/upload/UploadConnector.java14
-rw-r--r--server/src/com/vaadin/server/communication/PushRequestHandler.java14
-rw-r--r--server/src/com/vaadin/server/communication/ServerRpcHandler.java2
-rw-r--r--server/src/com/vaadin/ui/Upload.java14
-rw-r--r--shared/src/com/vaadin/shared/communication/PushConstants.java5
-rw-r--r--shared/src/com/vaadin/shared/ui/upload/UploadClientRpc.java26
-rw-r--r--uitest/src/com/vaadin/tests/components/AbstractTestUI.java4
-rw-r--r--uitest/src/com/vaadin/tests/components/table/ExpandingContainer.java429
-rw-r--r--uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceCondition.java67
-rw-r--r--uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceConditionTest.java90
-rw-r--r--uitest/src/com/vaadin/tests/components/table/SelectAllRows.java83
-rw-r--r--uitest/src/com/vaadin/tests/components/table/SelectAllRowsTest.java105
-rw-r--r--uitest/src/com/vaadin/tests/components/upload/UploadNoSelection.java83
-rw-r--r--uitest/src/com/vaadin/tests/components/upload/UploadNoSelectionTest.java56
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassConnector.java36
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassWidget.java33
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClass.java47
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassComponent.java29
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassTest.java35
27 files changed, 1216 insertions, 34 deletions
diff --git a/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss b/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss
index 3962ba9ccd..4554672da4 100644
--- a/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss
+++ b/WebContent/VAADIN/themes/chameleon/components/textfield/textfield.scss
@@ -20,7 +20,10 @@ textarea.v-textarea,
input.#{$primaryStyleName}[type="text"],
textarea.v-textarea,
.v-filterselect {
- padding: .1em;
+ padding-bottom: .1em;
+ padding-top: .1em;
+ padding-left: .2em;
+ padding-right: .2em;
}
input.#{$primaryStyleName}[type="text"] {
@@ -29,7 +32,7 @@ input.#{$primaryStyleName}[type="text"] {
input.v-widget.#{$primaryStyleName}[type="text"],
.v-filterselect {
- height: 1.6em;
+ height: 1.7em;
}
&.v-app input.#{$primaryStyleName},
diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java
index cbdd3e89aa..4d6a7ff6d7 100644
--- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java
+++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java
@@ -430,11 +430,11 @@ public class ConnectorBundle {
}
private static boolean isClientRpc(JClassType type) {
- return isType(type, ClientRpc.class);
+ return isInterfaceType(type, ClientRpc.class);
}
private static boolean isServerRpc(JClassType type) {
- return isType(type, ServerRpc.class);
+ return isInterfaceType(type, ServerRpc.class);
}
public static boolean isConnectedConnector(JClassType type) {
@@ -451,6 +451,10 @@ public class ConnectorBundle {
return isConnected(type) && isType(type, ComponentConnector.class);
}
+ private static boolean isInterfaceType(JClassType type, Class<?> class1) {
+ return type.isInterface() != null && isType(type, class1);
+ }
+
private static boolean isType(JClassType type, Class<?> class1) {
try {
return type.getOracle().getType(class1.getName())
diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java
index 8972670232..55d3d13c19 100644
--- a/client/src/com/vaadin/client/Util.java
+++ b/client/src/com/vaadin/client/Util.java
@@ -866,7 +866,7 @@ public class Util {
element = (Element) element.getParentElement();
}
}
- if (eventListener != null) {
+ if (eventListener instanceof Widget) {
/*
* Then find the first widget of type class1 from widget
* hierarchy
diff --git a/client/src/com/vaadin/client/ui/UnknownComponentConnector.java b/client/src/com/vaadin/client/ui/UnknownComponentConnector.java
index ca461eb640..b9b0388d9a 100644
--- a/client/src/com/vaadin/client/ui/UnknownComponentConnector.java
+++ b/client/src/com/vaadin/client/ui/UnknownComponentConnector.java
@@ -16,6 +16,8 @@
package com.vaadin.client.ui;
+import com.google.gwt.core.client.GWT;
+
public class UnknownComponentConnector extends AbstractComponentConnector {
@Override
@@ -31,7 +33,9 @@ public class UnknownComponentConnector extends AbstractComponentConnector {
public void setServerSideClassName(String serverClassName) {
getWidget()
.setCaption(
- "Widgetset does not contain implementation for "
+ "Widgetset '"
+ + GWT.getModuleName()
+ + "' does not contain implementation for "
+ serverClassName
+ ". Check its component connector's @Connect mapping, widgetsets "
+ "GWT module description file and re-compile your"
diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java
index 9f84c16020..545af2ce83 100644
--- a/client/src/com/vaadin/client/ui/VOverlay.java
+++ b/client/src/com/vaadin/client/ui/VOverlay.java
@@ -241,10 +241,10 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
private void removeShadowIfPresent() {
if (isShadowAttached()) {
- shadow.removeFromParent();
-
// Remove event listener from the shadow
unsinkShadowEvents();
+
+ shadow.removeFromParent();
}
}
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index 53a8ad6443..3a7e15626a 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -991,6 +991,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (scrollBody != null) {
scrollBody.removeFromParent();
}
+
+ // Without this call the scroll position is messed up in IE even after
+ // the lazy scroller has set the scroll position to the first visible
+ // item
+ scrollBodyPanel.getScrollPosition();
+
scrollBody = createScrollBody();
scrollBody.renderInitialRows(rowData, uidl.getIntAttribute("firstrow"),
@@ -1121,7 +1127,28 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
}
+ private boolean lazyScrollerIsActive;
+
+ private void disableLazyScroller() {
+ lazyScrollerIsActive = false;
+ scrollBodyPanel.getElement().getStyle().clearOverflowX();
+ scrollBodyPanel.getElement().getStyle().clearOverflowY();
+ }
+
+ private void enableLazyScroller() {
+ Scheduler.get().scheduleDeferred(lazyScroller);
+ lazyScrollerIsActive = true;
+ // prevent scrolling to jump in IE11
+ scrollBodyPanel.getElement().getStyle().setOverflowX(Overflow.HIDDEN);
+ scrollBodyPanel.getElement().getStyle().setOverflowY(Overflow.HIDDEN);
+ }
+
+ private boolean isLazyScrollerActive() {
+ return lazyScrollerIsActive;
+ }
+
private ScheduledCommand lazyScroller = new ScheduledCommand() {
+
@Override
public void execute() {
if (firstvisible > 0) {
@@ -1134,6 +1161,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
.setScrollPosition(measureRowHeightOffset(firstvisible));
}
}
+ disableLazyScroller();
}
};
@@ -1152,7 +1180,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// Only scroll if the first visible changes from the server side.
// Else we might unintentionally scroll even when the scroll
// position has not changed.
- Scheduler.get().scheduleDeferred(lazyScroller);
+ enableLazyScroller();
}
}
@@ -2172,7 +2200,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
isNewBody = false;
if (firstvisible > 0) {
- Scheduler.get().scheduleDeferred(lazyScroller);
+ enableLazyScroller();
}
if (enabled) {
@@ -6883,6 +6911,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
@Override
public void onScroll(ScrollEvent event) {
+ // Do not handle scroll events while there is scroll initiated from
+ // server side which is not yet executed (#11454)
+ if (isLazyScrollerActive()) {
+ return;
+ }
+
scrollLeft = scrollBodyPanel.getElement().getScrollLeft();
scrollTop = scrollBodyPanel.getScrollPosition();
/*
diff --git a/client/src/com/vaadin/client/ui/VUpload.java b/client/src/com/vaadin/client/ui/VUpload.java
index c08d75e9b7..8e55387d39 100644
--- a/client/src/com/vaadin/client/ui/VUpload.java
+++ b/client/src/com/vaadin/client/ui/VUpload.java
@@ -295,10 +295,13 @@ public class VUpload extends SimplePanel {
/** For internal use only. May be removed or replaced in the future. */
public void submit() {
- if (fu.getFilename().length() == 0 || submitted || !enabled) {
- VConsole.log("Submit cancelled (disabled, no file or already submitted)");
+ if (submitted || !enabled) {
+ VConsole.log("Submit cancelled (disabled or already submitted)");
return;
}
+ if (fu.getFilename().length() == 0) {
+ VConsole.log("Submitting empty selection (no file)");
+ }
// flush possibly pending variable changes, so they will be handled
// before upload
client.sendPendingVariableChanges();
diff --git a/client/src/com/vaadin/client/ui/table/TableConnector.java b/client/src/com/vaadin/client/ui/table/TableConnector.java
index eacd5bc77a..d2c700ab06 100644
--- a/client/src/com/vaadin/client/ui/table/TableConnector.java
+++ b/client/src/com/vaadin/client/ui/table/TableConnector.java
@@ -142,9 +142,6 @@ public class TableConnector extends AbstractHasComponentsConnector implements
getWidget().updateSortingProperties(uidl);
- boolean keyboardSelectionOverRowFetchInProgress = getWidget()
- .selectSelectedRows(uidl);
-
getWidget().updateActionMap(uidl);
getWidget().updateColumnProperties(uidl);
@@ -216,6 +213,9 @@ public class TableConnector extends AbstractHasComponentsConnector implements
}
}
+ boolean keyboardSelectionOverRowFetchInProgress = getWidget()
+ .selectSelectedRows(uidl);
+
// If a row had an open context menu before the update, and after the
// update there's a row with the same key as that row, restore the
// context menu. See #8526.
diff --git a/client/src/com/vaadin/client/ui/upload/UploadConnector.java b/client/src/com/vaadin/client/ui/upload/UploadConnector.java
index 937ff438ac..989a913adc 100644
--- a/client/src/com/vaadin/client/ui/upload/UploadConnector.java
+++ b/client/src/com/vaadin/client/ui/upload/UploadConnector.java
@@ -22,12 +22,22 @@ import com.vaadin.client.UIDL;
import com.vaadin.client.ui.AbstractComponentConnector;
import com.vaadin.client.ui.VUpload;
import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.upload.UploadClientRpc;
import com.vaadin.ui.Upload;
@Connect(Upload.class)
public class UploadConnector extends AbstractComponentConnector implements
Paintable {
+ public UploadConnector() {
+ registerRpc(UploadClientRpc.class, new UploadClientRpc() {
+ @Override
+ public void submitUpload() {
+ getWidget().submit();
+ }
+ });
+ }
+
@Override
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
if (!isRealUpdate(uidl)) {
@@ -37,10 +47,6 @@ public class UploadConnector extends AbstractComponentConnector implements
getWidget().t.schedule(400);
return;
}
- if (uidl.hasAttribute("forceSubmit")) {
- getWidget().submit();
- return;
- }
getWidget().setImmediate(getState().immediate);
getWidget().client = client;
getWidget().paintableId = uidl.getId();
diff --git a/server/src/com/vaadin/server/communication/PushRequestHandler.java b/server/src/com/vaadin/server/communication/PushRequestHandler.java
index 74595322a0..f3869a76f8 100644
--- a/server/src/com/vaadin/server/communication/PushRequestHandler.java
+++ b/server/src/com/vaadin/server/communication/PushRequestHandler.java
@@ -18,6 +18,7 @@ package com.vaadin.server.communication;
import java.io.IOException;
+import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.atmosphere.client.TrackMessageSizeInterceptor;
@@ -58,11 +59,22 @@ public class PushRequestHandler implements RequestHandler,
public PushRequestHandler(VaadinServletService service)
throws ServiceException {
+ final ServletConfig config = service.getServlet().getServletConfig();
+
atmosphere = new AtmosphereFramework() {
@Override
protected void analytics() {
// Overridden to disable version number check
}
+
+ @Override
+ public AtmosphereFramework addInitParameter(String name,
+ String value) {
+ if (config.getInitParameter(name) == null) {
+ super.addInitParameter(name, value);
+ }
+ return this;
+ }
};
service.addServiceDestroyListener(new ServiceDestroyListener() {
@@ -93,7 +105,7 @@ public class PushRequestHandler implements RequestHandler,
"false");
try {
- atmosphere.init(service.getServlet().getServletConfig());
+ atmosphere.init(config);
// Ensure the client-side knows how to split the message stream
// into individual messages when using certain transports
diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
index ff418a95e8..ce9cec5e2a 100644
--- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
@@ -439,7 +439,7 @@ public class ServerRpcHandler implements Serializable {
"Ignoring RPC call to " + interfaceName + "." + methodName
+ " in connector " + connector.getClass().getName()
+ "(" + connectorId
- + ") as no RPC implementation is regsitered");
+ + ") as no RPC implementation is registered");
return null;
}
diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java
index 08cabf979a..98f5d2ded9 100644
--- a/server/src/com/vaadin/ui/Upload.java
+++ b/server/src/com/vaadin/ui/Upload.java
@@ -28,6 +28,7 @@ import com.vaadin.server.NoOutputStreamException;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.server.StreamVariable.StreamingProgressEvent;
+import com.vaadin.shared.ui.upload.UploadClientRpc;
/**
* Component for uploading files from client to server.
@@ -107,11 +108,6 @@ public class Upload extends AbstractComponent implements Component.Focusable,
private int nextid;
/**
- * Flag to indicate that submitting file has been requested.
- */
- private boolean forceSubmit;
-
- /**
* Creates a new instance of Upload.
*
* The receiver must be set before performing an upload.
@@ -157,11 +153,6 @@ public class Upload extends AbstractComponent implements Component.Focusable,
notStarted = false;
return;
}
- if (forceSubmit) {
- target.addAttribute("forceSubmit", true);
- forceSubmit = true;
- return;
- }
// The field should be focused
if (focus) {
target.addAttribute("focus", true);
@@ -1011,12 +1002,11 @@ public class Upload extends AbstractComponent implements Component.Focusable,
*/
public void submitUpload() {
markAsDirty();
- forceSubmit = true;
+ getRpcProxy(UploadClientRpc.class).submitUpload();
}
@Override
public void markAsDirty() {
- forceSubmit = false;
super.markAsDirty();
}
diff --git a/shared/src/com/vaadin/shared/communication/PushConstants.java b/shared/src/com/vaadin/shared/communication/PushConstants.java
index f16cbb7390..4b4f247e5f 100644
--- a/shared/src/com/vaadin/shared/communication/PushConstants.java
+++ b/shared/src/com/vaadin/shared/communication/PushConstants.java
@@ -27,8 +27,11 @@ public class PushConstants implements Serializable {
/**
* The size, in <b>bytes</b>, of the receiving buffer used by some servers.
+ * <p>
+ * Should not be set to a value equal to or greater than 32768 due to a
+ * Jetty 9.1 issue (see #13087)
*/
- public static final int WEBSOCKET_BUFFER_SIZE = 65536;
+ public static final int WEBSOCKET_BUFFER_SIZE = 16384;
/**
* The maximum size, in <b>characters</b>, of a websocket message fragment.
diff --git a/shared/src/com/vaadin/shared/ui/upload/UploadClientRpc.java b/shared/src/com/vaadin/shared/ui/upload/UploadClientRpc.java
new file mode 100644
index 0000000000..1757ddb001
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/upload/UploadClientRpc.java
@@ -0,0 +1,26 @@
+/*
+ * 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.shared.ui.upload;
+
+import com.vaadin.shared.communication.ClientRpc;
+
+public interface UploadClientRpc extends ClientRpc {
+
+ /**
+ * Forces the upload the send selected file to the server.
+ */
+ void submitUpload();
+}
diff --git a/uitest/src/com/vaadin/tests/components/AbstractTestUI.java b/uitest/src/com/vaadin/tests/components/AbstractTestUI.java
index cbca4bcf7f..5c7076c07e 100644
--- a/uitest/src/com/vaadin/tests/components/AbstractTestUI.java
+++ b/uitest/src/com/vaadin/tests/components/AbstractTestUI.java
@@ -148,6 +148,10 @@ public abstract class AbstractTestUI extends UI {
getLayout().addComponent(c);
}
+ public void addComponents(Component... c) {
+ getLayout().addComponents(c);
+ }
+
public void removeComponent(Component c) {
getLayout().removeComponent(c);
}
diff --git a/uitest/src/com/vaadin/tests/components/table/ExpandingContainer.java b/uitest/src/com/vaadin/tests/components/table/ExpandingContainer.java
new file mode 100644
index 0000000000..829c29b95b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/ExpandingContainer.java
@@ -0,0 +1,429 @@
+package com.vaadin.tests.components.table;
+
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.AbstractContainer;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Label;
+
+@SuppressWarnings("serial")
+public class ExpandingContainer extends AbstractContainer implements
+ Container.Ordered, Container.Indexed, Container.ItemSetChangeNotifier {
+
+ public static final List<String> PROPERTY_IDS = Arrays.asList("id",
+ "column1", "column2");
+
+ private final Label sizeLabel;
+ private final Logger log = Logger.getLogger(this.getClass().getName());
+
+ private int currentSize = 300;
+
+ private boolean loggingEnabled;
+
+ public ExpandingContainer(Label sizeLabel) {
+ this.sizeLabel = sizeLabel;
+ updateLabel();
+ }
+
+ private void log(String message) {
+ if (loggingEnabled) {
+ log.info(message);
+ }
+ }
+
+ // Expand container if we scroll past 85%
+ public int checkExpand(int index) {
+ log("checkExpand(" + index + ")");
+ if (index >= currentSize * 0.85) {
+ final int oldsize = currentSize;
+ currentSize = (int) (oldsize * 1.3333);
+ log("*** getSizeWithHint(" + index + "): went past 85% of size="
+ + oldsize + ", new size=" + currentSize);
+ updateLabel();
+ }
+ return currentSize;
+ };
+
+ @Override
+ public void fireItemSetChange() {
+ super.fireItemSetChange();
+ }
+
+ private void updateLabel() {
+ sizeLabel.setValue("Container size: " + currentSize);
+ }
+
+ public void triggerItemSetChange() {
+ log("*** triggerItemSetChange(): scheduling item set change event");
+ final VaadinSession session = VaadinSession.getCurrent();
+ new Thread() {
+ @Override
+ public void run() {
+ ExpandingContainer.this.invoke(session, new Runnable() {
+ @Override
+ public void run() {
+ log("*** Firing item set change event");
+ ExpandingContainer.this.fireItemSetChange();
+ }
+ });
+ }
+ }.start();
+ }
+
+ private void invoke(VaadinSession session, Runnable action) {
+ session.lock();
+ VaadinSession previousSession = VaadinSession.getCurrent();
+ VaadinSession.setCurrent(session);
+ try {
+ action.run();
+ } finally {
+ session.unlock();
+ VaadinSession.setCurrent(previousSession);
+ }
+ }
+
+ // Container
+
+ @Override
+ public BeanItem<MyBean> getItem(Object itemId) {
+ if (!(itemId instanceof Integer)) {
+ return null;
+ }
+ final int index = ((Integer) itemId).intValue();
+ return new BeanItem<MyBean>(new MyBean(index));
+ }
+
+ @Override
+ public Collection<Integer> getItemIds() {
+ return new IntList(size());
+ }
+
+ @Override
+ public List<String> getContainerPropertyIds() {
+ return PROPERTY_IDS;
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public Property/* <?> */getContainerProperty(Object itemId,
+ Object propertyId) {
+ BeanItem<MyBean> item = getItem(itemId);
+ return item != null ? item.getItemProperty(propertyId) : null;
+ }
+
+ @Override
+ public Class<?> getType(Object propertyId) {
+ return Component.class;
+ }
+
+ @Override
+ public int size() {
+ return currentSize;
+ }
+
+ @Override
+ public boolean containsId(Object itemId) {
+ if (!(itemId instanceof Integer)) {
+ return false;
+ }
+ int index = ((Integer) itemId).intValue();
+ checkExpand(index);
+ return index >= 0 && index < currentSize;
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public Item addItem(Object itemId) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public Item addItem() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public boolean removeItem(Object itemId) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public boolean addContainerProperty(Object propertyId, Class<?> type,
+ Object defaultValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public boolean removeContainerProperty(Object propertyId) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public boolean removeAllItems() {
+ throw new UnsupportedOperationException();
+ }
+
+ // Container.Indexed
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public Object addItemAt(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public Item addItemAt(int index, Object newItemId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Integer getIdByIndex(int index) {
+ if (index < 0) {
+ throw new IndexOutOfBoundsException("index < " + index);
+ }
+ final int size = currentSize;
+ if (index >= size) {
+ throw new IndexOutOfBoundsException("index=" + index + " but size="
+ + size);
+ }
+ checkExpand(index);
+ return index;
+ }
+
+ @Override
+ public List<Integer> getItemIds(int startIndex, int numberOfItems) {
+ if (numberOfItems < 0) {
+ throw new IllegalArgumentException("numberOfItems < 0");
+ }
+ final int size = currentSize;
+ checkExpand(startIndex);
+ if (startIndex < 0 || startIndex > size) {
+ throw new IndexOutOfBoundsException("startIndex=" + startIndex
+ + " but size=" + size);
+ }
+ if (startIndex + numberOfItems > size) {
+ numberOfItems = size - startIndex;
+ }
+ return new IntList(startIndex, numberOfItems);
+ }
+
+ @Override
+ public int indexOfId(Object itemId) {
+ if (!(itemId instanceof Integer)) {
+ return -1;
+ }
+ final int index = ((Integer) itemId).intValue();
+ checkExpand(index);
+ if (index < 0 || index >= currentSize) {
+ return -1;
+ }
+ return index;
+ }
+
+ // Container.Ordered
+
+ @Override
+ public Integer nextItemId(Object itemId) {
+ if (!(itemId instanceof Integer)) {
+ return null;
+ }
+ int index = ((Integer) itemId).intValue();
+ checkExpand(index);
+ if (index < 0 || index + 1 >= currentSize) {
+ return null;
+ }
+ return index + 1;
+ }
+
+ @Override
+ public Integer prevItemId(Object itemId) {
+ if (!(itemId instanceof Integer)) {
+ return null;
+ }
+ int index = ((Integer) itemId).intValue();
+ checkExpand(index);
+ if (index - 1 < 0 || index >= currentSize) {
+ return null;
+ }
+ return index - 1;
+ }
+
+ @Override
+ public Integer firstItemId() {
+ return currentSize == 0 ? null : 0;
+ }
+
+ @Override
+ public Integer lastItemId() {
+ final int size = currentSize;
+ return size == 0 ? null : size - 1;
+ }
+
+ @Override
+ public boolean isFirstId(Object itemId) {
+ if (!(itemId instanceof Integer)) {
+ return false;
+ }
+ final int index = ((Integer) itemId).intValue();
+ checkExpand(index);
+ final int size = currentSize;
+ return size > 0 && index == 0;
+ }
+
+ @Override
+ public boolean isLastId(Object itemId) {
+ if (!(itemId instanceof Integer)) {
+ return false;
+ }
+ int index = ((Integer) itemId).intValue();
+ checkExpand(index);
+ int size = currentSize;
+ return size > 0 && index == size - 1;
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public Item addItemAfter(Object previousItemId) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ * always
+ */
+ @Override
+ public Item addItemAfter(Object previousItemId, Object newItemId) {
+ throw new UnsupportedOperationException();
+ }
+
+ // Container.ItemSetChangeNotifier
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public void addListener(Container.ItemSetChangeListener listener) {
+ super.addListener(listener);
+ }
+
+ @Override
+ public void addItemSetChangeListener(
+ Container.ItemSetChangeListener listener) {
+ super.addItemSetChangeListener(listener);
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public void removeListener(Container.ItemSetChangeListener listener) {
+ super.removeListener(listener);
+ }
+
+ @Override
+ public void removeItemSetChangeListener(
+ Container.ItemSetChangeListener listener) {
+ super.removeItemSetChangeListener(listener);
+ }
+
+ // IntList
+
+ private static class IntList extends AbstractList<Integer> {
+
+ private final int min;
+ private final int size;
+
+ public IntList(int size) {
+ this(0, size);
+ }
+
+ public IntList(int min, int size) {
+ if (size < 0) {
+ throw new IllegalArgumentException("size < 0");
+ }
+ this.min = min;
+ this.size = size;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Integer get(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException();
+ }
+ return min + index;
+ }
+ }
+
+ // MyBean
+ public class MyBean {
+
+ private final int index;
+
+ public MyBean(int index) {
+ this.index = index;
+ }
+
+ public String getId() {
+ return "ROW #" + index;
+ }
+
+ public String getColumn1() {
+ return genText();
+ }
+
+ public String getColumn2() {
+ return genText();
+ }
+
+ private String genText() {
+ return "this is a line of text in row #" + index;
+ }
+ }
+
+ public void logDetails(boolean enabled) {
+ loggingEnabled = enabled;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceCondition.java b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceCondition.java
new file mode 100644
index 0000000000..8ad2d7f9c7
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceCondition.java
@@ -0,0 +1,67 @@
+package com.vaadin.tests.components.table;
+
+import java.util.Map;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+@SuppressWarnings("serial")
+public class ExpandingContainerVisibleRowRaceCondition extends UI {
+
+ static final String TABLE = "table";
+
+ @Override
+ public void init(VaadinRequest request) {
+ final VerticalLayout rootLayout = new VerticalLayout();
+
+ rootLayout.setSpacing(true);
+ rootLayout.setSizeFull();
+ rootLayout.setMargin(true);
+
+ final Label sizeLabel = new Label();
+ final ExpandingContainer container = new ExpandingContainer(sizeLabel);
+ container.logDetails(false);
+
+ Table table = new Table(null, container) {
+ @Override
+ public void changeVariables(Object source,
+ Map<String, Object> variables) {
+ if (variables.containsKey("firstvisible")) {
+ int index = (Integer) variables.get("firstvisible");
+ container.checkExpand(index);
+ }
+ if (variables.containsKey("reqfirstrow")
+ || variables.containsKey("reqrows")) {
+ try {
+ int index = ((Integer) variables
+ .get("lastToBeRendered")).intValue();
+ container.checkExpand(index);
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ super.changeVariables(source, variables);
+ }
+ };
+ table.setId(TABLE);
+ table.setCacheRate(0);
+ table.setSizeFull();
+ table.setVisibleColumns(ExpandingContainer.PROPERTY_IDS
+ .toArray(new String[ExpandingContainer.PROPERTY_IDS.size()]));
+
+ table.setCurrentPageFirstItemIndex(120);
+
+ rootLayout.addComponent(table);
+ rootLayout.setExpandRatio(table, 1);
+
+ rootLayout.addComponent(sizeLabel);
+
+ setContent(rootLayout);
+
+ container.checkExpand(300);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceConditionTest.java b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceConditionTest.java
new file mode 100644
index 0000000000..73dd7b1f81
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/ExpandingContainerVisibleRowRaceConditionTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.table;
+
+import static com.vaadin.tests.components.table.ExpandingContainerVisibleRowRaceCondition.TABLE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class ExpandingContainerVisibleRowRaceConditionTest extends
+ MultiBrowserTest {
+
+ private static final int ROW_HEIGHT = 20;
+
+ @Test
+ public void testScrollingWorksWithoutJumpingWhenItemSetChangeOccurs() {
+ openTestURL();
+ sleep(1000);
+
+ WebElement table = vaadinElementById(TABLE);
+ assertFirstRowIdIs("ROW #120");
+
+ testBenchElement(table.findElement(By.className("v-scrollable")))
+ .scroll(320 * ROW_HEIGHT);
+ sleep(1000);
+
+ assertRowIdIsInThePage("ROW #330");
+ assertScrollPositionIsNotVisible();
+ }
+
+ @Override
+ protected void sleep(int milliseconds) {
+ try {
+ super.sleep(milliseconds);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void assertFirstRowIdIs(String expected) {
+ List<WebElement> cellsOfFirstColumn = getCellsOfFirstColumn();
+ WebElement first = cellsOfFirstColumn.get(0);
+ assertEquals(expected, first.getText());
+ }
+
+ private void assertRowIdIsInThePage(String expected) {
+ List<WebElement> cellsOfFirstColumn = getCellsOfFirstColumn();
+ for (WebElement rowId : cellsOfFirstColumn) {
+ if (expected.equals(rowId.getText())) {
+ return;
+ }
+ }
+ fail("Expected row was not found");
+ }
+
+ private void assertScrollPositionIsNotVisible() {
+ WebElement table = vaadinElementById(TABLE);
+ WebElement scrollPosition = table.findElement(By
+ .className("v-table-scrollposition"));
+ assertFalse(scrollPosition.isDisplayed());
+ }
+
+ private List<WebElement> getCellsOfFirstColumn() {
+ WebElement table = vaadinElementById(TABLE);
+ List<WebElement> firstCellOfRows = table.findElements(By
+ .cssSelector(".v-table-table tr > td"));
+ return firstCellOfRows;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/SelectAllRows.java b/uitest/src/com/vaadin/tests/components/table/SelectAllRows.java
new file mode 100644
index 0000000000..6007ea2984
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/SelectAllRows.java
@@ -0,0 +1,83 @@
+/*
+ * 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.table;
+
+import java.util.Set;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+
+public class SelectAllRows extends AbstractTestUI {
+
+ static final String TABLE = "table";
+ static final String COUNT_SELECTED_BUTTON = "button";
+ static final int TOTAL_NUMBER_OF_ROWS = 300;
+ static final String COUNT_OF_SELECTED_ROWS_LABEL = "label";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ VerticalLayout layout = new VerticalLayout();
+ layout.setMargin(true);
+ layout.setSpacing(true);
+ setContent(layout);
+
+ final Table table = new Table();
+ table.setId(TABLE);
+ table.setImmediate(true);
+ table.setMultiSelect(true);
+ table.setSelectable(true);
+ table.addContainerProperty("row", String.class, null);
+ layout.addComponent(table);
+
+ Button button = new Button("Count");
+ button.setId(COUNT_SELECTED_BUTTON);
+ layout.addComponent(button);
+
+ final Label label = new Label();
+ label.setId(COUNT_OF_SELECTED_ROWS_LABEL);
+ label.setCaption("Selected count:");
+ layout.addComponent(label);
+
+ button.addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(Button.ClickEvent event) {
+ Set selected = (Set) table.getValue();
+ label.setValue(String.valueOf(selected.size()));
+ }
+ });
+
+ for (int i = 0; i < TOTAL_NUMBER_OF_ROWS; i++) {
+ Object itemId = table.addItem();
+ table.getContainerProperty(itemId, "row").setValue("row " + i);
+ }
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Selecting all rows does not work by selecting first row, press shift then select last row";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 13008;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/SelectAllRowsTest.java b/uitest/src/com/vaadin/tests/components/table/SelectAllRowsTest.java
new file mode 100644
index 0000000000..664b36fa75
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/SelectAllRowsTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.table;
+
+import static com.vaadin.tests.components.table.SelectAllRows.COUNT_OF_SELECTED_ROWS_LABEL;
+import static com.vaadin.tests.components.table.SelectAllRows.COUNT_SELECTED_BUTTON;
+import static com.vaadin.tests.components.table.SelectAllRows.TABLE;
+import static com.vaadin.tests.components.table.SelectAllRows.TOTAL_NUMBER_OF_ROWS;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class SelectAllRowsTest extends MultiBrowserTest {
+
+ private final static String TABLE_ROW = "v-table-row";
+
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+ // Pressing Shift modifier key does not work with TestBench and IE
+ // (#8621)
+ return Arrays.asList(Browser.FIREFOX.getDesiredCapabilities(),
+ Browser.CHROME.getDesiredCapabilities());
+ }
+
+ @Test
+ public void testAllRowsAreSelected() {
+ openTestURL();
+
+ selectAllRowsInTable();
+ int selectedRows = countSelectedItems();
+
+ assertEquals(TOTAL_NUMBER_OF_ROWS, selectedRows);
+ }
+
+ private int countSelectedItems() {
+ WebElement countButton = vaadinElementById(COUNT_SELECTED_BUTTON);
+ countButton.click();
+ WebElement countOfSelectedRows = vaadinElementById(COUNT_OF_SELECTED_ROWS_LABEL);
+ String count = countOfSelectedRows.getText();
+ return Integer.parseInt(count);
+ }
+
+ private void selectAllRowsInTable() {
+ clickFirstRow();
+ scrollTableToBottom();
+ new Actions(getDriver()).keyDown(Keys.SHIFT).perform();
+ clickLastRow();
+ new Actions(getDriver()).keyUp(Keys.SHIFT).perform();
+ }
+
+ private void clickLastRow() {
+ List<WebElement> rows = allVisibleTableRows();
+ WebElement lastRow = rows.get(rows.size() - 1);
+ lastRow.click();
+ }
+
+ private void clickFirstRow() {
+ WebElement firstRow = allVisibleTableRows().get(0);
+ firstRow.click();
+ }
+
+ private void scrollTableToBottom() {
+ WebElement table = vaadinElementById(TABLE);
+ testBenchElement(table.findElement(By.className("v-scrollable")))
+ .scroll(TOTAL_NUMBER_OF_ROWS * 30);
+
+ // Wait for scrolling to complete. Otherwise, clicking last row will
+ // fail with Chrome
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private List<WebElement> allVisibleTableRows() {
+ WebElement table = vaadinElementById(TABLE);
+ List<WebElement> rows = table.findElements(By
+ .cssSelector(".v-table-table tr"));
+ return rows;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/upload/UploadNoSelection.java b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelection.java
new file mode 100644
index 0000000000..c304293170
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelection.java
@@ -0,0 +1,83 @@
+/*
+ * 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.upload;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.Upload;
+import com.vaadin.ui.Upload.FailedEvent;
+import com.vaadin.ui.Upload.FinishedEvent;
+import com.vaadin.ui.Upload.Receiver;
+
+public class UploadNoSelection extends AbstractTestUIWithLog implements
+ Receiver {
+
+ static final String LOG_ID_PREFIX = "Log_row_";
+ static final String UPLOAD_ID = "u";
+
+ static final String UPLOAD_FINISHED = "Upload Finished";
+ static final String RECEIVING_UPLOAD = "Receiving upload";
+
+ static final String FILE_LENGTH_PREFIX = "File length:";
+ static final String FILE_NAME_PREFIX = "File name:";
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 9602;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Uploading an empty selection (no file) will trigger FinishedEvent with 0-length file size and empty filename.";
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Upload u = new Upload("Upload", this);
+ u.setId(UPLOAD_ID);
+ u.setSizeUndefined();
+
+ addComponent(u);
+
+ u.addFinishedListener(new Upload.FinishedListener() {
+ @Override
+ public void uploadFinished(FinishedEvent event) {
+ log(UPLOAD_FINISHED);
+ log(FILE_LENGTH_PREFIX + " " + event.getLength());
+ log(FILE_NAME_PREFIX + " " + event.getFilename());
+ }
+ });
+ u.addFailedListener(new Upload.FailedListener() {
+
+ @Override
+ public void uploadFailed(FailedEvent event) {
+ log("Upload Failed");
+ log(FILE_LENGTH_PREFIX + " " + event.getLength());
+ log(FILE_NAME_PREFIX + " " + event.getFilename());
+ }
+ });
+ }
+
+ @Override
+ public OutputStream receiveUpload(String filename, String MIMEType) {
+ log(RECEIVING_UPLOAD);
+ return new ByteArrayOutputStream();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/upload/UploadNoSelectionTest.java b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelectionTest.java
new file mode 100644
index 0000000000..1b30c4080a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/upload/UploadNoSelectionTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.upload;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class UploadNoSelectionTest extends MultiBrowserTest {
+
+ @Test
+ public void testUploadNoSelection() throws Exception {
+ openTestURL();
+
+ // empty content is populated by com.vaadin.tests.util.Log
+ Assert.assertEquals(" ", getLogRow(0));
+
+ getSubmitButton().click();
+
+ // expecting empty file name
+ assertLogRow(0, 4, UploadNoSelection.FILE_NAME_PREFIX);
+ // expecting 0-length file
+ assertLogRow(1, 3, UploadNoSelection.FILE_LENGTH_PREFIX + " " + 0);
+ assertLogRow(2, 2, UploadNoSelection.UPLOAD_FINISHED);
+ assertLogRow(3, 1, UploadNoSelection.RECEIVING_UPLOAD);
+ }
+
+ private WebElement getSubmitButton() {
+ WebElement element = getDriver().findElement(
+ By.id(UploadNoSelection.UPLOAD_ID));
+ WebElement submitButton = element.findElement(By.className("v-button"));
+ return submitButton;
+ }
+
+ private void assertLogRow(int index, int expentedRowNo,
+ String expectedValueWithoutRowNo) {
+ Assert.assertEquals(expentedRowNo + ". " + expectedValueWithoutRowNo,
+ getLogRow(index));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassConnector.java
new file mode 100644
index 0000000000..fb28e94bfa
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassConnector.java
@@ -0,0 +1,36 @@
+/*
+ * 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.widgetset.client;
+
+import com.vaadin.client.ui.label.LabelConnector;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.MediaControl;
+import com.vaadin.tests.widgetset.server.ClientRpcClassComponent;
+
+@Connect(ClientRpcClassComponent.class)
+public class ClientRpcClassConnector extends LabelConnector {
+
+ @Override
+ protected void init() {
+ super.init();
+ registerRpc(MediaControl.class, getWidget());
+ }
+
+ @Override
+ public ClientRpcClassWidget getWidget() {
+ return (ClientRpcClassWidget) super.getWidget();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassWidget.java
new file mode 100644
index 0000000000..91b4f19d92
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/ClientRpcClassWidget.java
@@ -0,0 +1,33 @@
+/*
+ * 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.widgetset.client;
+
+import com.vaadin.client.ui.VLabel;
+import com.vaadin.shared.ui.MediaControl;
+
+public class ClientRpcClassWidget extends VLabel implements MediaControl {
+
+ @Override
+ public void play() {
+ setText("play");
+ }
+
+ @Override
+ public void pause() {
+ setText("pause");
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClass.java b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClass.java
new file mode 100644
index 0000000000..cbc46b26f5
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClass.java
@@ -0,0 +1,47 @@
+/*
+ * 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.widgetset.server;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class ClientRpcClass extends AbstractTestUI {
+
+ public static String TEST_COMPONENT_ID = "testComponent";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ ClientRpcClassComponent component = new ClientRpcClassComponent();
+ component.setId(TEST_COMPONENT_ID);
+ addComponent(component);
+
+ component.pause();
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "UI showing dummy component where the wiget type is implementing the RPC interface.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(13056);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassComponent.java b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassComponent.java
new file mode 100644
index 0000000000..135f112fe4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassComponent.java
@@ -0,0 +1,29 @@
+/*
+ * 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.widgetset.server;
+
+import com.vaadin.shared.ui.MediaControl;
+import com.vaadin.ui.Label;
+
+public class ClientRpcClassComponent extends Label {
+ public void play() {
+ getRpcProxy(MediaControl.class).play();
+ }
+
+ public void pause() {
+ getRpcProxy(MediaControl.class).pause();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassTest.java b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassTest.java
new file mode 100644
index 0000000000..16c5ba4b61
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/ClientRpcClassTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.widgetset.server;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class ClientRpcClassTest extends MultiBrowserTest {
+
+ @Test
+ public void pauseDisplayed() {
+ openTestURL();
+
+ WebElement element = getDriver().findElement(
+ By.id(ClientRpcClass.TEST_COMPONENT_ID));
+ Assert.assertEquals("pause", element.getText());
+ }
+}