summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/tests-tickets/folder with space/resource with special $chars@.txt1
-rw-r--r--WebContent/VAADIN/themes/tests-tickets/ordinary.txt1
-rw-r--r--WebContent/VAADIN/themes/tests-tickets/percentagein%20name.txt1
-rw-r--r--WebContent/VAADIN/themes/valo/components/_grid.scss5
-rw-r--r--client/src/com/vaadin/client/BrowserInfo.java16
-rw-r--r--client/src/com/vaadin/client/ComputedStyle.java57
-rw-r--r--client/src/com/vaadin/client/ResourceLoader.java8
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java25
-rw-r--r--client/src/com/vaadin/client/ui/FocusableScrollPanel.java2
-rw-r--r--client/src/com/vaadin/client/ui/VFilterSelect.java26
-rw-r--r--client/src/com/vaadin/client/ui/VFormLayout.java17
-rw-r--r--client/src/com/vaadin/client/ui/VOverlay.java14
-rw-r--r--client/src/com/vaadin/client/ui/VRichTextArea.java2
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java14
-rw-r--r--client/src/com/vaadin/client/ui/VTabsheet.java10
-rw-r--r--client/src/com/vaadin/client/ui/VTextArea.java8
-rw-r--r--client/src/com/vaadin/client/ui/VUI.java10
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java29
-rw-r--r--client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java9
-rw-r--r--client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java7
-rw-r--r--client/src/com/vaadin/client/ui/ui/UIConnector.java14
-rw-r--r--client/src/com/vaadin/client/ui/window/WindowConnector.java14
-rw-r--r--client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java4
-rw-r--r--client/src/com/vaadin/client/widgets/Escalator.java49
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java102
-rw-r--r--client/tests/src/com/vaadin/client/VBrowserDetailsUserAgentParserTest.java25
-rw-r--r--eclipse/Super Development Mode (vaadin).launch2
-rw-r--r--scripts/DeployHelpers.py37
-rw-r--r--scripts/GeneratePublishReport.py53
-rw-r--r--scripts/GenerateStagingReport.py41
-rw-r--r--server/ivy.xml2
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java20
-rw-r--r--server/src/com/vaadin/server/WebBrowser.java14
-rw-r--r--server/src/com/vaadin/server/communication/AtmospherePushConnection.java7
-rw-r--r--server/src/com/vaadin/server/communication/FileUploadHandler.java2
-rw-r--r--server/src/com/vaadin/ui/Grid.java30
-rw-r--r--server/src/com/vaadin/ui/HorizontalLayout.java7
-rw-r--r--server/src/com/vaadin/ui/VerticalLayout.java7
-rw-r--r--server/src/com/vaadin/ui/renderers/ImageRenderer.java2
-rw-r--r--server/tests/src/com/vaadin/server/communication/FileUploadHandlerTest.java120
-rw-r--r--shared/src/com/vaadin/shared/VBrowserDetails.java25
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java11
-rw-r--r--uitest/integration_tests.xml3
-rw-r--r--uitest/ivy.xml2
-rw-r--r--uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java2
-rw-r--r--uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandler.java14
-rw-r--r--uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandlerTest.java15
-rw-r--r--uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrolling.java40
-rw-r--r--uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrollingTest.java60
-rw-r--r--uitest/src/com/vaadin/tests/components/combobox/CustomComboBoxElement.java40
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java5
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRenderer.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRendererTest.java41
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java20
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java2
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java58
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanel.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanelTest.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpand.java51
-rw-r--r--uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpandTest.java46
-rw-r--r--uitest/src/com/vaadin/tests/components/window/GridInWindow.java49
-rw-r--r--uitest/src/com/vaadin/tests/components/window/GridInWindowTest.java36
-rw-r--r--uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusField.java62
-rw-r--r--uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusFieldTest.java48
-rw-r--r--uitest/src/com/vaadin/tests/push/ManualLongPollingPushUI.java94
-rw-r--r--uitest/src/com/vaadin/tests/push/ManualLongPollingPushUITest.java54
-rw-r--r--uitest/src/com/vaadin/tests/resources/SpecialCharsInThemeResources.java52
-rw-r--r--uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java94
-rw-r--r--uitest/src/com/vaadin/tests/tb3/newelements/WindowElement.java10
69 files changed, 1698 insertions, 179 deletions
diff --git a/WebContent/VAADIN/themes/tests-tickets/folder with space/resource with special $chars@.txt b/WebContent/VAADIN/themes/tests-tickets/folder with space/resource with special $chars@.txt
new file mode 100644
index 0000000000..dff31dd51f
--- /dev/null
+++ b/WebContent/VAADIN/themes/tests-tickets/folder with space/resource with special $chars@.txt
@@ -0,0 +1 @@
+Just ordinary contents here \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/tests-tickets/ordinary.txt b/WebContent/VAADIN/themes/tests-tickets/ordinary.txt
new file mode 100644
index 0000000000..dff31dd51f
--- /dev/null
+++ b/WebContent/VAADIN/themes/tests-tickets/ordinary.txt
@@ -0,0 +1 @@
+Just ordinary contents here \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/tests-tickets/percentagein%20name.txt b/WebContent/VAADIN/themes/tests-tickets/percentagein%20name.txt
new file mode 100644
index 0000000000..dff31dd51f
--- /dev/null
+++ b/WebContent/VAADIN/themes/tests-tickets/percentagein%20name.txt
@@ -0,0 +1 @@
+Just ordinary contents here \ No newline at end of file
diff --git a/WebContent/VAADIN/themes/valo/components/_grid.scss b/WebContent/VAADIN/themes/valo/components/_grid.scss
index 11134262eb..e9b4d249c7 100644
--- a/WebContent/VAADIN/themes/valo/components/_grid.scss
+++ b/WebContent/VAADIN/themes/valo/components/_grid.scss
@@ -21,6 +21,11 @@ $v-grid-details-marker-width: first-number($v-grid-border) * 2 !default;
$v-grid-details-marker-color: $v-selection-color !default;
$v-grid-details-border-top: valo-border($color: $v-grid-border-color-source, $strength: 0.3) !default;
$v-grid-details-border-top-stripe: valo-border($color: $v-grid-row-stripe-background-color, $strength: 0.3) !default;
+
+$v-grid-border-size: 1px !default;
+$v-grid-border: $v-grid-border-size solid #ddd !default;
+$v-grid-cell-vertical-border: $v-grid-border !default;
+$v-grid-cell-horizontal-border: $v-grid-cell-vertical-border !default;
$v-grid-details-border-bottom: $v-grid-cell-horizontal-border !default;
$v-grid-details-border-bottom-stripe: $v-grid-cell-horizontal-border !default;
diff --git a/client/src/com/vaadin/client/BrowserInfo.java b/client/src/com/vaadin/client/BrowserInfo.java
index 8b274623c1..8dcefddcf5 100644
--- a/client/src/com/vaadin/client/BrowserInfo.java
+++ b/client/src/com/vaadin/client/BrowserInfo.java
@@ -30,6 +30,7 @@ public class BrowserInfo {
private static final String BROWSER_OPERA = "op";
private static final String BROWSER_IE = "ie";
+ private static final String BROWSER_EDGE = "edge";
private static final String BROWSER_FIREFOX = "ff";
private static final String BROWSER_SAFARI = "sa";
@@ -171,6 +172,13 @@ public class BrowserInfo {
minorVersionClass = majorVersionClass
+ browserDetails.getBrowserMinorVersion();
browserEngineClass = ENGINE_TRIDENT;
+ } else if (browserDetails.isEdge()) {
+ browserIdentifier = BROWSER_EDGE;
+ majorVersionClass = browserIdentifier
+ + getBrowserMajorVersion();
+ minorVersionClass = majorVersionClass
+ + browserDetails.getBrowserMinorVersion();
+ browserEngineClass = "";
} else if (browserDetails.isOpera()) {
browserIdentifier = BROWSER_OPERA;
majorVersionClass = browserIdentifier
@@ -225,6 +233,10 @@ public class BrowserInfo {
return browserDetails.isIE();
}
+ public boolean isEdge() {
+ return browserDetails.isEdge();
+ }
+
public boolean isFirefox() {
return browserDetails.isFirefox();
}
@@ -245,6 +257,10 @@ public class BrowserInfo {
return isIE() && getBrowserMajorVersion() == 10;
}
+ public boolean isIE11() {
+ return isIE() && getBrowserMajorVersion() == 11;
+ }
+
public boolean isChrome() {
return browserDetails.isChrome();
}
diff --git a/client/src/com/vaadin/client/ComputedStyle.java b/client/src/com/vaadin/client/ComputedStyle.java
index 61cb3c2eb6..cd90e0e78b 100644
--- a/client/src/com/vaadin/client/ComputedStyle.java
+++ b/client/src/com/vaadin/client/ComputedStyle.java
@@ -155,10 +155,10 @@ public class ComputedStyle {
* the property to retrieve
* @return the double value of the property
*/
- public final int getDoubleProperty(String name) {
+ public final double getDoubleProperty(String name) {
Profiler.enter("ComputedStyle.getDoubleProperty");
String value = getProperty(name);
- int result = parseDoubleNative(value);
+ double result = parseDoubleNative(value);
Profiler.leave("ComputedStyle.getDoubleProperty");
return result;
}
@@ -275,9 +275,60 @@ public class ComputedStyle {
* @return the value from the string before any non-numeric characters or
* NaN if the value cannot be parsed as a number
*/
- private static native int parseDoubleNative(final String value)
+ private static native double parseDoubleNative(final String value)
/*-{
return parseFloat(value);
}-*/;
+ /**
+ * Returns the sum of the top and bottom border width
+ *
+ * @since 7.5.3
+ * @return the sum of the top and bottom border
+ */
+ public double getBorderHeight() {
+ double borderHeight = getDoubleProperty("borderTopWidth");
+ borderHeight += getDoubleProperty("borderBottomWidth");
+
+ return borderHeight;
+ }
+
+ /**
+ * Returns the sum of the left and right border width
+ *
+ * @since 7.5.3
+ * @return the sum of the left and right border
+ */
+ public double getBorderWidth() {
+ double borderWidth = getDoubleProperty("borderLeftWidth");
+ borderWidth += getDoubleProperty("borderRightWidth");
+
+ return borderWidth;
+ }
+
+ /**
+ * Returns the sum of the top and bottom padding
+ *
+ * @since 7.5.3
+ * @return the sum of the top and bottom padding
+ */
+ public double getPaddingHeight() {
+ double paddingHeight = getDoubleProperty("paddingTop");
+ paddingHeight += getDoubleProperty("paddingBottom");
+
+ return paddingHeight;
+ }
+
+ /**
+ * Returns the sum of the top and bottom padding
+ *
+ * @since 7.5.3
+ * @return the sum of the left and right padding
+ */
+ public double getPaddingWidth() {
+ double paddingWidth = getDoubleProperty("paddingLeft");
+ paddingWidth += getDoubleProperty("paddingRight");
+
+ return paddingWidth;
+ }
}
diff --git a/client/src/com/vaadin/client/ResourceLoader.java b/client/src/com/vaadin/client/ResourceLoader.java
index 9e9ce5ac49..559768d09c 100644
--- a/client/src/com/vaadin/client/ResourceLoader.java
+++ b/client/src/com/vaadin/client/ResourceLoader.java
@@ -283,8 +283,7 @@ public class ResourceLoader {
* @since 7.2.4
*/
public static boolean supportsInOrderScriptExecution() {
- return BrowserInfo.get().isIE()
- && BrowserInfo.get().getBrowserMajorVersion() >= 11;
+ return BrowserInfo.get().isIE11() || BrowserInfo.get().isEdge();
}
/**
@@ -486,10 +485,11 @@ public class ResourceLoader {
addOnloadHandler(linkElement, new ResourceLoadListener() {
@Override
public void onLoad(ResourceLoadEvent event) {
- // Chrome && IE fires load for errors, must check
+ // Chrome, IE, Edge all fire load for errors, must check
// stylesheet data
if (BrowserInfo.get().isChrome()
- || BrowserInfo.get().isIE()) {
+ || BrowserInfo.get().isIE()
+ || BrowserInfo.get().isEdge()) {
int styleSheetLength = getStyleSheetLength(url);
// Error if there's an empty stylesheet
if (styleSheetLength == 0) {
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java
index 62326c4b07..74f8a96bc0 100644
--- a/client/src/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/com/vaadin/client/connectors/GridConnector.java
@@ -34,6 +34,7 @@ import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
@@ -476,8 +477,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements
/**
* Class for handling scrolling issues with open details.
*
- * @since
- * @author Vaadin Ltd
+ * @since 7.5.2
*/
private class LazyDetailsScroller implements DeferredWorker {
@@ -507,7 +507,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements
/**
* Inform LazyDetailsScroller that a details row has opened on a row.
*
- * @since
* @param rowIndex
* index of row with details now open
*/
@@ -685,6 +684,26 @@ public class GridConnector extends AbstractHasComponentsConnector implements
public void recalculateColumnWidths() {
getWidget().recalculateColumnWidths();
}
+
+ @Override
+ public void setSelectAll(boolean allSelected) {
+ if (selectionModel instanceof SelectionModel.Multi
+ && selectionModel.getSelectionColumnRenderer() != null) {
+ final Widget widget;
+ try {
+ HeaderRow defaultHeaderRow = getWidget()
+ .getDefaultHeaderRow();
+ if (defaultHeaderRow != null) {
+ widget = defaultHeaderRow.getCell(
+ getWidget().getColumn(0)).getWidget();
+ ((CheckBox) widget).setValue(allSelected, false);
+ }
+ } catch (Exception e) {
+ getLogger().warning(
+ "Problems finding select all checkbox.");
+ }
+ }
+ }
});
getWidget().addSelectionHandler(internalSelectionChangeHandler);
diff --git a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
index 9dd9c17675..1ac5a08ccd 100644
--- a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
+++ b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
@@ -74,7 +74,7 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
style.setPosition(Position.FIXED);
style.setTop(0, Unit.PX);
style.setLeft(0, Unit.PX);
- if (browserInfo.isIE()) {
+ if (browserInfo.isIE() || browserInfo.isEdge()) {
// for #15294: artificially hide little bit more the
// focusElement, otherwise IE will make the window to scroll
// into it when focused
diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java
index 8d9e30ac6e..d756c88f79 100644
--- a/client/src/com/vaadin/client/ui/VFilterSelect.java
+++ b/client/src/com/vaadin/client/ui/VFilterSelect.java
@@ -599,7 +599,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
+ "]");
Element menuFirstChild = menu.getElement().getFirstChildElement();
- final int naturalMenuWidth = menuFirstChild.getOffsetWidth();
+ final int naturalMenuWidth = WidgetUtil
+ .getRequiredWidth(menuFirstChild);
if (popupOuterPadding == -1) {
popupOuterPadding = WidgetUtil
@@ -611,13 +612,20 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
menuFirstChild.getStyle().setWidth(100, Unit.PCT);
}
- if (BrowserInfo.get().isIE()) {
+ if (BrowserInfo.get().isIE()
+ && BrowserInfo.get().getBrowserMajorVersion() < 11) {
+ // Must take margin,border,padding manually into account for
+ // menu element as we measure the element child and set width to
+ // the element parent
+ int naturalMenuOuterWidth = naturalMenuWidth
+ + getMarginBorderPaddingWidth(menu.getElement());
+
/*
* IE requires us to specify the width for the container
* element. Otherwise it will be 100% wide
*/
- int rootWidth = Math.max(desiredWidth, naturalMenuWidth)
- - popupOuterPadding;
+ int rootWidth = Math.max(desiredWidth - popupOuterPadding,
+ naturalMenuOuterWidth);
getContainerElement().getStyle().setWidth(rootWidth, Unit.PX);
}
@@ -1283,6 +1291,16 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
sinkEvents(Event.ONPASTE);
}
+ private static int getMarginBorderPaddingWidth(Element element) {
+ final ComputedStyle s = new ComputedStyle(element);
+ int[] margin = s.getMargin();
+ int[] border = s.getBorder();
+ int[] padding = s.getPadding();
+ return margin[1] + margin[3] + border[1] + border[3] + padding[1]
+ + padding[3];
+
+ }
+
/*
* (non-Javadoc)
*
diff --git a/client/src/com/vaadin/client/ui/VFormLayout.java b/client/src/com/vaadin/client/ui/VFormLayout.java
index 84a9b4f3dd..bcbb3ebf7b 100644
--- a/client/src/com/vaadin/client/ui/VFormLayout.java
+++ b/client/src/com/vaadin/client/ui/VFormLayout.java
@@ -22,7 +22,6 @@ import java.util.List;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
@@ -327,22 +326,6 @@ public class VFormLayout extends SimplePanel {
requiredFieldIndicator = null;
}
}
-
- // Workaround for IE weirdness, sometimes returns bad height in some
- // circumstances when Caption is empty. See #1444
- // IE7 bugs more often. I wonder what happens when IE8 arrives...
- // FIXME: This could be unnecessary for IE8+
- if (BrowserInfo.get().isIE()) {
- if (isEmpty) {
- setHeight("0px");
- getElement().getStyle().setOverflow(Overflow.HIDDEN);
- } else {
- setHeight("");
- getElement().getStyle().clearOverflow();
- }
-
- }
-
}
/**
diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java
index e823e8ee80..3649afc74f 100644
--- a/client/src/com/vaadin/client/ui/VOverlay.java
+++ b/client/src/com/vaadin/client/ui/VOverlay.java
@@ -22,8 +22,6 @@ import java.util.logging.Logger;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.JavaScriptObject;
-import com.google.gwt.core.client.Scheduler;
-import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.IFrameElement;
@@ -473,17 +471,7 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> {
if (isAnimationEnabled()) {
new ResizeAnimation().run(POPUP_PANEL_ANIMATION_DURATION);
} else {
- if (BrowserInfo.get().isIE8()) {
- Scheduler.get().scheduleFinally(new ScheduledCommand() {
-
- @Override
- public void execute() {
- positionOrSizeUpdated(1.0);
- }
- });
- } else {
- positionOrSizeUpdated(1.0);
- }
+ positionOrSizeUpdated(1.0);
}
current = null;
}
diff --git a/client/src/com/vaadin/client/ui/VRichTextArea.java b/client/src/com/vaadin/client/ui/VRichTextArea.java
index 3f63f38067..cb4482f7cb 100644
--- a/client/src/com/vaadin/client/ui/VRichTextArea.java
+++ b/client/src/com/vaadin/client/ui/VRichTextArea.java
@@ -322,7 +322,7 @@ public class VRichTextArea extends Composite implements Field, KeyPressHandler,
if ("<br>".equals(result)) {
result = "";
}
- } else if (browser.isWebkit()) {
+ } else if (browser.isWebkit() || browser.isEdge()) {
if ("<br>".equals(result) || "<div><br></div>".equals(result)) {
result = "";
}
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index e036725ceb..4e030b8e49 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -1295,8 +1295,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (uidl.hasVariable("selected")) {
final Set<String> selectedKeys = uidl
.getStringArrayVariableAsSet("selected");
- removeUnselectedRowKeys(selectedKeys);
-
+ // Do not update focus if there is a single selected row
+ // that is the same as the previous selection. This prevents
+ // unwanted scrolling (#18247).
+ boolean rowsUnSelected = removeUnselectedRowKeys(selectedKeys);
+ boolean updateFocus = rowsUnSelected || selectedRowKeys.size() == 0
+ || focusedRow == null;
if (scrollBody != null) {
Iterator<Widget> iterator = scrollBody.iterator();
while (iterator.hasNext()) {
@@ -1313,7 +1317,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
selected = true;
keyboardSelectionOverRowFetchInProgress = true;
}
- if (selected && selectedKeys.size() == 1) {
+ if (selected && selectedKeys.size() == 1 && updateFocus) {
/*
* If a single item is selected, move focus to the
* selected row. (#10522)
@@ -1338,14 +1342,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return keyboardSelectionOverRowFetchInProgress;
}
- private void removeUnselectedRowKeys(final Set<String> selectedKeys) {
+ private boolean removeUnselectedRowKeys(final Set<String> selectedKeys) {
List<String> unselectedKeys = new ArrayList<String>(0);
for (String key : selectedRowKeys) {
if (!selectedKeys.contains(key)) {
unselectedKeys.add(key);
}
}
- selectedRowKeys.removeAll(unselectedKeys);
+ return selectedRowKeys.removeAll(unselectedKeys);
}
/** For internal use only. May be removed or replaced in the future. */
diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java
index ded9977f5e..e196870348 100644
--- a/client/src/com/vaadin/client/ui/VTabsheet.java
+++ b/client/src/com/vaadin/client/ui/VTabsheet.java
@@ -61,11 +61,12 @@ import com.google.gwt.user.client.ui.impl.FocusImpl;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.ComponentConnector;
+import com.vaadin.client.ComputedStyle;
import com.vaadin.client.Focusable;
import com.vaadin.client.TooltipInfo;
-import com.vaadin.client.WidgetUtil;
import com.vaadin.client.VCaption;
import com.vaadin.client.VTooltip;
+import com.vaadin.client.WidgetUtil;
import com.vaadin.client.ui.aria.AriaHelper;
import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.ComponentConstants;
@@ -1227,8 +1228,13 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware
public void updateContentNodeHeight() {
if (!isDynamicHeight()) {
int contentHeight = getOffsetHeight();
- contentHeight -= DOM.getElementPropertyInt(deco, "offsetHeight");
+ contentHeight -= deco.getOffsetHeight();
contentHeight -= tb.getOffsetHeight();
+
+ ComputedStyle cs = new ComputedStyle(contentNode);
+ contentHeight -= Math.ceil(cs.getPaddingHeight());
+ contentHeight -= Math.ceil(cs.getBorderHeight());
+
if (contentHeight < 0) {
contentHeight = 0;
}
diff --git a/client/src/com/vaadin/client/ui/VTextArea.java b/client/src/com/vaadin/client/ui/VTextArea.java
index 50930f2fee..bb3d3a476b 100644
--- a/client/src/com/vaadin/client/ui/VTextArea.java
+++ b/client/src/com/vaadin/client/ui/VTextArea.java
@@ -224,16 +224,16 @@ public class VTextArea extends VTextField implements DragImageModifier {
protected boolean browserSupportsMaxLengthAttribute() {
BrowserInfo info = BrowserInfo.get();
- if (info.isFirefox() && info.isBrowserVersionNewerOrEqual(4, 0)) {
+ if (info.isFirefox()) {
return true;
}
- if (info.isSafari() && info.isBrowserVersionNewerOrEqual(5, 0)) {
+ if (info.isSafari()) {
return true;
}
- if (info.isIE() && info.isBrowserVersionNewerOrEqual(10, 0)) {
+ if (info.isIE10() || info.isIE11() || info.isEdge()) {
return true;
}
- if (info.isAndroid() && info.isBrowserVersionNewerOrEqual(2, 3)) {
+ if (info.isAndroid()) {
return true;
}
return false;
diff --git a/client/src/com/vaadin/client/ui/VUI.java b/client/src/com/vaadin/client/ui/VUI.java
index 0c1b83ab0f..963d83a6e6 100644
--- a/client/src/com/vaadin/client/ui/VUI.java
+++ b/client/src/com/vaadin/client/ui/VUI.java
@@ -18,7 +18,6 @@ package com.vaadin.client.ui;
import java.util.ArrayList;
-import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.HasScrollHandlers;
@@ -44,8 +43,8 @@ import com.vaadin.client.ConnectorMap;
import com.vaadin.client.Focusable;
import com.vaadin.client.LayoutManager;
import com.vaadin.client.Profiler;
-import com.vaadin.client.WidgetUtil;
import com.vaadin.client.VConsole;
+import com.vaadin.client.WidgetUtil;
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
import com.vaadin.client.ui.ui.UIConnector;
@@ -515,13 +514,6 @@ public class VUI extends SimplePanel implements ResizeHandler,
public void focusStoredElement() {
if (storedFocus != null) {
storedFocus.focus();
-
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {
- @Override
- public void execute() {
- storedFocus.focus();
- }
- });
}
}
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index c5cab8ff6b..e34e12a20b 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -562,17 +562,10 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
}
private static void focusTopmostModalWindow() {
- // If we call focus() directly without scheduling, it does not work in
- // IE and FF.
- Scheduler.get().scheduleDeferred(new ScheduledCommand() {
- @Override
- public void execute() {
- VWindow topmost = getTopmostWindow();
- if ((topmost != null) && (topmost.vaadinModality)) {
- topmost.focus();
- }
- }
- });
+ VWindow topmost = getTopmostWindow();
+ if ((topmost != null) && (topmost.vaadinModality)) {
+ topmost.focus();
+ }
}
@Override
@@ -762,11 +755,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
modalityCurtain.removeFromParent();
- if (BrowserInfo.get().isIE()) {
- // IE leaks memory in certain cases unless we release the reference
- // (#9197)
- modalityCurtain = null;
- }
+ // IE leaks memory in certain cases unless we release the reference
+ // (#9197)
+ modalityCurtain = null;
}
/*
@@ -1375,7 +1366,11 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
@Override
public void focus() {
- contentPanel.focus();
+ // We don't want to use contentPanel.focus() as that will use a timer in
+ // Chrome/Safari and ultimately run focus events in the wrong order when
+ // opening a modal window and focusing some other component at the same
+ // time
+ contentPanel.getElement().focus();
}
private int getDecorationHeight() {
diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java b/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java
index 1a54fe0454..55834397d3 100644
--- a/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java
+++ b/client/src/com/vaadin/client/ui/calendar/schedule/DateCellDayEvent.java
@@ -268,8 +268,13 @@ public class DateCellDayEvent extends FocusableHTML implements
}
int endX = event.getClientX();
int endY = event.getClientY();
- int xDiff = startX - endX;
- int yDiff = startY - endY;
+ int xDiff = 0, yDiff = 0;
+ if (startX != -1 && startY != -1) {
+ // Drag started
+ xDiff = startX - endX;
+ yDiff = startY - endY;
+ }
+
startX = -1;
startY = -1;
mouseMoveStarted = false;
diff --git a/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java b/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java
index 3bf6930933..158241337b 100644
--- a/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java
+++ b/client/src/com/vaadin/client/ui/calendar/schedule/SimpleDayCell.java
@@ -392,8 +392,11 @@ public class SimpleDayCell extends FocusableFlowPanel implements
int endX = event.getClientX();
int endY = event.getClientY();
- int xDiff = startX - endX;
- int yDiff = startY - endY;
+ int xDiff = 0, yDiff = 0;
+ if (startX != -1 && startY != -1) {
+ xDiff = startX - endX;
+ yDiff = startY - endY;
+ }
startX = -1;
startY = -1;
prevDayDiff = 0;
diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java
index 9d8aa5b877..bcd90437a4 100644
--- a/client/src/com/vaadin/client/ui/ui/UIConnector.java
+++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java
@@ -72,6 +72,7 @@ import com.vaadin.client.ui.ShortcutActionHandler;
import com.vaadin.client.ui.VNotification;
import com.vaadin.client.ui.VOverlay;
import com.vaadin.client.ui.VUI;
+import com.vaadin.client.ui.VWindow;
import com.vaadin.client.ui.layout.MayScrollChildren;
import com.vaadin.client.ui.window.WindowConnector;
import com.vaadin.server.Page.Styles;
@@ -677,6 +678,19 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
if (c instanceof WindowConnector) {
WindowConnector wc = (WindowConnector) c;
wc.setWindowOrderAndPosition();
+ VWindow window = wc.getWidget();
+ if (!window.isAttached()) {
+
+ // Attach so that all widgets inside the Window are attached
+ // when their onStateChange is run
+
+ // Made invisible here for legacy reasons and made visible
+ // at the end of stateChange. This dance could probably be
+ // removed
+ window.setVisible(false);
+ window.show();
+ }
+
}
}
diff --git a/client/src/com/vaadin/client/ui/window/WindowConnector.java b/client/src/com/vaadin/client/ui/window/WindowConnector.java
index 9b710981d8..9ea3c8bb68 100644
--- a/client/src/com/vaadin/client/ui/window/WindowConnector.java
+++ b/client/src/com/vaadin/client/ui/window/WindowConnector.java
@@ -17,6 +17,8 @@ package com.vaadin.client.ui.window;
import java.util.logging.Logger;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Node;
@@ -354,10 +356,6 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
if (state.modal != window.vaadinModality) {
window.setVaadinModality(!window.vaadinModality);
}
- if (!window.isAttached()) {
- window.setVisible(false); // hide until possible centering
- window.show();
- }
boolean resizeable = state.resizable
&& state.windowMode == WindowMode.NORMAL;
window.setResizable(resizeable);
@@ -407,7 +405,13 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
window.centered = state.centered;
// Ensure centering before setting visible (#16486)
if (window.centered && getState().windowMode != WindowMode.MAXIMIZED) {
- window.center();
+ Scheduler.get().scheduleFinally(new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ getWidget().center();
+ }
+ });
}
window.setVisible(true);
diff --git a/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java b/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
index 1e47d3ad6b..c64908f24c 100644
--- a/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
+++ b/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
@@ -56,6 +56,8 @@ import com.vaadin.client.widgets.Grid;
public class MultiSelectionRenderer<T> extends
ClickableRenderer<Boolean, CheckBox> {
+ private static final String SELECTION_CHECKBOX_CLASSNAME = "-selection-checkbox";
+
/** The size of the autoscroll area, both top and bottom. */
private static final int SCROLL_AREA_GRADIENT_PX = 100;
@@ -591,6 +593,8 @@ public class MultiSelectionRenderer<T> extends
@Override
public CheckBox createWidget() {
final CheckBox checkBox = GWT.create(CheckBox.class);
+ checkBox.setStylePrimaryName(grid.getStylePrimaryName()
+ + SELECTION_CHECKBOX_CLASSNAME);
CheckBoxEventHandler handler = new CheckBoxEventHandler(checkBox);
// Sink events
diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java
index a6247aee12..5b3d4e1b70 100644
--- a/client/src/com/vaadin/client/widgets/Escalator.java
+++ b/client/src/com/vaadin/client/widgets/Escalator.java
@@ -1475,6 +1475,9 @@ public class Escalator extends Widget implements RequiresResize,
cellElem.addClassName("frozen");
position.set(cellElem, scroller.lastScrollLeft, 0);
}
+ if (columnConfiguration.frozenColumns > 0 && col == columnConfiguration.frozenColumns - 1) {
+ cellElem.addClassName("last-frozen");
+ }
}
referenceRow = paintInsertRow(referenceRow, tr, row);
@@ -1732,6 +1735,14 @@ public class Escalator extends Widget implements RequiresResize,
}
public void setColumnFrozen(int column, boolean frozen) {
+ toggleFrozenColumnClass(column, frozen, "frozen");
+
+ if (frozen) {
+ updateFreezePosition(column, scroller.lastScrollLeft);
+ }
+ }
+
+ private void toggleFrozenColumnClass(int column, boolean frozen, String className) {
final NodeList<TableRowElement> childRows = root.getRows();
for (int row = 0; row < childRows.getLength(); row++) {
@@ -1742,16 +1753,16 @@ public class Escalator extends Widget implements RequiresResize,
TableCellElement cell = tr.getCells().getItem(column);
if (frozen) {
- cell.addClassName("frozen");
+ cell.addClassName(className);
} else {
- cell.removeClassName("frozen");
+ cell.removeClassName(className);
position.reset(cell);
}
}
+ }
- if (frozen) {
- updateFreezePosition(column, scroller.lastScrollLeft);
- }
+ public void setColumnLastFrozen(int column, boolean lastFrozen) {
+ toggleFrozenColumnClass(column, lastFrozen, "last-frozen");
}
public void updateFreezePosition(int column, double scrollLeft) {
@@ -4309,6 +4320,17 @@ public class Escalator extends Widget implements RequiresResize,
firstUnaffectedCol = oldCount;
}
+ if (oldCount > 0) {
+ header.setColumnLastFrozen(oldCount - 1, false);
+ body.setColumnLastFrozen(oldCount - 1, false);
+ footer.setColumnLastFrozen(oldCount - 1, false);
+ }
+ if (count > 0) {
+ header.setColumnLastFrozen(count - 1, true);
+ body.setColumnLastFrozen(count - 1, true);
+ footer.setColumnLastFrozen(count - 1, true);
+ }
+
for (int col = firstAffectedCol; col < firstUnaffectedCol; col++) {
header.setColumnFrozen(col, frozen);
body.setColumnFrozen(col, frozen);
@@ -5619,14 +5641,29 @@ public class Escalator extends Widget implements RequiresResize,
horizontalScrollbar.setScrollbarThickness(scrollbarThickness);
horizontalScrollbar
.addVisibilityHandler(new ScrollbarBundle.VisibilityHandler() {
+
+ private boolean queued = false;
+
@Override
public void visibilityChanged(
ScrollbarBundle.VisibilityChangeEvent event) {
+ if (queued) {
+ return;
+ }
+ queued = true;
+
/*
* We either lost or gained a scrollbar. In any case, we
* need to change the height, if it's defined by rows.
*/
- applyHeightByRows();
+ Scheduler.get().scheduleFinally(new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ applyHeightByRows();
+ queued = false;
+ }
+ });
}
});
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index a17c59c795..eb54f9c720 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -216,6 +216,8 @@ public class Grid<T> extends ResizeComposite implements
HasSelectionHandlers<T>, SubPartAware, DeferredWorker, Focusable,
com.google.gwt.user.client.ui.Focusable, HasWidgets, HasEnabled {
+ private static final String SELECT_ALL_CHECKBOX_CLASSNAME = "-select-all-checkbox";
+
/**
* Enum describing different sections of Grid.
*/
@@ -2535,6 +2537,7 @@ public class Grid<T> extends ResizeComposite implements
private boolean initDone = false;
private boolean selected = false;
+ private CheckBox selectAllCheckBox;
SelectionColumn(final Renderer<Boolean> selectColumnRenderer) {
super(selectColumnRenderer);
@@ -2559,41 +2562,57 @@ public class Grid<T> extends ResizeComposite implements
* exist.
*/
final SelectionModel.Multi<T> model = (Multi<T>) getSelectionModel();
- final CheckBox checkBox = GWT.create(CheckBox.class);
- checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
- @Override
- public void onValueChange(ValueChangeEvent<Boolean> event) {
- if (event.getValue()) {
- fireEvent(new SelectAllEvent<T>(model));
- selected = true;
- } else {
- model.deselectAll();
- selected = false;
- }
- }
- });
- checkBox.setValue(selected);
- selectionCell.setWidget(checkBox);
- // Select all with space when "select all" cell is active
- addHeaderKeyUpHandler(new HeaderKeyUpHandler() {
- @Override
- public void onKeyUp(GridKeyUpEvent event) {
- if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE) {
- return;
- }
- HeaderRow targetHeaderRow = getHeader().getRow(
- event.getFocusedCell().getRowIndex());
- if (!targetHeaderRow.isDefault()) {
- return;
+ if (selectAllCheckBox == null) {
+ selectAllCheckBox = GWT.create(CheckBox.class);
+ selectAllCheckBox.setStylePrimaryName(getStylePrimaryName()
+ + SELECT_ALL_CHECKBOX_CLASSNAME);
+ selectAllCheckBox
+ .addValueChangeHandler(new ValueChangeHandler<Boolean>() {
+
+ @Override
+ public void onValueChange(
+ ValueChangeEvent<Boolean> event) {
+ if (event.getValue()) {
+ fireEvent(new SelectAllEvent<T>(model));
+ selected = true;
+ } else {
+ model.deselectAll();
+ selected = false;
+ }
+ }
+ });
+ selectAllCheckBox.setValue(selected);
+
+ // Select all with space when "select all" cell is active
+ addHeaderKeyUpHandler(new HeaderKeyUpHandler() {
+ @Override
+ public void onKeyUp(GridKeyUpEvent event) {
+ if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE) {
+ return;
+ }
+ HeaderRow targetHeaderRow = getHeader().getRow(
+ event.getFocusedCell().getRowIndex());
+ if (!targetHeaderRow.isDefault()) {
+ return;
+ }
+ if (event.getFocusedCell().getColumn() == SelectionColumn.this) {
+ // Send events to ensure state is updated
+ selectAllCheckBox.setValue(
+ !selectAllCheckBox.getValue(), true);
+ }
}
- if (event.getFocusedCell().getColumn() == SelectionColumn.this) {
- // Send events to ensure row selection state is
- // updated
- checkBox.setValue(!checkBox.getValue(), true);
+ });
+ } else {
+ for (HeaderRow row : header.getRows()) {
+ if (row.getCell(this).getType() == GridStaticCellType.WIDGET) {
+ // Detach from old header.
+ row.getCell(this).setText("");
}
}
- });
+ }
+
+ selectionCell.setWidget(selectAllCheckBox);
}
@Override
@@ -2655,7 +2674,6 @@ public class Grid<T> extends ResizeComposite implements
super.setEditable(editable);
return this;
}
-
}
/**
@@ -6927,11 +6945,21 @@ public class Grid<T> extends ResizeComposite implements
if (args.getIndicesLength() == 0) {
return editor.editorOverlay;
- } else if (args.getIndicesLength() == 1
- && args.getIndex(0) < columns.size()) {
- escalator
- .scrollToColumn(args.getIndex(0), ScrollDestination.ANY, 0);
- return editor.getWidget(columns.get(args.getIndex(0))).getElement();
+ } else if (args.getIndicesLength() == 1) {
+ int index = args.getIndex(0);
+ if (index >= columns.size()) {
+ return null;
+ }
+
+ escalator.scrollToColumn(index, ScrollDestination.ANY, 0);
+ Widget widget = editor.getWidget(columns.get(index));
+
+ if (widget != null) {
+ return widget.getElement();
+ }
+
+ // No widget for the column.
+ return null;
}
return null;
diff --git a/client/tests/src/com/vaadin/client/VBrowserDetailsUserAgentParserTest.java b/client/tests/src/com/vaadin/client/VBrowserDetailsUserAgentParserTest.java
index 62b727e5f5..24bf9b6558 100644
--- a/client/tests/src/com/vaadin/client/VBrowserDetailsUserAgentParserTest.java
+++ b/client/tests/src/com/vaadin/client/VBrowserDetailsUserAgentParserTest.java
@@ -56,6 +56,8 @@ public class VBrowserDetailsUserAgentParserTest extends TestCase {
private static final String ANDROID_MOTOROLA_3_0 = "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13";
private static final String ANDROID_GALAXY_NEXUS_4_0_4_CHROME = "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19";
+ private static final String EDGE_WINDOWS_10 = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240";
+
public void testSafari3() {
VBrowserDetails bd = new VBrowserDetails(SAFARI3_WINDOWS);
assertWebKit(bd);
@@ -423,6 +425,14 @@ public class VBrowserDetailsUserAgentParserTest extends TestCase {
assertWindows(bd, true);
}
+ public void testEdgeWindows10() {
+ VBrowserDetails bd = new VBrowserDetails(EDGE_WINDOWS_10);
+ assertEdge(bd);
+ assertBrowserMajorVersion(bd, 12);
+ assertBrowserMinorVersion(bd, 10240);
+ assertWindows(bd, false);
+ }
+
/*
* Helper methods below
*/
@@ -484,6 +494,7 @@ public class VBrowserDetailsUserAgentParserTest extends TestCase {
assertFalse(browserDetails.isIE());
assertFalse(browserDetails.isOpera());
assertFalse(browserDetails.isSafari());
+ assertFalse(browserDetails.isEdge());
}
private void assertChrome(VBrowserDetails browserDetails) {
@@ -493,6 +504,7 @@ public class VBrowserDetailsUserAgentParserTest extends TestCase {
assertFalse(browserDetails.isIE());
assertFalse(browserDetails.isOpera());
assertFalse(browserDetails.isSafari());
+ assertFalse(browserDetails.isEdge());
}
private void assertIE(VBrowserDetails browserDetails) {
@@ -502,6 +514,7 @@ public class VBrowserDetailsUserAgentParserTest extends TestCase {
assertTrue(browserDetails.isIE());
assertFalse(browserDetails.isOpera());
assertFalse(browserDetails.isSafari());
+ assertFalse(browserDetails.isEdge());
}
private void assertOpera(VBrowserDetails browserDetails) {
@@ -511,6 +524,7 @@ public class VBrowserDetailsUserAgentParserTest extends TestCase {
assertFalse(browserDetails.isIE());
assertTrue(browserDetails.isOpera());
assertFalse(browserDetails.isSafari());
+ assertFalse(browserDetails.isEdge());
}
private void assertSafari(VBrowserDetails browserDetails) {
@@ -520,6 +534,17 @@ public class VBrowserDetailsUserAgentParserTest extends TestCase {
assertFalse(browserDetails.isIE());
assertFalse(browserDetails.isOpera());
assertTrue(browserDetails.isSafari());
+ assertFalse(browserDetails.isEdge());
+ }
+
+ private void assertEdge(VBrowserDetails browserDetails) {
+ // Browser
+ assertFalse(browserDetails.isFirefox());
+ assertFalse(browserDetails.isChrome());
+ assertFalse(browserDetails.isIE());
+ assertFalse(browserDetails.isOpera());
+ assertFalse(browserDetails.isSafari());
+ assertTrue(browserDetails.isEdge());
}
private void assertMacOSX(VBrowserDetails browserDetails) {
diff --git a/eclipse/Super Development Mode (vaadin).launch b/eclipse/Super Development Mode (vaadin).launch
index 361a456e96..b03337e5ff 100644
--- a/eclipse/Super Development Mode (vaadin).launch
+++ b/eclipse/Super Development Mode (vaadin).launch
@@ -23,5 +23,5 @@
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.codeserver.CodeServer"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-noprecompile -strict -bindAddress 0.0.0.0 com.vaadin.DefaultWidgetSet com.vaadin.tests.widgetset.TestingWidgetSet"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="vaadin"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx512M -XX:MaxPermSize=256M"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx1G -XX:MaxPermSize=256M"/>
</launchConfiguration>
diff --git a/scripts/DeployHelpers.py b/scripts/DeployHelpers.py
index 2c879088ff..12c7baaaec 100644
--- a/scripts/DeployHelpers.py
+++ b/scripts/DeployHelpers.py
@@ -12,14 +12,51 @@ except Exception as e:
from requests.auth import HTTPDigestAuth
from os.path import join, expanduser, basename
from BuildHelpers import parser, getArgs
+from time import sleep
parser.add_argument("--deployUrl", help="Wildfly management URL")
parser.add_argument("--deployUser", help="Deployment user", default=None)
parser.add_argument("--deployPass", help="Deployment password", default=None)
+serverUp = None
+
+def testServer():
+ global serverUp
+
+ if serverUp is not None:
+ return serverUp
+
+ print("Checking server status")
+ i = 0
+ request = {"operation" : "read-attribute", "name" : "server-state"}
+ serverUp = False
+ while not serverUp and i < 2:
+ try:
+ print("Trying on url %s" % (getUrl()))
+ result = doPostJson(url=getUrl(), auth=getAuth(), data=json.dumps(request))
+ response = result.json()
+ if "outcome" not in response or response["outcome"] != "success":
+ # Failure
+ raise Exception(response)
+ elif "result" not in response or response["result"] != "running":
+ # Another failure
+ raise Exception(response)
+ # All OK
+ serverUp = True
+ print("Got server connection.")
+ except Exception as e:
+ print("Exception while checking server state: ", e)
+ print("Server connection failed, retrying in 5 seconds.")
+ i = i + 1
+ sleep(5)
+ return serverUp
+
# Helper for handling the full deployment
# name should end with .war
def deployWar(warFile, name=None):
+ if not testServer():
+ raise Exception("Server not up. Skipping deployment.")
+ return
if name is None:
name = basename(warFile).replace('.war', "-%s.war" % (getArgs().version.split('-')[0]))
diff --git a/scripts/GeneratePublishReport.py b/scripts/GeneratePublishReport.py
new file mode 100644
index 0000000000..0293bdbb44
--- /dev/null
+++ b/scripts/GeneratePublishReport.py
@@ -0,0 +1,53 @@
+#coding=UTF-8
+
+import argparse, cgi
+
+parser = argparse.ArgumentParser(description="Post-publish report generator")
+parser.add_argument("version", type=str, help="Vaadin version that was just built")
+parser.add_argument("buildResultUrl", type=str, help="URL for the build result page")
+
+args = parser.parse_args()
+
+(major, minor, maintenance) = args.version.split(".", 2)
+prerelease = "." in maintenance
+if prerelease:
+ maintenance = maintenance.split('.')[0]
+
+content = """<html>
+<head></head>
+<body>
+<table>
+"""
+
+if not prerelease:
+ content += "<tr><td><a href='http://vaadin.com/download/release/{maj}.{min}/{ver}/'>Check {ver} is published to vaadin.com/download</td></tr>".format(maj=major, min=minor, ver=args.version)
+else:
+ content += "<tr><td><a href='http://vaadin.com/download/prerelease/{maj}.{min}/{maj}.{min}.{main}/{ver}'>Check {ver} is published as prerelease to vaadin.com/download</td></tr>".format(maj=major, min=minor, main=maintenance, ver=args.version)
+
+content += """
+<tr><td>Verify Latest Vaadin 7: <iframe src="http://vaadin.com/download/LATEST7"></iframe></td></tr>
+<tr><td>Verify Vaadin 7 Version List: <iframe src="http://vaadin.com/download/VERSIONS_7"></iframe></td></tr>
+<tr><td>Verify Latest Vaadin 7.5: <iframe src="http://vaadin.com/download/release/7.5/LATEST"></iframe></td></tr>
+<tr><td>Verify Latest Vaadin 7.6: <iframe src="http://vaadin.com/download/release/7.6/LATEST"></iframe></td></tr>
+<tr><td>Verify Latest Vaadin 6: <iframe src="http://vaadin.com/download/LATEST"></iframe></td></tr>
+<tr><td>Verify Latest Vaadin 7 Prerelease: <iframe src="http://vaadin.com/download/PRERELEASES"></iframe></td></tr>"""
+
+if not prerelease:
+ content += '<tr><td><a href="https://dev.vaadin.com/admin/ticket/versions">Set latest version to default</a></td></tr>'
+
+content += """
+<tr><td><a href="http://test.vaadin.com/{version}/run/LabelModes?restartApplication">Verify uploaded to test.vaadin.com</a></td></tr>
+<tr><td><a href="https://github.com/vaadin/vaadin/tags">Verify tags pushed to GitHub</a></td></tr>""".format(version=args.version)
+
+if not prerelease:
+ content += '<tr><td><a href="http://vaadin.com/api">Verify API version list updated</a></td></tr>'
+
+content += """
+<tr><td><a href="https://dev.vaadin.com/query?status=pending-release&component=Core+Framework&resolution=fixed&milestone=Vaadin {version}&col=id&col=summary&col=component&col=milestone&col=status&col=type">Batch update tickets in Trac</a></td></tr>
+<tr><td><a href="{url}">Publish result page (See test results, pin and tag build and dependencies)</a></td></tr>
+</table>
+</body>
+</html>""".format(url=args.buildResultUrl, version=args.version)
+
+f = open("result/report.html", 'w')
+f.write(content)
diff --git a/scripts/GenerateStagingReport.py b/scripts/GenerateStagingReport.py
index cf53928379..23977aa933 100644
--- a/scripts/GenerateStagingReport.py
+++ b/scripts/GenerateStagingReport.py
@@ -9,6 +9,7 @@ parser.add_argument("version", type=str, help="Vaadin version that was just buil
parser.add_argument("deployUrl", type=str, help="Base url of the deployment server")
parser.add_argument("buildResultUrl", type=str, help="URL for the build result page")
parser.add_argument("stagingRepo", type=str, help="URL for the staging repository")
+parser.add_argument("tbapiUrl", type=str, help="URL for the TestBench API build")
args = parser.parse_args()
@@ -35,12 +36,48 @@ content += cgi.escape(""" <ibiblio name="vaadin-staging" usepoms="true" m2compat
root="{repoUrl}" />""".format(repoUrl=args.stagingRepo))
content += """</pre>
</td></tr>
-<tr><td><a href="https://dev.vaadin.com/milestone/Vaadin {version}">Trac Milestone</a></td></tr>
+<tr><td><a href="https://dev.vaadin.com/milestone/Vaadin {version}">Close Trac Milestone</a></td></tr>
+<tr><td><a href="https://dev.vaadin.com/query?status=pending-release&component=Core+Framework&resolution=fixed&col=id&col=summary&col=component&col=milestone&col=status&col=type">Verify pending release tickets still have milestone {version}</a></td></tr>
<tr><td><a href="https://dev.vaadin.com/admin/ticket/versions">Add version {version} to Trac</td></tr>
<tr><td><a href="{url}">Staging result page (See test results, pin and tag build and dependencies)</a></td></tr>
+<tr><td>Commands to tag all repositories (warning: do not run as a single script but set variables and check before any push commands - this has not been tested yet and the change IDs are missing)</td></tr>
+<tr><td><pre>
+VERSION={version}
+
+GERRIT_USER=[fill in your gerrit username]
+FRAMEWORK_REVISION=[fill in framework revision]
+SCREENSHOTS_REVISION=[fill in screenshot repository revision]
+ARCHETYPES_REVISION=[fill in maven-integration repository revision]
+PLUGIN_REVISION=[fill in maven plug-in repository revision]
+
+git clone ssh://$GERRIT_USER@dev.vaadin.com:29418/vaadin
+cd vaadin
+git tag -a -m"$VERSION" $VERSION $FRAMEWORK_REVISION
+git push --tags
+cd ..
+
+git clone ssh://$GERRIT_USER@dev.vaadin.com:29418/vaadin-screenshots
+cd vaadin-screenshots
+git tag -a -m"$VERSION" $VERSION $SCREENSHOTS_REVISION
+git push --tags
+cd ..
+
+git clone ssh://$GERRIT_USER@dev.vaadin.com:29418/maven-integration
+cd maven-integration
+git tag -a -m"$VERSION" $VERSION $ARCHETYPES_REVISION
+git push --tags
+cd ..
+
+git clone ssh://$GERRIT_USER@dev.vaadin.com:29418/maven-plugin
+cd maven-plugin
+git tag -a -m"$VERSION" $VERSION $PLUGIN_REVISION
+git push --tags
+cd ..
+</pre></td></tr>
+<tr><td><a href="{tbapi}">Build and publish TestBench API for version {version} if proceeding</a></td></tr>
</table>
</body>
-</html>""".format(url=args.buildResultUrl, repoUrl=args.stagingRepo, version=args.version)
+</html>""".format(url=args.buildResultUrl, repoUrl=args.stagingRepo, version=args.version, tbapi=args.tbapiUrl)
f = open("result/report.html", 'w')
f.write(content)
diff --git a/server/ivy.xml b/server/ivy.xml
index e9bc8b818d..0711b4b2ea 100644
--- a/server/ivy.xml
+++ b/server/ivy.xml
@@ -36,7 +36,7 @@
<!-- Google App Engine -->
<dependency org="com.google.appengine" name="appengine-api-1.0-sdk"
- rev="1.2.1" conf="build-provided,ide,test -> default" />
+ rev="1.7.7" conf="build-provided,ide,test -> default" />
<!-- Bean Validation API -->
<dependency org="javax.validation" name="validation-api"
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index 7aada2402d..61df02feaa 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -28,6 +28,7 @@ import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
+import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -694,17 +695,20 @@ public class VaadinServlet extends HttpServlet implements Constants {
return false;
}
+ String decodedRequestURI = URLDecoder.decode(request.getRequestURI(),
+ "UTF-8");
if ((request.getContextPath() != null)
- && (request.getRequestURI().startsWith("/VAADIN/"))) {
- serveStaticResourcesInVAADIN(request.getRequestURI(), request,
- response);
+ && (decodedRequestURI.startsWith("/VAADIN/"))) {
+ serveStaticResourcesInVAADIN(decodedRequestURI, request, response);
return true;
- } else if (request.getRequestURI().startsWith(
- request.getContextPath() + "/VAADIN/")) {
+ }
+
+ String decodedContextPath = URLDecoder.decode(request.getContextPath(),
+ "UTF-8");
+ if (decodedRequestURI.startsWith(decodedContextPath + "/VAADIN/")) {
serveStaticResourcesInVAADIN(
- request.getRequestURI().substring(
- request.getContextPath().length()), request,
- response);
+ decodedRequestURI.substring(decodedContextPath.length()),
+ request, response);
return true;
}
diff --git a/server/src/com/vaadin/server/WebBrowser.java b/server/src/com/vaadin/server/WebBrowser.java
index 66018b02f2..9bf30cb3db 100644
--- a/server/src/com/vaadin/server/WebBrowser.java
+++ b/server/src/com/vaadin/server/WebBrowser.java
@@ -126,6 +126,20 @@ public class WebBrowser implements Serializable {
}
/**
+ * Tests whether the user is using Edge.
+ *
+ * @return true if the user is using Edge, false if the user is not using
+ * Edge or if no information on the browser is present
+ */
+ public boolean isEdge() {
+ if (browserDetails == null) {
+ return false;
+ }
+
+ return browserDetails.isEdge();
+ }
+
+ /**
* Tests whether the user is using Safari.
*
* @return true if the user is using Safari, false if the user is not using
diff --git a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
index 357278f411..a45d9aa059 100644
--- a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
+++ b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
@@ -274,6 +274,13 @@ public class AtmospherePushConnection implements PushConnection {
public void disconnect() {
assert isConnected();
+ if (resource == null) {
+ // Already disconnected. Should not happen but if it does, we don't
+ // want to cause NPEs
+ getLogger()
+ .fine("AtmospherePushConnection.disconnect() called twice, this should not happen");
+ return;
+ }
if (resource.isResumed()) {
// This can happen for long polling because of
// http://dev.vaadin.com/ticket/16919
diff --git a/server/src/com/vaadin/server/communication/FileUploadHandler.java b/server/src/com/vaadin/server/communication/FileUploadHandler.java
index 576cbd8411..532c7fe95b 100644
--- a/server/src/com/vaadin/server/communication/FileUploadHandler.java
+++ b/server/src/com/vaadin/server/communication/FileUploadHandler.java
@@ -269,7 +269,7 @@ public class FileUploadHandler implements RequestHandler {
streamVariable = uI.getConnectorTracker().getStreamVariable(
connectorId, variableName);
String secKey = uI.getConnectorTracker().getSeckey(streamVariable);
- if (!secKey.equals(parts[3])) {
+ if (secKey == null || !secKey.equals(parts[3])) {
// TODO Should rethink error handling
return true;
}
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index bee424e98f..c7ad9632fa 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -1167,6 +1167,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
private int selectionLimit = DEFAULT_MAX_SELECTIONS;
+ private boolean allSelected;
+
@Override
public boolean select(final Object... itemIds)
throws IllegalArgumentException {
@@ -1212,6 +1214,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
fireSelectionEvent(oldSelection, selection);
}
+
+ updateAllSelectedState();
+
return selectionWillChange;
}
@@ -1277,6 +1282,9 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
selection.removeAll(itemIds);
fireSelectionEvent(oldSelection, selection);
}
+
+ updateAllSelectedState();
+
return hasCommonElements;
}
@@ -1357,6 +1365,8 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
fireSelectionEvent(oldSelection, selection);
}
+ updateAllSelectedState();
+
return changed;
}
@@ -1370,6 +1380,13 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
"Vararg array of itemIds may not be null");
}
}
+
+ private void updateAllSelectedState() {
+ if (allSelected != selection.size() >= selectionLimit) {
+ allSelected = selection.size() >= selectionLimit;
+ grid.getRpcProxy(GridClientRpc.class).setSelectAll(allSelected);
+ }
+ }
}
/**
@@ -3648,10 +3665,21 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
safeConverter.getPresentationType(), locale);
}
- JsonValue encodedValue = renderer.encode(presentationValue);
+ JsonValue encodedValue;
+ try {
+ encodedValue = renderer.encode(presentationValue);
+ } catch (Exception e) {
+ getLogger().log(Level.SEVERE, "Unable to encode data", e);
+ encodedValue = renderer.encode(null);
+ }
return encodedValue;
}
+
+ private static Logger getLogger() {
+ return Logger.getLogger(AbstractRenderer.class.getName());
+ }
+
}
/**
diff --git a/server/src/com/vaadin/ui/HorizontalLayout.java b/server/src/com/vaadin/ui/HorizontalLayout.java
index 54569570b9..616fa09225 100644
--- a/server/src/com/vaadin/ui/HorizontalLayout.java
+++ b/server/src/com/vaadin/ui/HorizontalLayout.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.ui;
+import com.vaadin.shared.ui.orderedlayout.HorizontalLayoutState;
+
/**
* Horizontal layout
*
@@ -48,4 +50,9 @@ public class HorizontalLayout extends AbstractOrderedLayout {
addComponents(children);
}
+ @Override
+ protected HorizontalLayoutState getState() {
+ return (HorizontalLayoutState) super.getState();
+ }
+
}
diff --git a/server/src/com/vaadin/ui/VerticalLayout.java b/server/src/com/vaadin/ui/VerticalLayout.java
index 12819e50bc..7002fbc7e6 100644
--- a/server/src/com/vaadin/ui/VerticalLayout.java
+++ b/server/src/com/vaadin/ui/VerticalLayout.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.ui;
+import com.vaadin.shared.ui.orderedlayout.VerticalLayoutState;
+
/**
* Vertical layout
*
@@ -48,4 +50,9 @@ public class VerticalLayout extends AbstractOrderedLayout {
this();
addComponents(children);
}
+
+ @Override
+ protected VerticalLayoutState getState() {
+ return (VerticalLayoutState) super.getState();
+ }
}
diff --git a/server/src/com/vaadin/ui/renderers/ImageRenderer.java b/server/src/com/vaadin/ui/renderers/ImageRenderer.java
index 2fb872583e..ad7d5cae2b 100644
--- a/server/src/com/vaadin/ui/renderers/ImageRenderer.java
+++ b/server/src/com/vaadin/ui/renderers/ImageRenderer.java
@@ -58,7 +58,7 @@ public class ImageRenderer extends ClickableRenderer<Resource> {
if (!(resource == null || resource instanceof ExternalResource || resource instanceof ThemeResource)) {
throw new IllegalArgumentException(
"ImageRenderer only supports ExternalResource and ThemeResource ("
- + resource.getClass().getSimpleName() + "given )");
+ + resource.getClass().getSimpleName() + " given)");
}
return encode(ResourceReference.create(resource, this, null),
diff --git a/server/tests/src/com/vaadin/server/communication/FileUploadHandlerTest.java b/server/tests/src/com/vaadin/server/communication/FileUploadHandlerTest.java
index 2cb4c3bf4d..286163541e 100644
--- a/server/tests/src/com/vaadin/server/communication/FileUploadHandlerTest.java
+++ b/server/tests/src/com/vaadin/server/communication/FileUploadHandlerTest.java
@@ -15,50 +15,136 @@
*/
package com.vaadin.server.communication;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mockito;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import com.vaadin.server.ClientConnector;
+import com.vaadin.server.ServletPortletHelper;
+import com.vaadin.server.StreamVariable;
import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinResponse;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.ui.ConnectorTracker;
+import com.vaadin.ui.UI;
-/**
- * Tests whether we get infinite loop if InputStream is already read (#10096)
- */
public class FileUploadHandlerTest {
private FileUploadHandler handler;
- private VaadinRequest request;
+ @Mock private VaadinResponse response;
+ @Mock private StreamVariable streamVariable;
+ @Mock private ClientConnector clientConnector;
+ @Mock private VaadinRequest request;
+ @Mock private UI ui;
+ @Mock private ConnectorTracker connectorTracker;
+ @Mock private VaadinSession session;
+ @Mock private OutputStream responseOutput;
+
+ private int uiId = 123;
+ private final String connectorId = "connectorId";
+ private final String variableName = "name";
+ private final String expectedSecurityKey = "key";
@Before
public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
handler = new FileUploadHandler();
- InputStream inputStream = new InputStream() {
- private int counter = 0;
+
+ mockRequest();
+ mockConnectorTracker();
+ mockUi();
+
+ when(clientConnector.isConnectorEnabled()).thenReturn(true);
+ when(streamVariable.getOutputStream()).thenReturn(mock(OutputStream.class));
+ when(response.getOutputStream()).thenReturn(responseOutput);
+ }
+
+ private void mockConnectorTracker() {
+ when(connectorTracker.getSeckey(streamVariable)).thenReturn(expectedSecurityKey);
+ when(connectorTracker.getStreamVariable(connectorId, variableName)).thenReturn(streamVariable);
+ when(connectorTracker.getConnector(connectorId)).thenReturn(clientConnector);
+ }
+
+ private void mockRequest() throws IOException {
+ when(request.getPathInfo()).thenReturn("/" + ServletPortletHelper.UPLOAD_URL_PREFIX + uiId + "/"+ connectorId + "/" + variableName + "/" + expectedSecurityKey);
+ when(request.getInputStream()).thenReturn(createInputStream("foobar"));
+ when(request.getHeader("Content-Length")).thenReturn("6");
+ when(request.getContentType()).thenReturn("foobar");
+ }
+
+ private InputStream createInputStream(final String content) {
+ return new InputStream() {
+ int counter = 0;
+ byte[] msg = content.getBytes();
@Override
public int read() throws IOException {
- counter++;
- if (counter > 6) {
- throw new RuntimeException(
- "-1 is ignored by FileUploadHandler");
+ if(counter > msg.length + 1) {
+ throw new AssertionError("-1 was ignored by FileUploadHandler.");
+ }
+
+ if(counter >= msg.length) {
+ counter++;
+ return -1;
}
- return -1;
- }
+ return msg[counter++];
+ }
};
- request = Mockito.mock(VaadinRequest.class);
- Mockito.when(request.getInputStream()).thenReturn(inputStream);
- Mockito.when(request.getHeader("Content-Length")).thenReturn("211");
}
+ private void mockUi() {
+ when(ui.getConnectorTracker()).thenReturn(connectorTracker);
+ when(session.getUIById(uiId)).thenReturn(ui);
+ }
+
+ /**
+ * Tests whether we get infinite loop if InputStream is already read (#10096)
+ */
@Test(expected = IOException.class)
- public void testStreamEnded() throws IOException {
+ public void exceptionIsThrownOnUnexpectedEnd() throws IOException {
+ when(request.getInputStream()).thenReturn(createInputStream(""));
+ when(request.getHeader("Content-Length")).thenReturn("1");
+
handler.doHandleSimpleMultipartFileUpload(null, request, null, null,
null, null, null);
+ }
+
+ @Test
+ public void responseIsSentOnCorrectSecurityKey() throws IOException {
+ when(connectorTracker.getSeckey(streamVariable)).thenReturn(expectedSecurityKey);
+
+ handler.handleRequest(session, request, response);
+ verify(responseOutput).close();
}
+ @Test
+ public void responseIsNotSentOnIncorrectSecurityKey() throws IOException {
+ when(connectorTracker.getSeckey(streamVariable)).thenReturn("another key expected");
+
+ handler.handleRequest(session, request, response);
+
+ verifyZeroInteractions(responseOutput);
+ }
+
+ @Test
+ public void responseIsNotSentOnMissingSecurityKey() throws IOException {
+ when(connectorTracker.getSeckey(streamVariable)).thenReturn(null);
+
+ handler.handleRequest(session, request, response);
+
+ verifyZeroInteractions(responseOutput);
+ }
}
diff --git a/shared/src/com/vaadin/shared/VBrowserDetails.java b/shared/src/com/vaadin/shared/VBrowserDetails.java
index 561b6c76d0..d0de8ffb9f 100644
--- a/shared/src/com/vaadin/shared/VBrowserDetails.java
+++ b/shared/src/com/vaadin/shared/VBrowserDetails.java
@@ -41,6 +41,7 @@ public class VBrowserDetails implements Serializable {
private boolean isFirefox = false;
private boolean isOpera = false;
private boolean isIE = false;
+ private boolean isEdge = false;
private boolean isPhantomJS = false;
private boolean isWindowsPhone;
@@ -88,6 +89,16 @@ public class VBrowserDetails implements Serializable {
isSafari = !isChrome && !isIE && userAgent.indexOf("safari") != -1;
isFirefox = userAgent.indexOf(" firefox/") != -1;
isPhantomJS = userAgent.indexOf("phantomjs/") != -1;
+ if (userAgent.indexOf(" edge/") != -1) {
+ isEdge = true;
+ isChrome = false;
+ isOpera = false;
+ isIE = false;
+ isSafari = false;
+ isFirefox = false;
+ isWebKit = false;
+ isGecko = false;
+ }
// chromeframe
isChromeFrameCapable = userAgent.indexOf("chromeframe") != -1;
@@ -115,6 +126,8 @@ public class VBrowserDetails implements Serializable {
tmp = tmp.replaceFirst("([0-9]+\\.[0-9]+).*", "$1");
browserEngineVersion = Float.parseFloat(tmp);
}
+ } else if (isEdge) {
+ browserEngineVersion = 0;
}
} catch (Exception e) {
// Browser engine version parsing failed
@@ -158,6 +171,9 @@ public class VBrowserDetails implements Serializable {
i = userAgent.indexOf("opera/") + 6;
}
parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } else if (isEdge) {
+ int i = userAgent.indexOf(" edge/") + 6;
+ parseVersionString(safeSubstring(userAgent, i, i + 8));
}
} catch (Exception e) {
// Browser version parsing failed
@@ -373,6 +389,15 @@ public class VBrowserDetails implements Serializable {
}
/**
+ * Tests if the browser is Edge.
+ *
+ * @return true if it is Edge, false otherwise
+ */
+ public boolean isEdge() {
+ return isEdge;
+ }
+
+ /**
* Tests if the browser is PhantomJS.
*
* @return true if it is PhantomJS, false otherwise
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java b/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java
index ac1b1d5a78..8711a757a1 100644
--- a/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java
+++ b/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java
@@ -55,4 +55,15 @@ public interface GridClientRpc extends ClientRpc {
* Command client Grid to recalculate column widths.
*/
public void recalculateColumnWidths();
+
+ /**
+ * Informs the Grid that all items have been selected or not selected on the
+ * server side.
+ *
+ * @since 7.5.3
+ * @param allSelected
+ * <code>true</code> to check the select all checkbox,
+ * <code>false</code> to uncheck it.
+ */
+ public void setSelectAll(boolean allSelected);
}
diff --git a/uitest/integration_tests.xml b/uitest/integration_tests.xml
index d56ba2683f..bdbf1f2e5b 100644
--- a/uitest/integration_tests.xml
+++ b/uitest/integration_tests.xml
@@ -404,7 +404,8 @@
<antcall target="integration-test-osgi" />
<antcall target="integration-test-tomcat7apacheproxy" />
<antcall target="integration-test-websphere8" />
- <antcall target="integration-test-websphereportal8" />
+ <!-- Currently the test system does not have a server for automatic testing of WebSphere Portal 8 -->
+ <!-- <antcall target="integration-test-websphereportal8" /> -->
</parallel>
</target>
diff --git a/uitest/ivy.xml b/uitest/ivy.xml
index 8f2765c7a4..281ba1ecdf 100644
--- a/uitest/ivy.xml
+++ b/uitest/ivy.xml
@@ -31,7 +31,7 @@
rev="4.2.0.Final" conf="build,ide -> default" />
<!-- Google App Engine -->
<dependency org="com.google.appengine" name="appengine-api-1.0-sdk"
- rev="1.2.1" conf="build-provided,ide -> default" />
+ rev="1.7.7" conf="build-provided,ide -> default" />
<!-- LIBRARY DEPENDENCIES (compile time) -->
<!-- Project modules -->
diff --git a/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java b/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java
index c6ccd1bf4c..ed0f1a9b4f 100644
--- a/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java
+++ b/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java
@@ -40,7 +40,7 @@ public class VerifyBrowserVersionTest extends MultiBrowserTest {
// Chrome version does not necessarily match the desired version
// because of auto updates...
browserIdentifier = getExpectedUserAgentString(getDesiredCapabilities())
- + "43";
+ + "44";
} else {
browserIdentifier = getExpectedUserAgentString(desiredCapabilities)
+ desiredCapabilities.getVersion();
diff --git a/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandler.java b/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandler.java
index c2dfdb26c1..40dd43abb2 100644
--- a/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandler.java
+++ b/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandler.java
@@ -5,17 +5,27 @@ import java.text.SimpleDateFormat;
import java.util.Locale;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.ui.Calendar;
import com.vaadin.ui.components.calendar.CalendarComponentEvents;
+import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventClick;
+import com.vaadin.ui.components.calendar.CalendarComponentEvents.EventClickHandler;
import com.vaadin.ui.components.calendar.event.BasicEvent;
-public class NullEventMoveHandler extends AbstractTestUI {
+public class NullEventMoveHandler extends AbstractTestUIWithLog {
@Override
protected void setup(VaadinRequest request) {
Calendar calendar = getCalendar();
calendar.setHandler((CalendarComponentEvents.EventMoveHandler) null);
+ calendar.setHandler(new EventClickHandler() {
+
+ @Override
+ public void eventClick(EventClick event) {
+ log("Clicked on " + event.getCalendarEvent().getCaption());
+
+ }
+ });
addComponent(calendar);
}
diff --git a/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandlerTest.java b/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandlerTest.java
index c40cd9ce97..156100310c 100644
--- a/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandlerTest.java
+++ b/uitest/src/com/vaadin/tests/components/calendar/NullEventMoveHandlerTest.java
@@ -3,6 +3,7 @@ package com.vaadin.tests.components.calendar;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import org.junit.Assert;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
@@ -23,11 +24,25 @@ public class NullEventMoveHandlerTest extends DndActionsTest {
}
@Test
+ public void eventIsClickableWhenNotMovableInMonthView() {
+ getEvent().click();
+ Assert.assertEquals("1. Clicked on foo", getLogRow(0));
+ }
+
+ @Test
public void eventIsNotMovableInWeekView() {
openWeekView();
assertEventCannotBeMoved();
}
+ @Test
+ public void eventIsClickableWhenNotMovableInWeekView() {
+ openWeekView();
+ getEvent().findElement(By.className("v-calendar-event-caption"))
+ .click();
+ Assert.assertEquals("1. Clicked on foo", getLogRow(0));
+ }
+
private void assertEventCannotBeMoved() {
int originalPosition = getEventXPosition();
diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrolling.java b/uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrolling.java
new file mode 100644
index 0000000000..9f1c4b9e03
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrolling.java
@@ -0,0 +1,40 @@
+package com.vaadin.tests.components.combobox;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.HorizontalLayout;
+
+@Theme("valo")
+public class ComboboxPopupScrolling extends AbstractTestUIWithLog {
+ @Override
+ protected void setup(VaadinRequest request) {
+ ComboBox combobox = new ComboBox("100px wide combobox");
+ combobox.setWidth("100px");
+ combobox.addItem("AMERICAN SAMOA");
+ combobox.addItem("ANTIGUA AND BARBUDA");
+
+ ComboBox combobox2 = new ComboBox("250px wide combobox");
+ combobox2.setWidth("250px");
+ combobox2.addItem("AMERICAN SAMOA");
+ combobox2.addItem("ANTIGUA AND BARBUDA");
+
+ ComboBox combobox3 = new ComboBox("Undefined wide combobox");
+ combobox3.setWidth(null);
+ combobox3.addItem("AMERICAN SAMOA");
+ combobox3.addItem("ANTIGUA AND BARBUDA");
+
+ ComboBox combobox4 = new ComboBox("Another 100px wide combobox");
+ combobox4.setWidth("100px");
+ for (int i = 0; i < 10; i++) {
+ combobox4.addItem("AMERICAN SAMOA " + i);
+ combobox4.addItem("ANTIGUA AND BARBUDA " + i);
+ }
+
+ HorizontalLayout hl = new HorizontalLayout(combobox, combobox2,
+ combobox3, combobox4);
+ addComponent(hl);
+ }
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrollingTest.java b/uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrollingTest.java
new file mode 100644
index 0000000000..ec5bc088da
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/combobox/ComboboxPopupScrollingTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2014 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.combobox;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class ComboboxPopupScrollingTest extends MultiBrowserTest {
+
+ @Test
+ public void testNoScrollbarsValo() {
+ testNoScrollbars("valo");
+ }
+
+ @Test
+ public void testNoScrollbarsChameleon() {
+ testNoScrollbars("chameleon");
+ }
+
+ @Test
+ public void testNoScrollbarsRuno() {
+ testNoScrollbars("runo");
+ }
+
+ @Test
+ public void testNoScrollbarsReindeer() {
+ testNoScrollbars("reindeer");
+ }
+
+ private void testNoScrollbars(String theme) {
+ openTestURL("theme=" + theme);
+
+ for (CustomComboBoxElement cb : $(CustomComboBoxElement.class).all()) {
+ String caption = cb.getCaption();
+ cb.openPopup();
+ WebElement popup = cb.getSuggestionPopup();
+ WebElement scrollable = popup.findElement(By
+ .className("v-filterselect-suggestmenu"));
+ assertNoHorizontalScrollbar(scrollable, caption);
+ assertNoVerticalScrollbar(scrollable, caption);
+ }
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/combobox/CustomComboBoxElement.java b/uitest/src/com/vaadin/tests/components/combobox/CustomComboBoxElement.java
new file mode 100644
index 0000000000..697d5eb932
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/combobox/CustomComboBoxElement.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 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.combobox;
+
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.ComboBoxElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.ComboBox")
+public class CustomComboBoxElement extends ComboBoxElement {
+ private static org.openqa.selenium.By bySuggestionPopup = By
+ .vaadin("#popup");
+
+ public WebElement getSuggestionPopup() {
+ ensurePopupOpen();
+ return findElement(bySuggestionPopup);
+ }
+
+ private void ensurePopupOpen() {
+ if (!isElementPresent(bySuggestionPopup)) {
+ openPopup();
+ }
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java b/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java
index f20cc0f6f4..33f66d35be 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java
@@ -23,7 +23,6 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
-import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
@@ -313,10 +312,6 @@ public class GridDetailsLocationTest extends MultiBrowserTest {
checkBoxElement.click(5, 5);
}
- private Object executeScript(String string, Object... param) {
- return ((JavascriptExecutor) getDriver()).executeScript(string, param);
- }
-
private void scrollAndToggle(int row) {
setRow(row);
getScrollAndToggle().click();
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRenderer.java b/uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRenderer.java
new file mode 100644
index 0000000000..4d44eeb248
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRenderer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 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.grid;
+
+import com.vaadin.server.ClassResource;
+import com.vaadin.server.Resource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.tests.integration.FlagSeResource;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.renderers.ImageRenderer;
+
+public class GridWithBrokenRenderer extends AbstractTestUIWithLog {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Grid grid = new Grid();
+ grid.addColumn("short", String.class);
+ grid.addColumn("icon", Resource.class);
+ grid.addColumn("country", String.class);
+
+ grid.getColumn("icon").setRenderer(new ImageRenderer());
+ addComponent(grid);
+
+ grid.addRow("FI", new ClassResource("fi.gif"), "Finland");
+ grid.addRow("SE", new FlagSeResource(), "Sweden");
+
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRendererTest.java b/uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRendererTest.java
new file mode 100644
index 0000000000..011c8c92ce
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridWithBrokenRendererTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 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.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class GridWithBrokenRendererTest extends SingleBrowserTest {
+
+ @Test
+ public void ensureRendered() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+ assertRow(grid, 0, "FI", "", "Finland");
+ assertRow(grid, 1, "SE", "", "Sweden");
+ }
+
+ private void assertRow(GridElement grid, int row, String... texts) {
+ for (int column = 0; column < texts.length; column++) {
+ Assert.assertEquals("Cell " + row + "," + column, texts[column],
+ grid.getCell(row, column).getText());
+ }
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
index 33a54b1c9a..23226fb6cf 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -792,6 +792,26 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
c.setColumnReorderingAllowed(value);
}
});
+
+ createClickAction("Select all", "State", new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ SelectionModel selectionModel = c.getSelectionModel();
+ if (selectionModel instanceof SelectionModel.Multi) {
+ ((SelectionModel.Multi) selectionModel).selectAll();
+ }
+ }
+ }, null);
+
+ createClickAction("Select none", "State", new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ SelectionModel selectionModel = c.getSelectionModel();
+ if (selectionModel instanceof SelectionModel.Multi) {
+ ((SelectionModel.Multi) selectionModel).deselectAll();
+ }
+ }
+ }, null);
}
protected void createHeaderActions() {
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java
index 0a77d690a4..0cba2ce34b 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java
@@ -207,6 +207,8 @@ public abstract class GridEditorTest extends GridBasicFeaturesTest {
assertTrue("Noneditable cell should contain v-grid-cell classname",
classNames.contains("v-grid-cell"));
+
+ assertNoErrorNotifications();
}
@Test
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
index 9953bbcae0..8bf8639d76 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
@@ -20,8 +20,10 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.ui.ExpectedCondition;
import com.vaadin.testbench.By;
import com.vaadin.testbench.elements.GridElement;
@@ -335,6 +337,62 @@ public class GridSelectionTest extends GridBasicFeaturesTest {
getRow(5).isSelected());
}
+ @Test
+ public void testSelectionCheckBoxesHaveStyleNames() {
+ openTestURL();
+
+ setSelectionModelMulti();
+
+ assertTrue(
+ "Selection column CheckBox should have the proper style name set",
+ getGridElement().getCell(0, 0).findElement(By.tagName("span"))
+ .getAttribute("class")
+ .contains("v-grid-selection-checkbox"));
+
+ GridCellElement header = getGridElement().getHeaderCell(0, 0);
+ assertTrue("Select all CheckBox should have the proper style name set",
+ header.findElement(By.tagName("span")).getAttribute("class")
+ .contains("v-grid-select-all-checkbox"));
+ }
+
+ @Test
+ public void testServerSideSelectTogglesSelectAllCheckBox() {
+ openTestURL();
+
+ setSelectionModelMulti();
+ GridCellElement header = getGridElement().getHeaderCell(0, 0);
+
+ WebElement selectAll = header.findElement(By.tagName("input"));
+
+ selectMenuPath("Component", "State", "Select all");
+ waitUntilCheckBoxValue(selectAll, true);
+ assertTrue("Select all CheckBox wasn't selected as expected",
+ selectAll.isSelected());
+
+ selectMenuPath("Component", "State", "Select none");
+ waitUntilCheckBoxValue(selectAll, false);
+ assertFalse("Select all CheckBox was selected unexpectedly",
+ selectAll.isSelected());
+
+ selectMenuPath("Component", "State", "Select all");
+ waitUntilCheckBoxValue(selectAll, true);
+ getGridElement().getCell(5, 0).click();
+ waitUntilCheckBoxValue(selectAll, false);
+ assertFalse("Select all CheckBox was selected unexpectedly",
+ selectAll.isSelected());
+ }
+
+ private void waitUntilCheckBoxValue(final WebElement checkBoxElememnt,
+ final boolean expectedValue) {
+ waitUntil(new ExpectedCondition<Boolean>() {
+ @Override
+ public Boolean apply(WebDriver input) {
+ return expectedValue ? checkBoxElememnt.isSelected()
+ : !checkBoxElememnt.isSelected();
+ }
+ }, 5);
+ }
+
private void setSelectionModelMulti() {
selectMenuPath("Component", "State", "Selection mode", "multi");
}
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanel.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanel.java
new file mode 100644
index 0000000000..b2313020a3
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanel.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 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.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalSplitPanel;
+import com.vaadin.ui.themes.ValoTheme;
+
+@Theme("valo")
+public class TabSheetInSplitPanel extends UI {
+
+ @Override
+ protected void init(VaadinRequest request) {
+ VerticalSplitPanel verticalSplitter = new VerticalSplitPanel();
+ setContent(verticalSplitter);
+ verticalSplitter.setSizeFull();
+ TabSheet t = new TabSheet();
+ t.setHeight("100%");
+ t.addTab(new Label("Hello in tab"), "Hello tab");
+ t.setStyleName(ValoTheme.TABSHEET_FRAMED);
+ verticalSplitter.addComponent(t);
+ verticalSplitter.addComponent(new Label("Hello"));
+
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanelTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanelTest.java
new file mode 100644
index 0000000000..8070133bde
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSheetInSplitPanelTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 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.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.TabSheetElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TabSheetInSplitPanelTest extends MultiBrowserTest {
+
+ @Test
+ public void ensureNoScrollbars() {
+ openTestURL();
+ TabSheetElement ts = $(TabSheetElement.class).first();
+ List<WebElement> scrollables = ts.findElements(By
+ .xpath("//*[contains(@class,'v-scrollable')]"));
+ for (WebElement scrollable : scrollables) {
+ assertNoHorizontalScrollbar(scrollable,
+ "Element should not have a horizontal scrollbar");
+ assertNoVerticalScrollbar(scrollable,
+ "Element should not have a vertical scrollbar");
+ }
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpand.java b/uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpand.java
new file mode 100644
index 0000000000..07cf7f8c2e
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpand.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2014 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.treetable;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.TreeTable;
+
+public class TreeTableScrollOnExpand extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ TreeTable t = new TreeTable();
+ t.setSelectable(true);
+ t.setImmediate(true);
+ t.setSizeFull();
+ t.addContainerProperty("Name", String.class, "null");
+ for (int i = 1; i <= 100; i++) {
+ String parentID = "Item " + i;
+ Object parent = t.addItem(new Object[] { parentID }, parentID);
+ String childID = "Item " + (100 + i);
+ Object child = t.addItem(new Object[] { childID }, childID);
+ t.getContainerDataSource().setParent(childID, parentID);
+ }
+ addComponent(t);
+ }
+
+ @Override
+ public Integer getTicketNumber() {
+ return 18247;
+ }
+
+ @Override
+ public String getTestDescription() {
+ return "After selecting an item and scrolling it out of view, TreeTable should not scroll to the "
+ + "selected item when expanding an item.";
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpandTest.java b/uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpandTest.java
new file mode 100644
index 0000000000..a17559cc81
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/treetable/TreeTableScrollOnExpandTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 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.treetable;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.TreeTableElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TreeTableScrollOnExpandTest extends MultiBrowserTest {
+
+ @Test
+ public void testScrollOnExpand() throws InterruptedException, IOException {
+ openTestURL();
+ TreeTableElement tt = $(TreeTableElement.class).first();
+ tt.getRow(0).click();
+ tt.scroll(300);
+ sleep(1000);
+ tt.getRow(20).toggleExpanded();
+ // Need to wait a bit to avoid accepting the case where the TreeTable is
+ // in the desired state only for a short while.
+ sleep(1000);
+ WebElement focusedRow = getDriver().findElement(
+ By.className("v-table-focus"));
+ assertEquals("Item 21", focusedRow.getText());
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/window/GridInWindow.java b/uitest/src/com/vaadin/tests/components/window/GridInWindow.java
new file mode 100644
index 0000000000..918a991cc1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/GridInWindow.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 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.AbstractTestUIWithLog;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Window;
+
+public class GridInWindow extends AbstractTestUIWithLog {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Grid grid = new Grid();
+
+ grid.addColumn("Hidable column").setHidable(true);
+ grid.addRow("Close and reopen and it vanishes");
+
+ Button popupButton = new Button("Open PopUp",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(Button.ClickEvent event) {
+ Window subWindow = new Window("Sub-window");
+ subWindow.setContent(grid);
+ subWindow.setWidth(600, Unit.PIXELS);
+ subWindow.setWidth(400, Unit.PIXELS);
+ getUI().addWindow(subWindow);
+ }
+ });
+
+ addComponent(popupButton);
+
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/window/GridInWindowTest.java b/uitest/src/com/vaadin/tests/components/window/GridInWindowTest.java
new file mode 100644
index 0000000000..301a7c60e4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/GridInWindowTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 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 org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+import com.vaadin.tests.tb3.newelements.WindowElement;
+
+public class GridInWindowTest extends SingleBrowserTest {
+
+ @Test
+ public void ensureAttachInHierachyChange() {
+ openTestURL("debug");
+ $(ButtonElement.class).first().click();
+ assertNoErrorNotifications();
+ $(WindowElement.class).first().close();
+ assertNoErrorNotifications();
+ $(ButtonElement.class).first().click();
+ assertNoErrorNotifications();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusField.java b/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusField.java
new file mode 100644
index 0000000000..1c82a3de02
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusField.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 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.AbstractTestUIWithLog;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.TextArea;
+import com.vaadin.ui.Window;
+
+public class OpenModalWindowAndFocusField extends AbstractTestUIWithLog {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Button button = new Button("Open modal and focus textarea");
+ button.setId("openFocus");
+ button.addClickListener(new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ open(true);
+ }
+ });
+ addComponent(button);
+
+ button = new Button("Only open modal");
+ button.setId("open");
+ button.addClickListener(new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ open(false);
+ }
+
+ });
+ addComponent(button);
+
+ }
+
+ private void open(boolean focus) {
+ Window wind = new Window();
+ wind.setModal(true);
+ TextArea ta = new TextArea();
+ wind.setContent(ta);
+ addWindow(wind);
+ if (focus) {
+ ta.focus();
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusFieldTest.java b/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusFieldTest.java
new file mode 100644
index 0000000000..5dba1c3285
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusFieldTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2014 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 org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TextAreaElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class OpenModalWindowAndFocusFieldTest extends MultiBrowserTest {
+
+ @Test
+ public void openModalAndFocusField() {
+ openTestURL();
+ $(ButtonElement.class).id("openFocus").click();
+ TextAreaElement textArea = $(TextAreaElement.class).first();
+
+ assertElementsEquals(textArea, getActiveElement());
+ }
+
+ @Test
+ public void openModal() {
+ openTestURL();
+ $(ButtonElement.class).id("open").click();
+ // WindowElement window = $(WindowElement.class).first();
+ WebElement windowFocusElement = findElement(By
+ .xpath("//div[@class='v-window-contents']/div[@class='v-scrollable']"));
+
+ assertElementsEquals(windowFocusElement, getActiveElement());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/push/ManualLongPollingPushUI.java b/uitest/src/com/vaadin/tests/push/ManualLongPollingPushUI.java
new file mode 100644
index 0000000000..190f6daa24
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/push/ManualLongPollingPushUI.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2014 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.push;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.vaadin.annotations.Push;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.communication.PushMode;
+import com.vaadin.shared.ui.ui.Transport;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+
+@Push(value = PushMode.MANUAL, transport = Transport.LONG_POLLING)
+public class ManualLongPollingPushUI extends AbstractTestUIWithLog {
+
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Button b = new Button("Manual push after 1s",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ access(new Runnable() {
+
+ @Override
+ public void run() {
+ log("Logged after 1s, followed by manual push");
+ push();
+ }
+ });
+
+ }
+ });
+ }
+ });
+ addComponent(b);
+
+ b = new Button("Double manual push after 1s",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ executor.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ access(new Runnable() {
+
+ @Override
+ public void run() {
+ log("First message logged after 1s, followed by manual push");
+ push();
+ log("Second message logged after 1s, followed by manual push");
+ push();
+ }
+ });
+
+ }
+ });
+ }
+ });
+ addComponent(b);
+
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/push/ManualLongPollingPushUITest.java b/uitest/src/com/vaadin/tests/push/ManualLongPollingPushUITest.java
new file mode 100644
index 0000000000..096204ff75
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/push/ManualLongPollingPushUITest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2014 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.push;
+
+import org.junit.Test;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class ManualLongPollingPushUITest extends SingleBrowserTest {
+
+ @Test
+ public void doubleManualPushDoesNotFreezeApplication() {
+ openTestURL();
+ $(ButtonElement.class).caption("Double manual push after 1s").first()
+ .click();
+ waitUntilLogText("2. Second message logged after 1s, followed by manual push");
+ $(ButtonElement.class).caption("Manual push after 1s").first().click();
+ waitUntilLogText("3. Logged after 1s, followed by manual push");
+ }
+
+ private void waitUntilLogText(final String expected) {
+ waitUntil(new ExpectedCondition<Boolean>() {
+ private String actual;
+
+ @Override
+ public Boolean apply(WebDriver arg0) {
+ actual = getLogRow(0);
+ return expected.equals(actual);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("log text to become '%s' (was: '%s')",
+ expected, actual);
+ }
+ });
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/resources/SpecialCharsInThemeResources.java b/uitest/src/com/vaadin/tests/resources/SpecialCharsInThemeResources.java
new file mode 100644
index 0000000000..e584ec73cc
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/resources/SpecialCharsInThemeResources.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2014 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.resources;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class SpecialCharsInThemeResources extends SingleBrowserTest {
+
+ @Test
+ public void loadThemeResource() {
+ loadResource("/VAADIN/themes/tests-tickets/ordinary.txt");
+ checkSource();
+ }
+
+ @Test
+ public void loadThemeResourceWithPercentage() {
+ loadResource("/VAADIN/themes/tests-tickets/percentagein%2520name.txt");
+ checkSource();
+ }
+
+ @Test
+ public void loadThemeResourceWithSpecialChars() {
+ loadResource("/VAADIN/themes/tests-tickets/folder%20with%20space/resource%20with%20special%20$chars@.txt");
+ checkSource();
+ }
+
+ private void loadResource(String path) {
+ getDriver().get(getBaseURL() + path);
+ }
+
+ private void checkSource() {
+ String source = getDriver().getPageSource();
+ Assert.assertTrue("Incorrect contents (was: " + source + ")",
+ source.contains("Just ordinary contents here"));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
index 842fcbb859..2e3854cb2b 100644
--- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
+++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
@@ -50,6 +50,7 @@ import org.openqa.selenium.interactions.Keyboard;
import org.openqa.selenium.interactions.Mouse;
import org.openqa.selenium.interactions.internal.Coordinates;
import org.openqa.selenium.internal.Locatable;
+import org.openqa.selenium.internal.WrapsElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.HttpCommandExecutor;
import org.openqa.selenium.remote.RemoteWebDriver;
@@ -368,8 +369,8 @@ public abstract class AbstractTB3Test extends ParallelTest {
* {@link org.openqa.selenium.JavascriptExecutor#executeScript(String, Object...)}
* returns
*/
- protected Object executeScript(String script) {
- return ((JavascriptExecutor) getDriver()).executeScript(script);
+ protected Object executeScript(String script, Object... args) {
+ return ((JavascriptExecutor) getDriver()).executeScript(script, args);
}
/**
@@ -1105,4 +1106,93 @@ public abstract class AbstractTB3Test extends ParallelTest {
return isElementPresent(By.className("v-debugwindow"));
}
+ protected void assertNoHorizontalScrollbar(WebElement element,
+ String errorMessage) {
+ // IE rounds clientWidth/clientHeight down and scrollHeight/scrollWidth
+ // up, so using clientWidth/clientHeight will fail if the element height
+ // is not an integer
+ int clientWidth = getClientWidth(element);
+ int scrollWidth = getScrollWidth(element);
+ boolean hasScrollbar = scrollWidth > clientWidth;
+
+ Assert.assertFalse(
+ "The element should not have a horizontal scrollbar (scrollWidth: "
+ + scrollWidth + ", clientWidth: " + clientWidth + "): "
+ + errorMessage, hasScrollbar);
+ }
+
+ protected void assertNoVerticalScrollbar(WebElement element,
+ String errorMessage) {
+ // IE rounds clientWidth/clientHeight down and scrollHeight/scrollWidth
+ // up, so using clientWidth/clientHeight will fail if the element height
+ // is not an integer
+ int clientHeight = getClientHeight(element);
+ int scrollHeight = getScrollHeight(element);
+ boolean hasScrollbar = scrollHeight > clientHeight;
+
+ Assert.assertFalse(
+ "The element should not have a vertical scrollbar (scrollHeight: "
+ + scrollHeight + ", clientHeight: " + clientHeight
+ + "): " + errorMessage, hasScrollbar);
+ }
+
+ protected int getScrollHeight(WebElement element) {
+ return ((Number) executeScript("return arguments[0].scrollHeight;",
+ element)).intValue();
+ }
+
+ protected int getScrollWidth(WebElement element) {
+ return ((Number) executeScript("return arguments[0].scrollWidth;",
+ element)).intValue();
+ }
+
+ /**
+ * Returns client height rounded up instead of as double because of IE9
+ * issues: https://dev.vaadin.com/ticket/18469
+ */
+ protected int getClientHeight(WebElement e) {
+ String script;
+ if (BrowserUtil.isIE8(getDesiredCapabilities())) {
+ script = "return arguments[0].clientHeight;"; //
+ } else {
+ script = "var cs = window.getComputedStyle(arguments[0]);"
+ + "return Math.ceil(parseFloat(cs.height)+parseFloat(cs.paddingTop)+parseFloat(cs.paddingBottom));";
+ }
+ return ((Number) executeScript(script, e)).intValue();
+ }
+
+ /**
+ * Returns client width rounded up instead of as double because of IE9
+ * issues: https://dev.vaadin.com/ticket/18469
+ */
+ protected int getClientWidth(WebElement e) {
+ String script;
+ if (BrowserUtil.isIE8(getDesiredCapabilities())) {
+ script = "return arguments[0].clientWidth;";
+ } else {
+ script = "var cs = window.getComputedStyle(arguments[0]);"
+ + "var h = parseFloat(cs.width)+parseFloat(cs.paddingLeft)+parseFloat(cs.paddingRight);"
+ + "return Math.ceil(h);";
+ }
+
+ return ((Number) executeScript(script, e)).intValue();
+ }
+
+ protected void assertElementsEquals(WebElement expectedElement,
+ WebElement actualElement) {
+ while (expectedElement instanceof WrapsElement) {
+ expectedElement = ((WrapsElement) expectedElement)
+ .getWrappedElement();
+ }
+ while (actualElement instanceof WrapsElement) {
+ actualElement = ((WrapsElement) actualElement).getWrappedElement();
+ }
+
+ Assert.assertEquals(expectedElement, actualElement);
+ }
+
+ protected WebElement getActiveElement() {
+ return (WebElement) executeScript("return document.activeElement;");
+
+ }
}
diff --git a/uitest/src/com/vaadin/tests/tb3/newelements/WindowElement.java b/uitest/src/com/vaadin/tests/tb3/newelements/WindowElement.java
index 34344324d0..784d203ab0 100644
--- a/uitest/src/com/vaadin/tests/tb3/newelements/WindowElement.java
+++ b/uitest/src/com/vaadin/tests/tb3/newelements/WindowElement.java
@@ -14,6 +14,7 @@ public class WindowElement extends com.vaadin.testbench.elements.WindowElement {
private final String restoreBoxClass = "v-window-restorebox";
private final String maximizeBoxClass = "v-window-maximizebox";
+ private final String closeBoxClass = "v-window-closebox";
public void restore() {
if (isMaximized()) {
@@ -63,4 +64,13 @@ public class WindowElement extends com.vaadin.testbench.elements.WindowElement {
public String getCaption() {
return findElement(By.className("v-window-header")).getText();
}
+
+ private WebElement getCloseButton() {
+ return findElement(By.className(closeBoxClass));
+ }
+
+ public void close() {
+ getCloseButton().click();
+
+ }
}