aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/base/browserframe/browserframe.scss7
-rw-r--r--WebContent/VAADIN/themes/base/common/common.scss17
-rw-r--r--WebContent/VAADIN/themes/valo/components/_datefield.scss33
-rw-r--r--WebContent/VAADIN/themes/valo/components/_table.scss8
-rw-r--r--WebContent/VAADIN/themes/valo/favicon.icobin0 -> 31005 bytes
-rw-r--r--WebContent/VAADIN/themes/valo/shared/_global.scss6
-rw-r--r--WebContent/release-notes.html4
-rw-r--r--buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java55
-rw-r--r--client/src/com/vaadin/client/ApplicationConfiguration.java6
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java8
-rw-r--r--client/src/com/vaadin/client/ui/AbstractFieldConnector.java3
-rw-r--r--client/src/com/vaadin/client/ui/VButton.java23
-rw-r--r--client/src/com/vaadin/client/ui/VFilterSelect.java6
-rw-r--r--client/src/com/vaadin/client/ui/VPopupView.java40
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java15
-rw-r--r--client/src/com/vaadin/client/ui/VTabsheet.java8
-rw-r--r--client/src/com/vaadin/client/ui/VTree.java60
-rw-r--r--client/src/com/vaadin/client/ui/VTreeTable.java12
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java66
-rw-r--r--client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java38
-rw-r--r--client/src/com/vaadin/client/ui/table/TableConnector.java13
-rw-r--r--client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java3
-rw-r--r--client/src/com/vaadin/client/ui/window/WindowConnector.java53
-rw-r--r--client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java14
-rw-r--r--server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java16
-rw-r--r--server/src/com/vaadin/data/fieldgroup/FieldGroup.java28
-rw-r--r--server/src/com/vaadin/data/util/BeanItem.java68
-rw-r--r--server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java2
-rw-r--r--server/src/com/vaadin/data/util/converter/StringToEnumConverter.java97
-rw-r--r--server/src/com/vaadin/server/AbstractDeploymentConfiguration.java54
-rw-r--r--server/src/com/vaadin/server/BootstrapHandler.java8
-rw-r--r--server/src/com/vaadin/server/BrowserWindowOpener.java49
-rw-r--r--server/src/com/vaadin/server/Constants.java2
-rw-r--r--server/src/com/vaadin/server/DefaultDeploymentConfiguration.java3
-rw-r--r--server/src/com/vaadin/server/DefaultUIProvider.java12
-rw-r--r--server/src/com/vaadin/server/DeploymentConfiguration.java32
-rw-r--r--server/src/com/vaadin/server/DragAndDropService.java5
-rw-r--r--server/src/com/vaadin/server/Page.java13
-rw-r--r--server/src/com/vaadin/server/ServletPortletHelper.java6
-rw-r--r--server/src/com/vaadin/server/VaadinPortletService.java10
-rw-r--r--server/src/com/vaadin/server/VaadinService.java4
-rw-r--r--server/src/com/vaadin/server/VaadinServletService.java7
-rw-r--r--server/src/com/vaadin/server/VaadinSession.java8
-rw-r--r--server/src/com/vaadin/server/WebBrowser.java21
-rw-r--r--server/src/com/vaadin/server/communication/AtmospherePushConnection.java1
-rw-r--r--server/src/com/vaadin/ui/AbstractField.java16
-rw-r--r--server/src/com/vaadin/ui/Button.java2
-rw-r--r--server/src/com/vaadin/ui/Calendar.java10
-rw-r--r--server/src/com/vaadin/ui/CustomLayout.java25
-rw-r--r--server/src/com/vaadin/ui/DateField.java10
-rw-r--r--server/src/com/vaadin/ui/Form.java17
-rw-r--r--server/src/com/vaadin/ui/Table.java82
-rw-r--r--server/src/com/vaadin/ui/UI.java9
-rw-r--r--server/src/com/vaadin/ui/Upload.java26
-rw-r--r--server/tests/src/com/vaadin/data/DefaultFieldGroupFieldFactoryTest.java26
-rw-r--r--server/tests/src/com/vaadin/data/fieldgroup/FieldGroupDate.java16
-rw-r--r--server/tests/src/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java33
-rw-r--r--server/tests/src/com/vaadin/data/util/BeanItemContainerGenerator.java153
-rw-r--r--server/tests/src/com/vaadin/data/util/BeanItemTest.java41
-rw-r--r--server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java157
-rw-r--r--server/tests/src/com/vaadin/server/BrowserWindowOpenerTest.java79
-rw-r--r--server/tests/src/com/vaadin/server/DragAndDropServiceTest.java125
-rw-r--r--server/tests/src/com/vaadin/server/PageTest.java92
-rw-r--r--server/tests/src/com/vaadin/server/VaadinPortletServiceTests.java5
-rw-r--r--server/tests/src/com/vaadin/server/VaadinSessionTest.java101
-rw-r--r--server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java59
-rw-r--r--server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java33
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java48
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/calendar/CalendarBasics.java26
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutTest.java148
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/form/FormTest.java68
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/upload/UploadTest.java101
-rw-r--r--server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java5
-rw-r--r--server/tests/src/com/vaadin/ui/TableTest.java78
-rw-r--r--server/tests/src/com/vaadin/ui/TextFieldTest.java48
-rw-r--r--shared/src/com/vaadin/shared/VBrowserDetails.java26
-rw-r--r--shared/src/com/vaadin/shared/ui/datefield/Resolution.java8
-rw-r--r--uitest/eclipse-run-selected-test.properties6
-rw-r--r--uitest/src/com/vaadin/tests/components/AbstractTestUI.java8
-rw-r--r--uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java218
-rw-r--r--uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java120
-rw-r--r--uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIcon.java59
-rw-r--r--uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIconTest.java47
-rw-r--r--uitest/src/com/vaadin/tests/components/combobox/ComboBoxInputPromptTest.java7
-rw-r--r--uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java68
-rw-r--r--uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffsetTest.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/formlayout/TableInFormLayoutCausesScrollingTest.java7
-rw-r--r--uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbars.java71
-rw-r--r--uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbarsTest.java31
-rw-r--r--uitest/src/com/vaadin/tests/components/popupview/DisabledPopupView.java23
-rw-r--r--uitest/src/com/vaadin/tests/components/popupview/DisabledPopupViewTest.java20
-rw-r--r--uitest/src/com/vaadin/tests/components/table/ContainerSizeChangeTest.java15
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableClickAndDragOnIconAndComponentsTest.java328
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRows.java130
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRowsTest.java122
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServer.java83
-rw-r--r--uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServerTest.java112
-rw-r--r--uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java50
-rw-r--r--uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java57
-rw-r--r--uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyField.java56
-rw-r--r--uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyFieldTest.java24
-rw-r--r--uitest/src/com/vaadin/tests/components/textfield/RequiredTextField.java57
-rw-r--r--uitest/src/com/vaadin/tests/components/textfield/RequiredTextFieldTest.java52
-rw-r--r--uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClick.java61
-rw-r--r--uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClickTest.java65
-rw-r--r--uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIcons.java57
-rw-r--r--uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIconsTest.java34
-rw-r--r--uitest/src/com/vaadin/tests/components/ui/ComboboxSelectedItemTextTest.java23
-rw-r--r--uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleName.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleNameTest.java55
-rw-r--r--uitest/src/com/vaadin/tests/components/ui/UISerializationTest.java15
-rw-r--r--uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java51
-rw-r--r--uitest/src/com/vaadin/tests/components/window/WindowWithIcon.java27
-rw-r--r--uitest/src/com/vaadin/tests/components/window/WindowWithIconTest.java16
-rw-r--r--uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java34
-rw-r--r--uitest/src/com/vaadin/tests/push/ReconnectLongPollingTest.java13
-rwxr-xr-xuitest/src/com/vaadin/tests/push/ReconnectStreamingTest.java13
-rw-r--r--uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java5
-rw-r--r--uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java9
-rw-r--r--uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java12
-rw-r--r--uitest/src/com/vaadin/tests/tb3/RetryOnFail.java24
-rw-r--r--uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java4
-rw-r--r--uitest/src/com/vaadin/tests/themes/FaviconTest.java60
-rw-r--r--uitest/src/com/vaadin/tests/themes/ThemeChangeOnTheFlyTest.java23
-rw-r--r--uitest/src/com/vaadin/tests/themes/valo/DateFields.java9
-rw-r--r--uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaption.java57
-rw-r--r--uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaptionTest.java42
-rw-r--r--uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java2
-rw-r--r--uitest/tb3test.xml2
129 files changed, 4550 insertions, 637 deletions
diff --git a/WebContent/VAADIN/themes/base/browserframe/browserframe.scss b/WebContent/VAADIN/themes/base/browserframe/browserframe.scss
index 149e38a744..fce9c11513 100644
--- a/WebContent/VAADIN/themes/base/browserframe/browserframe.scss
+++ b/WebContent/VAADIN/themes/base/browserframe/browserframe.scss
@@ -4,6 +4,13 @@
.v-browserframe {
font-size: 0;
}
+
+ /* fix for #14813 - unable to scroll on iOS devices */
+ .v-webkit.v-ios & .v-browserframe {
+ -webkit-overflow-scrolling: touch;
+ overflow:auto;
+ }
+
/* Some times a browser frame can contain a span with altenate text */
.v-browserframe > span {
font-size: $font-size;
diff --git a/WebContent/VAADIN/themes/base/common/common.scss b/WebContent/VAADIN/themes/base/common/common.scss
index 77248c0c96..ea8b5e5aa0 100644
--- a/WebContent/VAADIN/themes/base/common/common.scss
+++ b/WebContent/VAADIN/themes/base/common/common.scss
@@ -259,6 +259,18 @@ input::-ms-clear {
-webkit-overflow-scrolling: none;
}
+/* "Unnecessary scrollbar" related fixes (#14631, copied from Valo) */
+.v-scrollable.v-panel-content > .v-widget {
+ /* This is needed for IE */
+ vertical-align: middle;
+
+ /* Needed for all browsers. Can't really show anything outside the
+ * scrolling area anyway, so we can safely hide any overflow */
+ overflow: hidden;
+}
+
+
+
&.v-overlay-container {
width: 0;
height: 0;
@@ -274,3 +286,8 @@ input::-ms-clear {
width: 10px;
overflow: hidden;
}
+/* fix for #14681 - mobile safari 8 sometimes displayed text cursor on that element */
+.v-radiobutton {
+ -webkit-user-select: none;
+}
+
diff --git a/WebContent/VAADIN/themes/valo/components/_datefield.scss b/WebContent/VAADIN/themes/valo/components/_datefield.scss
index 48977d4d20..71b50b5a77 100644
--- a/WebContent/VAADIN/themes/valo/components/_datefield.scss
+++ b/WebContent/VAADIN/themes/valo/components/_datefield.scss
@@ -337,7 +337,10 @@
@include valo-datefield-calendarpanel-day-focused-style;
}
-
+ .#{$primary-stylename}-day.#{$primary-stylename}-day-outside-range,
+ .#{$primary-stylename}-day.#{$primary-stylename}-day-outside-range:hover {
+ @include valo-datefield-calendarpanel-outside-range-style;
+ }
.#{$primary-stylename}-weekdays {
height: round($v-unit-size * 0.7);
@@ -349,13 +352,12 @@
}
}
-
.#{$primary-stylename}-header {
white-space: nowrap;
}
- td[class$="year"],
- td[class$="month"] {
+ td[class*="year"],
+ td[class*="month"] {
button {
@include appearance(none);
border: none;
@@ -381,10 +383,16 @@
}
}
- &:hover {
- @include opacity(1);
- &:before {
- color: $v-focus-color;
+ &:hover:before {
+ color: $v-focus-color;
+ }
+
+ &.outside-range {
+ cursor: default;
+ @include opacity(.3);
+
+ &:hover:before {
+ color: mix($v-background-color, valo-font-color($v-background-color));
}
}
}
@@ -500,6 +508,15 @@
background: transparent;
}
+/**
+ * Outputs the styles for an individual day element, which are outside available range.
+ *
+ * @group datefield
+ */
+@mixin valo-datefield-calendarpanel-outside-range-style {
+ color: mix(valo-font-color($v-background-color), $v-background-color);
+ cursor: not-allowed;
+}
/**
* Outputs the styles for todays day element in a calendar panel.
diff --git a/WebContent/VAADIN/themes/valo/components/_table.scss b/WebContent/VAADIN/themes/valo/components/_table.scss
index e040a62d0f..d8a673294d 100644
--- a/WebContent/VAADIN/themes/valo/components/_table.scss
+++ b/WebContent/VAADIN/themes/valo/components/_table.scss
@@ -191,7 +191,15 @@ $v-table-background-color: null !default;
.#{$primary-stylename}-caption-container {
overflow: hidden;
line-height: 1;
+ min-height: $v-table-row-height;
@include box-sizing(border-box);
+
+ .v-ie8 & {
+ // IE8 has issues with border-box and min-height
+ // -> custom calculations to subtract vertical padding from row height.
+ $vertical-padding: round(($v-table-row-height - $v-table-header-font-size)/2);
+ min-height: $v-table-row-height - ($vertical-padding - $v-table-border-width) - $vertical-padding;
+ }
}
.#{$primary-stylename}-footer-container {
diff --git a/WebContent/VAADIN/themes/valo/favicon.ico b/WebContent/VAADIN/themes/valo/favicon.ico
new file mode 100644
index 0000000000..ffb34a65c7
--- /dev/null
+++ b/WebContent/VAADIN/themes/valo/favicon.ico
Binary files differ
diff --git a/WebContent/VAADIN/themes/valo/shared/_global.scss b/WebContent/VAADIN/themes/valo/shared/_global.scss
index 049518af73..4ce294b06a 100644
--- a/WebContent/VAADIN/themes/valo/shared/_global.scss
+++ b/WebContent/VAADIN/themes/valo/shared/_global.scss
@@ -121,6 +121,12 @@ $valo-global-included: false !default;
-webkit-overflow-scrolling: none;
}
+ //fix for #14813 - unable to scroll on iOS devices
+ .v-webkit.v-ios .v-browserframe {
+ -webkit-overflow-scrolling: touch;
+ overflow:auto;
+ }
+
.v-assistive-device-only {
position: absolute;
top: -2000px;
diff --git a/WebContent/release-notes.html b/WebContent/release-notes.html
index 3fa008f3f3..8ba85cfac1 100644
--- a/WebContent/release-notes.html
+++ b/WebContent/release-notes.html
@@ -67,7 +67,7 @@
<h2 id="overview">Overview of Vaadin @version@ Release</h2>
<p>
- Vaadin @version@ is a minor release that includes a
+ Vaadin @version@ is a maintenance release that includes a
number of new features and bug fixes, as listed in the <a
href="#enhancements">list of enhancements</a> and <a
href="#changelog">change log</a> below.
@@ -87,7 +87,7 @@
<br/>
<p>
You can also view the <a
- href="http://dev.vaadin.com/query?status=closed&resolution=fixed&milestone=Vaadin+@version@&order=id">list
+ href="http://dev.vaadin.com/query?status=pending-release&status=released&resolution=fixed&milestone=Vaadin+@version@&order=id">list
of the closed issues</a> at the Vaadin developer's site.
</p>
diff --git a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
index 497d8c0ff1..64ab86b84e 100644
--- a/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
+++ b/buildhelpers/src/com/vaadin/buildhelpers/FetchReleaseNotesTickets.java
@@ -99,12 +99,9 @@ public class FetchReleaseNotesTickets {
continue;
}
String summary = fields[1];
- if (summary.startsWith("\"") && summary.endsWith("\"")) {
- // If a summary starts with " and ends with " then all quotes in
- // the summary are encoded as double quotes
- summary = summary.substring(1, summary.length() - 1);
- summary = summary.replace("\"\"", "\"");
- }
+
+ summary = modifySummaryString(summary);
+
String badge = "<td></td>";
if (fields.length >= 8 && !fields[7].equals("")) {
badge = "<td class=\"bfp\"><span class=\"bfp\">Priority</span></td>";
@@ -119,6 +116,52 @@ public class FetchReleaseNotesTickets {
urlStream.close();
}
+ private static String modifySummaryString(String summary) {
+
+ if (summary.startsWith("\"") && summary.endsWith("\"")) {
+ // If a summary starts with " and ends with " then all quotes in
+ // the summary are encoded as double quotes
+ summary = summary.substring(1, summary.length() - 1);
+ summary = summary.replace("\"\"", "\"");
+ }
+
+ // this is needed for escaping html
+ summary = escapeHtml(summary);
+
+ return summary;
+ }
+
+ /**
+ * @since
+ * @param string
+ * the string to be html-escaped
+ * @return string in html-escape format
+ */
+ private static String escapeHtml(String string) {
+
+ StringBuffer buf = new StringBuffer(string.length() * 2);
+
+ // we check the string character by character and escape only special
+ // characters
+ for (int i = 0; i < string.length(); ++i) {
+
+ char ch = string.charAt(i);
+ String charString = ch + "";
+
+ if ((charString).matches("[a-zA-Z0-9., ]")) {
+ // character is letter, digit, dot, comma or whitespace
+ buf.append(ch);
+ } else {
+ int charInt = ch;
+ buf.append("&");
+ buf.append("#");
+ buf.append(charInt);
+ buf.append(";");
+ }
+ }
+ return buf.toString();
+ }
+
private static void usage() {
System.err.println("Usage: "
+ FetchReleaseNotesTickets.class.getSimpleName()
diff --git a/client/src/com/vaadin/client/ApplicationConfiguration.java b/client/src/com/vaadin/client/ApplicationConfiguration.java
index 87c8ea465f..83dd90b6c2 100644
--- a/client/src/com/vaadin/client/ApplicationConfiguration.java
+++ b/client/src/com/vaadin/client/ApplicationConfiguration.java
@@ -547,7 +547,11 @@ public class ApplicationConfiguration implements EntryPoint {
String getUnknownServerClassNameByTag(int tag) {
if (unknownComponents != null) {
- return unknownComponents.get(tag);
+ String className = unknownComponents.get(tag);
+ if (className == null) {
+ className = "unknown class with id " + tag;
+ }
+ return className;
}
return null;
}
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 3e3ad033a7..cba9639067 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -141,6 +141,8 @@ public class ApplicationConnection implements HasHandlers {
public static final String DISABLED_CLASSNAME = "v-disabled";
+ public static final String REQUIRED_CLASSNAME = "v-required";
+
public static final String REQUIRED_CLASSNAME_EXT = "-required";
public static final String ERROR_CLASSNAME_EXT = "-error";
@@ -1455,8 +1457,9 @@ public class ApplicationConnection implements HasHandlers {
VConsole.log("Handling message from server");
eventBus.fireEvent(new ResponseHandlingStartedEvent(this));
+ final int syncId;
if (json.containsKey(ApplicationConstants.SERVER_SYNC_ID)) {
- int syncId = json.getInt(ApplicationConstants.SERVER_SYNC_ID);
+ syncId = json.getInt(ApplicationConstants.SERVER_SYNC_ID);
/*
* Use sync id unless explicitly set as undefined, as is done by
@@ -1469,6 +1472,7 @@ public class ApplicationConnection implements HasHandlers {
lastSeenServerSyncId = syncId;
}
} else {
+ syncId = -1;
VConsole.error("Server response didn't contain a sync id. "
+ "Please verify that the server is up-to-date and that the response data has not been modified in transmission.");
}
@@ -1539,6 +1543,8 @@ public class ApplicationConnection implements HasHandlers {
Command c = new Command() {
@Override
public void execute() {
+ assert syncId == -1 || syncId == lastSeenServerSyncId;
+
handleUIDLDuration.logDuration(" * Loading widgets completed",
10);
diff --git a/client/src/com/vaadin/client/ui/AbstractFieldConnector.java b/client/src/com/vaadin/client/ui/AbstractFieldConnector.java
index a3c3779eb6..965e79b6fd 100644
--- a/client/src/com/vaadin/client/ui/AbstractFieldConnector.java
+++ b/client/src/com/vaadin/client/ui/AbstractFieldConnector.java
@@ -57,5 +57,8 @@ public abstract class AbstractFieldConnector extends AbstractComponentConnector
// add / remove error style name to Fields
setWidgetStyleNameWithPrefix(getWidget().getStylePrimaryName(),
ApplicationConnection.REQUIRED_CLASSNAME_EXT, isRequired());
+
+ getWidget().setStyleName(ApplicationConnection.REQUIRED_CLASSNAME,
+ isRequired());
}
}
diff --git a/client/src/com/vaadin/client/ui/VButton.java b/client/src/com/vaadin/client/ui/VButton.java
index 2e5494ec18..dcc364c1da 100644
--- a/client/src/com/vaadin/client/ui/VButton.java
+++ b/client/src/com/vaadin/client/ui/VButton.java
@@ -95,6 +95,7 @@ public class VButton extends FocusWidget implements ClickHandler {
private HandlerRegistration focusHandlerRegistration;
private HandlerRegistration blurHandlerRegistration;
+ private long lastClickTime = 0;
public VButton() {
super(DOM.createDiv());
@@ -163,13 +164,29 @@ public class VButton extends FocusWidget implements ClickHandler {
int type = DOM.eventGetType(event);
switch (type) {
case Event.ONCLICK:
- // If clicks are currently disallowed, keep it from bubbling or
- // being passed to the superclass.
- if (disallowNextClick) {
+ // fix for #14632 - on mobile safari 8, if we press the button long
+ // enough, we might get two click events, so we are suppressing
+ // second if it is too soon
+ boolean isPhantomClickPossible = BrowserInfo.get().isSafari()
+ && BrowserInfo.get().isTouchDevice()
+ && BrowserInfo.get().getBrowserMajorVersion() == 8;
+ long clickTime = isPhantomClickPossible ? System
+ .currentTimeMillis() : 0;
+ // If clicks are currently disallowed or phantom, keep it from
+ // bubbling or being passed to the superclass.
+ if (disallowNextClick || isPhantomClickPossible
+ && (clickTime - lastClickTime < 100)) { // the maximum
+ // interval observed
+ // for phantom click
+ // is 69, with
+ // majority under
+ // 50, so we select
+ // 100 to be safe
event.stopPropagation();
disallowNextClick = false;
return;
}
+ lastClickTime = clickTime;
break;
case Event.ONMOUSEDOWN:
if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))) {
diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java
index 356e7291c4..bb217f2de2 100644
--- a/client/src/com/vaadin/client/ui/VFilterSelect.java
+++ b/client/src/com/vaadin/client/ui/VFilterSelect.java
@@ -446,16 +446,13 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
private void selectItem(final MenuItem newSelectedItem) {
menu.selectItem(newSelectedItem);
- String text = newSelectedItem != null ? newSelectedItem.getText()
- : "";
-
// Set the icon.
FilterSelectSuggestion suggestion = (FilterSelectSuggestion) newSelectedItem
.getCommand();
setSelectedItemIcon(suggestion.getIconUri());
// Set the text.
- setText(text);
+ setText(suggestion.getReplacementString());
menu.updateKeyboardSelectedItem();
}
@@ -1145,6 +1142,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
private class IconWidget extends Widget {
IconWidget(Icon icon) {
setElement(icon.getElement());
+ addDomHandler(VFilterSelect.this, ClickEvent.getType());
}
}
diff --git a/client/src/com/vaadin/client/ui/VPopupView.java b/client/src/com/vaadin/client/ui/VPopupView.java
index 1a59501d38..7d98110446 100644
--- a/client/src/com/vaadin/client/ui/VPopupView.java
+++ b/client/src/com/vaadin/client/ui/VPopupView.java
@@ -33,13 +33,7 @@ import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.Focusable;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HasWidgets;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.*;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.DeferredWorker;
@@ -51,7 +45,7 @@ import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.client.ui.popupview.VisibilityChangeEvent;
import com.vaadin.client.ui.popupview.VisibilityChangeHandler;
-public class VPopupView extends HTML implements Iterable<Widget>,
+public class VPopupView extends HTML implements HasEnabled, Iterable<Widget>,
DeferredWorker {
public static final String CLASSNAME = "v-popupview";
@@ -78,6 +72,7 @@ public class VPopupView extends HTML implements Iterable<Widget>,
private final Label loading = new Label();
private boolean popupShowInProgress;
+ private boolean enabled = true;
/**
* loading constructor
@@ -97,10 +92,12 @@ public class VPopupView extends HTML implements Iterable<Widget>,
addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- preparePopup(popup);
- showPopup(popup);
- center();
- fireEvent(new VisibilityChangeEvent(true));
+ if(isEnabled()) {
+ preparePopup(popup);
+ showPopup(popup);
+ center();
+ fireEvent(new VisibilityChangeEvent(true));
+ }
}
});
@@ -197,6 +194,25 @@ public class VPopupView extends HTML implements Iterable<Widget>,
}-*/;
/**
+ * Returns true if the popup is enabled, false if not.
+ */
+ @Override
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * Sets whether this popup is enabled.
+ *
+ * @param enabled <code>true</code> to enable the popup, <code>false</code>
+ * to disable it
+ */
+ @Override
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ /**
* This class is only public to enable overriding showPopup, and is
* currently not intended to be extended or otherwise used directly. Its API
* (other than it being a VOverlay) is to be considered private and
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index 859d600daf..42fef9f0c0 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -6989,8 +6989,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
}
- Util.runWebkitOverflowAutoFixDeferred(scrollBodyPanel.getElement());
-
forceRealignColumnHeaders();
}
@@ -7119,15 +7117,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (initializedAndAttached) {
updatePageLength();
}
- if (!rendering) {
- // Webkit may sometimes get an odd rendering bug (white space
- // between header and body), see bug #3875. Running
- // overflow hack here to shake body element a bit.
- // We must run the fix as a deferred command to prevent it from
- // overwriting the scroll position with an outdated value, see
- // #7607.
- Util.runWebkitOverflowAutoFixDeferred(scrollBodyPanel.getElement());
- }
triggerLazyColumnAdjustment(false);
@@ -7529,7 +7518,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// Set new focused row
focusedRow = row;
- ensureRowIsVisible(row);
+ if (hasFocus) {
+ ensureRowIsVisible(row);
+ }
return true;
}
diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java
index 745f2bca61..9c3af5c568 100644
--- a/client/src/com/vaadin/client/ui/VTabsheet.java
+++ b/client/src/com/vaadin/client/ui/VTabsheet.java
@@ -694,9 +694,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware
private final Element deco;
- /** For internal use only. May be removed or replaced in the future. */
- public boolean waitingForResponse;
-
private String currentStyle;
/**
@@ -704,8 +701,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware
*/
private boolean canSelectTab(final int tabIndex) {
Tab tab = tb.getTab(tabIndex);
- if (getApplicationConnection() == null || disabled
- || waitingForResponse) {
+ if (getApplicationConnection() == null || disabled) {
return false;
}
if (!tab.isEnabledOnServer() || tab.isHiddenOnServer()) {
@@ -739,8 +735,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware
getRpcProxy().setSelected(tabKeys.get(tabIndex).toString());
- waitingForResponse = true;
-
tb.getTab(tabIndex).focus(); // move keyboard focus to active tab
return true;
diff --git a/client/src/com/vaadin/client/ui/VTree.java b/client/src/com/vaadin/client/ui/VTree.java
index 02ad7cfb3e..82ffaced1f 100644
--- a/client/src/com/vaadin/client/ui/VTree.java
+++ b/client/src/com/vaadin/client/ui/VTree.java
@@ -162,10 +162,10 @@ public class VTree extends FocusElementPanel implements VHasDropHandler,
/*
* to fix #14388. The cause of defect #14388: event 'clickEvent' is sent to
- * server before updating of "selected" variable, but should be send after
+ * server before updating of "selected" variable, but should be sent after
* it
*/
- private boolean sendClickEventNow = false;
+ private boolean clickEventPending = false;
/** For internal use only. May be removed or replaced in the future. */
public String[] bodyActionKeys;
@@ -480,13 +480,13 @@ public class VTree extends FocusElementPanel implements VHasDropHandler,
public void execute() {
/*
* we should send selection to server immediately in 2 cases: 1)
- * 'immediate' property of Tree is true 2) sendClickEventNow is
+ * 'immediate' property of Tree is true 2) clickEventPending is
* true
*/
client.updateVariable(paintableId, "selected",
selectedIds.toArray(new String[selectedIds.size()]),
- sendClickEventNow || immediate);
- sendClickEventNow = false;
+ clickEventPending || immediate);
+ clickEventPending = false;
selectionHasChanged = false;
}
};
@@ -844,41 +844,25 @@ public class VTree extends FocusElementPanel implements VHasDropHandler,
// server. We do not want to send the event if there is a
// selection event happening after this. In all other cases
// we want to send it immediately.
- sendClickEventNow = true;
-
- if (details.getButton() == MouseButton.LEFT && selectable) {
- if (immediate) {
- // event to be sent
- sendClickEventNow = false;
-
- // The exception is that user clicked on the
- // currently selected row and null selection is not
- // allowed == no selection event
- if (isSelected() && selectedIds.size() == 1
- && !isNullSelectionAllowed) {
- sendClickEventNow = true;
- }
+ clickEventPending = false;
+ if ((details.getButton() == MouseButton.LEFT || details
+ .getButton() == MouseButton.MIDDLE)
+ && !details.isDoubleClick() && selectable) {
+ // Probably a selection that will cause a value change
+ // event to be sent
+ clickEventPending = true;
+
+ // The exception is that user clicked on the
+ // currently selected row and null selection is not
+ // allowed == no selection event
+ if (isSelected() && selectedIds.size() == 1
+ && !isNullSelectionAllowed) {
+ clickEventPending = false;
}
-
- client.updateVariable(paintableId, "clickedKey", key,
- false);
-
- /*
- * in any case event should not be send immediately here
- * - send after updating of "selected" variable
- */
- client.updateVariable(paintableId, "clickEvent",
- details.toString(), false);
-
- } else { // for all another mouse buttons (RIGHT, MIDDLE) or
- // if not selectable
- client.updateVariable(paintableId, "clickedKey", key,
- false);
-
- client.updateVariable(paintableId, "clickEvent",
- details.toString(), sendClickEventNow);
- sendClickEventNow = false; // reset it
}
+ client.updateVariable(paintableId, "clickedKey", key, false);
+ client.updateVariable(paintableId, "clickEvent",
+ details.toString(), !clickEventPending);
}
});
}
diff --git a/client/src/com/vaadin/client/ui/VTreeTable.java b/client/src/com/vaadin/client/ui/VTreeTable.java
index 49d398246f..9b7e9702b2 100644
--- a/client/src/com/vaadin/client/ui/VTreeTable.java
+++ b/client/src/com/vaadin/client/ui/VTreeTable.java
@@ -26,7 +26,6 @@ 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.ImageElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
@@ -174,13 +173,10 @@ public class VTreeTable extends VScrollTable {
.getFirstChild();
if (rowUidl.hasAttribute("icon")) {
- // icons are in first content cell in TreeTable
- ImageElement icon = Document.get().createImageElement();
- icon.setClassName("v-icon");
- icon.setAlt("icon");
- icon.setSrc(client.translateVaadinUri(rowUidl
- .getStringAttribute("icon")));
- container.insertFirst(icon);
+ Icon icon = client.getIcon(rowUidl
+ .getStringAttribute("icon"));
+ icon.setAlternateText("icon");
+ container.insertFirst(icon.getElement());
}
String classname = "v-treetable-treespacer";
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index 58e7a83012..5c9a2ab47d 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -75,7 +75,7 @@ import com.vaadin.shared.ui.window.WindowRole;
/**
* "Sub window" component.
- *
+ *
* @author Vaadin Ltd
*/
public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
@@ -233,7 +233,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/*
* Stores the element that has focus in the application UI when the
* window is opened, so it can be restored when the window closes.
- *
+ *
* This is currently implemented for the case when one non-modal window
* can be open at the same time, and the focus is not changed while the
* window is open.
@@ -267,7 +267,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/*
* Restores the previously stored focused element.
- *
+ *
* When the focus was changed outside the window while the window was
* open, the originally stored element is restored.
*/
@@ -309,7 +309,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* Returns true if this window is the topmost VWindow
- *
+ *
* @return
*/
private boolean isActive() {
@@ -460,7 +460,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* is prevented.
* <p>
* This message is not visible on the screen.
- *
+ *
* @param topMessage
* String provided when the user navigates with Shift-Tab keys to
* the top of the window
@@ -475,7 +475,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* key is prevented.
* <p>
* This message is not visible on the screen.
- *
+ *
* @param bottomMessage
* String provided when the user navigates with the Tab key to
* the bottom of the window
@@ -488,7 +488,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* Gets the message that is provided to users of assistive devices when the
* user reaches the top of the window when leaving a window with the tab key
* is prevented.
- *
+ *
* @return the top message
*/
public String getTabStopTopAssistiveText() {
@@ -499,7 +499,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* Gets the message that is provided to users of assistive devices when the
* user reaches the bottom of the window when leaving a window with the tab
* key is prevented.
- *
+ *
* @return the bottom message
*/
public String getTabStopBottomAssistiveText() {
@@ -609,7 +609,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* Sets the closable state of the window. Additionally hides/shows the close
* button according to the new state.
- *
+ *
* @param closable
* true if the window can be closed by the user
*/
@@ -631,7 +631,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* Returns the closable state of the sub window. If the sub window is
* closable a decoration (typically an X) is shown to the user. By clicking
* on the X the user can close the window.
- *
+ *
* @return true if the sub window is closable
*/
protected boolean isClosable() {
@@ -663,7 +663,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* correctly if clicking on the "close" button in the window header but
* closing the window from a button for example in the window will fail.
* Symptom described in #10776
- *
+ *
* The problematic part is that for the focus to be returned correctly
* an input element needs to be focused in the root panel. Focusing some
* other element apparently won't work.
@@ -871,13 +871,8 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
setCaption(c, null);
}
- public void setCaption(String c, String icon) {
+ public void setCaption(String c, String iconURL) {
String html = Util.escapeHTML(c);
- if (icon != null) {
- icon = client.translateVaadinUri(icon);
- html = "<img src=\"" + Util.escapeAttribute(icon)
- + "\" class=\"v-icon\" alt=\"\" />" + html;
- }
// Provide information to assistive device users that a sub window was
// opened
@@ -889,13 +884,18 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
+ assistivePostfix + "</span>";
html = prefix + html + postfix;
- DOM.setInnerHTML(headerText, html);
+ headerText.setInnerHTML(html);
+
+ if (iconURL != null) {
+ Icon icon = client.getIcon(iconURL);
+ DOM.insertChild(headerText, icon.getElement(), 0);
+ }
}
/**
* Setter for the text for assistive devices the window caption is prefixed
* with.
- *
+ *
* @param assistivePrefix
* the assistivePrefix to set
*/
@@ -906,7 +906,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* Getter for the text for assistive devices the window caption is prefixed
* with.
- *
+ *
* @return the assistivePrefix
*/
public String getAssistivePrefix() {
@@ -916,7 +916,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* Setter for the text for assistive devices the window caption is postfixed
* with.
- *
+ *
* @param assistivePostfix
* the assistivePostfix to set
*/
@@ -927,7 +927,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* Getter for the text for assistive devices the window caption is postfixed
* with.
- *
+ *
* @return the assistivePostfix
*/
public String getAssistivePostfix() {
@@ -1079,14 +1079,14 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* TODO check if we need to support this with touch based devices.
- *
+ *
* Checks if the cursor was inside the browser content area when the event
* happened.
- *
+ *
* @param event
* The event to be checked
* @return true, if the cursor is inside the browser content area
- *
+ *
* false, otherwise
*/
private boolean cursorInsideBrowserContentArea(Event event) {
@@ -1372,7 +1372,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* assistive devices when it is opened.
* <p>
* When the provided array is empty, an existing description is removed.
- *
+ *
* @param connectors
* with the connectors of the widgets to use as description
*/
@@ -1410,7 +1410,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* Gets the connectors that are used as assistive description. Text
* contained in these connectors will be read by assistive devices when the
* window is opened.
- *
+ *
* @return list of previously set connectors
*/
public List<Connector> getAssistiveDescription() {
@@ -1419,14 +1419,14 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* Sets the WAI-ARIA role the window.
- *
+ *
* This role defines how an assistive device handles a window. Available
* roles are alertdialog and dialog (@see <a
* href="http://www.w3.org/TR/2011/CR-wai-aria-20110118/roles">Roles
* Model</a>).
- *
+ *
* The default role is dialog.
- *
+ *
* @param role
* WAI-ARIA role to set for the window
*/
@@ -1445,7 +1445,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
* The value of the parameter doTabStop is stored and used for non-modal
* windows. For modal windows, the handlers are always registered, while
* preserving the stored value.
- *
+ *
* @param doTabStop
* true to prevent leaving the window, false to allow leaving the
* window for non modal windows
@@ -1462,9 +1462,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
/**
* Adds a Handler for when user moves the window.
- *
+ *
* @since 7.1.9
- *
+ *
* @return {@link HandlerRegistration} used to remove the handler
*/
public HandlerRegistration addMoveHandler(WindowMoveHandler handler) {
diff --git a/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java b/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java
index 366775e9a2..e1234d436a 100644
--- a/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java
+++ b/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java
@@ -183,8 +183,42 @@ public class AbsoluteLayoutConnector extends
}
private void setChildWidgetPosition(ComponentConnector child) {
- getWidget().setWidgetPosition(child.getWidget(),
- getState().connectorToCssPosition.get(child.getConnectorId()));
+ String position = getState().connectorToCssPosition.get(child
+ .getConnectorId());
+ if (position == null) {
+ position = "";
+ }
+ // make sure relative sizes get displayed correctly
+ String width = child.getState().width;
+ if (width != null && width.endsWith("%")) {
+ position = addDefaultPositionIfMissing(position, "left");
+ position = addDefaultPositionIfMissing(position, "right");
+ }
+ String height = child.getState().height;
+ if (height != null && height.endsWith("%")) {
+ position = addDefaultPositionIfMissing(position, "top");
+ position = addDefaultPositionIfMissing(position, "bottom");
+ }
+ getWidget().setWidgetPosition(child.getWidget(), position);
+ }
+
+ /**
+ * Adds default value of 0.0px for the given property if it's missing from
+ * the position string altogether. If the property value is already set no
+ * changes are needed.
+ *
+ * @param position
+ * original position styles
+ * @param property
+ * the property that needs to have a value
+ * @return updated position, or the original string if no updates were
+ * needed
+ */
+ private String addDefaultPositionIfMissing(String position, String property) {
+ if (!position.contains(property)) {
+ position = position + property + ":0.0px;";
+ }
+ return position;
}
/*
diff --git a/client/src/com/vaadin/client/ui/table/TableConnector.java b/client/src/com/vaadin/client/ui/table/TableConnector.java
index 56b35cce56..7fb4bc108a 100644
--- a/client/src/com/vaadin/client/ui/table/TableConnector.java
+++ b/client/src/com/vaadin/client/ui/table/TableConnector.java
@@ -198,19 +198,6 @@ public class TableConnector extends AbstractHasComponentsConnector implements
uidl.getIntAttribute("rows"));
if (getWidget().headerChangedDuringUpdate) {
getWidget().triggerLazyColumnAdjustment(true);
- } else if (!getWidget().isScrollPositionVisible()
- || totalRowsHaveChanged
- || getWidget().lastRenderedHeight != getWidget().scrollBody
- .getOffsetHeight()) {
- // webkits may still bug with their disturbing scrollbar
- // bug, see #3457
- // Run overflow fix for the scrollable area
- // #6698 - If there's a scroll going on, don't abort it
- // by changing overflows as the length of the contents
- // *shouldn't* have changed (unless the number of rows
- // or the height of the widget has also changed)
- Util.runWebkitOverflowAutoFixDeferred(getWidget().scrollBodyPanel
- .getElement());
}
} else {
getWidget().initializeRows(uidl, rowData);
diff --git a/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java b/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java
index 8c6afd1c4f..94961a6a50 100644
--- a/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java
+++ b/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java
@@ -41,6 +41,7 @@ public class TabsheetConnector extends TabsheetBaseConnector implements
final String key = getState().tabs.get(i).key;
final boolean selected = key.equals(getState().selected);
if (selected) {
+ getWidget().setActiveTabIndex(i);
getWidget().selectTab(i);
break;
}
@@ -92,8 +93,6 @@ public class TabsheetConnector extends TabsheetBaseConnector implements
}
getWidget().iLayout();
-
- getWidget().waitingForResponse = false;
}
@Override
diff --git a/client/src/com/vaadin/client/ui/window/WindowConnector.java b/client/src/com/vaadin/client/ui/window/WindowConnector.java
index 4ee9f0c732..b3e3c9f70f 100644
--- a/client/src/com/vaadin/client/ui/window/WindowConnector.java
+++ b/client/src/com/vaadin/client/ui/window/WindowConnector.java
@@ -28,6 +28,7 @@ import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
+import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.vaadin.client.ApplicationConnection;
@@ -291,37 +292,51 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
// the contents visible for the duration of a possible
// 'out-animation')
- // Fix for #14645 - as soon as we clone audio and video tags with
- // autoplay attribute, they start playing immediately in background,
- // so we have to clear them before cloning. And we can't just erase
- // them, because there are corresponding player widgets to animate
- Node content = getWidget().getElement().getFirstChild();
- toggleAutoPlay(content);
- windowClone = content.cloneNode(true);
- toggleAutoPlay(content);
+ // Fix for #14645 and #14785 - as soon as we clone audio and video
+ // tags, they start fetching data, and playing immediately in
+ // background, in case autoplay attribute is present. Therefore we
+ // have to replace them with stubs in the clone. And we can't just
+ // erase them, because there are corresponding player widgets to
+ // animate
+ windowClone = cloneNodeFilteringMedia(getWidget().getElement()
+ .getFirstChild());
}
}
- private void toggleAutoPlay(Node node) {
+ private Node cloneNodeFilteringMedia(Node node) {
if (node instanceof Element) {
- Element el = (Element) node;
- if ("audio".equalsIgnoreCase(el.getTagName())
- || "video".equalsIgnoreCase(el.getTagName())) {
- if (el.hasAttribute("autoplay")) {
- el.removeAttribute("autoplay");
- el.setAttribute("_autoplay", "");
- } else if (el.hasAttribute("_autoplay")) {
- el.removeAttribute("_autoplay");
- el.setAttribute("autoplay", "");
+ Element old = (Element) node;
+ if ("audio".equalsIgnoreCase(old.getTagName())
+ || "video".equalsIgnoreCase(old.getTagName())) {
+ if (!old.hasAttribute("controls")
+ && "audio".equalsIgnoreCase(old.getTagName())) {
+ return null; // nothing to animate, so we won't add this to
+ // the clone
}
+ Element newEl = DOM.createElement(old.getTagName());
+ if (old.hasAttribute("controls")) {
+ newEl.setAttribute("controls", old.getAttribute("controls"));
+ }
+ if (old.hasAttribute("style")) {
+ newEl.setAttribute("style", old.getAttribute("style"));
+ }
+ if (old.hasAttribute("class")) {
+ newEl.setAttribute("class", old.getAttribute("class"));
+ }
+ return newEl;
}
}
+ Node res = node.cloneNode(false);
if (node.hasChildNodes()) {
NodeList<Node> nl = node.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
- toggleAutoPlay(nl.getItem(i));
+ Node clone = cloneNodeFilteringMedia(nl.getItem(i));
+ if (clone != null) {
+ res.appendChild(clone);
+ }
}
}
+ return res;
}
@Override
diff --git a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java
index dd892b19ec..6cd0630137 100644
--- a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java
+++ b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java
@@ -85,6 +85,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
// assertBrowserMinorVersion(bd, 1);
assertEngineVersion(bd, 536f);
assertIOS(bd, 6, 1);
+ assertIPhone(bd);
}
public void testIPhoneIOS5() {
@@ -95,6 +96,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
assertBrowserMinorVersion(bd, 1);
assertEngineVersion(bd, 534f);
assertIOS(bd, 5, 1);
+ assertIPhone(bd);
}
public void testIPhoneIOS4() {
@@ -105,6 +107,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
assertBrowserMinorVersion(bd, 0);
assertEngineVersion(bd, 532f);
assertIOS(bd, 4, 0);
+ assertIPhone(bd);
}
public void testIPadIOS4() {
@@ -115,6 +118,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
assertBrowserMinorVersion(bd, 0);
assertEngineVersion(bd, 533f);
assertIOS(bd, 4, 3);
+ assertIPad(bd);
}
public void testAndroid21() {
@@ -539,6 +543,16 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
assertOSMinorVersion(browserDetails, minorVersion);
}
+ private void assertIPhone(VBrowserDetails browserDetails) {
+ assertTrue(browserDetails.isIPhone());
+ assertFalse(browserDetails.isIPad());
+ }
+
+ private void assertIPad(VBrowserDetails browserDetails) {
+ assertFalse(browserDetails.isIPhone());
+ assertTrue(browserDetails.isIPad());
+ }
+
private void assertWindows(VBrowserDetails browserDetails) {
assertWindows(browserDetails, false);
}
diff --git a/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java b/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java
index b1bf58199a..9c2e4b2f83 100644
--- a/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java
+++ b/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java
@@ -36,10 +36,26 @@ import com.vaadin.ui.RichTextArea;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
+/**
+ * This class contains a basic implementation for {@link FieldGroupFieldFactory}
+ * .The class is singleton, use {@link #get()} method to get reference to the
+ * instance.
+ *
+ * @author Vaadin Ltd
+ */
public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory {
+ private static final DefaultFieldGroupFieldFactory INSTANCE = new DefaultFieldGroupFieldFactory();
+
public static final Object CAPTION_PROPERTY_ID = "Caption";
+ protected DefaultFieldGroupFieldFactory() {
+ }
+
+ public static DefaultFieldGroupFieldFactory get() {
+ return INSTANCE;
+ }
+
@Override
public <T extends Field> T createField(Class<?> type, Class<T> fieldType) {
if (Enum.class.isAssignableFrom(type)) {
diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
index e647bdbf6d..c5aab5a053 100644
--- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
+++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
@@ -28,6 +28,7 @@ import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.util.TransactionalPropertyWrapper;
+import com.vaadin.ui.AbstractField;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
@@ -67,7 +68,8 @@ public class FieldGroup implements Serializable {
/**
* The field factory used by builder methods.
*/
- private FieldGroupFieldFactory fieldFactory = new DefaultFieldGroupFieldFactory();
+ private FieldGroupFieldFactory fieldFactory = DefaultFieldGroupFieldFactory
+ .get();
/**
* Constructs a field binder. Use {@link #setItemDataSource(Item)} to set a
@@ -435,8 +437,14 @@ public class FieldGroup implements Serializable {
return;
}
for (Field<?> f : fieldToPropertyId.keySet()) {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .startTransaction();
+ Property.Transactional<?> property = (Property.Transactional<?>) f
+ .getPropertyDataSource();
+ if (property == null) {
+ throw new CommitException("Property \""
+ + fieldToPropertyId.get(f)
+ + "\" not bound to datasource.");
+ }
+ property.startTransaction();
}
try {
firePreCommitEvent();
@@ -1095,4 +1103,18 @@ public class FieldGroup implements Serializable {
}
return memberFieldInOrder;
}
+
+ /**
+ * Clears the value of all fields.
+ *
+ * @since
+ */
+ public void clear() {
+ for (Field<?> f : getFields()) {
+ if (f instanceof AbstractField) {
+ ((AbstractField) f).clear();
+ }
+ }
+
+ }
}
diff --git a/server/src/com/vaadin/data/util/BeanItem.java b/server/src/com/vaadin/data/util/BeanItem.java
index ac3ef86434..12d9b23d0a 100644
--- a/server/src/com/vaadin/data/util/BeanItem.java
+++ b/server/src/com/vaadin/data/util/BeanItem.java
@@ -214,13 +214,75 @@ public class BeanItem<BT> extends PropertysetItem {
}
BeanInfo info = Introspector.getBeanInfo(beanClass);
- propertyDescriptors.addAll(Arrays.asList(info
- .getPropertyDescriptors()));
+ propertyDescriptors.addAll(getPropertyDescriptors(info));
return propertyDescriptors;
} else {
BeanInfo info = Introspector.getBeanInfo(beanClass);
- return Arrays.asList(info.getPropertyDescriptors());
+ return getPropertyDescriptors(info);
+ }
+ }
+
+ // Workaround for Java6 bug JDK-6788525. Do nothing for JDK7+.
+ private static List<PropertyDescriptor> getPropertyDescriptors(
+ BeanInfo beanInfo) {
+ PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
+ List<PropertyDescriptor> result = new ArrayList<PropertyDescriptor>(
+ descriptors.length);
+ for (PropertyDescriptor descriptor : descriptors) {
+ try {
+ Method readMethod = getMethodFromBridge(descriptor
+ .getReadMethod());
+ if (readMethod != null) {
+ Method writeMethod = getMethodFromBridge(
+ descriptor.getWriteMethod(),
+ readMethod.getReturnType());
+ if (writeMethod == null) {
+ writeMethod = descriptor.getWriteMethod();
+ }
+ PropertyDescriptor descr = new PropertyDescriptor(
+ descriptor.getName(), readMethod, writeMethod);
+ result.add(descr);
+ } else {
+ result.add(descriptor);
+ }
+ } catch (SecurityException ignore) {
+ // handle next descriptor
+ } catch (IntrospectionException e) {
+ result.add(descriptor);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Return not bridged method for bridge {@code bridgeMethod} method. If
+ * method {@code bridgeMethod} is not bridge method then return null.
+ */
+ private static Method getMethodFromBridge(Method bridgeMethod)
+ throws SecurityException {
+ if (bridgeMethod == null) {
+ return null;
+ }
+ return getMethodFromBridge(bridgeMethod,
+ bridgeMethod.getParameterTypes());
+ }
+
+ /**
+ * Return not bridged method for bridge {@code bridgeMethod} method and
+ * declared {@code paramTypes}. If method {@code bridgeMethod} is not bridge
+ * method then return null.
+ */
+ private static Method getMethodFromBridge(Method bridgeMethod,
+ Class<?>... paramTypes) throws SecurityException {
+ if (bridgeMethod == null || !bridgeMethod.isBridge()) {
+ return null;
+ }
+ try {
+ return bridgeMethod.getDeclaringClass().getMethod(
+ bridgeMethod.getName(), paramTypes);
+ } catch (NoSuchMethodException e) {
+ return null;
}
}
diff --git a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
index fdf858a528..26613c5d02 100644
--- a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
+++ b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
@@ -110,6 +110,8 @@ public class DefaultConverterFactory implements ConverterFactory {
return new StringToBooleanConverter();
} else if (Date.class.isAssignableFrom(sourceType)) {
return new StringToDateConverter();
+ } else if (Enum.class.isAssignableFrom(sourceType)) {
+ return new StringToEnumConverter();
} else {
return null;
}
diff --git a/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java
new file mode 100644
index 0000000000..a1328d831c
--- /dev/null
+++ b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java
@@ -0,0 +1,97 @@
+/*
+ * 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.data.util.converter;
+
+import java.util.EnumSet;
+import java.util.Locale;
+
+/**
+ * A converter that converts from {@link String} to an {@link Enum} and back.
+ * <p>
+ * Designed to provide nice human readable strings for {@link Enum} classes
+ * where the constants are named SOME_UPPERCASE_WORDS. Will not necessarily work
+ * correctly for other cases.
+ * </p>
+ *
+ * @author Vaadin Ltd
+ * @since
+ */
+public class StringToEnumConverter implements Converter<String, Enum> {
+
+ @Override
+ public Enum convertToModel(String value, Class<? extends Enum> targetType,
+ Locale locale) throws ConversionException {
+ if (value == null) {
+ return null;
+ }
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ // Foo -> FOO
+ // Foo bar -> FOO_BAR
+ String result = value.replace(" ", "_").toUpperCase(locale);
+ try {
+ return Enum.valueOf(targetType, result);
+ } catch (IllegalArgumentException ee) {
+ // There was no match. Try to compare the available values to see if
+ // the constant is using something else than all upper case
+
+ EnumSet<?> set = EnumSet.allOf(targetType);
+ for (Enum e : set) {
+ if (e.name().toUpperCase(locale).equals(result)) {
+ return e;
+ }
+ }
+
+ // Fallback did not work either, re-throw original exception so user
+ // knows what went wrong
+ throw new ConversionException(ee);
+ }
+ }
+
+ @Override
+ public String convertToPresentation(Enum value,
+ Class<? extends String> targetType, Locale locale)
+ throws ConversionException {
+ if (value == null) {
+ return null;
+ }
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ String enumString = value.toString();
+ // FOO -> Foo
+ // FOO_BAR -> Foo bar
+ // _FOO -> _foo
+ String result = enumString.substring(0, 1).toUpperCase(locale);
+ result += enumString.substring(1).toLowerCase(locale).replace('_', ' ');
+
+ return result;
+ }
+
+ @Override
+ public Class<Enum> getModelType() {
+ return Enum.class;
+ }
+
+ @Override
+ public Class<String> getPresentationType() {
+ return String.class;
+ }
+
+}
diff --git a/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java
new file mode 100644
index 0000000000..43d4570d90
--- /dev/null
+++ b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.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.server;
+
+/**
+ * An abstract base class for DeploymentConfiguration implementations. This
+ * class provides default implementation for common config properties.
+ *
+ * @author Vaadin Ltd
+ */
+public abstract class AbstractDeploymentConfiguration implements
+ DeploymentConfiguration {
+
+ @Override
+ public String getUIClassName() {
+ return getApplicationOrSystemProperty(VaadinSession.UI_PARAMETER, null);
+ }
+
+ @Override
+ public String getUIProviderClassName() {
+ return getApplicationOrSystemProperty(
+ Constants.SERVLET_PARAMETER_UI_PROVIDER, null);
+ }
+
+ @Override
+ public String getWidgetset(String defaultValue) {
+ return getApplicationOrSystemProperty(Constants.PARAMETER_WIDGETSET,
+ defaultValue);
+ }
+
+ @Override
+ public String getResourcesPath() {
+ return getApplicationOrSystemProperty(
+ Constants.PARAMETER_VAADIN_RESOURCES, null);
+ }
+
+ @Override
+ public String getClassLoaderName() {
+ return getApplicationOrSystemProperty("ClassLoader", null);
+ }
+}
diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java
index 0605d6a2b8..f0666f63fc 100644
--- a/server/src/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/com/vaadin/server/BootstrapHandler.java
@@ -350,7 +350,6 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
/*- Add classnames;
* .v-app
* .v-app-loading
- * .v-app-<simpleName for app class>
*- Additionally added from javascript:
* <themeName, remove non-alphanum>
*/
@@ -362,6 +361,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
mainDiv.attr("id", context.getAppId());
mainDiv.addClass("v-app");
mainDiv.addClass(context.getThemeName());
+ mainDiv.addClass(context.getUIClass().getSimpleName()
+ .toLowerCase(Locale.ENGLISH));
if (style != null && style.length() != 0) {
mainDiv.attr("style", style);
}
@@ -401,7 +402,7 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
builder.append("//<![CDATA[\n");
builder.append("if (!window.vaadin) alert("
+ JsonUtil.quote("Failed to load the bootstrap javascript: "
- + bootstrapLocation) + ");\n");
+ + bootstrapLocation) + ");\n");
appendMainScriptTagContents(context, builder);
@@ -501,7 +502,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
if (systemMessages.getAuthenticationErrorURL() == null) {
authErrMsg.put("url", Json.createNull());
} else {
- authErrMsg.put("url", systemMessages.getAuthenticationErrorURL());
+ authErrMsg.put("url",
+ systemMessages.getAuthenticationErrorURL());
}
appConfig.put("authErrMsg", authErrMsg);
diff --git a/server/src/com/vaadin/server/BrowserWindowOpener.java b/server/src/com/vaadin/server/BrowserWindowOpener.java
index 44679fbfbb..8cc1faa728 100644
--- a/server/src/com/vaadin/server/BrowserWindowOpener.java
+++ b/server/src/com/vaadin/server/BrowserWindowOpener.java
@@ -126,6 +126,55 @@ public class BrowserWindowOpener extends AbstractExtension {
}
/**
+ * Sets the provided URL {@code url} for this instance. The {@code url} will
+ * be opened in a new browser window/tab when the extended component is
+ * clicked.
+ *
+ * @param url
+ * URL to open
+ */
+ public void setUrl(String url) {
+ setResource(new ExternalResource(url));
+ }
+
+ /**
+ * Sets the provided {@code resource} for this instance. The
+ * {@code resource} will be opened in a new browser window/tab when the
+ * extended component is clicked.
+ *
+ * @param resource
+ * resource to open
+ */
+ public void setResource(Resource resource) {
+ setResource(BrowserWindowOpenerState.locationResource, resource);
+ }
+
+ /**
+ * Returns the resource for this instance.
+ *
+ * @return resource to open browser window
+ */
+ public Resource getResource() {
+ return getResource(BrowserWindowOpenerState.locationResource);
+ }
+
+ /**
+ * Returns the URL for this BrowserWindowOpener instance. Returns
+ * {@code null} if this instance is not URL resource based (a non URL based
+ * resource has been set for it).
+ *
+ * @return URL to open in the new browser window/tab when the extended
+ * component is clicked
+ */
+ public String getUrl() {
+ Resource resource = getResource();
+ if (resource instanceof ExternalResource) {
+ return ((ExternalResource) resource).getURL();
+ }
+ return null;
+ }
+
+ /**
* Sets the target window name that will be used. If a window has already
* been opened with the same name, the contents of that window will be
* replaced instead of opening a new window. If the name is
diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java
index 2b868c12a6..fc0bf7381a 100644
--- a/server/src/com/vaadin/server/Constants.java
+++ b/server/src/com/vaadin/server/Constants.java
@@ -162,4 +162,6 @@ public interface Constants {
static final String PORTAL_PARAMETER_VAADIN_WIDGETSET = "vaadin.widgetset";
static final String PORTAL_PARAMETER_VAADIN_RESOURCE_PATH = "vaadin.resources.path";
static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
+
+ static final String PORTLET_CONTEXT = "PORTLET_CONTEXT";
}
diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
index fd14c3cd3f..22d5210eaa 100644
--- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
+++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
@@ -29,7 +29,8 @@ import com.vaadin.shared.communication.PushMode;
* @author Vaadin Ltd
* @since 7.0.0
*/
-public class DefaultDeploymentConfiguration implements DeploymentConfiguration {
+public class DefaultDeploymentConfiguration extends
+ AbstractDeploymentConfiguration {
/**
* Default value for {@link #getResourceCacheTime()} = {@value} .
*/
diff --git a/server/src/com/vaadin/server/DefaultUIProvider.java b/server/src/com/vaadin/server/DefaultUIProvider.java
index 2a1a59dbe6..38525fc020 100644
--- a/server/src/com/vaadin/server/DefaultUIProvider.java
+++ b/server/src/com/vaadin/server/DefaultUIProvider.java
@@ -24,15 +24,9 @@ public class DefaultUIProvider extends UIProvider {
public Class<? extends UI> getUIClass(UIClassSelectionEvent event) {
VaadinRequest request = event.getRequest();
- Object uiClassNameObj = request
- .getService()
- .getDeploymentConfiguration()
- .getApplicationOrSystemProperty(VaadinSession.UI_PARAMETER,
- null);
-
- if (uiClassNameObj instanceof String) {
- String uiClassName = uiClassNameObj.toString();
-
+ String uiClassName = request.getService().getDeploymentConfiguration()
+ .getUIClassName();
+ if (uiClassName != null) {
ClassLoader classLoader = request.getService().getClassLoader();
try {
Class<? extends UI> uiClass = Class.forName(uiClassName, true,
diff --git a/server/src/com/vaadin/server/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java
index fcfeecc31f..3124729773 100644
--- a/server/src/com/vaadin/server/DeploymentConfiguration.java
+++ b/server/src/com/vaadin/server/DeploymentConfiguration.java
@@ -163,6 +163,38 @@ public interface DeploymentConfiguration extends Serializable {
String defaultValue);
/**
+ * Gets UI class configuration option value.
+ *
+ * @return UI class name
+ */
+ public String getUIClassName();
+
+ /**
+ * Gets UI provider class configuration option value.
+ *
+ * @return UI class name
+ */
+ public String getUIProviderClassName();
+
+ /**
+ * Gets Widgetset configuration option value. {@code defaultValue} is
+ * returned if widgetset parameter is not configured.
+ *
+ * @return UI class name
+ */
+ public String getWidgetset(String defaultValue);
+
+ /**
+ * Gets resources path configuration option value.
+ */
+ public String getResourcesPath();
+
+ /**
+ * Gets class loader configuration option value.
+ */
+ public String getClassLoaderName();
+
+ /**
* Returns to legacy Property.toString() mode used. See
* {@link AbstractProperty#isLegacyToStringEnabled()} for more information.
*
diff --git a/server/src/com/vaadin/server/DragAndDropService.java b/server/src/com/vaadin/server/DragAndDropService.java
index c21f27de97..c0c3eebca3 100644
--- a/server/src/com/vaadin/server/DragAndDropService.java
+++ b/server/src/com/vaadin/server/DragAndDropService.java
@@ -38,6 +38,7 @@ import com.vaadin.shared.communication.SharedState;
import com.vaadin.shared.ui.dd.DragEventType;
import com.vaadin.ui.Component;
import com.vaadin.ui.UI;
+
import elemental.json.JsonObject;
public class DragAndDropService implements VariableOwner, ClientConnector {
@@ -64,7 +65,7 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
final Component sourceComponent = (Component) variables
.get("component");
- if (sourceComponent != null && !sourceComponent.isEnabled()) {
+ if (sourceComponent != null && !sourceComponent.isConnectorEnabled()) {
// source component not supposed to be enabled
getLogger().warning(
"Client dropped from " + sourceComponent
@@ -83,7 +84,7 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
DropTarget dropTarget = (DropTarget) owner;
- if (!dropTarget.isEnabled()) {
+ if (!dropTarget.isConnectorEnabled()) {
getLogger()
.warning(
"Client dropped on " + owner
diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java
index 3acea97c0f..3ddf4862b2 100644
--- a/server/src/com/vaadin/server/Page.java
+++ b/server/src/com/vaadin/server/Page.java
@@ -485,14 +485,14 @@ public class Page implements Serializable {
}
private void addListener(Class<?> eventType, Object target, Method method) {
- if (eventRouter == null) {
+ if (!hasEventRouter()) {
eventRouter = new EventRouter();
}
eventRouter.addListener(eventType, target, method);
}
private void removeListener(Class<?> eventType, Object target, Method method) {
- if (eventRouter != null) {
+ if (hasEventRouter()) {
eventRouter.removeListener(eventType, target, method);
}
}
@@ -599,7 +599,7 @@ public class Page implements Serializable {
}
private void fireEvent(EventObject event) {
- if (eventRouter != null) {
+ if (hasEventRouter()) {
eventRouter.fireEvent(event);
}
}
@@ -776,8 +776,8 @@ public class Page implements Serializable {
BrowserWindowResizeListener resizeListener) {
removeListener(BrowserWindowResizeEvent.class, resizeListener,
BROWSER_RESIZE_METHOD);
- getState(true).hasResizeListeners = eventRouter
- .hasListeners(BrowserWindowResizeEvent.class);
+ getState(true).hasResizeListeners = hasEventRouter()
+ && eventRouter.hasListeners(BrowserWindowResizeEvent.class);
}
/**
@@ -1242,4 +1242,7 @@ public class Page implements Serializable {
return state;
}
+ private boolean hasEventRouter() {
+ return eventRouter != null;
+ }
}
diff --git a/server/src/com/vaadin/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java
index 2ec747ba3a..197d9fe416 100644
--- a/server/src/com/vaadin/server/ServletPortletHelper.java
+++ b/server/src/com/vaadin/server/ServletPortletHelper.java
@@ -130,8 +130,7 @@ public class ServletPortletHelper implements Serializable {
public static void initDefaultUIProvider(VaadinSession session,
VaadinService vaadinService) throws ServiceException {
String uiProperty = vaadinService.getDeploymentConfiguration()
- .getApplicationOrSystemProperty(VaadinSession.UI_PARAMETER,
- null);
+ .getUIClassName();
// Add provider for UI parameter first to give it lower priority
// (providers are FILO)
@@ -141,8 +140,7 @@ public class ServletPortletHelper implements Serializable {
}
String uiProviderProperty = vaadinService.getDeploymentConfiguration()
- .getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_UI_PROVIDER, null);
+ .getUIProviderClassName();
// Then add custom UI provider if defined
if (uiProviderProperty != null) {
UIProvider uiProvider = getUIProvider(uiProviderProperty,
diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java
index 2b290b4cc4..cff024672c 100644
--- a/server/src/com/vaadin/server/VaadinPortletService.java
+++ b/server/src/com/vaadin/server/VaadinPortletService.java
@@ -124,9 +124,7 @@ public class VaadinPortletService extends VaadinService {
@Override
public String getConfiguredWidgetset(VaadinRequest request) {
- String widgetset = getDeploymentConfiguration()
- .getApplicationOrSystemProperty(
- VaadinPortlet.PARAMETER_WIDGETSET, null);
+ String widgetset = getDeploymentConfiguration().getWidgetset(null);
if (widgetset == null) {
widgetset = getParameter(request,
@@ -162,7 +160,11 @@ public class VaadinPortletService extends VaadinService {
String staticFileLocation = getParameter(request,
Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH, "/html");
- return trimTrailingSlashes(staticFileLocation);
+ if (Constants.PORTLET_CONTEXT.equals(staticFileLocation)) {
+ return request.getContextPath();
+ } else{
+ return trimTrailingSlashes(staticFileLocation);
+ }
}
private PortletContext getPortletContext() {
diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java
index 8fd6da8dee..4d8e7e9bc9 100644
--- a/server/src/com/vaadin/server/VaadinService.java
+++ b/server/src/com/vaadin/server/VaadinService.java
@@ -155,7 +155,7 @@ public abstract class VaadinService implements Serializable {
this.deploymentConfiguration = deploymentConfiguration;
final String classLoaderName = getDeploymentConfiguration()
- .getApplicationOrSystemProperty("ClassLoader", null);
+ .getClassLoaderName();
if (classLoaderName != null) {
try {
final Class<?> classLoaderClass = getClass().getClassLoader()
@@ -448,7 +448,7 @@ public abstract class VaadinService implements Serializable {
*/
public void fireSessionDestroy(VaadinSession vaadinSession) {
final VaadinSession session = vaadinSession;
- session.accessSynchronously(new Runnable() {
+ session.access(new Runnable() {
@Override
public void run() {
if (session.getState() == State.CLOSED) {
diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java
index a4ff3943c9..8946ac4fae 100644
--- a/server/src/com/vaadin/server/VaadinServletService.java
+++ b/server/src/com/vaadin/server/VaadinServletService.java
@@ -118,9 +118,7 @@ public class VaadinServletService extends VaadinService {
VaadinServletRequest servletRequest = (VaadinServletRequest) request;
String staticFileLocation;
// if property is defined in configurations, use that
- staticFileLocation = getDeploymentConfiguration()
- .getApplicationOrSystemProperty(
- VaadinServlet.PARAMETER_VAADIN_RESOURCES, null);
+ staticFileLocation = getDeploymentConfiguration().getResourcesPath();
if (staticFileLocation != null) {
return staticFileLocation;
}
@@ -159,8 +157,7 @@ public class VaadinServletService extends VaadinService {
@Override
public String getConfiguredWidgetset(VaadinRequest request) {
- return getDeploymentConfiguration().getApplicationOrSystemProperty(
- VaadinServlet.PARAMETER_WIDGETSET,
+ return getDeploymentConfiguration().getWidgetset(
VaadinServlet.DEFAULT_WIDGETSET);
}
diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java
index f93cb8e070..e5d63a6961 100644
--- a/server/src/com/vaadin/server/VaadinSession.java
+++ b/server/src/com/vaadin/server/VaadinSession.java
@@ -721,6 +721,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* {@link InheritableThreadLocal}). In other cases, (e.g. from background
* threads started in some other way), the current session is not
* automatically defined.
+ * <p>
+ * The session is stored using a weak reference to avoid leaking memory in
+ * case it is not explicitly cleared.
*
* @return the current session instance if available, otherwise
* <code>null</code>
@@ -741,9 +744,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* The application developer can also use this method to define the current
* session outside the normal request handling and treads started from
* request handling threads, e.g. when initiating custom background threads.
- * </p>
+ * <p>
+ * The session is stored using a weak reference to avoid leaking memory in
+ * case it is not explicitly cleared.
*
* @param session
+ * the session to set as current
*
* @see #getCurrent()
* @see ThreadLocal
diff --git a/server/src/com/vaadin/server/WebBrowser.java b/server/src/com/vaadin/server/WebBrowser.java
index 5ec4e6b19c..cb5979d612 100644
--- a/server/src/com/vaadin/server/WebBrowser.java
+++ b/server/src/com/vaadin/server/WebBrowser.java
@@ -264,6 +264,7 @@ public class WebBrowser implements Serializable {
* @return true if the user is using Windows Phone, false if the user is not
* using Windows Phone or if no information on the browser is
* present
+ * @since 7.3.2
*/
public boolean isWindowsPhone() {
return browserDetails.isWindowsPhone();
@@ -290,6 +291,26 @@ public class WebBrowser implements Serializable {
}
/**
+ * Tests if the browser is run on IPhone.
+ *
+ * @return true if run on IPhone false if the user is not using IPhone or if
+ * no information on the browser is present
+ */
+ public boolean isIPhone() {
+ return browserDetails.isIPhone();
+ }
+
+ /**
+ * Tests if the browser is run on IPad.
+ *
+ * @return true if run on IPad false if the user is not using IPad or if no
+ * information on the browser is present
+ */
+ public boolean isIPad() {
+ return browserDetails.isIPad();
+ }
+
+ /**
* Returns the browser-reported TimeZone offset in milliseconds from GMT.
* This includes possible daylight saving adjustments, to figure out which
* TimeZone the user actually might be in, see
diff --git a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
index f8ef360eda..a274fbbb9b 100644
--- a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
+++ b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
@@ -269,6 +269,7 @@ public class AtmospherePushConnection implements PushConnection {
// the resource is already resumed; this is a bit hacky and should
// be implemented in a better way in 7.2.
resource = null;
+ state = State.DISCONNECTED;
return;
}
diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java
index 47ac953319..369ad1253c 100644
--- a/server/src/com/vaadin/ui/AbstractField.java
+++ b/server/src/com/vaadin/ui/AbstractField.java
@@ -1402,7 +1402,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements
valueLocale);
T newinternalValue = convertFromModel(convertedValue);
if (!SharedUtil.equals(getInternalValue(), newinternalValue)) {
- setConvertedValue(convertedValue);
+ setInternalValue(newinternalValue);
+ fireValueChange(false);
}
}
}
@@ -1512,6 +1513,19 @@ public abstract class AbstractField<T> extends AbstractComponent implements
}
/**
+ * Clear the value of the field.
+ * <p>
+ * The field value is typically reset to the initial value of the field but
+ * this is not mandatory. Calling {@link #isEmpty()} on a cleared field must
+ * always returns true.
+ *
+ * @since
+ */
+ public void clear() {
+ setValue(null);
+ }
+
+ /**
* Is automatic, visible validation enabled?
*
* If automatic validation is enabled, any validators connected to this
diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java
index 76b82aa034..e58ad7bee5 100644
--- a/server/src/com/vaadin/ui/Button.java
+++ b/server/src/com/vaadin/ui/Button.java
@@ -359,7 +359,7 @@ public class Button extends AbstractComponent implements
* No action is taken is the button is disabled.
*/
public void click() {
- if (isEnabled() && !isReadOnly()) {
+ if (isConnectorEnabled() && !isReadOnly()) {
fireClick();
}
}
diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java
index 59dfceec9b..63ac9fe35c 100644
--- a/server/src/com/vaadin/ui/Calendar.java
+++ b/server/src/com/vaadin/ui/Calendar.java
@@ -890,17 +890,21 @@ public class Calendar extends AbstractComponent implements
* @see #isEventClickAllowed()
*/
protected boolean isClientChangeAllowed() {
- return !isReadOnly() && isEnabled();
+ return !isReadOnly();
}
/**
- * Is the user allowed to trigger click events
+ * Is the user allowed to trigger click events. Returns {@code true} by
+ * default. Subclass can override this method to disallow firing event
+ * clicks got from the client side.
*
* @return true if the client is allowed to click events
* @see #isClientChangeAllowed()
+ * @deprecated Override {@link #fireEventClick(Integer)} instead.
*/
+ @Deprecated
protected boolean isEventClickAllowed() {
- return isEnabled();
+ return true;
}
/**
diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java
index 7f1aa1ce46..f4fe7fa66c 100644
--- a/server/src/com/vaadin/ui/CustomLayout.java
+++ b/server/src/com/vaadin/ui/CustomLayout.java
@@ -16,6 +16,7 @@
package com.vaadin.ui;
+import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -101,22 +102,20 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent {
protected void initTemplateContentsFromInputStream(
InputStream templateStream) throws IOException {
- InputStreamReader reader = new InputStreamReader(templateStream,
- "UTF-8");
- StringBuilder b = new StringBuilder(BUFFER_SIZE);
-
- char[] cbuf = new char[BUFFER_SIZE];
- int offset = 0;
-
- while (true) {
- int nrRead = reader.read(cbuf, offset, BUFFER_SIZE);
- b.append(cbuf, 0, nrRead);
- if (nrRead < BUFFER_SIZE) {
- break;
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ templateStream, "UTF-8"));
+ StringBuilder builder = new StringBuilder(BUFFER_SIZE);
+ try {
+ char[] cbuf = new char[BUFFER_SIZE];
+ int nRead;
+ while ((nRead = reader.read(cbuf, 0, BUFFER_SIZE)) > 0) {
+ builder.append(cbuf, 0, nRead);
}
+ } finally {
+ reader.close();
}
- setTemplateContents(b.toString());
+ setTemplateContents(builder.toString());
}
@Override
diff --git a/server/src/com/vaadin/ui/DateField.java b/server/src/com/vaadin/ui/DateField.java
index e88d767bc9..030bd5f6c2 100644
--- a/server/src/com/vaadin/ui/DateField.java
+++ b/server/src/com/vaadin/ui/DateField.java
@@ -815,17 +815,15 @@ public class DateField extends AbstractField<Date> implements
// Clone the instance
final Calendar newCal = (Calendar) calendar.clone();
- // Assigns the current time tom calendar.
- final Date currentDate = getValue();
- if (currentDate != null) {
- newCal.setTime(currentDate);
- }
-
final TimeZone currentTimeZone = getTimeZone();
if (currentTimeZone != null) {
newCal.setTimeZone(currentTimeZone);
}
+ final Date currentDate = getValue();
+ if (currentDate != null) {
+ newCal.setTime(currentDate);
+ }
return newCal;
}
diff --git a/server/src/com/vaadin/ui/Form.java b/server/src/com/vaadin/ui/Form.java
index 391ee45536..48239b09e3 100644
--- a/server/src/com/vaadin/ui/Form.java
+++ b/server/src/com/vaadin/ui/Form.java
@@ -1064,7 +1064,7 @@ public class Form extends AbstractField<Object> implements Item.Editor,
for (Object id : itemPropertyIds) {
if (id != null) {
Field<?> field = getField(id);
- if (field.isEnabled() && !field.isReadOnly()) {
+ if (field.isConnectorEnabled() && !field.isReadOnly()) {
return field;
}
}
@@ -1202,6 +1202,21 @@ public class Form extends AbstractField<Object> implements Item.Editor,
return true;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractField#clear()
+ */
+ @Override
+ public void clear() {
+ for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) {
+ Field<?> f = i.next();
+ if (f instanceof AbstractField) {
+ ((AbstractField<?>) f).clear();
+ }
+ }
+ }
+
/**
* Adding validators directly to form is not supported.
*
diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java
index 3a1ab82be5..34d48a9b18 100644
--- a/server/src/com/vaadin/ui/Table.java
+++ b/server/src/com/vaadin/ui/Table.java
@@ -422,61 +422,11 @@ public class Table extends AbstractSelect implements Action.Container,
private Object currentPageFirstItemId = null;
/*
- * This class stores the hashcode and scroll position of the previous
- * container so that the scroll position can be restored if the same
- * container is removed and then re-added. This resolves #14581.
+ * If all rows get removed then scroll position of the previous container
+ * can be restored after re-adding/replacing rows via addAll(). This
+ * resolves #14581.
*/
- protected static class ScrollPositionRepairOnReAddAllRowsData implements
- Serializable {
-
- private static final long serialVersionUID = 1L;
- // current page first item index (to repair scroll position)
- private int itemIndex;
- /*
- * hashCode() of container before it was cleared via
- * container.removeAllItems();
- */
- private int containerHashCode;
-
- public ScrollPositionRepairOnReAddAllRowsData() {
- itemIndex = -1;
- containerHashCode = -1;
- }
-
- public int getItemId() {
- return itemIndex;
- }
-
- public void setItemId(int itemId) {
- itemIndex = itemId;
- }
-
- public void resetItemId() {
- itemIndex = -1;
- }
-
- public void setContainerData(Container container) {
- if (container != null) {
- containerHashCode = container.hashCode();
- } else {
- containerHashCode = -1;
- }
- }
-
- public boolean needRepairScrollPosition(Container newContainer) {
- return (itemIndex != -1) && isTheSameContainer(newContainer);
- }
-
- private boolean isTheSameContainer(Container newContainer) {
- boolean theSame = false;
- if (newContainer != null) {
- theSame = (newContainer.hashCode() == containerHashCode);
- }
- return theSame;
- }
- }
-
- private final ScrollPositionRepairOnReAddAllRowsData scrollRepairOnReAdding = new ScrollPositionRepairOnReAddAllRowsData();
+ private int repairOnReAddAllRowsDataScrollPositionItemIndex = -1;
/**
* Index of the first item on the current page.
@@ -2734,10 +2684,6 @@ public class Table extends AbstractSelect implements Action.Container,
newDataSource = new IndexedContainer();
}
- if (scrollRepairOnReAdding != null) {
- // this is important if container is set for table after filling
- scrollRepairOnReAdding.setContainerData(newDataSource);
- }
Collection<Object> generated;
if (columnGenerators != null) {
generated = columnGenerators.keySet();
@@ -4571,14 +4517,22 @@ public class Table extends AbstractSelect implements Action.Container,
int currentFirstItemIndex = getCurrentPageFirstItemIndex();
if (event.getContainer().size() == 0) {
- scrollRepairOnReAdding.setItemId(getCurrentPageFirstItemIndex());
+ repairOnReAddAllRowsDataScrollPositionItemIndex = getCurrentPageFirstItemIndex();
} else {
- if (scrollRepairOnReAdding.needRepairScrollPosition(event
- .getContainer())) {
- currentFirstItemIndex = scrollRepairOnReAdding.getItemId();
+ if (repairOnReAddAllRowsDataScrollPositionItemIndex != -1) {
+ currentFirstItemIndex = repairOnReAddAllRowsDataScrollPositionItemIndex;
+ /*
+ * Reset repairOnReAddAllRowsDataScrollPositionItemIndex.
+ *
+ * Next string should be commented (removed) if we want to have
+ * possibility to restore scroll position during adding items to
+ * container one by one via add() but not only addAll(). The
+ * problem in this case: we cannot track what happened between
+ * add() and add()... So it is ambiguous where to stop restore
+ * scroll position.
+ */
+ repairOnReAddAllRowsDataScrollPositionItemIndex = -1;
}
- scrollRepairOnReAdding.resetItemId();
- scrollRepairOnReAdding.setContainerData(event.getContainer());
}
// ensure that page still has first item in page, ignore buffer refresh
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index d67e08828a..438b086ec2 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -719,9 +719,11 @@ public abstract class UI extends AbstractSingleComponentContainer implements
* The application developer can also use this method to define the current
* UI outside the normal request handling, e.g. when initiating custom
* background threads.
- * </p>
+ * <p>
+ * The UI is stored using a weak reference to avoid leaking memory in case
+ * it is not explicitly cleared.
*
- * @param uI
+ * @param ui
* the UI to register as the current UI
*
* @see #getCurrent()
@@ -735,6 +737,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements
* Gets the currently used UI. The current UI is automatically defined when
* processing requests to the server. In other cases, (e.g. from background
* threads), the current UI is not automatically defined.
+ * <p>
+ * The UI is stored using a weak reference to avoid leaking memory in case
+ * it is not explicitly cleared.
*
* @return the current UI instance if available, otherwise <code>null</code>
*
diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java
index 1c953779e4..693bd74dbf 100644
--- a/server/src/com/vaadin/ui/Upload.java
+++ b/server/src/com/vaadin/ui/Upload.java
@@ -1150,23 +1150,25 @@ public class Upload extends AbstractComponent implements Component.Focusable,
fireUploadSuccess(event.getFileName(), event.getMimeType(),
event.getContentLength());
endUpload();
- markAsDirty();
}
@Override
public void streamingFailed(StreamingErrorEvent event) {
- Exception exception = event.getException();
- if (exception instanceof NoInputStreamException) {
- fireNoInputStream(event.getFileName(),
- event.getMimeType(), 0);
- } else if (exception instanceof NoOutputStreamException) {
- fireNoOutputStream(event.getFileName(),
- event.getMimeType(), 0);
- } else {
- fireUploadInterrupted(event.getFileName(),
- event.getMimeType(), 0, exception);
+ try {
+ Exception exception = event.getException();
+ if (exception instanceof NoInputStreamException) {
+ fireNoInputStream(event.getFileName(),
+ event.getMimeType(), 0);
+ } else if (exception instanceof NoOutputStreamException) {
+ fireNoOutputStream(event.getFileName(),
+ event.getMimeType(), 0);
+ } else {
+ fireUploadInterrupted(event.getFileName(),
+ event.getMimeType(), 0, exception);
+ }
+ } finally {
+ endUpload();
}
- endUpload();
}
};
}
diff --git a/server/tests/src/com/vaadin/data/DefaultFieldGroupFieldFactoryTest.java b/server/tests/src/com/vaadin/data/DefaultFieldGroupFieldFactoryTest.java
index a5fee5175e..bbf74bfb21 100644
--- a/server/tests/src/com/vaadin/data/DefaultFieldGroupFieldFactoryTest.java
+++ b/server/tests/src/com/vaadin/data/DefaultFieldGroupFieldFactoryTest.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.data;
+import java.lang.reflect.Constructor;
import java.util.Date;
import org.junit.Assert;
@@ -34,7 +35,30 @@ public class DefaultFieldGroupFieldFactoryTest {
@Before
public void setupFieldFactory() {
- fieldFactory = new DefaultFieldGroupFieldFactory();
+ fieldFactory = DefaultFieldGroupFieldFactory.get();
+ }
+
+ @Test
+ public void noPublicConstructor() {
+ Class<DefaultFieldGroupFieldFactory> clazz = DefaultFieldGroupFieldFactory.class;
+ Constructor<?>[] constructors = clazz.getConstructors();
+ Assert.assertEquals(
+ "DefaultFieldGroupFieldFactory contains public constructors",
+ 0, constructors.length);
+ }
+
+ @Test
+ public void testSameInstance() {
+ DefaultFieldGroupFieldFactory factory1 = DefaultFieldGroupFieldFactory
+ .get();
+ DefaultFieldGroupFieldFactory factory2 = DefaultFieldGroupFieldFactory
+ .get();
+ Assert.assertTrue(
+ "DefaultFieldGroupFieldFactory.get() method returns different instances",
+ factory1 == factory2);
+ Assert.assertNotNull(
+ "DefaultFieldGroupFieldFactory.get() method returns null",
+ factory1);
}
@Test
diff --git a/server/tests/src/com/vaadin/data/fieldgroup/FieldGroupDate.java b/server/tests/src/com/vaadin/data/fieldgroup/FieldGroupDate.java
index 07e36b93f9..fd5d47b32f 100644
--- a/server/tests/src/com/vaadin/data/fieldgroup/FieldGroupDate.java
+++ b/server/tests/src/com/vaadin/data/fieldgroup/FieldGroupDate.java
@@ -78,4 +78,20 @@ public class FieldGroupDate {
Assert.assertEquals(PopupDateField.class, f.getClass());
}
+ @Test
+ public void clearFields() {
+ PopupDateField sqlDate = new PopupDateField();
+ PopupDateField javaDate = new PopupDateField();
+ fieldGroup.bind(sqlDate, "sqlDate");
+ fieldGroup.bind(javaDate, "javaDate");
+
+ Assert.assertEquals(new Date(2010, 5, 7), javaDate.getValue());
+ Assert.assertEquals(new Date(2011, 6, 8), sqlDate.getValue());
+
+ fieldGroup.clear();
+ Assert.assertEquals(null, javaDate.getValue());
+ Assert.assertEquals(null, sqlDate.getValue());
+
+ }
+
}
diff --git a/server/tests/src/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java b/server/tests/src/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java
new file mode 100644
index 0000000000..636162de54
--- /dev/null
+++ b/server/tests/src/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.data.fieldgroup;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.ui.PopupDateField;
+
+public class FieldGroupExceptionTest {
+
+ @Test(expected = CommitException.class)
+ public void testUnboundCommitException() throws CommitException {
+ FieldGroup fieldGroup = new FieldGroup();
+ PopupDateField dateField = new PopupDateField();
+ fieldGroup.bind(dateField, "date");
+ fieldGroup.commit();
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/data/util/BeanItemContainerGenerator.java b/server/tests/src/com/vaadin/data/util/BeanItemContainerGenerator.java
new file mode 100644
index 0000000000..7400f0efcf
--- /dev/null
+++ b/server/tests/src/com/vaadin/data/util/BeanItemContainerGenerator.java
@@ -0,0 +1,153 @@
+package com.vaadin.data.util;
+
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.junit.Ignore;
+
+@Ignore
+public class BeanItemContainerGenerator {
+
+ public static class PortableRandom {
+ private final static long multiplier = 0x5DEECE66DL;
+ private final static long addend = 0xBL;
+ private final static long mask = (1L << 48) - 1;
+ private AtomicLong seed;
+
+ public PortableRandom(long seed) {
+ this.seed = new AtomicLong(0L);
+ setSeed(seed);
+ }
+
+ synchronized public void setSeed(long seed) {
+ seed = (seed ^ multiplier) & mask;
+ this.seed.set(seed);
+ }
+
+ public int nextInt(int n) {
+ if (n <= 0) {
+ throw new IllegalArgumentException("n must be positive");
+ }
+
+ if ((n & -n) == n) {
+ return (int) ((n * (long) next(31)) >> 31);
+ }
+
+ int bits, val;
+ do {
+ bits = next(31);
+ val = bits % n;
+ } while (bits - val + (n - 1) < 0);
+ return val;
+ }
+
+ protected int next(int bits) {
+ long oldseed, nextseed;
+ AtomicLong seed = this.seed;
+ do {
+ oldseed = seed.get();
+ nextseed = (oldseed * multiplier + addend) & mask;
+ } while (!seed.compareAndSet(oldseed, nextseed));
+ return (int) (nextseed >>> (48 - bits));
+ }
+
+ public boolean nextBoolean() {
+ return next(1) != 0;
+ }
+
+ }
+
+ public static BeanItemContainer<TestBean> createContainer(int size) {
+ return createContainer(size, new Date().getTime());
+ }
+
+ public static BeanItemContainer<TestBean> createContainer(int size,
+ long seed) {
+
+ BeanItemContainer<TestBean> container = new BeanItemContainer<TestBean>(
+ TestBean.class);
+ PortableRandom r = new PortableRandom(seed);
+ for (int i = 0; i < size; i++) {
+ container.addBean(new TestBean(r));
+ }
+
+ return container;
+
+ }
+
+ public static class TestBean {
+ private String name, address, city, country;
+ private int age, shoesize;
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public int getShoesize() {
+ return shoesize;
+ }
+
+ public void setShoesize(int shoesize) {
+ this.shoesize = shoesize;
+ }
+
+ public TestBean(PortableRandom r) {
+ age = r.nextInt(100) + 5;
+ shoesize = r.nextInt(10) + 35;
+ name = createRandomString(r, r.nextInt(5) + 5);
+ address = createRandomString(r, r.nextInt(15) + 5) + " "
+ + r.nextInt(100) + 1;
+ city = createRandomString(r, r.nextInt(7) + 3);
+ if (r.nextBoolean()) {
+ country = createRandomString(r, r.nextInt(4) + 4);
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ }
+
+ public static String createRandomString(PortableRandom r, int len) {
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < len; i++) {
+ b.append((char) (r.nextInt('z' - 'a') + 'a'));
+ }
+
+ return b.toString();
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/data/util/BeanItemTest.java b/server/tests/src/com/vaadin/data/util/BeanItemTest.java
index b458856826..89c56b1779 100644
--- a/server/tests/src/com/vaadin/data/util/BeanItemTest.java
+++ b/server/tests/src/com/vaadin/data/util/BeanItemTest.java
@@ -13,6 +13,8 @@ import junit.framework.TestCase;
import org.junit.Assert;
+import com.vaadin.data.Property;
+
/**
* Test BeanItem specific features.
*
@@ -122,6 +124,31 @@ public class BeanItemTest extends TestCase {
public int getSuper2();
}
+ protected static class Generic<T> {
+
+ public T getProperty() {
+ return null;
+ }
+
+ public void setProperty(T t) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ protected static class SubClass extends Generic<String> {
+
+ @Override
+ // Has a bridged method
+ public String getProperty() {
+ return "";
+ }
+
+ @Override
+ // Has a bridged method
+ public void setProperty(String t) {
+ }
+ }
+
protected static interface MySubInterface extends MySuperInterface,
MySuperInterface2 {
public int getSub();
@@ -331,4 +358,18 @@ public class BeanItemTest extends TestCase {
Assert.assertEquals(6, item.getItemPropertyIds().size());
Assert.assertEquals(null, item.getItemProperty("myname"));
}
+
+ public void testOverridenGenericMethods() {
+ BeanItem<SubClass> item = new BeanItem<SubClass>(new SubClass());
+
+ Property<?> property = item.getItemProperty("property");
+ Assert.assertEquals("Unexpected class for property type", String.class,
+ property.getType());
+
+ Assert.assertEquals("Unexpected property value", "",
+ property.getValue());
+
+ // Should not be exception
+ property.setValue(null);
+ }
}
diff --git a/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java
new file mode 100644
index 0000000000..7370bd3fac
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.server;
+
+import java.util.Properties;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.shared.communication.PushMode;
+
+/**
+ * Test for {@link AbstractDeploymentConfiguration}
+ *
+ * @author Vaadin Ltd
+ */
+public class AbstractDeploymentConfigurationTest {
+
+ @Test
+ public void getUIClass_returnsUIParameterPropertyValue() {
+ String ui = UUID.randomUUID().toString();
+ DeploymentConfiguration config = getConfig(VaadinSession.UI_PARAMETER,
+ ui);
+ Assert.assertEquals("Unexpected UI class configuration option value",
+ ui, config.getUIClassName());
+ }
+
+ @Test
+ public void getUIProviderClass_returnsUIProviderPropertyValue() {
+ String uiProvider = UUID.randomUUID().toString();
+ DeploymentConfiguration config = getConfig(
+ Constants.SERVLET_PARAMETER_UI_PROVIDER, uiProvider);
+ Assert.assertEquals(
+ "Unexpected UI providerclass configuration option value",
+ uiProvider, config.getUIProviderClassName());
+ }
+
+ @Test
+ public void getWidgetset_returnsWidgetsetProviderPropertyValue() {
+ String widgetset = UUID.randomUUID().toString();
+ DeploymentConfiguration config = getConfig(
+ Constants.PARAMETER_WIDGETSET, widgetset);
+ Assert.assertEquals("Unexpected widgetset configuration option value",
+ widgetset, config.getWidgetset(null));
+ }
+
+ @Test
+ public void getWidgetset_noWidgetsetPropertyValue_returnsProvidedDefaultValue() {
+ DeploymentConfiguration config = getConfig(null, null);
+ String widgetset = UUID.randomUUID().toString();
+ Assert.assertEquals("Unexpected widgetset configuration option value",
+ widgetset, config.getWidgetset(widgetset));
+ }
+
+ @Test
+ public void getResourcesPath_returnsResourcesPathPropertyValue() {
+ String resources = UUID.randomUUID().toString();
+ DeploymentConfiguration config = getConfig(
+ Constants.PARAMETER_VAADIN_RESOURCES, resources);
+ Assert.assertEquals(
+ "Unexpected resources path configuration option value",
+ resources, config.getResourcesPath());
+ }
+
+ @Test
+ public void getClassLoader_returnsClassloaderPropertyValue() {
+ String classLoader = UUID.randomUUID().toString();
+ DeploymentConfiguration config = getConfig("ClassLoader", classLoader);
+ Assert.assertEquals(
+ "Unexpected classLoader configuration option value",
+ classLoader, config.getClassLoaderName());
+ }
+
+ private DeploymentConfiguration getConfig(String property, String value) {
+ Properties props = new Properties();
+ if (property != null) {
+ props.put(property, value);
+ }
+ return new DeploymentConfigImpl(props);
+ }
+
+ private static class DeploymentConfigImpl extends
+ AbstractDeploymentConfiguration {
+
+ private Properties properties;
+
+ DeploymentConfigImpl(Properties props) {
+ properties = props;
+ }
+
+ @Override
+ public boolean isProductionMode() {
+ return false;
+ }
+
+ @Override
+ public boolean isXsrfProtectionEnabled() {
+ return false;
+ }
+
+ @Override
+ public boolean isSyncIdCheckEnabled() {
+ return false;
+ }
+
+ @Override
+ public int getResourceCacheTime() {
+ return 0;
+ }
+
+ @Override
+ public int getHeartbeatInterval() {
+ return 0;
+ }
+
+ @Override
+ public boolean isCloseIdleSessions() {
+ return false;
+ }
+
+ @Override
+ public PushMode getPushMode() {
+ return null;
+ }
+
+ @Override
+ public Properties getInitParameters() {
+ return null;
+ }
+
+ @Override
+ public String getApplicationOrSystemProperty(String propertyName,
+ String defaultValue) {
+ return properties.getProperty(propertyName, defaultValue);
+ }
+
+ @Override
+ public LegacyProperyToStringMode getLegacyPropertyToStringMode() {
+ return null;
+ }
+
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/BrowserWindowOpenerTest.java b/server/tests/src/com/vaadin/server/BrowserWindowOpenerTest.java
new file mode 100644
index 0000000000..7c76f7d421
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/BrowserWindowOpenerTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.server;
+
+import static org.junit.Assert.assertEquals;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.shared.communication.URLReference;
+import com.vaadin.shared.ui.BrowserWindowOpenerState;
+
+/**
+ *
+ * @author Vaadin Ltd
+ */
+public class BrowserWindowOpenerTest {
+
+ @Test
+ public void setResource_urlBasedOpener_resourceIsSetAndUrlIsNull() {
+ BrowserWindowOpener opener = new BrowserWindowOpener("url");
+
+ StreamResource resource = EasyMock.createMock(StreamResource.class);
+ opener.setResource(resource);
+
+ assertEquals("Unexpected resource is got on getResource() method",
+ resource, opener.getResource());
+ Assert.assertNull("Unexpected resource is got on getUrl() method",
+ opener.getUrl());
+
+ URLReference ref = opener.getState(false).resources
+ .get(BrowserWindowOpenerState.locationResource);
+ Assert.assertTrue(
+ "Url reference in the state is not ResourceReference",
+ ref instanceof ResourceReference);
+ Assert.assertEquals("Unexpected resource saved in state", resource,
+ ((ResourceReference) ref).getResource());
+ }
+
+ @Test
+ public void setUrl_urlBasedOpener_urlIsSet() {
+ BrowserWindowOpener opener = new BrowserWindowOpener("url");
+
+ String url = "newUrl";
+ opener.setUrl(url);
+
+ assertEquals("Unexpected URL is got on getURL() method", url,
+ opener.getUrl());
+ Assert.assertNotNull(
+ "Unexpected resource is got on getResource() method",
+ opener.getResource());
+
+ URLReference ref = opener.getState(false).resources
+ .get(BrowserWindowOpenerState.locationResource);
+ Assert.assertTrue(
+ "Url reference in the state is not ResourceReference",
+ ref instanceof ResourceReference);
+ Resource resource = ((ResourceReference) ref).getResource();
+ Assert.assertTrue("Resource reference is not ExternalResource",
+ resource instanceof ExternalResource);
+ Assert.assertEquals("Unexpected URL in resource saved in state", url,
+ ((ExternalResource) resource).getURL());
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/server/DragAndDropServiceTest.java b/server/tests/src/com/vaadin/server/DragAndDropServiceTest.java
new file mode 100644
index 0000000000..d0cb0ca5a6
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/DragAndDropServiceTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.server;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.StreamHandler;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.TargetDetails;
+import com.vaadin.ui.AbstractComponent;
+
+/**
+ * Tests for {@link DragAndDropService}.
+ *
+ * @author Vaadin Ltd
+ */
+public class DragAndDropServiceTest {
+
+ @Test
+ public void changeVariables_isSourceConnectorEnabledCalled() {
+ final List<Level> levels = new ArrayList<Level>();
+ Logger.getLogger(DragAndDropService.class.getName()).addHandler(
+ new StreamHandler() {
+ @Override
+ public synchronized void publish(LogRecord record) {
+ levels.add(record.getLevel());
+ }
+ });
+ Map<String, Object> variables = new HashMap<String, Object>();
+ final boolean[] isConnectorEnabledCalled = new boolean[1];
+ AbstractComponent component = new AbstractComponent() {
+ @Override
+ public boolean isConnectorEnabled() {
+ isConnectorEnabledCalled[0] = true;
+ return false;
+ }
+ };
+ variables.put("component", component);
+
+ DragAndDropService service = new DragAndDropService(
+ EasyMock.createMock(VaadinSession.class));
+ service.changeVariables(null, variables);
+
+ Assert.assertTrue("isConnectorEnabled() method is not called",
+ isConnectorEnabledCalled[0]);
+ Assert.assertTrue("No warning on drop from disabled source",
+ levels.contains(Level.WARNING));
+
+ }
+
+ @Test
+ public void changeVariables_isTargetConnectorEnabledCalled() {
+ final List<Level> levels = new ArrayList<Level>();
+ Logger.getLogger(DragAndDropService.class.getName()).addHandler(
+ new StreamHandler() {
+ @Override
+ public void publish(LogRecord record) {
+ levels.add(record.getLevel());
+ }
+ });
+ Map<String, Object> variables = new HashMap<String, Object>();
+ TestDropTarget target = new TestDropTarget();
+ variables.put("dhowner", target);
+
+ DragAndDropService service = new DragAndDropService(
+ EasyMock.createMock(VaadinSession.class));
+ service.changeVariables(null, variables);
+
+ Assert.assertTrue("isConnectorEnabled() method is not called",
+ target.isConnectorEnabledCalled());
+ Assert.assertTrue("No warning on drop to disabled target",
+ levels.contains(Level.WARNING));
+
+ }
+
+ private static class TestDropTarget extends AbstractComponent implements
+ com.vaadin.event.dd.DropTarget {
+ @Override
+ public boolean isConnectorEnabled() {
+ isConnectorEnabledCalled = true;
+ return false;
+ }
+
+ @Override
+ public DropHandler getDropHandler() {
+ return null;
+ }
+
+ @Override
+ public TargetDetails translateDropTargetDetails(
+ Map<String, Object> clientVariables) {
+ return null;
+ }
+
+ boolean isConnectorEnabledCalled() {
+ return isConnectorEnabledCalled;
+ }
+
+ private boolean isConnectorEnabledCalled;
+
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/PageTest.java b/server/tests/src/com/vaadin/server/PageTest.java
new file mode 100644
index 0000000000..b782b1f67d
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/PageTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.server;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.server.Page.BrowserWindowResizeEvent;
+import com.vaadin.server.Page.BrowserWindowResizeListener;
+import com.vaadin.shared.ui.ui.PageState;
+import com.vaadin.ui.UI;
+
+/**
+ *
+ * Tests for {@link Page}
+ *
+ * @author Vaadin Ltd
+ */
+public class PageTest {
+
+ @Test
+ public void removeBrowserWindowResizeListener_listenerIsAttached_listenerRemoved() {
+ Page page = new Page(EasyMock.createMock(UI.class),
+ EasyMock.createMock(PageState.class));
+
+ TestBrowserWindowResizeListener listener = new TestBrowserWindowResizeListener();
+ page.addBrowserWindowResizeListener(listener);
+ page.removeBrowserWindowResizeListener(listener);
+
+ page.updateBrowserWindowSize(0, 0, true);
+
+ Assert.assertFalse("Listener is called after removal",
+ listener.isCalled());
+ }
+
+ @Test
+ public void removeBrowserWindowResizeListener_listenerIsNotAttached_stateIsUpdated() {
+ TestPage page = new TestPage(EasyMock.createMock(UI.class),
+ EasyMock.createMock(PageState.class));
+
+ BrowserWindowResizeListener listener = EasyMock
+ .createMock(BrowserWindowResizeListener.class);
+ page.removeBrowserWindowResizeListener(listener);
+
+ Assert.assertFalse(
+ "Page state 'hasResizeListeners' property has wrong value",
+ page.getState(false).hasResizeListeners);
+ }
+
+ private static class TestPage extends Page {
+
+ public TestPage(UI uI, PageState state) {
+ super(uI, state);
+ }
+
+ @Override
+ protected PageState getState(boolean markAsDirty) {
+ return super.getState(markAsDirty);
+ }
+
+ }
+
+ private static class TestBrowserWindowResizeListener implements
+ BrowserWindowResizeListener {
+
+ @Override
+ public void browserWindowResized(BrowserWindowResizeEvent event) {
+ isCalled = true;
+ }
+
+ public boolean isCalled() {
+ return isCalled;
+ }
+
+ private boolean isCalled;
+
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/VaadinPortletServiceTests.java b/server/tests/src/com/vaadin/server/VaadinPortletServiceTests.java
index f7a69c2edb..0e094bfabb 100644
--- a/server/tests/src/com/vaadin/server/VaadinPortletServiceTests.java
+++ b/server/tests/src/com/vaadin/server/VaadinPortletServiceTests.java
@@ -86,10 +86,7 @@ public class VaadinPortletServiceTests {
}
private void mockWidgetsetConfiguration(String widgetset) {
- when(
- conf.getApplicationOrSystemProperty(
- Constants.PARAMETER_WIDGETSET, null)).thenReturn(
- widgetset);
+ when(conf.getWidgetset(null)).thenReturn(widgetset);
}
@Test
diff --git a/server/tests/src/com/vaadin/server/VaadinSessionTest.java b/server/tests/src/com/vaadin/server/VaadinSessionTest.java
index b710ee483f..fa7e892066 100644
--- a/server/tests/src/com/vaadin/server/VaadinSessionTest.java
+++ b/server/tests/src/com/vaadin/server/VaadinSessionTest.java
@@ -15,7 +15,9 @@
*/
package com.vaadin.server;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.ServletConfig;
@@ -30,6 +32,7 @@ import org.junit.Test;
import com.vaadin.server.ClientConnector.DetachEvent;
import com.vaadin.server.ClientConnector.DetachListener;
+import com.vaadin.server.communication.UIInitHandler;
import com.vaadin.ui.UI;
import com.vaadin.util.CurrentInstance;
@@ -43,9 +46,11 @@ public class VaadinSessionTest {
private WrappedSession mockWrappedSession;
private VaadinServletRequest vaadinRequest;
private UI ui;
+ private Lock httpSessionLock;
@Before
public void setup() throws Exception {
+ httpSessionLock = new ReentrantLock();
mockServletConfig = new MockServletConfig();
mockServlet = new VaadinServlet();
mockServlet.init(mockServletConfig);
@@ -60,11 +65,30 @@ public class VaadinSessionTest {
@Override
public Object getAttribute(String name) {
- String lockAttribute = mockService.getServiceName() + ".lock";
- if (lockAttribute.equals(name)) {
- return lock;
+ Object res;
+ try {
+ Thread.sleep(100); // for deadlock testing
+ org.junit.Assert.assertTrue("Deadlock detected",
+ httpSessionLock.tryLock(5, TimeUnit.SECONDS)); // simulates
+ // servlet
+ // container's
+ // session
+ // locking
+ String lockAttribute = mockService.getServiceName()
+ + ".lock";
+ if (lockAttribute.equals(name)) {
+ res = lock;
+ } else if ("com.vaadin.server.VaadinSession.Mock Servlet"
+ .equals(name)) {
+ res = session;
+ } else {
+ res = super.getAttribute(name);
+ }
+ httpSessionLock.unlock();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
- return super.getAttribute(name);
+ return res;
}
};
@@ -91,12 +115,26 @@ public class VaadinSessionTest {
EasyMock.createMock(HttpServletRequest.class), mockService) {
@Override
public String getParameter(String name) {
- if ("theme".equals(name)) {
+ if ("theme".equals(name) || "restartApplication".equals(name)
+ || "ignoreRestart".equals(name)
+ || "closeApplication".equals(name)) {
return null;
+ } else if (UIInitHandler.BROWSER_DETAILS_PARAMETER.equals(name)) {
+ return "1";
}
-
return super.getParameter(name);
}
+
+ @Override
+ public String getMethod() {
+ return "POST";
+ }
+
+ @Override
+ public WrappedSession getWrappedSession(boolean allowSessionCreation) {
+ return mockWrappedSession;
+ }
+
};
ui.doInit(vaadinRequest, session.getNextUIid(), null);
@@ -106,8 +144,43 @@ public class VaadinSessionTest {
}
+ /**
+ * This reproduces #14452 situation with deadlock - see diagram
+ */
+ @Test
+ public void testInvalidationDeadlock() {
+
+ // this simulates servlet container's session invalidation from another
+ // thread
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(150); // delay selected so that VaadinSession
+ // will be already locked by the main
+ // thread
+ // when we get here
+ httpSessionLock.lock();// simulating servlet container's
+ // session lock
+ mockService.fireSessionDestroy(session);
+ httpSessionLock.unlock();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }).start();
+
+ try {
+ mockService.findVaadinSession(vaadinRequest);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
@Test
- public void threadLocalsAfterUnderlyingSessionTimeout() {
+ public void threadLocalsAfterUnderlyingSessionTimeout()
+ throws InterruptedException {
final AtomicBoolean detachCalled = new AtomicBoolean(false);
ui.addDetachListener(new DetachListener() {
@@ -123,11 +196,17 @@ public class VaadinSessionTest {
});
session.valueUnbound(EasyMock.createMock(HttpSessionBindingEvent.class));
+ mockService.runPendingAccessTasks(session); // as soon as we changed
+ // session.accessSynchronously
+ // to session.access in
+ // VaadinService.fireSessionDestroy,
+ // we need to run the
+ // pending task ourselves
Assert.assertTrue(detachCalled.get());
}
@Test
- public void threadLocalsAfterSessionDestroy() {
+ public void threadLocalsAfterSessionDestroy() throws InterruptedException {
final AtomicBoolean detachCalled = new AtomicBoolean(false);
ui.addDetachListener(new DetachListener() {
@Override
@@ -143,6 +222,12 @@ public class VaadinSessionTest {
CurrentInstance.clearAll();
session.close();
mockService.cleanupSession(session);
+ mockService.runPendingAccessTasks(session); // as soon as we changed
+ // session.accessSynchronously
+ // to session.access in
+ // VaadinService.fireSessionDestroy,
+ // we need to run the
+ // pending task ourselves
Assert.assertTrue(detachCalled.get());
}
diff --git a/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java b/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java
new file mode 100644
index 0000000000..2b19395c08
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/data/converter/TestStringToEnumConverter.java
@@ -0,0 +1,59 @@
+package com.vaadin.tests.data.converter;
+
+import junit.framework.TestCase;
+
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.ReverseConverter;
+import com.vaadin.data.util.converter.StringToEnumConverter;
+
+public class TestStringToEnumConverter extends TestCase {
+
+ public static enum FooEnum {
+ VALUE1, SOME_VALUE, FOO_BAR_BAZ, Bar, nonStandardCase, _HUGH;
+ }
+
+ StringToEnumConverter converter = new StringToEnumConverter();
+ Converter<Enum, String> reverseConverter = new ReverseConverter<Enum, String>(
+ converter);
+
+ public void testNullConversion() {
+ assertEquals(null, converter.convertToModel(null, Enum.class, null));
+ }
+
+ public void testReverseNullConversion() {
+ assertEquals(null,
+ reverseConverter.convertToModel(null, String.class, null));
+ }
+
+ public void testValueConversion() {
+ assertEquals(FooEnum.VALUE1,
+ converter.convertToModel("Value1", FooEnum.class, null));
+ assertEquals(FooEnum.SOME_VALUE,
+ converter.convertToModel("Some value", FooEnum.class, null));
+ assertEquals(FooEnum.FOO_BAR_BAZ,
+ converter.convertToModel("Foo bar baz", FooEnum.class, null));
+ assertEquals(FooEnum.Bar,
+ converter.convertToModel("Bar", FooEnum.class, null));
+ assertEquals(FooEnum.nonStandardCase, converter.convertToModel(
+ "Nonstandardcase", FooEnum.class, null));
+ assertEquals(FooEnum._HUGH,
+ converter.convertToModel("_hugh", FooEnum.class, null));
+ }
+
+ public void testReverseValueConversion() {
+ assertEquals("Value1", reverseConverter.convertToModel(FooEnum.VALUE1,
+ String.class, null));
+ assertEquals("Some value", reverseConverter.convertToModel(
+ FooEnum.SOME_VALUE, String.class, null));
+ assertEquals("Foo bar baz", reverseConverter.convertToModel(
+ FooEnum.FOO_BAR_BAZ, String.class, null));
+ assertEquals("Bar", reverseConverter.convertToModel(FooEnum.Bar,
+ String.class, null));
+ assertEquals("Nonstandardcase", reverseConverter.convertToModel(
+ FooEnum.nonStandardCase, String.class, null));
+ assertEquals("_hugh", reverseConverter.convertToModel(FooEnum._HUGH,
+ String.class, null));
+
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java
index 63f79504ff..1220209479 100644
--- a/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java
+++ b/server/tests/src/com/vaadin/tests/server/TestClassesSerializable.java
@@ -16,6 +16,7 @@ import java.util.jar.JarFile;
import junit.framework.TestCase;
+import org.junit.Ignore;
import org.junit.Test;
public class TestClassesSerializable extends TestCase {
@@ -95,15 +96,8 @@ public class TestClassesSerializable extends TestCase {
if (cls.isAnnotation() || cls.isSynthetic()) {
continue;
}
- // Don't add classes that have a @Test annotation on any methods
- boolean testPresent = false;
- for (Method method : cls.getMethods()) {
- if (method.isAnnotationPresent(Test.class)) {
- testPresent = true;
- break;
- }
- }
- if (testPresent) {
+ // Don't add classes that have a @Ignore annotation on the class
+ if (isTestClass(cls)) {
continue;
}
@@ -152,6 +146,27 @@ public class TestClassesSerializable extends TestCase {
}
}
+ private boolean isTestClass(Class<?> cls) {
+ // @Ignore is used on test util classes
+ if (cls.isAnnotationPresent(Ignore.class)) {
+ return true;
+ }
+
+ if (cls.getEnclosingClass() != null
+ && isTestClass(cls.getEnclosingClass())) {
+ return true;
+ }
+
+ // Test classes with a @Test annotation on some method
+ for (Method method : cls.getMethods()) {
+ if (method.isAnnotationPresent(Test.class)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Lists all class path entries by splitting the class path string.
*
diff --git a/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java b/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java
index f82bbfe907..b41e93900f 100644
--- a/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java
+++ b/server/tests/src/com/vaadin/tests/server/component/button/ButtonClick.java
@@ -1,11 +1,12 @@
package com.vaadin.tests.server.component.button;
-import static org.junit.Assert.assertEquals;
-
+import org.junit.Assert;
import org.junit.Test;
+import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.UI;
/**
* Tests the public click() method.
@@ -16,7 +17,7 @@ public class ButtonClick {
@Test
public void testClick() {
getButton().click();
- assertEquals(clicked, true);
+ Assert.assertTrue("Button doesn't fire clicks", clicked);
}
@Test
@@ -24,7 +25,7 @@ public class ButtonClick {
Button b = getButton();
b.setEnabled(false);
b.click();
- assertEquals(clicked, false);
+ Assert.assertFalse("Disabled button fires click events", clicked);
}
@Test
@@ -32,17 +33,50 @@ public class ButtonClick {
Button b = getButton();
b.setReadOnly(true);
b.click();
- assertEquals(clicked, false);
+ Assert.assertFalse("Read only button fires click events", clicked);
+ }
+
+ @Test
+ public void testClickConnectorDisabled() {
+ Button b = new Button() {
+ @Override
+ public boolean isConnectorEnabled() {
+ return false;
+ }
+ };
+ UI ui = createUI();
+ b.setParent(ui);
+ addClickListener(b);
+ b.click();
+ Assert.assertFalse("Button with disabled connector fires click events",
+ clicked);
}
private Button getButton() {
Button b = new Button();
- b.addListener(new Button.ClickListener() {
+ UI ui = createUI();
+ b.setParent(ui);
+ addClickListener(b);
+ return b;
+ }
+
+ private UI createUI() {
+ UI ui = new UI() {
+
+ @Override
+ protected void init(VaadinRequest request) {
+ }
+ };
+ return ui;
+ }
+
+ private void addClickListener(Button b) {
+ clicked = false;
+ b.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent ev) {
clicked = true;
}
});
- return b;
}
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/calendar/CalendarBasics.java b/server/tests/src/com/vaadin/tests/server/component/calendar/CalendarBasics.java
index ab2bc7c8c0..773631642a 100644
--- a/server/tests/src/com/vaadin/tests/server/component/calendar/CalendarBasics.java
+++ b/server/tests/src/com/vaadin/tests/server/component/calendar/CalendarBasics.java
@@ -24,6 +24,7 @@ import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
+import org.junit.Assert;
import org.junit.Test;
import com.vaadin.ui.Calendar;
@@ -207,4 +208,29 @@ public class CalendarBasics {
assertEquals(23, calendar.getLastVisibleHourOfDay());
}
+ @Test
+ public void isClientChangeAllowed_connectorEnabled() {
+ TestCalendar calendar = new TestCalendar(true);
+ Assert.assertTrue(
+ "Calendar with enabled connector doesn't allow client change",
+ calendar.isClientChangeAllowed());
+ }
+
+ private static class TestCalendar extends Calendar {
+ TestCalendar(boolean connectorEnabled) {
+ isConnectorEnabled = connectorEnabled;
+ }
+
+ @Override
+ public boolean isConnectorEnabled() {
+ return isConnectorEnabled;
+ }
+
+ @Override
+ public boolean isClientChangeAllowed() {
+ return super.isClientChangeAllowed();
+ }
+
+ private final boolean isConnectorEnabled;
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutTest.java b/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutTest.java
new file mode 100644
index 0000000000..4d327e70a6
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.server.component.customlayout;
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.ui.CustomLayout;
+
+/**
+ *
+ * Tests for {@link CustomLayout}
+ *
+ * @author Vaadin Ltd
+ */
+public class CustomLayoutTest {
+
+ @Test
+ public void ctor_inputStreamProvided_inputStreamIsRead()
+ throws IOException, IllegalArgumentException,
+ IllegalAccessException {
+ Integer buffer = getBufferSize();
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < buffer; i++) {
+ builder.append('a');
+ }
+ byte[] bytes = builder.toString().getBytes(Charset.forName("UTF-8"));
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
+ InputStreamImpl stream = new InputStreamImpl(inputStream, buffer / 2);
+ new CustomLayout(stream);
+
+ Assert.assertTrue("Stream is not closed in CustomLayout CTOR ",
+ stream.isClosed());
+ Assert.assertEquals("Number of read bytes is incorrect", bytes.length,
+ stream.getCount());
+ }
+
+ private Integer getBufferSize() throws IllegalAccessException {
+ Field[] fields = CustomLayout.class.getDeclaredFields();
+ List<Field> list = new ArrayList<Field>(fields.length);
+ for (Field field : fields) {
+ if ((field.getModifiers() & Modifier.STATIC) > 0) {
+ list.add(field);
+ }
+ }
+ Field field = null;
+ if (list.size() == 1) {
+ field = list.get(0);
+ } else {
+ for (Field fld : list) {
+ if (fld.getName().toLowerCase(Locale.ENGLISH)
+ .startsWith("buffer")) {
+ field = fld;
+ break;
+ }
+ }
+ }
+ Assert.assertNotNull(
+ "Unable to find default buffer size in CustomLayout class",
+ field);
+ field.setAccessible(true);
+ Integer buffer = (Integer) field.get(null);
+ return buffer;
+ }
+
+ private static class InputStreamImpl extends FilterInputStream {
+
+ InputStreamImpl(InputStream inputStream, int maxArrayLength) {
+ super(inputStream);
+ this.maxArrayLength = maxArrayLength;
+ }
+
+ @Override
+ public int read() throws IOException {
+ int read = super.read();
+ if (read != -1) {
+ readCount++;
+ }
+ return read;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ if (b.length > maxArrayLength) {
+ return read(b, 0, maxArrayLength);
+ }
+ int count = super.read(b);
+ if (count != -1) {
+ readCount += count;
+ }
+ return count;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (len > maxArrayLength) {
+ return read(b, off, maxArrayLength);
+ }
+ int count = super.read(b, off, len);
+ if (count != -1) {
+ readCount += count;
+ }
+ return count;
+ }
+
+ @Override
+ public void close() throws IOException {
+ isClosed = true;
+ super.close();
+ }
+
+ int getCount() {
+ return readCount;
+ }
+
+ boolean isClosed() {
+ return isClosed;
+ }
+
+ private int readCount;
+ private boolean isClosed;
+ private int maxArrayLength;
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/form/FormTest.java b/server/tests/src/com/vaadin/tests/server/component/form/FormTest.java
new file mode 100644
index 0000000000..2075f7b115
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/form/FormTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.server.component.form;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.ui.Form;
+import com.vaadin.ui.TextField;
+
+/**
+ * Test for {@link Form}.
+ *
+ * @author Vaadin Ltd
+ */
+public class FormTest {
+
+ @Test
+ public void testFocus() {
+ Form form = new Form();
+ final boolean firstFieldIsFocused[] = new boolean[1];
+ TextField field1 = new TextField() {
+ @Override
+ public boolean isConnectorEnabled() {
+ return false;
+ }
+
+ @Override
+ public void focus() {
+ firstFieldIsFocused[0] = true;
+ }
+ };
+
+ final boolean secondFieldIsFocused[] = new boolean[1];
+ TextField field2 = new TextField() {
+ @Override
+ public boolean isConnectorEnabled() {
+ return true;
+ }
+
+ @Override
+ public void focus() {
+ secondFieldIsFocused[0] = true;
+ }
+ };
+ form.addField("a", field1);
+ form.addField("b", field2);
+ form.focus();
+
+ Assert.assertTrue("Field with enabled connector is not focused",
+ secondFieldIsFocused[0]);
+ Assert.assertFalse("Field with disabled connector is focused",
+ firstFieldIsFocused[0]);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/upload/UploadTest.java b/server/tests/src/com/vaadin/tests/server/component/upload/UploadTest.java
new file mode 100644
index 0000000000..2132829c0a
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/upload/UploadTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.server.component.upload;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.server.StreamVariable;
+import com.vaadin.server.StreamVariable.StreamingErrorEvent;
+import com.vaadin.ui.Upload;
+
+/**
+ *
+ * @author Vaadin Ltd
+ */
+public class UploadTest {
+
+ @Test
+ public void getStreamVariable_streamingFailed_endUploadIsCalled() {
+ TestUpload upload = new TestUpload();
+ upload.startUpload();
+ StreamVariable variable = upload.getStreamVariable();
+ try {
+ variable.streamingFailed(new TestStreamingErrorEvent());
+ } catch (Exception e) {
+ }
+ Assert.assertFalse(upload.isUploading());
+ }
+
+ private static class TestStreamingErrorEvent implements StreamingErrorEvent {
+
+ @Override
+ public String getFileName() {
+ return null;
+ }
+
+ @Override
+ public String getMimeType() {
+ return null;
+ }
+
+ @Override
+ public long getContentLength() {
+ return 0;
+ }
+
+ @Override
+ public long getBytesReceived() {
+ return 0;
+ }
+
+ @Override
+ public Exception getException() {
+ return new Exception();
+ }
+
+ }
+
+ private static class TestUpload extends Upload {
+
+ @Override
+ public StreamVariable getStreamVariable() {
+ return super.getStreamVariable();
+ }
+
+ @Override
+ protected void fireNoInputStream(String filename, String MIMEType,
+ long length) {
+ fireEvent();
+ }
+
+ @Override
+ protected void fireNoOutputStream(String filename, String MIMEType,
+ long length) {
+ fireEvent();
+ }
+
+ @Override
+ protected void fireUploadInterrupted(String filename, String MIMEType,
+ long length, Exception e) {
+ fireEvent();
+ }
+
+ private void fireEvent() {
+ throw new NullPointerException();
+ }
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java
index fe7f9ba03e..8eceaea53f 100644
--- a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java
+++ b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java
@@ -4,10 +4,11 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-import com.vaadin.server.DeploymentConfiguration;
+import com.vaadin.server.AbstractDeploymentConfiguration;
import com.vaadin.shared.communication.PushMode;
-public class MockDeploymentConfiguration implements DeploymentConfiguration {
+public class MockDeploymentConfiguration extends
+ AbstractDeploymentConfiguration {
private boolean productionMode = false;
private boolean xsrfProtectionEnabled = true;
diff --git a/server/tests/src/com/vaadin/ui/TableTest.java b/server/tests/src/com/vaadin/ui/TableTest.java
new file mode 100644
index 0000000000..86237abbe0
--- /dev/null
+++ b/server/tests/src/com/vaadin/ui/TableTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.ui;
+
+import java.util.Collection;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.util.BeanItemContainerGenerator;
+
+public class TableTest {
+
+ Table table;
+
+ @Before
+ public void init() {
+ table = new Table();
+ }
+
+ @Test
+ public void initiallyEmpty() {
+ Assert.assertTrue(table.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClearSingleSelect() {
+ table.setContainerDataSource(BeanItemContainerGenerator
+ .createContainer(100));
+ Assert.assertTrue(table.isEmpty());
+ Object first = table.getContainerDataSource().getItemIds().iterator()
+ .next();
+ table.setValue(first);
+ Assert.assertEquals(first, table.getValue());
+ Assert.assertFalse(table.isEmpty());
+ table.clear();
+ Assert.assertEquals(null, table.getValue());
+ Assert.assertTrue(table.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClearMultiSelect() {
+ table.setMultiSelect(true);
+ table.setContainerDataSource(BeanItemContainerGenerator
+ .createContainer(100));
+
+ Assert.assertTrue(table.isEmpty());
+ Assert.assertArrayEquals(new Object[] {},
+ ((Collection) table.getValue()).toArray());
+
+ Object first = table.getContainerDataSource().getItemIds().iterator()
+ .next();
+ table.select(first);
+ Assert.assertArrayEquals(new Object[] { first },
+ ((Collection) table.getValue()).toArray());
+ Assert.assertFalse(table.isEmpty());
+
+ table.clear();
+ Assert.assertArrayEquals(new Object[] {},
+ ((Collection) table.getValue()).toArray());
+ Assert.assertTrue(table.isEmpty());
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/ui/TextFieldTest.java b/server/tests/src/com/vaadin/ui/TextFieldTest.java
new file mode 100644
index 0000000000..bfd452bd3b
--- /dev/null
+++ b/server/tests/src/com/vaadin/ui/TextFieldTest.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.ui;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.data.util.ObjectProperty;
+
+public class TextFieldTest {
+
+ @Test
+ public void initiallyEmpty() {
+ TextField tf = new TextField();
+ Assert.assertTrue(tf.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClearUsingPDS() {
+ TextField tf = new TextField(new ObjectProperty<String>("foo"));
+ Assert.assertFalse(tf.isEmpty());
+ tf.clear();
+ Assert.assertTrue(tf.isEmpty());
+ }
+
+ @Test
+ public void emptyAfterClear() {
+ TextField tf = new TextField();
+ tf.setValue("foobar");
+ Assert.assertFalse(tf.isEmpty());
+ tf.clear();
+ Assert.assertTrue(tf.isEmpty());
+ }
+
+}
diff --git a/shared/src/com/vaadin/shared/VBrowserDetails.java b/shared/src/com/vaadin/shared/VBrowserDetails.java
index 3c89bdb6bb..a85d031c49 100644
--- a/shared/src/com/vaadin/shared/VBrowserDetails.java
+++ b/shared/src/com/vaadin/shared/VBrowserDetails.java
@@ -43,6 +43,8 @@ public class VBrowserDetails implements Serializable {
private boolean isIE = false;
private boolean isWindowsPhone;
+ private boolean isIPad;
+ private boolean isIPhone;
private OperatingSystem os = OperatingSystem.UNKNOWN;
@@ -176,8 +178,9 @@ public class VBrowserDetails implements Serializable {
} else if (userAgent.contains("macintosh")
|| userAgent.contains("mac osx")
|| userAgent.contains("mac os x")) {
- if (userAgent.contains("ipad") || userAgent.contains("ipod")
- || userAgent.contains("iphone")) {
+ isIPad = userAgent.contains("ipad");
+ isIPhone = userAgent.contains("iphone");
+ if (isIPad || userAgent.contains("ipod") || isIPhone) {
os = OperatingSystem.IOS;
parseIOSVersion(userAgent);
} else {
@@ -431,6 +434,7 @@ public class VBrowserDetails implements Serializable {
* Tests if the browser is run on Windows Phone.
*
* @return true if run on Windows Phone, false otherwise
+ * @since 7.3.2
*/
public boolean isWindowsPhone() {
return isWindowsPhone;
@@ -473,6 +477,24 @@ public class VBrowserDetails implements Serializable {
}
/**
+ * Tests if the browser is run on iPhone.
+ *
+ * @return
+ */
+ public boolean isIPhone() {
+ return isIPhone;
+ }
+
+ /**
+ * Tests if the browser is run on iPad.
+ *
+ * @return
+ */
+ public boolean isIPad() {
+ return isIPad;
+ }
+
+ /**
* Returns the major version of the operating system. Currently only
* supported for mobile devices (iOS/Android)
*
diff --git a/shared/src/com/vaadin/shared/ui/datefield/Resolution.java b/shared/src/com/vaadin/shared/ui/datefield/Resolution.java
index 6d467e233c..689db11188 100644
--- a/shared/src/com/vaadin/shared/ui/datefield/Resolution.java
+++ b/shared/src/com/vaadin/shared/ui/datefield/Resolution.java
@@ -16,7 +16,6 @@
package com.vaadin.shared.ui.datefield;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.List;
/**
@@ -26,8 +25,9 @@ import java.util.List;
* @since 7.0
*/
public enum Resolution {
- SECOND(Calendar.SECOND), MINUTE(Calendar.MINUTE), HOUR(Calendar.HOUR_OF_DAY), DAY(
- Calendar.DAY_OF_MONTH), MONTH(Calendar.MONTH), YEAR(Calendar.YEAR);
+ // Values from Calendar.SECOND etc. Set as ints to avoid Calendar dependency
+ // (does not exist on the client side)
+ SECOND(13), MINUTE(12), HOUR(11), DAY(5), MONTH(2), YEAR(1);
private int calendarField;
@@ -36,7 +36,7 @@ public enum Resolution {
}
/**
- * Returns the field in {@link Calendar} that corresponds to this
+ * Returns the field in java.util.Calendar that corresponds to this
* resolution.
*
* @return one of the field numbers used by Calendar
diff --git a/uitest/eclipse-run-selected-test.properties b/uitest/eclipse-run-selected-test.properties
index 70010fd1da..f8fb0a8c14 100644
--- a/uitest/eclipse-run-selected-test.properties
+++ b/uitest/eclipse-run-selected-test.properties
@@ -14,6 +14,9 @@
com.vaadin.testbench.screenshot.directory=<enter the full path to the screenshots directory, parent of "references" directory>
+; Deployment url to use for testing. Context path must be /
+; com.vaadin.testbench.deployment.url=http://<enter your ip here>:8888/
+
;
; For only TestBench 3
;
@@ -29,9 +32,6 @@ com.vaadin.testbench.screenshot.directory=<enter the full path to the screenshot
; Location where TestBench 2 jar can be found
com.vaadin.testbench.lib.dir=<enter location of testbench here>
-; Deployment url to use for testing. Context path must be /
-com.vaadin.testbench.deployment.url=http://<enter your ip here>:8888/
-
; Run the whole test even if a screenshot comparison fails
com.vaadin.testbench.screenshot.softfail=true
diff --git a/uitest/src/com/vaadin/tests/components/AbstractTestUI.java b/uitest/src/com/vaadin/tests/components/AbstractTestUI.java
index d7fb7d03fb..558379260b 100644
--- a/uitest/src/com/vaadin/tests/components/AbstractTestUI.java
+++ b/uitest/src/com/vaadin/tests/components/AbstractTestUI.java
@@ -181,9 +181,13 @@ public abstract class AbstractTestUI extends UI {
getLayout().replaceComponent(oldComponent, newComponent);
}
- protected abstract String getTestDescription();
+ protected String getTestDescription() {
+ return null;
+ };
- protected abstract Integer getTicketNumber();
+ protected Integer getTicketNumber() {
+ return null;
+ };
protected WebBrowser getBrowser() {
return getSession().getBrowser();
diff --git a/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java
new file mode 100644
index 0000000000..4e1c8f5ca2
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java
@@ -0,0 +1,218 @@
+/*
+ * 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.absolutelayout;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.MarginInfo;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.AbsoluteLayout;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Table;
+
+/**
+ * Tests how AbsoluteLayout handles relative sized contents.
+ *
+ * @author Vaadin Ltd
+ */
+@Theme("tests-tickets")
+public class AbsoluteLayoutRelativeSizeContent extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ HorizontalLayout level1 = new HorizontalLayout(
+ createComparisonTableOnFixed(), createTableOnFixed(),
+ createHalfTableOnFixed(),
+ createHalfTableAndFixedTableOnFixed(), createHalfTableOnFull());
+ level1.setSpacing(true);
+ level1.setWidth(100, Unit.PERCENTAGE);
+ level1.setExpandRatio(
+ level1.getComponent(level1.getComponentCount() - 1), 1);
+ level1.setMargin(new MarginInfo(true, false, false, false));
+
+ HorizontalLayout level2 = new HorizontalLayout(createFullOnFixed(),
+ createFullOnFull());
+ level2.setSpacing(true);
+ level2.setWidth(100, Unit.PERCENTAGE);
+ level2.setExpandRatio(
+ level2.getComponent(level2.getComponentCount() - 1), 1);
+ level2.setMargin(new MarginInfo(true, false, false, false));
+
+ addComponent(level1);
+ addComponent(level2);
+ }
+
+ /**
+ * Creates an {@link AbsoluteLayout} of fixed size that contains a
+ * full-sized {@link Table} that has been forced to full size with css.
+ * Represents the workaround given for this ticket.
+ *
+ * @return the created layout
+ */
+ private Component createComparisonTableOnFixed() {
+ AbsoluteLayout absoluteLayout = new AbsoluteLayout();
+ absoluteLayout.setWidth(200, Unit.PIXELS);
+ absoluteLayout.setHeight(200, Unit.PIXELS);
+ absoluteLayout.setCaption("comparison table in full size");
+
+ Table table = new Table();
+ table.setSizeFull();
+ table.setId("comparison-table");
+ absoluteLayout.addComponent(table, "top:0;bottom:0;left:0;right:0;");
+ return absoluteLayout;
+ }
+
+ /**
+ * Creates an {@link AbsoluteLayout} of fixed size that contains a
+ * full-sized {@link Table}.
+ *
+ * @return the created layout
+ */
+ private Component createTableOnFixed() {
+ AbsoluteLayout absoluteLayout = new AbsoluteLayout();
+ absoluteLayout.setWidth(200, Unit.PIXELS);
+ absoluteLayout.setHeight(200, Unit.PIXELS);
+ absoluteLayout.setCaption("full-sized table expected");
+
+ Table table = new Table();
+ table.setSizeFull();
+ table.setId("full-table");
+ absoluteLayout.addComponent(table);
+ return absoluteLayout;
+ }
+
+ /**
+ * Creates an {@link AbsoluteLayout} of fixed size that contains a
+ * half-sized {@link Table}.
+ *
+ * @return the created layout
+ */
+ private Component createHalfTableOnFixed() {
+ AbsoluteLayout absoluteLayout = new AbsoluteLayout();
+ absoluteLayout.setWidth(200, Unit.PIXELS);
+ absoluteLayout.setHeight(200, Unit.PIXELS);
+ absoluteLayout.setCaption("half-sized table expected");
+
+ Table table = new Table();
+ table.setWidth(50, Unit.PERCENTAGE);
+ table.setHeight(50, Unit.PERCENTAGE);
+ table.setId("half-table");
+ absoluteLayout.addComponent(table);
+ return absoluteLayout;
+ }
+
+ /**
+ * Creates an {@link AbsoluteLayout} of fixed size that contains a
+ * half-sized {@link Table} and a fixed size {@link Table}.
+ *
+ * @return the created layout
+ */
+ private Component createHalfTableAndFixedTableOnFixed() {
+ AbsoluteLayout absoluteLayout = new AbsoluteLayout();
+ absoluteLayout.setWidth(200, Unit.PIXELS);
+ absoluteLayout.setHeight(200, Unit.PIXELS);
+ absoluteLayout.setCaption("half-sized and tiny expected");
+
+ Table table = new Table();
+ table.setWidth(50, Unit.PERCENTAGE);
+ table.setHeight(50, Unit.PERCENTAGE);
+ table.setId("halfwithtiny-table");
+ absoluteLayout.addComponent(table);
+
+ Table tableTiny = new Table();
+ tableTiny.setWidth(50, Unit.PIXELS);
+ tableTiny.setHeight(50, Unit.PIXELS);
+ absoluteLayout.addComponent(tableTiny, "right:50;");
+ return absoluteLayout;
+ }
+
+ /**
+ * Creates an {@link AbsoluteLayout} of full size that contains a half-sized
+ * {@link Table}.
+ *
+ * @return the created layout
+ */
+ private Component createHalfTableOnFull() {
+ AbsoluteLayout absoluteLayout = new AbsoluteLayout();
+ absoluteLayout.setSizeFull();
+ absoluteLayout.setId("halfinfull-layout");
+ absoluteLayout.setCaption("half-sized table expected");
+
+ Table table = new Table();
+ table.setWidth(50, Unit.PERCENTAGE);
+ table.setHeight(50, Unit.PERCENTAGE);
+ table.setId("halfinfull-table");
+ absoluteLayout.addComponent(table);
+ return absoluteLayout;
+ }
+
+ /**
+ * Creates an {@link AbsoluteLayout} of fixed size that contains a
+ * fixed-sized {@link AbsoluteLayout}.
+ *
+ * @return the created layout
+ */
+ private Component createFullOnFixed() {
+ AbsoluteLayout absoluteLayout = new AbsoluteLayout();
+ absoluteLayout.setWidth(200, Unit.PIXELS);
+ absoluteLayout.setHeight(200, Unit.PIXELS);
+ absoluteLayout.setId("fullonfixed-outer");
+ absoluteLayout.addStyleName("green");
+ absoluteLayout.setCaption("yellow area expected");
+
+ AbsoluteLayout absoluteLayout2 = new AbsoluteLayout();
+ absoluteLayout2.setSizeFull();
+ absoluteLayout2.setId("fullonfixed-inner");
+ absoluteLayout2.addStyleName("yellow");
+
+ absoluteLayout.addComponent(absoluteLayout2, "top:50px;left:100px;");
+ return absoluteLayout;
+ }
+
+ /**
+ * Creates an {@link AbsoluteLayout} of full size that contains another
+ * full-sized {@link AbsoluteLayout}.
+ *
+ * @return the created layout
+ */
+ private AbsoluteLayout createFullOnFull() {
+ AbsoluteLayout absoluteLayout = new AbsoluteLayout();
+ absoluteLayout.setSizeFull();
+ absoluteLayout.setId("fullonfull-outer");
+ absoluteLayout.addStyleName("cyan");
+ absoluteLayout.setCaption("area with red border expected");
+
+ AbsoluteLayout absoluteLayout2 = new AbsoluteLayout();
+ absoluteLayout2.setSizeFull();
+ absoluteLayout2.setId("fullonfull-inner");
+ absoluteLayout2.addStyleName("redborder");
+
+ absoluteLayout.addComponent(absoluteLayout2, "top:50px;left:100px;");
+ return absoluteLayout;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Full size component in AbsoluteLayout shouldn't get undefined size";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 13131;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java
new file mode 100644
index 0000000000..6cb8c476c9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.absolutelayout;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.number.IsCloseTo.closeTo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Tests how AbsoluteLayout handles relative sized contents.
+ *
+ * @author Vaadin Ltd
+ */
+public class AbsoluteLayoutRelativeSizeContentTest extends MultiBrowserTest {
+
+ @Override
+ @Before
+ public void setup() throws Exception {
+ super.setup();
+ openTestURL();
+
+ waitForElementPresent(By.id("comparison-table"));
+ };
+
+ @Test
+ public void testFullAgainstComparison() {
+ WebElement comparison = findElement(By.id("comparison-table"));
+ WebElement full = findElement(By.id("full-table"));
+
+ assertThat("Full table should be as wide as comparison table",
+ full.getSize().width, is(comparison.getSize().width));
+ assertThat("Full table should be as high as comparison table",
+ full.getSize().height, is(comparison.getSize().height));
+ }
+
+ @Test
+ public void testHalfAgainstComparison() {
+ WebElement comparison = findElement(By.id("comparison-table"));
+ WebElement half = findElement(By.id("half-table"));
+
+ assertThat(
+ "Half-sized table should be half as wide as comparison table",
+ half.getSize().width, is(comparison.getSize().width / 2));
+ assertThat(
+ "Half-sized table should be half as high as comparison table",
+ half.getSize().height, is(comparison.getSize().height / 2));
+ }
+
+ @Test
+ public void testHalfWithTinyAgainstComparison() {
+ WebElement comparison = findElement(By.id("comparison-table"));
+ WebElement half = findElement(By.id("halfwithtiny-table"));
+
+ assertThat(
+ "Half-sized table should be half as wide as comparison table even if there are other components in the layout",
+ half.getSize().width, is(comparison.getSize().width / 2));
+ assertThat(
+ "Half-sized table should be half as high as comparison table even if there are other components in the layout",
+ half.getSize().height, is(comparison.getSize().height / 2));
+ }
+
+ @Test
+ public void testHalfAgainstFullLayout() {
+ WebElement layout = findElement(By.id("halfinfull-layout"));
+ WebElement half = findElement(By.id("halfinfull-table"));
+
+ assertThat("Half-sized table should be half as wide as full layout",
+ (double) half.getSize().width,
+ closeTo(((double) layout.getSize().width) / 2, 0.5));
+ assertThat("Half-sized table should be half as high as full layout",
+ (double) half.getSize().height,
+ closeTo(((double) layout.getSize().height) / 2, 0.5));
+ }
+
+ @Test
+ public void testFullOnFixedWithSetLocation() {
+ WebElement outer = findElement(By.id("fullonfixed-outer"));
+ WebElement inner = findElement(By.id("fullonfixed-inner"));
+
+ assertThat(
+ "Inner layout should be as wide as outer layout minus left position",
+ inner.getSize().width, is(outer.getSize().width - 100));
+ assertThat(
+ "Inner layout should be as high as outer layout minus top position",
+ inner.getSize().height, is(outer.getSize().height - 50));
+ }
+
+ @Test
+ public void testFullOnFullWithSetLocation() {
+ WebElement outer = findElement(By.id("fullonfull-outer"));
+ WebElement inner = findElement(By.id("fullonfull-inner"));
+
+ assertThat(
+ "Inner layout should be as wide as outer layout minus left position",
+ inner.getSize().width, is(outer.getSize().width - 100));
+ assertThat(
+ "Inner layout should be as high as outer layout minus top position",
+ inner.getSize().height, is(outer.getSize().height - 50));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIcon.java b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIcon.java
new file mode 100644
index 0000000000..b0450e22c3
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIcon.java
@@ -0,0 +1,59 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.server.FontAwesome;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.ComboBox;
+
+/**
+ * Test UI to check click on icon in the combobox.
+ *
+ * @author Vaadin Ltd
+ */
+public class ComboBoxClickIcon extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final List<String> items = new ArrayList<String>();
+ items.add("A");
+ items.add("B");
+ items.add("C");
+ final ComboBox combo = new ComboBox();
+ combo.setImmediate(true);
+ combo.setItemIcon(items.get(0), FontAwesome.ALIGN_CENTER);
+ combo.setItemIcon(items.get(1), FontAwesome.ALIGN_CENTER);
+ combo.setItemIcon(items.get(2), FontAwesome.ALIGN_CENTER);
+ combo.addItems(items);
+ combo.setTextInputAllowed(false);
+ addComponent(combo);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Combobox icon should handle click events";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14624;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIconTest.java b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIconTest.java
new file mode 100644
index 0000000000..949fcdb882
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxClickIconTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.ComboBoxElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Test to check whether combobox is expanded when icon is clicked.
+ *
+ * @author Vaadin Ltd
+ */
+public class ComboBoxClickIconTest extends MultiBrowserTest {
+
+ @Test
+ public void testClickOnIconInCombobox() {
+ openTestURL();
+
+ $(ComboBoxElement.class).first().openPopup();
+
+ getDriver().findElements(By.className("gwt-MenuItem")).get(1).click();
+
+ getDriver().findElement(By.className("v-filterselect"))
+ .findElement(By.className("v-icon")).click();
+
+ Assert.assertTrue("Unable to find menu items in combobox popup",
+ isElementPresent(By.className("gwt-MenuItem")));
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/combobox/ComboBoxInputPromptTest.java b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxInputPromptTest.java
index cbd83c5734..1e6f7e4170 100644
--- a/uitest/src/com/vaadin/tests/components/combobox/ComboBoxInputPromptTest.java
+++ b/uitest/src/com/vaadin/tests/components/combobox/ComboBoxInputPromptTest.java
@@ -18,16 +18,13 @@ package com.vaadin.tests.components.combobox;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyString;
-import static org.junit.Assert.assertEquals;
-import com.vaadin.testbench.elements.ButtonElement;
-import com.vaadin.testbench.elements.ComboBoxElement;
-import com.vaadin.testbench.elements.TextFieldElement;
-import com.vaadin.tests.tb3.AbstractTB3Test;
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.ComboBoxElement;
import com.vaadin.tests.tb3.MultiBrowserTest;
public class ComboBoxInputPromptTest extends MultiBrowserTest {
diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java
new file mode 100644
index 0000000000..62db60be76
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffset.java
@@ -0,0 +1,68 @@
+package com.vaadin.tests.components.datefield;
+
+import com.vaadin.data.Property;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.datefield.Resolution;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.DateField;
+import com.vaadin.ui.Label;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class DateFieldDayResolutionOffset extends AbstractTestUI {
+
+ private final String initialDateString = "09/01/2014 00:00:00";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Label dateValue = new Label(initialDateString);
+ dateValue.setId("dateValue");
+
+ final TimeZone timezone = TimeZone.getTimeZone("GMT");
+ final SimpleDateFormat dateformat = getDateFormat(timezone);
+ final DateField dateField = getDateField(timezone, dateformat);
+
+ addComponent(dateValue);
+ addComponent(dateField);
+
+ dateField.addValueChangeListener( new Property.ValueChangeListener(){
+ @Override
+ public void valueChange(Property.ValueChangeEvent event) {
+ dateValue.setValue(dateformat.format(dateField.getValue()));
+ }
+ });
+ }
+
+ private DateField getDateField(TimeZone timezone, SimpleDateFormat dateformat) {
+ final DateField dateField = new DateField();
+ try {
+ Date initialDate = dateformat.parse(initialDateString);
+ dateField.setResolution(Resolution.DAY);
+ dateField.setTimeZone(timezone);
+ dateField.setValue(initialDate);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return dateField;
+ }
+
+ private SimpleDateFormat getDateFormat(TimeZone timezone) {
+ final SimpleDateFormat dateformat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
+ dateformat.setTimeZone(timezone);
+ return dateformat;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "The time should stay at 00:00:00 when selecting dates with Resolution.DAY selected.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14653;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffsetTest.java b/uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffsetTest.java
new file mode 100644
index 0000000000..c3b3af9aa4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/datefield/DateFieldDayResolutionOffsetTest.java
@@ -0,0 +1,43 @@
+package com.vaadin.tests.components.datefield;
+
+import com.vaadin.testbench.elements.DateFieldElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.tests.tb3.AbstractTB3Test;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+public class DateFieldDayResolutionOffsetTest extends MultiBrowserTest {
+
+ @Test
+ public void dateValueDoesNotHaveOffset() throws InterruptedException {
+ openTestURL();
+
+ openDatePicker();
+ select2ndOfSeptember();
+
+ LabelElement dateValue = $(LabelElement.class).id("dateValue");
+ assertThat(dateValue.getText(), is("09/02/2014 00:00:00"));
+ }
+
+ private void select2ndOfSeptember() {
+ for(WebElement e : findElements(By.className("v-datefield-calendarpanel-day"))) {
+ if(e.getText().equals("2")) {
+ e.click();
+ break;
+ }
+ }
+ }
+
+ private void openDatePicker() {
+ DateFieldElement dateField = $(DateFieldElement.class).first();
+
+ dateField.findElement(By.tagName("button"))
+ .click();
+ }
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/formlayout/TableInFormLayoutCausesScrollingTest.java b/uitest/src/com/vaadin/tests/components/formlayout/TableInFormLayoutCausesScrollingTest.java
index dc10217efb..3a0dcafe1f 100644
--- a/uitest/src/com/vaadin/tests/components/formlayout/TableInFormLayoutCausesScrollingTest.java
+++ b/uitest/src/com/vaadin/tests/components/formlayout/TableInFormLayoutCausesScrollingTest.java
@@ -2,6 +2,7 @@ package com.vaadin.tests.components.formlayout;
import com.vaadin.testbench.elements.TableElement;
import com.vaadin.tests.tb3.MultiBrowserTest;
+import org.junit.Ignore;
import org.junit.Test;
import org.openqa.selenium.Keys;
import org.openqa.selenium.interactions.Actions;
@@ -11,6 +12,12 @@ import java.io.IOException;
public class TableInFormLayoutCausesScrollingTest extends MultiBrowserTest {
@Test
+ @Ignore
+ //This test is actually testing that #7309 is NOT fixed.
+ //Ignoring the test because it is not stable and it's
+ //occasionally failing on browsers even when it shouldn't.
+
+ //There's no point fixing this test before #7309 is actually fixed.
public void pageIsNotScrolled() throws IOException {
openTestURL();
diff --git a/uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbars.java b/uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbars.java
new file mode 100644
index 0000000000..ef535baa0a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbars.java
@@ -0,0 +1,71 @@
+/*
+ * 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.panel;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+
+public class UndefinedSizeScrollbars extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ VerticalLayout layout = new VerticalLayout();
+ layout.setSpacing(true);
+ layout.setSizeFull();
+ setContent(layout);
+
+ GridLayout grid = new GridLayout();
+ grid.setSpacing(true);
+
+ TextField text1 = new TextField();
+ text1.setCaption("Text1");
+ text1.setRequired(true);
+
+ TextField text2 = new TextField();
+ text2.setCaption("Text2");
+ text2.setRequired(true);
+
+ ComboBox combo = new ComboBox();
+ combo.setCaption("Combo1");
+
+ CheckBox check = new CheckBox();
+ check.setCaption("Check");
+
+ grid.setColumns(2);
+ grid.setRows(2);
+
+ grid.addComponent(text1);
+ grid.addComponent(text2);
+ grid.addComponent(combo);
+ grid.addComponent(check);
+
+ grid.setSizeUndefined();
+
+ Panel panel = new Panel();
+ panel.setContent(grid);
+
+ panel.setSizeUndefined();
+
+ layout.addComponent(panel);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbarsTest.java b/uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbarsTest.java
new file mode 100644
index 0000000000..c055356624
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/panel/UndefinedSizeScrollbarsTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.panel;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class UndefinedSizeScrollbarsTest extends MultiBrowserTest {
+
+ @Test
+ public void testNoScrollbars() throws IOException {
+ openTestURL();
+ compareScreen("noscrollbars");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/popupview/DisabledPopupView.java b/uitest/src/com/vaadin/tests/components/popupview/DisabledPopupView.java
new file mode 100644
index 0000000000..ecce1781a5
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/popupview/DisabledPopupView.java
@@ -0,0 +1,23 @@
+package com.vaadin.tests.components.popupview;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.PopupView;
+
+public class DisabledPopupView extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ PopupView popupView = new PopupView("Disabled Popup", new Button("Hi!"));
+
+ popupView.setEnabled(false);
+
+ addComponent(popupView);
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14797;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/popupview/DisabledPopupViewTest.java b/uitest/src/com/vaadin/tests/components/popupview/DisabledPopupViewTest.java
new file mode 100644
index 0000000000..be9345d588
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/popupview/DisabledPopupViewTest.java
@@ -0,0 +1,20 @@
+package com.vaadin.tests.components.popupview;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.PopupViewElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+
+public class DisabledPopupViewTest extends MultiBrowserTest {
+
+ @Test
+ public void disabledPopupDoesNotOpen() {
+ openTestURL();
+
+ $(PopupViewElement.class).first().click();
+
+ assertFalse($(ButtonElement.class).exists());
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/table/ContainerSizeChangeTest.java b/uitest/src/com/vaadin/tests/components/table/ContainerSizeChangeTest.java
index 041b23749c..e13238e10d 100644
--- a/uitest/src/com/vaadin/tests/components/table/ContainerSizeChangeTest.java
+++ b/uitest/src/com/vaadin/tests/components/table/ContainerSizeChangeTest.java
@@ -1,5 +1,6 @@
package com.vaadin.tests.components.table;
+import static junit.framework.TestCase.fail;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -19,9 +20,6 @@ import com.vaadin.tests.tb3.MultiBrowserTest;
public class ContainerSizeChangeTest extends MultiBrowserTest {
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
@Test
public void tableShouldLoadCorrectItems() throws IOException,
InterruptedException {
@@ -52,11 +50,12 @@ public class ContainerSizeChangeTest extends MultiBrowserTest {
}
private void assertRowDoesNotExist(TableElement table, int rowIndex) {
- // This is a really crappy way to workaround JUnit's limitation to
- // provide a proper assert.throws method...
- thrown.expect(NoSuchElementException.class);
- table.getCell(rowIndex, 0);
+ try {
+ table.getCell(rowIndex, 0);
+
+ fail(String.format("Row %s should not exists.", rowIndex));
+ } catch (NoSuchElementException e) {
- Assert.fail(String.format("Row %s should not exists.", rowIndex));
+ }
}
}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableClickAndDragOnIconAndComponentsTest.java b/uitest/src/com/vaadin/tests/components/table/TableClickAndDragOnIconAndComponentsTest.java
index 4a46342cab..aee8cc96d9 100644
--- a/uitest/src/com/vaadin/tests/components/table/TableClickAndDragOnIconAndComponentsTest.java
+++ b/uitest/src/com/vaadin/tests/components/table/TableClickAndDragOnIconAndComponentsTest.java
@@ -15,19 +15,22 @@
*/
package com.vaadin.tests.components.table;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.List;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import com.vaadin.tests.tb3.SingleBrowserTest;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
-import org.openqa.selenium.interactions.Actions;
import com.vaadin.testbench.elements.TableElement;
-import com.vaadin.tests.tb3.MultiBrowserTest;
+import org.openqa.selenium.interactions.Actions;
/**
* Tests that clicking on active fields doesn't change Table selection, nor does
@@ -36,203 +39,174 @@ import com.vaadin.tests.tb3.MultiBrowserTest;
* @author Vaadin Ltd
*/
public class TableClickAndDragOnIconAndComponentsTest extends MultiBrowserTest {
- @Test
- public void testClickingAndDragging() {
+
+ @Override
+ public void setup() throws Exception {
+ super.setup();
+
openTestURL();
+ }
- TableElement table = $(TableElement.class).first();
+ @Test
+ public void clickOnTextFieldDoesNotSelectRow() {
+ selectRow(1);
- // ensure there's no initial selection
- List<WebElement> selected = table.findElements(By
- .className("v-selected"));
- assertTrue("selection found when there should be none",
- selected.isEmpty());
-
- // click a cell
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 2nd row expected)",
- "red 1foo", table.getCell(1, 2).getText());
- table.getCell(1, 2).click();
-
- // ensure the correct row and nothing but that got selected
- selected = table.findElements(By.className("v-selected"));
- assertFalse("no selection found when there should be some",
- selected.isEmpty());
- // find cell contents (row header included)
- List<WebElement> cellContents = selected.get(0).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 2nd row expected)",
- "red 1foo", cellContents.get(2).getText());
- assertEquals("unexpected table selection size", 1, selected.size());
+ clickOnTextField(2);
+ assertThatFocusTextFieldHasText("foo 2foo");
- List<WebElement> rows = table.findElement(By.className("v-table-body"))
- .findElements(By.tagName("tr"));
- assertEquals("unexpected table row count", 5, rows.size());
+ assertThat(getSelectedRowTextValue(), is(1));
+ }
- // find a row that isn't the one selected
- cellContents = rows.get(2).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 3rd row expected)",
- "red 2foo", cellContents.get(2).getText());
-
- // click on a TextField on that row
- WebElement textField = rows.get(2)
- .findElements(By.className("v-textfield")).get(0);
- assertEquals(
- "expected value not found, wrong cell or contents (6th column of the 3rd row expected)",
- "foo 2foo", textField.getAttribute("value"));
- textField.click();
+ @Test
+ public void clickOnReadOnlyTextFieldSelectsRow() {
+ selectRow(1);
+
+ clickOnReadOnlyTextField(2);
+
+ assertThat(getSelectedRowTextValue(), is(2));
+ }
+
+ @Test
+ public void clickOnLabelSelectsRow() {
+ selectRow(1);
+
+ clickOnLabel(2);
- // ensure the focus shifted correctly
- List<WebElement> focused = table.findElements(By
+ assertThat(getSelectedRowTextValue(), is(2));
+ }
+
+ @Test
+ public void clickOnEmbeddedIconSelectsRow() {
+ selectRow(1);
+
+ clickOnEmbeddedIcon(2);
+
+ assertThat(getSelectedRowTextValue(), is(2));
+ }
+
+ @Test
+ public void dragAndDroppingRowDoesNotSelectRow() {
+ selectRow(1);
+
+ moveRow(0, 3);
+
+ assertThat(getSelectedRowTextValue(), is(1));
+ assertThat(getSelectedRowIndex(), is(0));
+ }
+
+ @Test
+ public void dragAndDroppingSelectedRowStaysSelected() {
+ selectRow(1);
+
+ moveRow(1, 4);
+
+ assertThat(getSelectedRowTextValue(), is(1));
+ assertThat(getSelectedRowIndex(), is(4));
+ }
+
+ private void assertThatFocusTextFieldHasText(String text) {
+ List<WebElement> focused = getTable().findElements(By
.className("v-textfield-focus"));
- assertEquals("unexpected amount of focused textfields", 1,
- focused.size());
- assertEquals(
- "expected value not found, wrong cell or contents (6th column of the 3rd row expected)",
- "foo 2foo", focused.get(0).getAttribute("value"));
-
- // ensure the selection didn't change
- selected = table.findElements(By.className("v-selected"));
- assertEquals("unexpected table selection size", 1, selected.size());
- cellContents = selected.get(0).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 2nd row expected)",
- "red 1foo", cellContents.get(2).getText());
-
- // click on a Label on that row
- WebElement label = rows.get(2).findElements(By.className("v-label"))
- .get(0);
- assertEquals(
- "expected value not found, wrong cell or contents (5th column of the 3rd row expected)",
- "foo 2foo", label.getText());
- label.click();
- // ensure the focus shifted correctly
- focused = table.findElements(By.className("v-textfield-focus"));
- assertTrue("focused textfields found when there should be none",
- focused.isEmpty());
+ assertThat(focused.get(0).getAttribute("value"), is(text));
+ }
+
+ private int getSelectedRowTextValue() {
+ WebElement selectedRow = getSelectedRow();
- // ensure the selection changed
- selected = table.findElements(By.className("v-selected"));
- assertEquals("unexpected table selection size", 1, selected.size());
- cellContents = selected.get(0).findElements(
+ //i.e. 'red 1foo'
+ String text = getText(selectedRow, 2);
+
+ return Integer.parseInt(text.substring(4, 5));
+ }
+
+ private String getText(WebElement row, int column) {
+ List<WebElement> cellContents = getCellContents(row);
+
+ return cellContents.get(column).getText();
+ }
+
+ private List<WebElement> getCellContents(WebElement row) {
+ return row.findElements(
By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 3rd row expected)",
- "red 2foo", cellContents.get(2).getText());
+ }
+
+ private WebElement getSelectedRow() {
+ return getTable().findElement(By
+ .className("v-selected"));
+ }
+
+ private void clickOnTextField(int row) {
+ WebElement textField = getTextField(row, 0);
- // click on the selected row's textfield (same as earlier)
textField.click();
+ }
+
+ private void clickOnReadOnlyTextField(int row) {
+ WebElement textField = getTextField(row, 1);
- // ensure the focus shifted correctly
- focused = table.findElements(By.className("v-textfield-focus"));
- assertEquals("unexpected amount of focused textfields", 1,
- focused.size());
- assertEquals(
- "expected value not found, wrong cell or contents (6th column of the 3rd row expected)",
- "foo 2foo", focused.get(0).getAttribute("value"));
-
- // ensure the selection didn't change
- selected = table.findElements(By.className("v-selected"));
- assertEquals("unexpected table selection size", 1, selected.size());
- cellContents = selected.get(0).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 3rd row expected)",
- "red 2foo", cellContents.get(2).getText());
-
- // find the readOnly TextField of the previously selected row
- textField = rows.get(1).findElements(By.className("v-textfield"))
- .get(1);
- assertEquals(
- "expected value not found, wrong cell or contents (7th column of the 2nd row expected)",
- "foo 1foo", textField.getAttribute("value"));
- assertEquals(
- "expected readonly status not found, wrong cell or contents (7th column of the 2nd row expected)",
- "true", textField.getAttribute("readonly"));
-
- // click on that TextField
textField.click();
+ }
- // ensure the focus shifted correctly
- focused = table.findElements(By.className("v-textfield-focus"));
- assertTrue("focused textfields found when there should be none",
- focused.isEmpty());
+ private WebElement getTextField(int row, int index) {
+ return getElement(row, index, "v-textfield");
+ }
- // ensure the selection changed
- selected = table.findElements(By.className("v-selected"));
- assertEquals("unexpected table selection size", 1, selected.size());
- cellContents = selected.get(0).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 2nd row expected)",
- "red 1foo", cellContents.get(2).getText());
-
- // click the embedded icon of the other row
- WebElement embedded = rows.get(2).findElement(
- By.className("v-embedded"));
- embedded.click();
-
- // ensure the selection changed
- selected = table.findElements(By.className("v-selected"));
- assertEquals("unexpected table selection size", 1, selected.size());
- cellContents = selected.get(0).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 3rd row expected)",
- "red 2foo", cellContents.get(2).getText());
+ private WebElement getElement(int row, String className) {
+ return getElement(row, 0, className);
+ }
- // check row you are about to drag
- cellContents = rows.get(4).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 5th row expected)",
- "red 4foo", cellContents.get(2).getText());
+ private WebElement getElement(int row, int index, String className) {
+ return getRows()
+ .get(row)
+ .findElements(By.className(className))
+ .get(index);
+ }
- // check the row above it
- cellContents = rows.get(3).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 4th row expected)",
- "red 3foo", cellContents.get(2).getText());
+ private List<WebElement> getRows() {
+ return getTable().findElement(By.className("v-table-body"))
+ .findElements(By.tagName("tr"));
+ }
- // drag the row to the row that's two places above it (gets dropped
- // below that)
- cellContents = rows.get(4).findElements(
- By.className("v-table-cell-content"));
- new Actions(getDriver()).moveToElement(cellContents.get(2))
- .clickAndHold().moveToElement(rows.get(2)).release().perform();
+ private void selectRow(int row) {
+ TableElement table = getTable();
+
+ table.getCell(row, 2).click();
+ }
- // find the current order of the rows
- rows = table.findElement(By.className("v-table-body")).findElements(
- By.tagName("tr"));
- assertEquals("unexpected table row count", 5, rows.size());
+ private TableElement getTable() {
+ return $(TableElement.class).first();
+ }
- // ensure the row got dragged
- cellContents = rows.get(3).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the dragged row expected, should be on 4th row now)",
- "red 4foo", cellContents.get(2).getText());
- cellContents = rows.get(4).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the previous 4th row expected, should be on 5th row now)",
- "red 3foo", cellContents.get(2).getText());
-
- // ensure the selection didn't change
- selected = table.findElements(By.className("v-selected"));
- assertEquals("unexpected table selection size", 1, selected.size());
- cellContents = selected.get(0).findElements(
- By.className("v-table-cell-content"));
- assertEquals(
- "expected value not found, wrong cell or contents (3rd column of the 3rd row expected)",
- "red 2foo", cellContents.get(2).getText());
+ private void clickOnLabel(int row) {
+ WebElement label = getElement(row, "v-label");
+ label.click();
+ }
+
+ private void clickOnEmbeddedIcon(int row) {
+ WebElement embeddedIcon = getElement(row, "v-embedded");
+ embeddedIcon.click();
+ }
+
+ private void moveRow(int from, int to) {
+ List<WebElement> rows = getRows();
+ List<WebElement> cellContents = getCellContents(rows.get(from));
+
+ new Actions(getDriver()).moveToElement(cellContents.get(2))
+ .clickAndHold().moveToElement(rows.get(to)).release().perform();
}
+ private int getSelectedRowIndex() {
+ List<WebElement> rows = getRows();
+
+ //Unfortunately rows.getIndexOf(getSelectedRow()) doesn't work.
+ for(WebElement r : rows) {
+ if(r.getAttribute("class").contains("v-selected")) {
+ return rows.indexOf(r);
+ }
+ }
+
+ return -1;
+ }
}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRows.java b/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRows.java
index d9cbf007df..df06580dae 100644
--- a/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRows.java
+++ b/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRows.java
@@ -11,6 +11,12 @@ import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Table;
+/**
+ * Scroll position should be restored when removing and re-adding all rows in
+ * Table.
+ *
+ * @author Vaadin Ltd
+ */
public class TableRepairsScrollPositionOnReAddingAllRows extends AbstractTestUI {
private static final long serialVersionUID = 1L;
@@ -19,32 +25,130 @@ public class TableRepairsScrollPositionOnReAddingAllRows extends AbstractTestUI
protected void setup(VaadinRequest request) {
final BeanItemContainer<TableItem> cont = new BeanItemContainer<TableItem>(
TableItem.class);
- final List<TableItem> itemList = new ArrayList<TableItem>();
+ final List<TableItem> restoringItemList = new ArrayList<TableItem>();
- Button button1 = new Button("ReAdd rows");
- button1.setId("button1");
- button1.addClickListener(new ClickListener() {
+ final Table table = new Table();
+ table.setWidth("400px");
+ table.setPageLength(-1);
+ table.setContainerDataSource(cont);
+ table.setSelectable(true);
+
+ Button buttonRestore = new Button("Restore table rows");
+ buttonRestore.setId("buttonRestore");
+ buttonRestore.addClickListener(new ClickListener() {
@Override
public void buttonClick(com.vaadin.ui.Button.ClickEvent event) {
cont.removeAllItems();
- cont.addAll(itemList);
+ cont.addAll(restoringItemList);
}
});
+ Button buttonReAddAllViaAddAll = new Button("Re-add rows all at once");
+ buttonReAddAllViaAddAll.setId("buttonReAddAllViaAddAll");
+ buttonReAddAllViaAddAll.addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(com.vaadin.ui.Button.ClickEvent event) {
+ List<TableItem> originalItemIds = new ArrayList<TableItem>(cont
+ .getItemIds());
+ cont.removeAllItems();
+ cont.addAll(originalItemIds);
+ }
+ });
+
+ Button buttonReplaceByAnotherCollectionViaAddAll = new Button(
+ "Replace by another items (via addAll())");
+ buttonReplaceByAnotherCollectionViaAddAll
+ .setId("buttonReplaceByAnotherCollectionViaAddAll");
+ buttonReplaceByAnotherCollectionViaAddAll
+ .addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(
+ com.vaadin.ui.Button.ClickEvent event) {
+ cont.removeAllItems();
+ // create new collection (of different items) with other
+ // size
+ List<TableItem> itemList = new ArrayList<TableItem>();
+ for (int i = 0; i < 79; i++) {
+ TableItem ti = new TableItem();
+ ti.setName("AnotherItem1_" + i);
+ itemList.add(ti);
+ }
+ cont.addAll(itemList);
+ }
+ });
+
+ Button buttonReplaceByAnotherCollectionViaAdd = new Button(
+ "Replace by another items (via add(), add()..)");
+ buttonReplaceByAnotherCollectionViaAdd
+ .setId("buttonReplaceByAnotherCollectionViaAdd");
+ buttonReplaceByAnotherCollectionViaAdd
+ .addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(
+ com.vaadin.ui.Button.ClickEvent event) {
+ cont.removeAllItems();
+ for (int i = 0; i < 81; i++) {
+ TableItem ti = new TableItem();
+ ti.setName("AnotherItem2_" + i);
+ // add one by one in container
+ cont.addBean(ti);
+ }
+ }
+ });
+
+ Button buttonReplaceBySubsetOfSmallerSize = new Button(
+ "Replace rows by sub-set of smaller size (size not enought for restoring scroll position)");
+ buttonReplaceBySubsetOfSmallerSize
+ .setId("buttonReplaceBySubsetOfSmallerSize");
+ buttonReplaceBySubsetOfSmallerSize
+ .addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(
+ com.vaadin.ui.Button.ClickEvent event) {
+ cont.removeAllItems();
+ cont.addAll(restoringItemList.subList(0, 20));
+ }
+ });
+
+ Button buttonReplaceByWholeSubsetPlusOnNew = new Button(
+ "Replace rows by whole subset plus one new item");
+ buttonReplaceByWholeSubsetPlusOnNew
+ .setId("buttonReplaceByWholeSubsetPlusOnNew");
+ buttonReplaceByWholeSubsetPlusOnNew
+ .addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(
+ com.vaadin.ui.Button.ClickEvent event) {
+ cont.removeAllItems();
+
+ List<TableItem> list = new ArrayList<TableItem>(
+ restoringItemList);
+ TableItem ti = new TableItem();
+ ti.setName("AnotherItem3_" + 80);
+ list.add(ti);
+ cont.addAll(list);
+ }
+ });
+
for (int i = 0; i < 80; i++) {
TableItem ti = new TableItem();
- ti.setName("Name_" + i);
- itemList.add(ti);
+ ti.setName("Item_" + i);
+ restoringItemList.add(ti);
cont.addBean(ti);
}
- final Table table = new Table();
- table.setPageLength(-1);
- table.setContainerDataSource(cont);
- table.setSelectable(true);
-
- getLayout().addComponent(button1);
+ getLayout().addComponent(buttonReAddAllViaAddAll);
+ getLayout().addComponent(buttonReplaceByAnotherCollectionViaAddAll);
+ getLayout().addComponent(buttonReplaceByAnotherCollectionViaAdd);
+ getLayout().addComponent(buttonReplaceBySubsetOfSmallerSize);
+ getLayout().addComponent(buttonReplaceByWholeSubsetPlusOnNew);
+ getLayout().addComponent(buttonRestore);
getLayout().addComponent(table);
}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRowsTest.java b/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRowsTest.java
index 807a80d182..a3e7f29dfe 100644
--- a/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRowsTest.java
+++ b/uitest/src/com/vaadin/tests/components/table/TableRepairsScrollPositionOnReAddingAllRowsTest.java
@@ -15,8 +15,8 @@
*/
package com.vaadin.tests.components.table;
-import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.number.IsCloseTo.closeTo;
import org.junit.Test;
import org.openqa.selenium.By;
@@ -31,6 +31,12 @@ import com.vaadin.testbench.screenshot.ImageComparison;
import com.vaadin.testbench.screenshot.ReferenceNameGenerator;
import com.vaadin.tests.tb3.MultiBrowserTest;
+/**
+ * Scroll position should be restored when removing and re-adding all rows in
+ * Table.
+ *
+ * @author Vaadin Ltd
+ */
public class TableRepairsScrollPositionOnReAddingAllRowsTest extends
MultiBrowserTest {
@@ -39,28 +45,126 @@ public class TableRepairsScrollPositionOnReAddingAllRowsTest extends
throws InterruptedException {
openTestURL();
- WebElement buttonReAddRows = findElement(By.id("button1"));
+ WebElement row0 = $(TableElement.class).first().getCell(0, 0);
+ int rowLocation0 = row0.getLocation().getY();
+ // case 1
scrollUp();
waitUntilNot(new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver input) {
- return $(TableElement.class).first().getCell(49, 0) == null;
+ return $(TableElement.class).first().getCell(48, 0) == null;
}
}, 10);
- WebElement row = $(TableElement.class).first().getCell(49, 0);
+ WebElement row = $(TableElement.class).first().getCell(48, 0);
int rowLocation = row.getLocation().getY();
- buttonReAddRows.click();
+ // This button is for re-adding all rows (original itemIds) at once
+ // (removeAll() + addAll())
+ hitButton("buttonReAddAllViaAddAll");
- row = $(TableElement.class).first().getCell(49, 0);
+ row = $(TableElement.class).first().getCell(48, 0);
int newRowLocation = row.getLocation().getY();
+ // ranged check because IE9 consistently misses the mark by 1 pixel
+ assertThat(
+ "Scroll position should be the same as before Re-Adding rows via addAll()",
+ (double) newRowLocation,
+ closeTo(rowLocation, row.getSize().height + 1));
+
+ // case 2
+ scrollUp();
+
+ waitUntilNot(new ExpectedCondition<Boolean>() {
+ @Override
+ public Boolean apply(WebDriver input) {
+ return $(TableElement.class).first().getCell(48, 0) == null;
+ }
+ }, 10);
+
+ row = $(TableElement.class).first().getCell(48, 0);
+ rowLocation = row.getLocation().getY();
+
+ // This button is for replacing all rows at once (removeAll() +
+ // addAll())
+ hitButton("buttonReplaceByAnotherCollectionViaAddAll");
+
+ row = $(TableElement.class).first().getCell(48, 0);
+ newRowLocation = row.getLocation().getY();
+
+ // ranged check because IE9 consistently misses the mark by 1 pixel
assertThat(
- "Scroll position should be the same as before Re-Adding all rows",
- rowLocation == newRowLocation, is(true));
+ "Scroll position should be the same as before Replacing rows via addAll()",
+ (double) newRowLocation,
+ closeTo(rowLocation, row.getSize().height + 1));
+
+ // case 3
+ // This button is for replacing all rows one by one (removeAll() + add()
+ // + add()..)
+ hitButton("buttonReplaceByAnotherCollectionViaAdd");
+
+ row = $(TableElement.class).first().getCell(0, 0);
+ newRowLocation = row.getLocation().getY();
+
+ // ranged check because IE9 consistently misses the mark by 1 pixel
+ assertThat("Scroll position should be 0", (double) newRowLocation,
+ closeTo(rowLocation0, 1));
+
+ // case 4
+ // This button is for restoring initial list and for scrolling to 0
+ // position
+ hitButton("buttonRestore");
+ scrollUp();
+
+ waitUntilNot(new ExpectedCondition<Boolean>() {
+ @Override
+ public Boolean apply(WebDriver input) {
+ return $(TableElement.class).first().getCell(48, 0) == null;
+ }
+ }, 10);
+
+ // This button is for replacing all rows at once but the count of rows
+ // is less then first index to scroll
+ hitButton("buttonReplaceBySubsetOfSmallerSize");
+
+ row = $(TableElement.class).first().getCell(5, 0);
+
+ newRowLocation = row.getLocation().getY();
+
+ // ranged check because IE9 consistently misses the mark by 1 pixel
+ assertThat("Scroll position should be 0", (double) newRowLocation,
+ closeTo(rowLocation0, 1));
+
+ // case 5
+ // This button is for restoring initial list and for scrolling to 0
+ // position
+ hitButton("buttonRestore");
+ scrollUp();
+
+ waitUntilNot(new ExpectedCondition<Boolean>() {
+ @Override
+ public Boolean apply(WebDriver input) {
+ return $(TableElement.class).first().getCell(48, 0) == null;
+ }
+ }, 10);
+
+ row = $(TableElement.class).first().getCell(48, 0);
+ rowLocation = row.getLocation().getY();
+
+ // This button is for replacing by whole original sub-set of items plus
+ // one new
+ hitButton("buttonReplaceByWholeSubsetPlusOnNew");
+
+ row = $(TableElement.class).first().getCell(48, 0);
+ newRowLocation = row.getLocation().getY();
+
+ // ranged check because IE9 consistently misses the mark by 1 pixel
+ assertThat("Scroll position should be the same as before Replacing",
+ (double) newRowLocation,
+ closeTo(rowLocation, row.getSize().height + 1));
+
}
private void scrollUp() {
@@ -68,6 +172,6 @@ public class TableRepairsScrollPositionOnReAddingAllRowsTest extends
By.className("v-table-body-wrapper"));
JavascriptExecutor js = new TestBenchCommandExecutor(getDriver(),
new ImageComparison(), new ReferenceNameGenerator());
- js.executeScript("arguments[0].scrollTop = " + 1200, actualElement);
+ js.executeScript("arguments[0].scrollTop = " + 1205, actualElement);
}
}
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServer.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServer.java
new file mode 100644
index 0000000000..b51a8dde08
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServer.java
@@ -0,0 +1,83 @@
+package com.vaadin.tests.components.tabsheet;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
+import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
+
+/**
+ * TabSheet test in case user selects a tab and on the selection listener the
+ * selected tab is changed to another one.
+ *
+ * This test used to cause nonfunctional TabSheet if the current tab was 1, user
+ * selects 5, then the selection listener will revert the selected tab to 1.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class TabSelectionRevertedByServer extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ final TabSheet tabsheet = new TabSheet();
+ tabsheet.setWidth("400px");
+
+ Component lastLabel = null;
+
+ for (int i = 1; i <= 5; i++) {
+ String caption = "Tab " + i;
+ Label label = new Label(caption);
+ tabsheet.addTab(label, caption);
+
+ lastLabel = label;
+ }
+
+ tabsheet.setSelectedTab(0);
+
+ final Component lastTab = lastLabel;
+
+ tabsheet.addSelectedTabChangeListener(new SelectedTabChangeListener() {
+
+ @Override
+ public void selectedTabChange(SelectedTabChangeEvent event) {
+ if (tabsheet.getSelectedTab().equals(lastTab)) {
+
+ // Set focus back to first tab in tabsheet
+ tabsheet.setSelectedTab(0);
+ Notification.show("Focus set back to tab at position 0");
+ }
+ }
+ });
+
+ addComponent(tabsheet);
+
+ Button button = new Button("Select Last Tab");
+ button.addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ tabsheet.setSelectedTab(lastTab);
+ }
+ });
+ addComponent(button);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Clicking on Tab 5 will revert to Tab 1. The action is handled on the server side and will set the selected tab to 1 if Tab 5 is selected.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14710;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServerTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServerTest.java
new file mode 100644
index 0000000000..64aee8768b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabSelectionRevertedByServerTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * If user selected the last tab the test will change it back to the first one
+ * from a server side selection listener. This test makes sure that actually
+ * happen.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class TabSelectionRevertedByServerTest extends MultiBrowserTest {
+
+ @Test
+ public void testFocus() throws InterruptedException, IOException {
+ openTestURL();
+
+ // Selects Tab 4 which should be selected.
+ click(4);
+ assertSelection(4, 1);
+
+ // Select Tab 5 which should revert to Tab 1.
+ click(5);
+ assertSelection(1, 5);
+
+ // Make sure after reverting the selection the tab selection still
+ // works.
+ click(3);
+ assertSelection(3, 1);
+
+ }
+
+ private void assertSelection(int expectedIndex, int wrongIndex) {
+ TestBenchElement tabExpected = tab(expectedIndex);
+ String attributeClassExpected = tabExpected.getAttribute("class");
+
+ Assert.assertTrue("Tab " + expectedIndex + " should be selected.",
+ attributeClassExpected
+ .contains("v-tabsheet-tabitemcell-selected"));
+
+ TestBenchElement tabWrong = tab(wrongIndex);
+ String attributeClassWrong = tabWrong.getAttribute("class");
+
+ Assert.assertTrue("Tab " + wrongIndex
+ + " should be selected when click on Tab 4",
+ !attributeClassWrong
+ .contains("v-tabsheet-tabitemcell-selected"));
+ }
+
+ /*
+ * Click on the element.
+ */
+ private void click(int tabIndex) throws InterruptedException {
+ click(tab(tabIndex));
+ }
+
+ /*
+ * Click on the element.
+ */
+ private void click(TestBenchElement element) throws InterruptedException {
+
+ element.click(10, 10);
+ if (DELAY > 0) {
+ sleep(DELAY);
+ }
+ }
+
+ /*
+ * Delay for PhantomJS.
+ */
+ private final static int DELAY = 10;
+
+ /*
+ * Provide the tab at specified index.
+ */
+ private TestBenchElement tab(int index) {
+ By by = By.className("v-tabsheet-tabitemcell");
+
+ TestBenchElement element = (TestBenchElement) getDriver().findElements(
+ by).get(index - 1);
+
+ String expected = "Tab " + index;
+ Assert.assertEquals(expected,
+ element.getText().substring(0, expected.length()));
+
+ return element;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java b/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java
new file mode 100644
index 0000000000..67b3b84688
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textfield/EnumTextField.java
@@ -0,0 +1,50 @@
+/*
+ * 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.textfield;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.data.util.ObjectProperty;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.TextField;
+
+public class EnumTextField extends AbstractTestUIWithLog {
+
+ public enum MyEnum {
+ FIRST_VALUE, VALUE, THE_LAST_VALUE;
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final TextField tf = new TextField();
+ tf.addValueChangeListener(new ValueChangeListener() {
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ if (tf.isValid()) {
+ log(tf.getValue() + " (valid)");
+ } else {
+ log(tf.getValue() + " (INVALID)");
+ }
+ }
+ });
+
+ tf.setPropertyDataSource(new ObjectProperty<Enum>(MyEnum.FIRST_VALUE));
+ addComponent(tf);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java b/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java
new file mode 100644
index 0000000000..113acee3a2
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textfield/EnumTextFieldTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.textfield;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+
+import com.vaadin.testbench.elements.TextFieldElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class EnumTextFieldTest extends SingleBrowserTest {
+ @Test
+ public void validValues() {
+ openTestURL();
+ $(TextFieldElement.class).first().clear();
+ $(TextFieldElement.class).first().sendKeys("Value");
+ $(TextFieldElement.class).first().sendKeys(Keys.TAB);
+ Assert.assertEquals("3. Value (valid)", getLogRow(0));
+
+ $(TextFieldElement.class).first().clear();
+ $(TextFieldElement.class).first().sendKeys("VaLuE");
+ $(TextFieldElement.class).first().sendKeys(Keys.TAB);
+ Assert.assertEquals("5. Value (valid)", getLogRow(0));
+
+ $(TextFieldElement.class).first().clear();
+ $(TextFieldElement.class).first().sendKeys("The last value");
+ $(TextFieldElement.class).first().sendKeys(Keys.TAB);
+ Assert.assertEquals("7. The last value (valid)", getLogRow(0));
+
+ }
+
+ @Test
+ public void invalidValue() {
+ openTestURL();
+ $(TextFieldElement.class).first().clear();
+ Assert.assertEquals("2. (INVALID)", getLogRow(0));
+
+ $(TextFieldElement.class).first().sendKeys("bar");
+ $(TextFieldElement.class).first().sendKeys(Keys.TAB);
+ Assert.assertEquals("3. bar (INVALID)", getLogRow(0));
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyField.java b/uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyField.java
new file mode 100644
index 0000000000..a1cabe914e
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyField.java
@@ -0,0 +1,56 @@
+package com.vaadin.tests.components.textfield;
+
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.TextField;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+
+public class LocaleChangeOnReadOnlyField extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final TextField textField = getReadOnlyTextField();
+ addComponent(textField);
+
+ Button changeLocaleButton = addLocaleChangeButton(textField);
+ addComponent(changeLocaleButton);
+ }
+
+ private TextField getReadOnlyTextField() {
+ final TextField textField = new TextField();
+
+ textField.setConverter(BigDecimal.class);
+ textField.setLocale(Locale.US);
+ textField.setValue("1024000");
+ textField.setReadOnly(true);
+
+ return textField;
+ }
+
+ private Button addLocaleChangeButton(final TextField textField) {
+ Button changeLocaleButton = new Button();
+ changeLocaleButton.setCaption("Change Locale");
+ changeLocaleButton.addClickListener(new Button.ClickListener() {
+ @Override
+ public void buttonClick(Button.ClickEvent event) {
+ textField.setLocale(Locale.GERMANY);
+ }
+ });
+
+ return changeLocaleButton;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Read-only fields throw exception when setting converted value in localeMightHaveChanged()";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14400;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyFieldTest.java b/uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyFieldTest.java
new file mode 100644
index 0000000000..03f490c73c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textfield/LocaleChangeOnReadOnlyFieldTest.java
@@ -0,0 +1,24 @@
+package com.vaadin.tests.components.textfield;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TextFieldElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+public class LocaleChangeOnReadOnlyFieldTest extends MultiBrowserTest {
+
+ @Test
+ public void localeIsChangedOnReadOnlyField() {
+ openTestURL();
+
+ TextFieldElement textField = $(TextFieldElement.class).first();
+ assertThat(textField.getValue(), is("1,024,000"));
+
+ $(ButtonElement.class).caption("Change Locale").first().click();
+ assertThat(textField.getValue(), is("1.024.000"));
+ }
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/textfield/RequiredTextField.java b/uitest/src/com/vaadin/tests/components/textfield/RequiredTextField.java
new file mode 100644
index 0000000000..79f5a7e83b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textfield/RequiredTextField.java
@@ -0,0 +1,57 @@
+/*
+ * 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.textfield;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.TextField;
+
+/**
+ * Test for required text field.
+ *
+ * @author Vaadin Ltd
+ */
+public class RequiredTextField extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final TextField field = new TextField();
+
+ addComponent(field);
+
+ Button button = new Button("Set/unset required", new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ field.setRequired(!field.isRequired());
+ }
+ });
+ addComponent(button);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Add .v-required style when setRequired() is used";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 10201;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/textfield/RequiredTextFieldTest.java b/uitest/src/com/vaadin/tests/components/textfield/RequiredTextFieldTest.java
new file mode 100644
index 0000000000..c6ed6c1a58
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textfield/RequiredTextFieldTest.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.components.textfield;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TextFieldElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Test for .v-required style
+ *
+ * @author Vaadin Ltd
+ */
+public class RequiredTextFieldTest extends MultiBrowserTest {
+
+ @Test
+ public void testRequiredStyleName() {
+ openTestURL();
+
+ $(ButtonElement.class).first().click();
+
+ Assert.assertTrue("Text field doesn't contain .v-required style",
+ getStyles().contains("v-required"));
+
+ $(ButtonElement.class).first().click();
+
+ Assert.assertFalse(
+ "Text field contains .v-required style for non-required field",
+ getStyles().contains("v-required"));
+ }
+
+ private String getStyles() {
+ return $(TextFieldElement.class).first().getAttribute("class");
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClick.java b/uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClick.java
new file mode 100644
index 0000000000..8b7890e63c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClick.java
@@ -0,0 +1,61 @@
+package com.vaadin.tests.components.tree;
+
+import com.vaadin.event.ItemClickEvent;
+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.Tree;
+
+public class TreeItemDoubleClick extends AbstractTestUIWithLog {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Tree tree = new Tree("Immediate With ItemClickListener");
+ tree.setImmediate(true);
+ tree.setNullSelectionAllowed(false);
+
+ for (int i = 1; i < 6; i++) {
+ tree.addItem("Tree Item " + i);
+ }
+
+ ItemClickEvent.ItemClickListener listener = new ItemClickEvent.ItemClickListener() {
+ @Override
+ public void itemClick(ItemClickEvent event) {
+ if (event.isDoubleClick()) {
+ log.log("Double Click " + event.getItemId());
+ }
+ }
+ };
+
+ tree.addItemClickListener(listener);
+
+ addComponent(tree);
+
+ Button button = new Button("Change immediate flag");
+ button.addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ // this wouldn't work if tree had a value change listener
+ tree.setImmediate(!tree.isImmediate());
+ log.log("tree.isImmediate() is now " + tree.isImmediate());
+ }
+
+ });
+
+ addComponent(button);
+
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Tests that double click is fired";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14745;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClickTest.java b/uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClickTest.java
new file mode 100644
index 0000000000..95a3f02d60
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/tree/TreeItemDoubleClickTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.tree;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TreeItemDoubleClickTest extends MultiBrowserTest {
+
+ @Test
+ public void test() throws InterruptedException {
+ openTestURL();
+ String caption = "Tree Item 2";
+ doubleClick(getTreeNodeByCaption(caption));
+ assertLogText("Double Click " + caption);
+
+ changeImmediate();
+
+ caption = "Tree Item 3";
+ doubleClick(getTreeNodeByCaption(caption));
+ assertLogText("Double Click " + caption);
+ }
+
+ private void changeImmediate() {
+ $(ButtonElement.class).caption("Change immediate flag").first().click();
+ assertLogText("tree.isImmediate() is now");
+ }
+
+ private WebElement getTreeNodeByCaption(String caption) {
+ return getDriver().findElement(
+ By.xpath("//span[text() = '" + caption + "']"));
+ }
+
+ private void doubleClick(WebElement element) {
+ new Actions(getDriver()).doubleClick(element).build().perform();
+
+ }
+
+ private void assertLogText(String text) {
+ assertThat(
+ String.format("Couldn't find text '%s' from the log.", text),
+ logContainsText(text));
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIcons.java b/uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIcons.java
new file mode 100644
index 0000000000..0668a6aeeb
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIcons.java
@@ -0,0 +1,57 @@
+package com.vaadin.tests.components.treetable;
+
+import static com.vaadin.server.Sizeable.Unit.PIXELS;
+
+import com.vaadin.server.FontAwesome;
+import com.vaadin.server.Resource;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.TreeTable;
+
+public class TreeTableRowIcons extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ HorizontalLayout layout = new HorizontalLayout();
+ layout.setSpacing(true);
+ addComponent(layout);
+
+ layout.addComponent(createTreeTableAndPopulate(new ThemeResource(
+ "../runo/icons/16/ok.png")));
+ layout.addComponent(createTreeTableAndPopulate(FontAwesome.ANDROID));
+ }
+
+ private TreeTable createTreeTableAndPopulate(Resource icon) {
+ TreeTable tt = new TreeTable();
+ tt.addContainerProperty("Foo", String.class, "");
+ tt.setColumnWidth("Foo", 100);
+ tt.addContainerProperty("Bar", String.class, "");
+ tt.setColumnWidth("Bar", 100);
+ tt.setIcon(icon);
+ tt.setHeight(400, PIXELS);
+
+ Object item1 = tt.addItem(new Object[] { "Foo", "Bar" }, null);
+ Object item2 = tt.addItem(new Object[] { "Foo2", "Bar2" }, null);
+ tt.setItemIcon(item1, icon);
+ tt.setItemIcon(item2, icon);
+
+ tt.setParent(item2, item1);
+
+ tt.setCollapsed(item1, false);
+
+ return tt;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "TreeTable should support font icons for items";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14077;
+ }
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIconsTest.java b/uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIconsTest.java
new file mode 100644
index 0000000000..2e299d62ea
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/treetable/TreeTableRowIconsTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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 java.io.IOException;
+
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TreeTableRowIconsTest extends MultiBrowserTest {
+
+ public final String SCREENSHOT_NAME = "TreeTableRowIcons";
+
+ @Test
+ public void checkScreenshot() throws IOException {
+ openTestURL();
+ compareScreen(SCREENSHOT_NAME);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/ui/ComboboxSelectedItemTextTest.java b/uitest/src/com/vaadin/tests/components/ui/ComboboxSelectedItemTextTest.java
index f826654022..ab398035ac 100644
--- a/uitest/src/com/vaadin/tests/components/ui/ComboboxSelectedItemTextTest.java
+++ b/uitest/src/com/vaadin/tests/components/ui/ComboboxSelectedItemTextTest.java
@@ -18,9 +18,11 @@ package com.vaadin.tests.components.ui;
import java.io.IOException;
import org.junit.Test;
-import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+import com.vaadin.testbench.By;
import com.vaadin.tests.tb3.MultiBrowserTest;
/**
@@ -59,24 +61,26 @@ public class ComboboxSelectedItemTextTest extends MultiBrowserTest {
WebElement comboBoxFocus = vaadinElement("/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot["
+ indexToFocus + "]/VFilterSelect[0]");
- // Select an element from the first (editable) combobox.
+ // Select an element from the first (to test) combobox.
comboBox.findElement(By.className("v-filterselect-button")).click();
+ waitForPopup(comboBox);
WebElement comboBoxPopup = vaadinElement("/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot["
+ indexToTest + "]/VFilterSelect[0]#popup");
comboBoxPopup.findElements(By.tagName("td")).get(2).click();
- // Select an element from the second (non-editable combobox) to remove
+ // Select an element from the second (to focus) combobox to remove
// focus from the first combobox
comboBoxFocus.findElement(By.className("v-filterselect-button"))
.click();
+ waitForPopup(comboBoxFocus);
comboBoxPopup = vaadinElement("/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot["
+ indexToFocus + "]/VFilterSelect[0]#popup");
comboBoxPopup.findElements(By.tagName("td")).get(2).click();
- // click the popup on the first combobox. This would reveal the unwanted
- // behaviour.
+ // click the button of the first combobox. This would reveal the
+ // unwanted behaviour.
comboBox.findElement(By.className("v-filterselect-button")).click();
@@ -87,4 +91,13 @@ public class ComboboxSelectedItemTextTest extends MultiBrowserTest {
}
+ private void waitForPopup(final WebElement comboBox) {
+ waitUntilNot(new ExpectedCondition<Boolean>() {
+ @Override
+ public Boolean apply(WebDriver input) {
+ return comboBox.findElements(By.vaadin("#popup")).isEmpty();
+ }
+ }, 10);
+ }
+
} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleName.java b/uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleName.java
new file mode 100644
index 0000000000..35dc4cd325
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleName.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.ui;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+
+/**
+ * Empty test ui to check auto-generated style name for UI.
+ *
+ * @author Vaadin Ltd
+ */
+public class UIAutoGeneratedStyleName extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Add UI specific autogenerated style name to ui div element"
+ + " and overlays container";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14670;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleNameTest.java b/uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleNameTest.java
new file mode 100644
index 0000000000..73e0a7f6b9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/ui/UIAutoGeneratedStyleNameTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ui;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import java.util.Locale;
+
+/**
+ * Test to check auto-generated style name for UI div and overlays div.
+ *
+ * @author Vaadin Ltd
+ */
+public class UIAutoGeneratedStyleNameTest extends MultiBrowserTest {
+
+ @Test
+ public void testUiStyleName() {
+ openTestURL();
+
+ Assert.assertTrue(
+ "UI div element doesn't contain autogenerated style name",
+ containsStyle(getDriver().findElement(By.className("v-app")),
+ UIAutoGeneratedStyleName.class.getSimpleName()
+ .toLowerCase(Locale.ENGLISH)));
+
+ Assert.assertTrue(
+ "Overlays div element doesn't contain autogenerated style name",
+ containsStyle(
+ getDriver().findElement(
+ By.className("v-overlay-container")),
+ UIAutoGeneratedStyleName.class.getSimpleName()
+ .toLowerCase(Locale.ENGLISH)));
+ }
+
+ private boolean containsStyle(WebElement element, String style) {
+ return element.getAttribute("class").contains(style);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/ui/UISerializationTest.java b/uitest/src/com/vaadin/tests/components/ui/UISerializationTest.java
index cbe4dbdf29..2b6ba40e8c 100644
--- a/uitest/src/com/vaadin/tests/components/ui/UISerializationTest.java
+++ b/uitest/src/com/vaadin/tests/components/ui/UISerializationTest.java
@@ -1,18 +1,17 @@
package com.vaadin.tests.components.ui;
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.endsWith;
-import static org.hamcrest.Matchers.startsWith;
-import static org.junit.Assert.assertThat;
-
-import org.junit.Test;
-
import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.tests.tb3.SingleBrowserTest;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertThat;
public class UISerializationTest extends SingleBrowserTest {
+
@Test
+ @Ignore //Broken on all browsers since 9696e6c3e7e952b66ac3f5c9ddc3dfca4233451e
public void tb2test() throws Exception {
openTestURL();
$(ButtonElement.class).first().click();
diff --git a/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java
index 44aea3522a..4ec1dc5c98 100644
--- a/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java
+++ b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAriaTest.java
@@ -47,26 +47,26 @@ public class ExtraWindowShownWaiAriaTest extends MultiBrowserTest {
assertFalse(buttons.isEmpty());
// open alert dialog
- buttons.get(0).click();
+ ButtonElement button = buttons.get(0);
+ button.click();
// ensure dialog opened
- List<WindowElement> windows = $(WindowElement.class).all();
- assertFalse(windows.isEmpty());
+ waitForElementPresent(By.className("v-window"));
+ WindowElement window = $(WindowElement.class).first();
// ensure correct attributes
- assertEquals("alertdialog", windows.get(0).getAttribute("role"));
+ assertEquals("alertdialog", window.getAttribute("role"));
- WebElement header = windows.get(0).findElement(
- By.className("v-window-header"));
+ WebElement header = window.findElement(By.className("v-window-header"));
assertEquals(header.getAttribute("id"),
- windows.get(0).getAttribute("aria-labelledby"));
+ window.getAttribute("aria-labelledby"));
- WebElement label = windows.get(0).findElement(By.className("v-label"));
+ WebElement label = window.findElement(By.className("v-label"));
assertEquals(label.getAttribute("id"),
- windows.get(0).getAttribute("aria-describedby"));
+ window.getAttribute("aria-describedby"));
- List<WebElement> wButtons = windows.get(0).findElements(
- By.className("v-button"));
+ List<WebElement> wButtons = window.findElements(By
+ .className("v-button"));
assertEquals("button", wButtons.get(0).getAttribute("role"));
assertEquals("button", wButtons.get(1).getAttribute("role"));
@@ -74,7 +74,7 @@ public class ExtraWindowShownWaiAriaTest extends MultiBrowserTest {
wButtons.get(0).click();
// ensure dialog closed
- windows = $(WindowElement.class).all();
+ List<WindowElement> windows = $(WindowElement.class).all();
assertTrue(windows.isEmpty());
// check additional description (second checkbox on the page)
@@ -87,19 +87,20 @@ public class ExtraWindowShownWaiAriaTest extends MultiBrowserTest {
assertEquals("true", input.getAttribute("checked"));
// open alert dialog
- buttons = $(ButtonElement.class).all();
- buttons.get(0).click();
+ button = $(ButtonElement.class).first();
+ button.click();
+
+ waitForElementPresent(By.className("v-window"));
// ensure correct attributes
- windows = $(WindowElement.class).all();
- List<WebElement> labels = windows.get(0).findElements(
- By.className("v-label"));
+ window = $(WindowElement.class).first();
+ List<WebElement> labels = window.findElements(By.className("v-label"));
assertEquals(labels.get(0).getAttribute("id") + " "
- + labels.get(1).getAttribute("id"), windows.get(0)
- .getAttribute("aria-describedby"));
+ + labels.get(1).getAttribute("id"),
+ window.getAttribute("aria-describedby"));
// close dialog
- wButtons = windows.get(0).findElements(By.className("v-button"));
+ wButtons = window.findElements(By.className("v-button"));
wButtons.get(0).click();
// ensure dialog closed
@@ -112,12 +113,14 @@ public class ExtraWindowShownWaiAriaTest extends MultiBrowserTest {
textFields.get(1).sendKeys(" - do ASAP");
// open alert dialog
- buttons = $(ButtonElement.class).all();
- buttons.get(0).click();
+ button = $(ButtonElement.class).first();
+ button.click();
+
+ waitForElementPresent(By.className("v-window"));
// ensure the assistive spans have been added to the header
- windows = $(WindowElement.class).all();
- header = windows.get(0).findElement(By.className("v-window-header"));
+ window = $(WindowElement.class).first();
+ header = window.findElement(By.className("v-window-header"));
List<WebElement> assistiveElements = header.findElements(By
.className("v-assistive-device-only"));
assertEquals("Important",
diff --git a/uitest/src/com/vaadin/tests/components/window/WindowWithIcon.java b/uitest/src/com/vaadin/tests/components/window/WindowWithIcon.java
new file mode 100644
index 0000000000..15ceb569b4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/WindowWithIcon.java
@@ -0,0 +1,27 @@
+package com.vaadin.tests.components.window;
+
+import com.vaadin.server.FontAwesome;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Window;
+
+public class WindowWithIcon extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Window window = new Window("Window Caption");
+ window.setIcon(FontAwesome.ROCKET);
+ addWindow(window);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Window should work properly with font icons.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14481;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/window/WindowWithIconTest.java b/uitest/src/com/vaadin/tests/components/window/WindowWithIconTest.java
new file mode 100644
index 0000000000..25c7f57238
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/WindowWithIconTest.java
@@ -0,0 +1,16 @@
+package com.vaadin.tests.components.window;
+
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class WindowWithIconTest extends MultiBrowserTest {
+
+ @Test
+ public void testWindowWithIcon() throws Exception {
+ openTestURL();
+
+ compareScreen("icon-rendered-properly");
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java b/uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java
index 61a38bf552..948c3c13b2 100644
--- a/uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java
+++ b/uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java
@@ -15,9 +15,14 @@
*/
package com.vaadin.tests.fonticon;
+import static org.junit.Assert.assertEquals;
+
import java.io.IOException;
import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
import com.vaadin.tests.tb3.MultiBrowserTest;
@@ -28,4 +33,33 @@ public class FontIconsTest extends MultiBrowserTest {
openTestURL();
compareScreen("all");
}
+
+ @Test
+ public void comboBoxItemIconsOnKeyboardNavigation() throws Exception {
+ openTestURL();
+ WebElement comboBoxInput = getDriver().findElement(
+ By.className("v-filterselect-input"));
+
+ // No initial value.
+ assertEquals("", comboBoxInput.getText());
+
+ // Navigate to the first item with keyboard navigation.
+ sendKeys(comboBoxInput, Keys.ARROW_DOWN, Keys.ARROW_DOWN,
+ Keys.ARROW_DOWN);
+
+ // Value must be "One" without any extra characters.
+ // See ticket #14660
+ assertEquals("One", comboBoxInput.getAttribute("value"));
+
+ // Check also the second item.
+ sendKeys(comboBoxInput, Keys.ARROW_DOWN);
+ assertEquals("Two", comboBoxInput.getAttribute("value"));
+ }
+
+ private void sendKeys(WebElement element, Keys... keys) throws Exception {
+ for (Keys key : keys) {
+ element.sendKeys(key);
+ sleep(10); // For PhantomJS.
+ }
+ }
}
diff --git a/uitest/src/com/vaadin/tests/push/ReconnectLongPollingTest.java b/uitest/src/com/vaadin/tests/push/ReconnectLongPollingTest.java
index 28ef30a04a..22d020b631 100644
--- a/uitest/src/com/vaadin/tests/push/ReconnectLongPollingTest.java
+++ b/uitest/src/com/vaadin/tests/push/ReconnectLongPollingTest.java
@@ -15,9 +15,22 @@
*/
package com.vaadin.tests.push;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import java.util.List;
+
public class ReconnectLongPollingTest extends ReconnectTest {
@Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+
+ // PhantomJS doesn't seem to detect disconnection on
+ // Long-Polling/Streaming:
+ // https://github.com/ariya/phantomjs/issues/11938
+ return getBrowsersExcludingPhantomJS();
+ }
+
+ @Override
protected Class<?> getUIClass() {
return BasicPushLongPolling.class;
}
diff --git a/uitest/src/com/vaadin/tests/push/ReconnectStreamingTest.java b/uitest/src/com/vaadin/tests/push/ReconnectStreamingTest.java
index 0a0275c4d0..4a669e723c 100755
--- a/uitest/src/com/vaadin/tests/push/ReconnectStreamingTest.java
+++ b/uitest/src/com/vaadin/tests/push/ReconnectStreamingTest.java
@@ -15,9 +15,22 @@
*/
package com.vaadin.tests.push;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import java.util.List;
+
public class ReconnectStreamingTest extends ReconnectTest {
@Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+
+ // PhantomJS doesn't seem to detect disconnection on
+ // Long-Polling/Streaming:
+ // https://github.com/ariya/phantomjs/issues/11938
+ return getBrowsersExcludingPhantomJS();
+ }
+
+ @Override
protected Class<?> getUIClass() {
return BasicPushStreaming.class;
}
diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
index 1d03a7df76..76b851fd23 100644
--- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
+++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
@@ -40,6 +40,7 @@ import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
@@ -94,6 +95,10 @@ import elemental.json.impl.JsonUtil;
*/
@RunWith(value = TB3Runner.class)
public abstract class AbstractTB3Test extends TestBenchTestCase {
+
+ @Rule
+ public RetryOnFail retry = new RetryOnFail();
+
/**
* Height of the screenshots we want to capture
*/
diff --git a/uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java b/uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java
index 72fb2c18d1..d6eed3e5c8 100644
--- a/uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java
+++ b/uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java
@@ -40,6 +40,14 @@ import org.openqa.selenium.remote.DesiredCapabilities;
*/
public abstract class MultiBrowserTest extends PrivateTB3Configuration {
+ protected List<DesiredCapabilities> getBrowsersExcludingPhantomJS() {
+ List<DesiredCapabilities> browsers = new ArrayList<DesiredCapabilities>(getAllBrowsers());
+
+ browsers.remove(Browser.PHANTOMJS.getDesiredCapabilities());
+
+ return browsers;
+ }
+
protected List<DesiredCapabilities> getBrowsersExcludingIE() {
List<DesiredCapabilities> browsers = new ArrayList<DesiredCapabilities>(getAllBrowsers());
browsers.remove(Browser.IE8.getDesiredCapabilities());
@@ -50,7 +58,6 @@ public abstract class MultiBrowserTest extends PrivateTB3Configuration {
return browsers;
}
-
protected List<DesiredCapabilities> getBrowsersSupportingShiftClick() {
List<DesiredCapabilities> browsers = new ArrayList<DesiredCapabilities>(getAllBrowsers());
diff --git a/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java
index ff824ad98a..a4bb85bb53 100644
--- a/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java
+++ b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java
@@ -49,6 +49,7 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
private static final String RUN_LOCALLY_PROPERTY = "com.vaadin.testbench.runLocally";
private static final String HOSTNAME_PROPERTY = "com.vaadin.testbench.deployment.hostname";
private static final String PORT_PROPERTY = "com.vaadin.testbench.deployment.port";
+ private static final String DEPLOYMENT_PROPERTY = "com.vaadin.testbench.deployment.url";
private static final Properties properties = new Properties();
private static final File propertiesFile = new File("work",
"eclipse-run-selected-test.properties");
@@ -97,6 +98,15 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
}
@Override
+ protected String getBaseURL() {
+ String url = getProperty(DEPLOYMENT_PROPERTY);
+ if (url == null || url.trim().isEmpty()) {
+ return super.getBaseURL();
+ }
+ return url;
+ }
+
+ @Override
protected String getDeploymentHostname() {
if (getRunLocallyBrowser() != null) {
return "localhost";
@@ -180,7 +190,7 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test {
/*
* (non-Javadoc)
- *
+ *
* @see com.vaadin.tests.tb3.AbstractTB3Test#setupLocalDriver()
*/
@Override
diff --git a/uitest/src/com/vaadin/tests/tb3/RetryOnFail.java b/uitest/src/com/vaadin/tests/tb3/RetryOnFail.java
index 9c12147314..3c22057863 100644
--- a/uitest/src/com/vaadin/tests/tb3/RetryOnFail.java
+++ b/uitest/src/com/vaadin/tests/tb3/RetryOnFail.java
@@ -19,20 +19,7 @@ import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
-/**
- * <strong>ALWAYS</strong> declare the reason for using this test rule in a
- * test.
- *
- * <p>
- * Violators and abusers of this rule will be punished.
- * </p>
- *
- * @since 7.1.14
- * @author Vaadin Ltd
- */
public class RetryOnFail implements TestRule {
- private int retryCount = 1;
-
@Override
public Statement apply(Statement base, Description description) {
return statement(base, description);
@@ -44,6 +31,7 @@ public class RetryOnFail implements TestRule {
@Override
public void evaluate() throws Throwable {
Throwable caughtThrowable = null;
+ int retryCount = getRetryCount();
for (int i = 0; i <= retryCount; i++) {
try {
@@ -60,6 +48,16 @@ public class RetryOnFail implements TestRule {
}
throw caughtThrowable;
}
+
+ private int getRetryCount() {
+ String retryCount = System.getProperty("com.vaadin.testbench.max.retries");
+
+ if(retryCount != null && retryCount != "") {
+ return Integer.parseInt(retryCount);
+ }
+
+ return 0;
+ }
};
}
}
diff --git a/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java
index a99eea9bf6..ed5a2ed8aa 100644
--- a/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java
+++ b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java
@@ -68,13 +68,15 @@ public abstract class ScreenshotTB3Test extends AbstractTB3Test {
* Contains a list of screenshot identifiers for which
* {@link #compareScreen(String)} has failed during the test
*/
- private List<String> screenshotFailures = new ArrayList<String>();
+ private List<String> screenshotFailures;
/**
* Defines TestBench screen comparison parameters before each test run
*/
@Before
public void setupScreenComparisonParameters() {
+ screenshotFailures = new ArrayList<String>();
+
Parameters.setScreenshotErrorDirectory(getScreenshotErrorDirectory());
Parameters
.setScreenshotReferenceDirectory(getScreenshotReferenceDirectory());
diff --git a/uitest/src/com/vaadin/tests/themes/FaviconTest.java b/uitest/src/com/vaadin/tests/themes/FaviconTest.java
new file mode 100644
index 0000000000..31134f656f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/themes/FaviconTest.java
@@ -0,0 +1,60 @@
+package com.vaadin.tests.themes;
+
+import com.vaadin.tests.tb3.SingleBrowserTest;
+import org.junit.Test;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+//Extending SingleBrowserTest just to include the test into our test suites.
+public class FaviconTest extends SingleBrowserTest {
+
+ @Test
+ public void chameleonHasFavicon() {
+ assertThatThemeHasFavicon("chameleon");
+ }
+
+ @Test
+ public void liferayHasFavicon() {
+ assertThatThemeHasFavicon("liferay");
+ }
+
+ @Test
+ public void runoHasFavicon() {
+ assertThatThemeHasFavicon("runo");
+ }
+
+ @Test
+ public void reindeerHasFavicon() {
+ assertThatThemeHasFavicon("reindeer");
+ }
+
+ @Test
+ public void valoHasFavicon() {
+ assertThatThemeHasFavicon("valo");
+ }
+
+ private void assertThatThemeHasFavicon(String theme) {
+ assertThat(getResponseCode(theme), is(200));
+ }
+
+ private int getResponseCode(String theme) {
+ try {
+ URL url = new URL(String.format("%s/VAADIN/themes/%s/favicon.ico", getBaseURL(), theme));
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.connect();
+
+ return connection.getResponseCode();
+
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ return 0;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/themes/ThemeChangeOnTheFlyTest.java b/uitest/src/com/vaadin/tests/themes/ThemeChangeOnTheFlyTest.java
index eb010e82ee..a5657c4eec 100644
--- a/uitest/src/com/vaadin/tests/themes/ThemeChangeOnTheFlyTest.java
+++ b/uitest/src/com/vaadin/tests/themes/ThemeChangeOnTheFlyTest.java
@@ -15,10 +15,8 @@
*/
package com.vaadin.tests.themes;
-import java.io.IOException;
-import java.util.List;
-
-import org.junit.Assert;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
@@ -26,8 +24,11 @@ import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedCondition;
-import com.vaadin.testbench.elements.ButtonElement;
-import com.vaadin.tests.tb3.MultiBrowserTest;
+import java.io.IOException;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
public class ThemeChangeOnTheFlyTest extends MultiBrowserTest {
@@ -100,9 +101,8 @@ public class ThemeChangeOnTheFlyTest extends MultiBrowserTest {
@Override
public Boolean apply(WebDriver input) {
String rootClass = rootDiv.getAttribute("class").trim();
- String expected = "v-app " + theme;
- expected = expected.trim();
- return rootClass.equals(expected);
+
+ return rootClass.contains(theme);
}
}, 30);
}
@@ -110,12 +110,9 @@ public class ThemeChangeOnTheFlyTest extends MultiBrowserTest {
private void assertOverlayTheme(String theme) {
final WebElement overlayContainerDiv = findElement(By
.xpath("//div[contains(@class,'v-overlay-container')]"));
- String expected = "v-app v-overlay-container " + theme;
- expected = expected.trim();
-
String overlayClass = overlayContainerDiv.getAttribute("class").trim();
- Assert.assertEquals(expected, overlayClass);
+ assertThat(overlayClass, containsString(theme));
}
}
diff --git a/uitest/src/com/vaadin/tests/themes/valo/DateFields.java b/uitest/src/com/vaadin/tests/themes/valo/DateFields.java
index 5dca5ab9af..5a752cd985 100644
--- a/uitest/src/com/vaadin/tests/themes/valo/DateFields.java
+++ b/uitest/src/com/vaadin/tests/themes/valo/DateFields.java
@@ -190,6 +190,7 @@ public class DateFields extends VerticalLayout implements View {
date = new InlineDateField("Date picker");
setDate(date);
+ setDateRange(date);
row.addComponent(date);
date = new InlineDateField("Date picker with week numbers");
@@ -211,6 +212,14 @@ public class DateFields extends VerticalLayout implements View {
row.addComponent(form);
}
+ private void setDateRange(DateField date) {
+ date.setRangeStart(getDefaultDate());
+
+ Date endDate = getDefaultDate();
+ endDate.setMonth(endDate.getMonth() + 1);
+ date.setRangeEnd(endDate);
+ }
+
private void setDate(DateField date) {
date.setValue(getDefaultDate());
}
diff --git a/uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaption.java b/uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaption.java
new file mode 100644
index 0000000000..a3a81b3798
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaption.java
@@ -0,0 +1,57 @@
+/*
+ * 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.themes.valo;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Table;
+
+@Theme("valo")
+public class TableWithEmptyCaption extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Table table = new Table();
+ table.addContainerProperty("first", String.class, "");
+ table.addContainerProperty("last", String.class, "");
+ table.addContainerProperty("actions", Component.class, null);
+
+ table.addItem(new Object[] { "Teemu", "Test", new Button("Edit") }, 1);
+ table.addItem(new Object[] { "Dummy", "Test", new Button("Edit") }, 2);
+
+ table.setPageLength(0);
+ table.setColumnHeaders("First Name", "Last Name", "");
+
+ table.setFooterVisible(true);
+ table.setColumnFooter("first", "Footer");
+ table.setColumnFooter("last", "");
+ table.setColumnFooter("actions", "");
+ addComponent(table);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test that column headers (and footers) work properly with empty captions.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14812;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaptionTest.java b/uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaptionTest.java
new file mode 100644
index 0000000000..04de8b498c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/themes/valo/TableWithEmptyCaptionTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.themes.valo;
+
+import org.junit.Test;
+import org.openqa.selenium.TimeoutException;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TableWithEmptyCaptionTest extends MultiBrowserTest {
+
+ @Test
+ public void testEmptyCaption() throws Exception {
+ openTestURL();
+
+ // Wait for the loading bar to disappear before taking the screenshot.
+ try {
+ waitUntil(ExpectedConditions.invisibilityOfElementLocated(By
+ .className("v-loading-indicator")), 5);
+ } catch (TimeoutException e) {
+ // Just take the screenshot, PhantomJS always times out.
+ }
+
+ compareScreen("table-empty-caption");
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java
index 20c74bff5e..d4ddf2dcf9 100644
--- a/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java
+++ b/uitest/src/com/vaadin/tests/themes/valo/ValoThemeUITest.java
@@ -64,7 +64,7 @@ public class ValoThemeUITest extends MultiBrowserTest {
// Note that this can look broken in IE9 because of some browser
// rendering issue... The problem seems to be in the customized
// horizontal layout in the test app
- compareScreen("datefields-with-disabled");
+ compareScreen("datefields-with-range");
}
@Test
diff --git a/uitest/tb3test.xml b/uitest/tb3test.xml
index a39725f1bb..975298926e 100644
--- a/uitest/tb3test.xml
+++ b/uitest/tb3test.xml
@@ -8,6 +8,7 @@
<property name="categories.include" value="" />
<property name="categories.exclude" value="" />
<property name="useLocalWebDriver" value="false" />
+ <property name="com.vaadin.testbench.max.retries" value="0" />
<ivy:resolve file="${tb3test.dir}/ivy.xml" conf="build, build-provided" />
<ivy:cachepath pathid="classpath.tb3.lib" conf="build, build-provided" />
@@ -39,6 +40,7 @@
<jvmarg value="-Dcategories.include=${categories.include}" />
<jvmarg value="-Dcategories.exclude=${categories.exclude}" />
<jvmarg value="-DuseLocalWebDriver=${useLocalWebDriver}" />
+ <jvmarg value="-Dcom.vaadin.testbench.max.retries=${com.vaadin.testbench.max.retries}" />
<test name="${junit.test.suite}" todir="${report.dir}" />
</junit>