]> source.dussan.org Git - vaadin-framework.git/commitdiff
Migrating 7.7.1, 7.7.2, 7.7.3 to V8.
authorDenis Anisimov <denis@vaadin.com>
Wed, 28 Sep 2016 10:24:42 +0000 (13:24 +0300)
committerDenis Anisimov <denis@vaadin.com>
Mon, 3 Oct 2016 06:00:48 +0000 (09:00 +0300)
commit 11c3f8bd9ea65f7a7b8da9a282c31a127bd475a6 - Test and its UI class
are added (both V8 and V7). Required functionality should be available
via modern GWT version.

commit 729dbf96fe76e7627168ab2c9d1d71c4eb7214c8 - About update release
notes. No need to be included.

commit 675f38349c43ac45dae40cf33a7b1fd0f8f261ca - V8 already contains
correct Import-Packages section which uses osgi.javax.servlet.version
variable whise version is 3.0.0 at the moment.

commit 5da7c052f55cb4703b74f38f5bb19fc3f3fa2a76 - Use Vaadin plugin
7.7.0 from 7.7.0.alpha1. Is not applicable.

commit 1df80001ab6c916effa917781dba652d09d01056 - Updated tutorial to
Vaadin 7.7.0. Is not applicable. The tutorial already contains correct
links and updated source code snippets.

commit 8b4f0ed8a894b04902a5d4258119dcdc8e76d1e0 - set-property-fallback
name="user.agent" value="safari". Is already there.

commit 28ed04e827669cc4dd329331dac9699bd93f70bc - Fix animation end
listeners so they are always removed. Is already there.

commit 408253bc3f8bd3975f0525ce6832be214a3552e9 - Use servlet context
classloader when finding servlet class for websockets. Is already there.

commit 7a6f250d89474849648ed2ee96a6bfb78c3b9ca8 - Fire actions before
removing menu from the DOM. Is already there.

commit 9b66c6eb9bebf657d3f2def8c767e0e9d51cc92c - Do not run test on IE8
as IE8 is broken. Transplanted.

commit 3faa43ff39ecda56587b93f0c5e262a2907871a7 - Discard for DateField
when the data source contains null. It is not applicable for V8 (There
is no anymore discard method in DateField (and no datasource suport in
field)). Transplanted for DateField in compatibility.

commit e0c1f91a3d6d1884e07ce8d1ba957aff6a9bf29a - Fix ComboBox paging
when number of items equals page length. It's already done by another
fix which replaced ComboBox in compatibility package to the V7 version.

commit 83a1b8a0961cc9b2d43e01757530cefd035b0a22 - Update DOM and update
escalator row count in the correct order. Transplanted.

commit 45f2fba8ff7a4b62680618a325d4afcebfb7a1e9 - Prevent editor from
being canceled while it is being saved. Transplanted to compatibility
package. Is not applicable to modern Grid.

commit ad67f7f43afb0feec5e029aea90297f2abe4f2c1 - Delete broken
stylesheet and revert to default style until a new stylesheet is
created. Is already there.

commit c970a78d42a2d8f1745df7a11a74f3731f8be9a5 - Always show loading
indicator for JavaScript RPC. Transplanted.

commit 2aad3416061586f7e2649160bd832eefe03702ad - Make test independent
of any converters present in the factory. It's already there.

commit c9ad48430be135d18fe9f30868e091dd51c57b94 - Do not include
yuicompressor for Sass compiler. Transplanted. Exclusion is added into
vaadin/pom.xml

commit 52d01a68e91ce73306b3a1747af97e928048ecdf - Test for Firefox
download disconnecting push channel. Transplanted.

commit 4bc375d1d21f468e6433da3a183150e0bfe0cae4 - Handle encoded URL
characters correctly when constructing widget set name. Transplanted.

commit 17ba88eaf87e15e6f3c729e5c7f8e875d5f86d8d - Update version to
7.7-SNAPSHOT. Is not applicable.

commit 47b7b13e5c959de3bd925693b074d85e7625a87e - Ensure Firefox always
updates the grid scrollbar. Transplanted. Made changes in the logic to
the test for modern Grid component.

commit 4d851ba21d1b8f35685b631d2845731f8fb33252 - Calculate column
widths immediately if there is data. Transplanted to both client side
modules.

commit 8f0b1a1dd026a756912c9f21bd2b34ea46897c7f - Skip Maven enforcer
plugin during demo validation. Transplanted (one build file is
affected).

commit 62815353e1b9d3cd126809f5c818ad35bf913807 - Build demos from 7.7
branch (now for master branch). FW8 demos are added (one build file is
affected).

commit 815d72115d5aaf3676daefd5642115577e4151ef - Make test pass on all
browsers. Transplanted to both V7 and V8 version tests.

commit 516c428ca127e3c31b7b4d74220e4b7eed4571be - Use widget set
specified by init parameter. Transplanted to the one UIProvider class.

commit b00c580ed70f682a42afbfa91f978921bb86c2cd - Use correct column
index when calculating min width during resize. Transplanted into both
client side classes (main and compatibility) as is. Test for V7 is
transplanted as is. Test for V8 is written from scratch based on V7
version.

commit 7dd91cf057eb06a09009096a8278f34aad9bd8d9 - Fix regression that
broke widget set compilation in 7.7.1. It's already there.

commit c665731b0b97b697e80c47955d3558c19f0c81cb - Ensure temporary
layout manager state is cleared at the end of a layout phase.
Transplanted to the one LayoutManager class.

commit 57a965251afdb5ee9ac1913a0101d854d8215aa6 - Fix assertion error
when column widths are calculated. Transplanted to both versions of the
client Grid widget.

commit c5c52684eb30d924cb75a632b526a0f879d5a33c - Format Java files
using Eclipse Neon and Vaadin settings. Only formatting changes. Is not
transplanted.

f5d06d877165bf413ec71c4fc88cf46c8c57a372 - Change javadoc to a style
Eclipse formatter can handle. Transplanted to both versions of the
client Grid widget.

commit 6033e13c20b3d6e8b6f5add0f786d5ab2e1bb3fe - Make initially
disabled grid work when enabled. Transplanted to both client side
modules.

commit a2d6e4fb4b1fd13e9a1b88f2ab1b78d14d8b64a9 - Use
requestAnimationFrame when scrolling in Grid. Transplanted to both
client side modules.

commit fe9438e7b77c606855cfd739dd7e30b3f8cd4165 - Specify branch also
for Sampler. Is not applicable for master branch.

commit 1ec5d8ef7cb8bbd82bae1c9b79a376a5dca28f48 - Update to Chrome 53.
Is already there.

commit 961851bfbc4844474299433c34af6c9e4323d891 - Updated link to new
step 1 video in tutorial. Is already there.

commit 41dc2fe1611adc70d00e6f77debb2a6d4dcdefb0 - Revert "Use widget set
specified by init parameter. Transplanted to the one UIProvider class.

commit 092b4f7f3192555fe3ae22ac03a89ac2ada2a2dd - Use widget set
specified by init parameter. Transplanted to the common server side
classes.

commit 977cec7e3107c2da306d46449dbf32f6544313be - Fix widget set builder
to create widget set in correct location. Transplanted to the one
ClassPathExplorer class file.

commit 6c12ad89ea1064cd4cc0456baca5ee00ae76d032 - Format project pom
files using correct settings. Is not transplanted: only formatting
changes for POM files.

commit 0aad93ecc1ce743dffc093ce7ae2ef88831f6073 - Add tests for
widgetset compilation in different modes. Transplanted. New test
projects.

commit 0a3a1ef8321ed421be2337034fdb1cae2c434c3d - Use
versions-maven-plugin 2.3 to avoid NPE while setting project version. Is
already there.

Change-Id: Ie3a5088f25de1772f01ea30c4a5eba0b169ee0ab

79 files changed:
client/src/main/java/com/vaadin/client/AnimationUtil.java
client/src/main/java/com/vaadin/client/LayoutManager.java
client/src/main/java/com/vaadin/client/communication/ServerRpcQueue.java
client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java
client/src/main/java/com/vaadin/client/data/DataSource.java
client/src/main/java/com/vaadin/client/widget/escalator/ScrollbarBundle.java
client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java
client/src/main/java/com/vaadin/client/widgets/Escalator.java
client/src/main/java/com/vaadin/client/widgets/Grid.java
compatibility-client/src/main/java/com/vaadin/v7/client/connectors/RpcDataSourceConnector.java
compatibility-client/src/main/java/com/vaadin/v7/client/widget/escalator/ScrollbarBundle.java
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/datasources/ListDataSource.java
compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java
compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java
compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java
compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/ItemSetChangeDuringEditorCommit.java [new file with mode: 0644]
pom.xml
scripts/BuildDemos.py
scripts/BuildHelpers.py
server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java
server/src/main/java/com/vaadin/server/UIProvider.java
server/src/main/java/com/vaadin/server/VaadinServlet.java
server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java
server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java
test/addon-using-init-param-widget-set/pom.xml [new file with mode: 0644]
test/addon-using-init-param-widget-set/src/main/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetUI.java [new file with mode: 0644]
test/addon-using-init-param-widget-set/src/test/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetIT.java [new file with mode: 0644]
test/addon-using-no-defined-widget-set/pom.xml [new file with mode: 0644]
test/addon-using-no-defined-widget-set/src/main/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetUI.java [new file with mode: 0644]
test/addon-using-no-defined-widget-set/src/test/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetIT.java [new file with mode: 0644]
test/addon-using-own-widget-set/pom.xml [new file with mode: 0644]
test/addon-using-own-widget-set/src/main/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetUI.java [new file with mode: 0644]
test/addon-using-own-widget-set/src/main/resources/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSet.gwt.xml [new file with mode: 0644]
test/addon-using-own-widget-set/src/test/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetIT.java [new file with mode: 0644]
test/default-widget-set/pom.xml [new file with mode: 0644]
test/default-widget-set/src/main/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetUI.java [new file with mode: 0644]
test/default-widget-set/src/test/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetIT.java [new file with mode: 0644]
test/own-widget-set/pom.xml [new file with mode: 0644]
test/own-widget-set/src/main/java/com/vaadin/test/ownwidgetset/OwnWidgetSetUI.java [new file with mode: 0644]
test/own-widget-set/src/test/java/com/vaadin/test/ownwidgetset/OwnWidgetSetIT.java [new file with mode: 0644]
test/pom.xml [new file with mode: 0644]
test/space in directory/pom.xml [new file with mode: 0644]
test/space in directory/src/main/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryUI.java [new file with mode: 0644]
test/space in directory/src/main/resources/com/vaadin/test/spaceindirectory/SpaceInDirectory.gwt.xml [new file with mode: 0644]
test/space in directory/src/test/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryIT.java [new file with mode: 0644]
test/vaadinservletconfiguration-widget-set/pom.xml [new file with mode: 0644]
test/vaadinservletconfiguration-widget-set/src/main/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetUI.java [new file with mode: 0644]
test/vaadinservletconfiguration-widget-set/src/main/resources/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSet.gwt.xml [new file with mode: 0644]
test/vaadinservletconfiguration-widget-set/src/test/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetIT.java [new file with mode: 0644]
test/widget-set-testutil/pom.xml [new file with mode: 0644]
test/widget-set-testutil/src/main/java/com/vaadin/test/widgetset/AbstractTestWidgetSetUI.java [new file with mode: 0644]
test/widget-set-testutil/src/test/java/com/vaadin/test/defaultwidgetset/AbstractWidgetSetIT.java [new file with mode: 0644]
uitest-common/src/main/java/com/vaadin/tests/tb3/AbstractTB3Test.java
uitest/src/main/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDown.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/grid/GridColumnHiding.java
uitest/src/main/java/com/vaadin/tests/components/grid/InitiallyDisabledGrid.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicator.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/core/SpecialCharactersEncodingUI.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/resources/DownloadWithPush.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridCellFocusOnResetSizeWidget.java
uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridClientColumnRendererConnector.java
uitest/src/main/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValue.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDown.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGrid.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/v7/tests/components/grid/basicfeatures/GridBasicFeatures.java
uitest/src/main/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUI.java [new file with mode: 0644]
uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JSComponent.js [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/grid/GridColumnHidingTest.java
uitest/src/test/java/com/vaadin/tests/components/grid/InitiallyDisabledGridTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicatorTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/tabsheet/TabsheetScrollIntoViewTest.java
uitest/src/test/java/com/vaadin/tests/core/SpecialCharactersEncodingUITest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValueTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGridTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java
uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java
uitest/src/test/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUITest.java [new file with mode: 0644]

index bbefcffbdd652df5111642d650b8f4d4e8e4e8cc..e2cf9e690aa5e2d7d419f813713acff0d02c42dd 100644 (file)
@@ -19,7 +19,6 @@ import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.dom.client.Style;
-import com.vaadin.client.AnimationUtil.AnimationEndListener;
 
 /**
  * Utility methods for working with CSS transitions and animations.
@@ -67,15 +66,15 @@ public class AnimationUtil {
         listener.@com.vaadin.client.AnimationUtil.AnimationEndListener::onAnimationEnd(Lcom/google/gwt/dom/client/NativeEvent;)(e);
       });
       callbackFunc.listener = listener;
-
+    
       elem.addEventListener(@com.vaadin.client.AnimationUtil::ANIMATION_END_EVENT_NAME, callbackFunc, false);
-
+    
       // Store function reference for later removal
       if(!elem._vaadin_animationend_callbacks) {
         elem._vaadin_animationend_callbacks = [];
       }
       elem._vaadin_animationend_callbacks.push(callbackFunc);
-
+    
       return callbackFunc;
     }-*/;
 
@@ -138,7 +137,7 @@ public class AnimationUtil {
             return event.mozAnimationName;
         else if(event.oAnimationName)
             return event.oAnimationName;
-
+    
         return "";
     }-*/;
 
@@ -146,22 +145,22 @@ public class AnimationUtil {
     public static native String getAnimationName(ComputedStyle cstyle)
     /*-{
         var cs = cstyle.@com.vaadin.client.ComputedStyle::computedStyle;
-
+    
         if(!cs.getPropertyValue)
             return "";
-
+    
         if(cs.getPropertyValue("-webkit-animation-name"))
             return cs.getPropertyValue("-webkit-animation-name");
-
+    
         else if(cs.getPropertyValue("animation-name"))
             return cs.getPropertyValue("animation-name");
-
+    
         else if(cs.getPropertyValue("-moz-animation-name"))
             return cs.getPropertyValue("-moz-animation-name");
-
+    
         else if(cs.getPropertyValue("-o-animation-name"))
             return cs.getPropertyValue("-o-animation-name");
-
+    
         return "";
     }-*/;
 
@@ -176,7 +175,7 @@ public class AnimationUtil {
           'MozAnimation': 'animationend',
           'WebkitAnimation': 'webkitAnimationEnd'
         }
-
+    
         for(var a in anims){
             if( el.style[a] !== undefined ){
                 return anims[a];
@@ -195,7 +194,7 @@ public class AnimationUtil {
           'mozAnimation',
           'webkitAnimation'
         ]
-
+    
         for(var i=0; i < anims.length; i++) {
             if( el.style[anims[i]] !== undefined ){
                 return anims[i];
index 841eead561f83ca89f823e443ac869eeb81c1fd4..ad0a3f8c383cb9a64ce6293d53e4121c30d924bc 100644 (file)
@@ -600,6 +600,14 @@ public class LayoutManager {
         }
         Profiler.leave("layout PostLayoutListener");
 
+        // Ensure temporary variables are cleaned
+        if (!pendingOverflowFixes.isEmpty()) {
+            getLogger().warning(
+                    "pendingOverflowFixes is not empty at the end of doLayout: "
+                            + pendingOverflowFixes.dump());
+            pendingOverflowFixes = FastStringSet.create();
+        }
+
         getLogger().info("Total layout phase time: "
                 + totalDuration.elapsedMillis() + "ms");
     }
index 35d6f48565ff85b5c06fae7e34dcf2bca21c8838..ce07fc0baf9c53b87f402dc88aa5cbb048bee08b 100644 (file)
@@ -226,10 +226,11 @@ public class ServerRpcQueue {
      */
     public boolean showLoadingIndicator() {
         for (MethodInvocation invocation : getAll()) {
-            if (isLegacyVariableChange(invocation)) {
+            if (isLegacyVariableChange(invocation)
+                    || isJavascriptRpc(invocation)) {
                 // Always show loading indicator for legacy requests
                 return true;
-            } else if (!isJavascriptRpc(invocation)) {
+            } else {
                 Type type = new Type(invocation.getInterfaceName(), null);
                 Method method = type.getMethod(invocation.getMethodName());
                 if (!TypeDataStore.isNoLoadingIndicator(method)) {
index 33f96e009c15dcc7525e57a7b3e382962957fe8b..9dd1a504ab17d13f320dfc729bd99918a90f17f6 100644 (file)
@@ -378,7 +378,7 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
     }
 
     private void handleMissingRows(Range range) {
-        if (range.isEmpty()) {
+        if (range.isEmpty() || !canFetchData()) {
             return;
         }
         currentRequestCallback = new RequestRowsCallback<>(this, range);
@@ -794,4 +794,17 @@ public abstract class AbstractRemoteDataSource<T> implements DataSource<T> {
     protected boolean isPinned(T row) {
         return pinnedRows.containsKey(getRowKey(row));
     }
+
+    /**
+     * Checks if it is possible to currently fetch data from the remote data
+     * source.
+     * 
+     * @return <code>true</code> if it is ok to try to fetch data,
+     *         <code>false</code> if it is known that fetching data will fail
+     *         and should not be tried right now.
+     * @since 7.7.2
+     */
+    protected boolean canFetchData() {
+        return true;
+    }
 }
index fdec4b9a38e6122a8b75703f1e34ead0d2dd2368..4645957111d6b33ebae9ea86eed51fa3d6fcb2f6 100644 (file)
@@ -217,4 +217,14 @@ public interface DataSource<T> {
      *        means that the row is not currently in this data source's cache.
      */
     public RowHandle<T> getHandle(T row);
+
+    /**
+     * Checks whether this data source is currently waiting for more rows to
+     * become available.
+     *
+     * @return <code>true</code> if waiting for data; otherwise
+     *         <code>false</code>
+     * @since 7.7.2
+     */
+    public boolean isWaitingForData();
 }
index 7e11c6c0d9d52a935885d64f6ce49b6bd21d888b..c62c5f032f136e78e5c0cb9bc5c097bd9b128f16 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.vaadin.client.widget.escalator;
 
+import com.google.gwt.animation.client.AnimationScheduler;
+import com.google.gwt.animation.client.AnimationScheduler.AnimationSupportDetector;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.dom.client.Element;
@@ -31,6 +33,7 @@ import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.EventListener;
 import com.google.gwt.user.client.Timer;
+import com.vaadin.client.BrowserInfo;
 import com.vaadin.client.DeferredWorker;
 import com.vaadin.client.WidgetUtil;
 import com.vaadin.client.widget.grid.events.ScrollEvent;
@@ -47,6 +50,9 @@ import com.vaadin.client.widget.grid.events.ScrollHandler;
  */
 public abstract class ScrollbarBundle implements DeferredWorker {
 
+    private static final boolean supportsRequestAnimationFrame = new AnimationSupportDetector()
+            .isNativelySupported();
+
     private class ScrollEventFirer {
         private final ScheduledCommand fireEventCommand = new ScheduledCommand() {
             @Override
@@ -91,7 +97,17 @@ public abstract class ScrollbarBundle implements DeferredWorker {
                  * We'll gather all the scroll events, and only fire once, once
                  * everything has calmed down.
                  */
-                Scheduler.get().scheduleDeferred(fireEventCommand);
+                if (supportsRequestAnimationFrame) {
+                    // Chrome MUST use this as deferred commands will sometimes
+                    // be run with a 300+ ms delay when scrolling.
+                    AnimationScheduler.get().requestAnimationFrame(
+                            timestamp -> fireEventCommand.execute());
+                } else {
+                    // Does not support requestAnimationFrame and the fallback
+                    // uses a delay of 16ms, we stick to the old deferred
+                    // command which uses a delay of 0ms
+                    Scheduler.get().scheduleDeferred(fireEventCommand);
+                }
                 isBeingFired = true;
             }
         }
@@ -449,13 +465,25 @@ public abstract class ScrollbarBundle implements DeferredWorker {
      * set either <code>overflow-x</code> or <code>overflow-y</code> to "
      * <code>scroll</code>" in the scrollbar's direction.
      * <p>
-     * This is an IE8 workaround, since it doesn't always show scrollbars with
-     * <code>overflow: auto</code> enabled.
+     * This method is an IE8 workaround, since it doesn't always show scrollbars
+     * with <code>overflow: auto</code> enabled.
+     * <p>
+     * Firefox on the other hand loses pending scroll events when the scrollbar
+     * is hidden, so the event must be fired manually.
+     * <p>
+     * When IE8 support is dropped, this should really be simplified.
      */
     protected void forceScrollbar(boolean enable) {
         if (enable) {
             root.getStyle().clearDisplay();
         } else {
+            if (BrowserInfo.get().isFirefox()) {
+                /*
+                 * This is related to the Firefox workaround in setScrollSize
+                 * for setScrollPos(0)
+                 */
+                scrollEventFirer.scheduleEvent();
+            }
             root.getStyle().setDisplay(Display.NONE);
         }
         internalForceScrollbar(enable);
@@ -603,21 +631,37 @@ public abstract class ScrollbarBundle implements DeferredWorker {
          * This needs to be made step-by-step because IE8 flat-out refuses to
          * fire a scroll event when the scroll size becomes smaller than the
          * offset size. All other browser need to suffer alongside.
+         * 
+         * This really should be changed to not use any temporary scroll
+         * handlers at all once IE8 support is dropped, like now done only for
+         * Firefox.
          */
 
         boolean newScrollSizeIsSmallerThanOffsetSize = px <= getOffsetSize();
         boolean scrollSizeBecomesSmallerThanOffsetSize = showsScrollHandle()
                 && newScrollSizeIsSmallerThanOffsetSize;
         if (scrollSizeBecomesSmallerThanOffsetSize && getScrollPos() != 0) {
-            // must be a field because Java insists.
-            scrollSizeTemporaryScrollHandler = addScrollHandler(
-                    new ScrollHandler() {
-                        @Override
-                        public void onScroll(ScrollEvent event) {
-                            setScrollSizeNow(px);
-                        }
-                    });
+            /*
+             * For whatever reason, Firefox loses the scroll event in this case
+             * and the onscroll handler is never called (happens when reducing
+             * size from 1000 items to 1 while being scrolled a bit down, see
+             * #19802). Based on the comment above, only IE8 should really use
+             * 'delayedSizeSet'
+             */
+            boolean delayedSizeSet = !BrowserInfo.get().isFirefox();
+            if (delayedSizeSet) {
+                scrollSizeTemporaryScrollHandler = addScrollHandler(
+                        new ScrollHandler() {
+                            @Override
+                            public void onScroll(ScrollEvent event) {
+                                setScrollSizeNow(px);
+                            }
+                        });
+            }
             setScrollPos(0);
+            if (!delayedSizeSet) {
+                setScrollSizeNow(px);
+            }
         } else {
             setScrollSizeNow(px);
         }
@@ -863,7 +907,10 @@ public abstract class ScrollbarBundle implements DeferredWorker {
 
     @Override
     public boolean isWorkPending() {
+        // Need to include scrollEventFirer.isBeingFired as it might use
+        // requestAnimationFrame - which is not automatically checked
         return scrollSizeTemporaryScrollHandler != null
-                || offsetSizeTemporaryScrollHandler != null;
+                || offsetSizeTemporaryScrollHandler != null
+                || scrollEventFirer.isBeingFired;
     }
 }
index 9767a230bbe8791ef7a8cf15354ec98ae7afb22f..355840d4ce4715f3ab01fbf7e1463a7058ecfd6e 100644 (file)
@@ -457,6 +457,11 @@ public class ListDataSource<T> implements DataSource<T> {
         };
     }
 
+    @Override
+    public boolean isWaitingForData() {
+        return false;
+    }
+
     private Stream<DataChangeHandler> getHandlers() {
         Set<DataChangeHandler> copy = new LinkedHashSet<>(changeHandlers);
         return copy.stream();
index 77afccdb30de3cf57c87c165b227d30aeffa5838..fdd4c22645fac4db1583b14880f6861e35b84fe9 100644 (file)
@@ -672,13 +672,13 @@ public class Escalator extends Widget
         /*-{
             var vScroll = esc.@com.vaadin.client.widgets.Escalator::verticalScrollbar;
             var vScrollElem = vScroll.@com.vaadin.client.widget.escalator.ScrollbarBundle::getElement()();
-
+        
             var hScroll = esc.@com.vaadin.client.widgets.Escalator::horizontalScrollbar;
             var hScrollElem = hScroll.@com.vaadin.client.widget.escalator.ScrollbarBundle::getElement()();
-
+        
             return $entry(function(e) {
                 var target = e.target;
-
+        
                 // in case the scroll event was native (i.e. scrollbars were dragged, or
                 // the scrollTop/Left was manually modified), the bundles have old cache
                 // values. We need to make sure that the caches are kept up to date.
@@ -699,29 +699,29 @@ public class Escalator extends Widget
             return $entry(function(e) {
                 var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX;
                 var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY;
-
+        
                 // Delta mode 0 is in pixels; we don't need to do anything...
-
+        
                 // A delta mode of 1 means we're scrolling by lines instead of pixels
                 // We need to scale the number of lines by the default line height
                 if(e.deltaMode === 1) {
                     var brc = esc.@com.vaadin.client.widgets.Escalator::body;
                     deltaY *= brc.@com.vaadin.client.widgets.Escalator.AbstractRowContainer::getDefaultRowHeight()();
                 }
-
+        
                 // Other delta modes aren't supported
                 if((e.deltaMode !== undefined) && (e.deltaMode >= 2 || e.deltaMode < 0)) {
                     var msg = "Unsupported wheel delta mode \"" + e.deltaMode + "\"";
-
+        
                     // Print warning message
                     esc.@com.vaadin.client.widgets.Escalator::logWarning(*)(msg);
                 }
-
+        
                 // IE8 has only delta y
                 if (isNaN(deltaY)) {
                     deltaY = -0.5*e.wheelDelta;
                 }
-
+        
                 @com.vaadin.client.widgets.Escalator.JsniUtil::moveScrollFromEvent(*)(esc, deltaX, deltaY, e);
             });
         }-*/;
@@ -4170,6 +4170,11 @@ public class Escalator extends Widget
                 frozenColumns += numberOfColumns;
             }
 
+            // Add to DOM
+            header.paintInsertColumns(index, numberOfColumns, frozen);
+            body.paintInsertColumns(index, numberOfColumns, frozen);
+            footer.paintInsertColumns(index, numberOfColumns, frozen);
+
             // this needs to be before the scrollbar adjustment.
             boolean scrollbarWasNeeded = horizontalScrollbar
                     .getOffsetSize() < horizontalScrollbar.getScrollSize();
@@ -4177,14 +4182,12 @@ public class Escalator extends Widget
             boolean scrollbarIsNowNeeded = horizontalScrollbar
                     .getOffsetSize() < horizontalScrollbar.getScrollSize();
             if (!scrollbarWasNeeded && scrollbarIsNowNeeded) {
+                // This might as a side effect move rows around (when scrolled
+                // all the way down) and require the DOM to be up to date, i.e.
+                // the column to be added
                 body.verifyEscalatorCount();
             }
 
-            // Add to DOM
-            header.paintInsertColumns(index, numberOfColumns, frozen);
-            body.paintInsertColumns(index, numberOfColumns, frozen);
-            footer.paintInsertColumns(index, numberOfColumns, frozen);
-
             // fix initial width
             if (header.getRowCount() > 0 || body.getRowCount() > 0
                     || footer.getRowCount() > 0) {
index 9a87d82363af1fbf8b70b339ad40550c4005c852..eac958fdce976aee6320a9ce85afe0b78afbafce 100644 (file)
@@ -3163,7 +3163,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                         rescheduleCount = 0;
                         Scheduler.get().scheduleDeferred(this);
                     }
-                } else if (dataIsBeingFetched) {
+                } else if (currentDataAvailable.isEmpty()
+                        && dataSource.isWaitingForData()) {
                     Scheduler.get().scheduleDeferred(this);
                 } else {
                     calculate();
@@ -3199,7 +3200,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             isScheduled = false;
             rescheduleCount = 0;
 
-            assert !dataIsBeingFetched : "Trying to calculate column widths even though data is still being fetched.";
+            assert !(currentDataAvailable.isEmpty() && dataSource
+                    .isWaitingForData()) : "Trying to calculate column widths without data while data is still being fetched.";
 
             if (columnsAreGuaranteedToBeWiderThanGrid()) {
                 applyColumnWidths();
@@ -4060,21 +4062,15 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
     private final Editor<T> editor = GWT.create(Editor.class);
 
-    private boolean dataIsBeingFetched = false;
-
     /**
      * The cell a click event originated from
      * <p>
      * This is a workaround to make Chrome work like Firefox. In Chrome,
      * normally if you start a drag on one cell and release on:
      * <ul>
-     * <li>that same cell, the click event is that {@code
-     *
-    <td>}.
-     * <li>a cell on that same row, the click event is the parent {@code
-     *
-    <tr>
-     * }.
+     * <li>that same cell, the click event is that <code>&lt;td></code>.
+     * <li>a cell on that same row, the click event is the parent
+     * <code>&lt;tr></code>.
      * <li>a cell on another row, the click event is the table section ancestor
      * ({@code <thead>}, {@code <tbody>} or {@code <tfoot>}).
      * </ul>
@@ -5672,7 +5668,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                                     initialWidth = col.getWidthActual();
 
                                     minCellWidth = escalator.getMinCellWidth(
-                                            getColumns().indexOf(col));
+                                            getVisibleColumns().indexOf(col));
                                     for (Column<?, T> c : getVisibleColumns()) {
                                         if (selectionColumn == c) {
                                             // Don't modify selection column.
@@ -5681,8 +5677,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
                                         if (c.getWidth() < 0) {
                                             c.setWidth(c.getWidthActual());
-                                            fireEvent(new ColumnResizeEvent<>(
-                                                    c));
+                                            fireEvent(
+                                                    new ColumnResizeEvent<>(c));
                                         }
                                     }
 
@@ -5907,7 +5903,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                     public void onRowVisibilityChange(
                             RowVisibilityChangeEvent event) {
                         if (dataSource != null && dataSource.size() != 0) {
-                            dataIsBeingFetched = true;
                             dataSource.ensureAvailability(
                                     event.getFirstVisibleRow(),
                                     event.getVisibleRowCount());
@@ -5947,12 +5942,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             }
         });
 
-        addDataAvailableHandler(new DataAvailableHandler() {
-            @Override
-            public void onDataAvailable(DataAvailableEvent event) {
-                dataIsBeingFetched = false;
-            }
-        });
     }
 
     @Override
@@ -6291,8 +6280,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * @return A unmodifiable list of the columns in the grid
      */
     public List<Column<?, T>> getColumns() {
-        return Collections
-                .unmodifiableList(new ArrayList<>(columns));
+        return Collections.unmodifiableList(new ArrayList<>(columns));
     }
 
     /**
@@ -6717,8 +6705,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                         int oldSize = body.getRowCount();
 
                         // Hide all details.
-                        Set<Integer> oldDetails = new HashSet<>(
-                                visibleDetails);
+                        Set<Integer> oldDetails = new HashSet<>(visibleDetails);
                         for (int i : oldDetails) {
                             setDetailsVisible(i, false);
                         }
@@ -6734,7 +6721,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                         }
 
                         if (newSize > 0) {
-                            dataIsBeingFetched = true;
                             Range visibleRowRange = escalator
                                     .getVisibleRowRange();
                             dataSource.ensureAvailability(
@@ -7829,7 +7815,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         Scheduler.get().scheduleFinally(new ScheduledCommand() {
             @Override
             public void execute() {
-                if (!dataIsBeingFetched) {
+                if (!dataSource.isWaitingForData()) {
                     handler.onDataAvailable(
                             new DataAvailableEvent(currentDataAvailable));
                 }
@@ -8108,8 +8094,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     private void sort(boolean userOriginated) {
         refreshHeader();
-        fireEvent(new SortEvent<>(this,
-                Collections.unmodifiableList(sortOrder), userOriginated));
+        fireEvent(new SortEvent<>(this, Collections.unmodifiableList(sortOrder),
+                userOriginated));
     }
 
     private int getLastVisibleRowIndex() {
@@ -8150,7 +8136,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
     @Override
     public boolean isWorkPending() {
-        return escalator.isWorkPending() || dataIsBeingFetched
+        return escalator.isWorkPending() || dataSource.isWaitingForData()
                 || autoColumnWidthsRecalculator.isScheduled()
                 || editor.isWorkPending();
     }
index 363d3c047da430b163bd643b038d6ed7b5d0c784..f8003004404955d714c8d68c43c7735b97fbccc7 100644 (file)
@@ -73,7 +73,7 @@ public class RpcDataSourceConnector extends AbstractExtensionConnector {
             registerRpc(DataProviderRpc.class, new DataProviderRpc() {
                 @Override
                 public void setRowData(int firstRow, JsonArray rowArray) {
-                    ArrayList<JsonObject> rows = new ArrayList<JsonObject>(
+                    ArrayList<JsonObject> rows = new ArrayList<>(
                             rowArray.length());
                     for (int i = 0; i < rowArray.length(); i++) {
                         JsonObject rowObject = rowArray.getObject(i);
@@ -240,6 +240,11 @@ public class RpcDataSourceConnector extends AbstractExtensionConnector {
                 droppedRowKeys.set(droppedRowKeys.length(), getRowKey(row));
             }
         }
+
+        @Override
+        protected boolean canFetchData() {
+            return isEnabled();
+        }
     }
 
     private final RpcDataSource dataSource = new RpcDataSource();
index bdd4240818db1d837a2ad35dbcd36eb8f1b4fc73..20b1e5d1b98d85ebf31cf7ccb889fe512e2acbf5 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.vaadin.v7.client.widget.escalator;
 
+import com.google.gwt.animation.client.AnimationScheduler;
+import com.google.gwt.animation.client.AnimationScheduler.AnimationSupportDetector;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.dom.client.Element;
@@ -31,6 +33,7 @@ import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.EventListener;
 import com.google.gwt.user.client.Timer;
+import com.vaadin.client.BrowserInfo;
 import com.vaadin.client.DeferredWorker;
 import com.vaadin.client.WidgetUtil;
 import com.vaadin.v7.client.widget.grid.events.ScrollEvent;
@@ -47,6 +50,9 @@ import com.vaadin.v7.client.widget.grid.events.ScrollHandler;
  */
 public abstract class ScrollbarBundle implements DeferredWorker {
 
+    private static final boolean supportsRequestAnimationFrame = new AnimationSupportDetector()
+            .isNativelySupported();
+
     private class ScrollEventFirer {
         private final ScheduledCommand fireEventCommand = new ScheduledCommand() {
             @Override
@@ -91,7 +97,17 @@ public abstract class ScrollbarBundle implements DeferredWorker {
                  * We'll gather all the scroll events, and only fire once, once
                  * everything has calmed down.
                  */
-                Scheduler.get().scheduleDeferred(fireEventCommand);
+                if (supportsRequestAnimationFrame) {
+                    // Chrome MUST use this as deferred commands will sometimes
+                    // be run with a 300+ ms delay when scrolling.
+                    AnimationScheduler.get().requestAnimationFrame(
+                            timestamp -> fireEventCommand.execute());
+                } else {
+                    // Does not support requestAnimationFrame and the fallback
+                    // uses a delay of 16ms, we stick to the old deferred
+                    // command which uses a delay of 0ms
+                    Scheduler.get().scheduleDeferred(fireEventCommand);
+                }
                 isBeingFired = true;
             }
         }
@@ -449,13 +465,25 @@ public abstract class ScrollbarBundle implements DeferredWorker {
      * set either <code>overflow-x</code> or <code>overflow-y</code> to "
      * <code>scroll</code>" in the scrollbar's direction.
      * <p>
-     * This is an IE8 workaround, since it doesn't always show scrollbars with
-     * <code>overflow: auto</code> enabled.
+     * This method is an IE8 workaround, since it doesn't always show scrollbars
+     * with <code>overflow: auto</code> enabled.
+     * <p>
+     * Firefox on the other hand loses pending scroll events when the scrollbar
+     * is hidden, so the event must be fired manually.
+     * <p>
+     * When IE8 support is dropped, this should really be simplified.
      */
     protected void forceScrollbar(boolean enable) {
         if (enable) {
             root.getStyle().clearDisplay();
         } else {
+            if (BrowserInfo.get().isFirefox()) {
+                /*
+                 * This is related to the Firefox workaround in setScrollSize
+                 * for setScrollPos(0)
+                 */
+                scrollEventFirer.scheduleEvent();
+            }
             root.getStyle().setDisplay(Display.NONE);
         }
         internalForceScrollbar(enable);
@@ -603,21 +631,37 @@ public abstract class ScrollbarBundle implements DeferredWorker {
          * This needs to be made step-by-step because IE8 flat-out refuses to
          * fire a scroll event when the scroll size becomes smaller than the
          * offset size. All other browser need to suffer alongside.
+         * 
+         * This really should be changed to not use any temporary scroll
+         * handlers at all once IE8 support is dropped, like now done only for
+         * Firefox.
          */
 
         boolean newScrollSizeIsSmallerThanOffsetSize = px <= getOffsetSize();
         boolean scrollSizeBecomesSmallerThanOffsetSize = showsScrollHandle()
                 && newScrollSizeIsSmallerThanOffsetSize;
         if (scrollSizeBecomesSmallerThanOffsetSize && getScrollPos() != 0) {
-            // must be a field because Java insists.
-            scrollSizeTemporaryScrollHandler = addScrollHandler(
-                    new ScrollHandler() {
-                        @Override
-                        public void onScroll(ScrollEvent event) {
-                            setScrollSizeNow(px);
-                        }
-                    });
+            /*
+             * For whatever reason, Firefox loses the scroll event in this case
+             * and the onscroll handler is never called (happens when reducing
+             * size from 1000 items to 1 while being scrolled a bit down, see
+             * #19802). Based on the comment above, only IE8 should really use
+             * 'delayedSizeSet'
+             */
+            boolean delayedSizeSet = !BrowserInfo.get().isFirefox();
+            if (delayedSizeSet) {
+                scrollSizeTemporaryScrollHandler = addScrollHandler(
+                        new ScrollHandler() {
+                            @Override
+                            public void onScroll(ScrollEvent event) {
+                                setScrollSizeNow(px);
+                            }
+                        });
+            }
             setScrollPos(0);
+            if (!delayedSizeSet) {
+                setScrollSizeNow(px);
+            }
         } else {
             setScrollSizeNow(px);
         }
@@ -863,7 +907,10 @@ public abstract class ScrollbarBundle implements DeferredWorker {
 
     @Override
     public boolean isWorkPending() {
+        // Need to include scrollEventFirer.isBeingFired as it might use
+        // requestAnimationFrame - which is not automatically checked
         return scrollSizeTemporaryScrollHandler != null
-                || offsetSizeTemporaryScrollHandler != null;
+                || offsetSizeTemporaryScrollHandler != null
+                || scrollEventFirer.isBeingFired;
     }
 }
index 994e8059eb2389276deb2c4cf94b1475ce0fc28d..d80cdad3c9a1a664b9f30072542659a0ee8a47e9 100644 (file)
@@ -344,7 +344,7 @@ public class ListDataSource<T> implements DataSource<T> {
         if (datasource == null) {
             throw new IllegalArgumentException("datasource cannot be null");
         }
-        ds = new ArrayList<T>(datasource);
+        ds = new ArrayList<>(datasource);
         wrapper = new ListWrapper();
     }
 
@@ -358,9 +358,9 @@ public class ListDataSource<T> implements DataSource<T> {
      */
     public ListDataSource(T... rows) {
         if (rows == null) {
-            ds = new ArrayList<T>();
+            ds = new ArrayList<>();
         } else {
-            ds = new ArrayList<T>(Arrays.asList(rows));
+            ds = new ArrayList<>(Arrays.asList(rows));
         }
         wrapper = new ListWrapper();
     }
@@ -457,6 +457,11 @@ public class ListDataSource<T> implements DataSource<T> {
         };
     }
 
+    @Override
+    public boolean isWaitingForData() {
+        return false;
+    }
+
     private Stream<DataChangeHandler> getHandlers() {
         Set<DataChangeHandler> copy = new LinkedHashSet<>(changeHandlers);
         return copy.stream();
index e79237702b7cc1880a067e01b1d5e445dd0c8fbb..afc9cd8a45b0c44fb833c96849f01b0fa0aef21d 100644 (file)
@@ -442,14 +442,14 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
          */
         public abstract static class StaticRow<CELLTYPE extends StaticCell> {
 
-            private Map<Column<?, ?>, CELLTYPE> cells = new HashMap<Column<?, ?>, CELLTYPE>();
+            private Map<Column<?, ?>, CELLTYPE> cells = new HashMap<>();
 
             private StaticSection<?> section;
 
             /**
              * Map from set of spanned columns to cell meta data.
              */
-            private Map<Set<Column<?, ?>>, CELLTYPE> cellGroups = new HashMap<Set<Column<?, ?>>, CELLTYPE>();
+            private Map<Set<Column<?, ?>>, CELLTYPE> cellGroups = new HashMap<>();
 
             /**
              * A custom style name for the row or null if none is set.
@@ -497,7 +497,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                             "You can't merge less than 2 columns together.");
                 }
 
-                HashSet<Column<?, ?>> columnGroup = new HashSet<Column<?, ?>>();
+                HashSet<Column<?, ?>> columnGroup = new HashSet<>();
                 // NOTE: this doesn't care about hidden columns, those are
                 // filtered in calculateColspans()
                 for (Column<?, ?> column : columns) {
@@ -591,7 +591,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             private boolean checkMergedCellIsContinuous(
                     Set<Column<?, ?>> mergedCell) {
                 // no matter if hidden or not, just check for continuous order
-                final List<Column<?, ?>> columnOrder = new ArrayList<Column<?, ?>>(
+                final List<Column<?, ?>> columnOrder = new ArrayList<>(
                         section.grid.getColumns());
 
                 if (!columnOrder.containsAll(mergedCell)) {
@@ -661,7 +661,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
              */
             void detach() {
                 // Avoid calling detach twice for a merged cell
-                HashSet<CELLTYPE> cells = new HashSet<CELLTYPE>();
+                HashSet<CELLTYPE> cells = new HashSet<>();
                 for (Column<?, ?> column : getSection().grid.getColumns()) {
                     cells.add(getCell(column));
                 }
@@ -673,7 +673,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
         private Grid<?> grid;
 
-        private List<ROWTYPE> rows = new ArrayList<ROWTYPE>();
+        private List<ROWTYPE> rows = new ArrayList<>();
 
         private boolean visible = true;
 
@@ -1337,8 +1337,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         // Should only be added to the DOM when there's a message to show
         private DivElement message = DivElement.as(DOM.createDiv());
 
-        private Map<Column<?, T>, Widget> columnToWidget = new HashMap<Column<?, T>, Widget>();
-        private List<HandlerRegistration> focusHandlers = new ArrayList<HandlerRegistration>();
+        private Map<Column<?, T>, Widget> columnToWidget = new HashMap<>();
+        private List<HandlerRegistration> focusHandlers = new ArrayList<>();
 
         private boolean enabled = false;
         private State state = State.INACTIVE;
@@ -1433,7 +1433,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         };
 
         /** A set of all the columns that display an error flag. */
-        private final Set<Column<?, T>> columnErrors = new HashSet<Grid.Column<?, T>>();
+        private final Set<Column<?, T>> columnErrors = new HashSet<>();
         private boolean buffered = true;
 
         /** Original position of editor */
@@ -1629,7 +1629,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                 throw new IllegalStateException(
                         "Cannot cancel edit: editor is not in edit mode");
             }
-            handler.cancel(new EditorRequestImpl<T>(grid, rowIndex,
+            handler.cancel(new EditorRequestImpl<>(grid, rowIndex,
                     focusedColumnIndex, null));
             doCancel();
         }
@@ -1675,7 +1675,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             state = State.SAVING;
             setButtonsEnabled(false);
             saveTimeout.schedule(SAVE_TIMEOUT_MS);
-            EditorRequest<T> request = new EditorRequestImpl<T>(grid, rowIndex,
+            EditorRequest<T> request = new EditorRequestImpl<>(grid, rowIndex,
                     focusedColumnIndex, saveRequestCallback);
             handler.save(request);
             updateSelectionCheckboxesAsNeeded(true);
@@ -1739,7 +1739,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             if (state == State.ACTIVATING) {
                 state = State.BINDING;
                 bindTimeout.schedule(BIND_TIMEOUT_MS);
-                EditorRequest<T> request = new EditorRequestImpl<T>(grid,
+                EditorRequest<T> request = new EditorRequestImpl<>(grid,
                         rowIndex, columnIndex, bindRequestCallback);
                 handler.bind(request);
                 grid.getEscalator().setScrollLocked(Direction.VERTICAL,
@@ -2270,7 +2270,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             extends KeyEvent<HANDLER> {
 
         private Grid<?> grid;
-        private final Type<HANDLER> associatedType = new Type<HANDLER>(
+        private final Type<HANDLER> associatedType = new Type<>(
                 getBrowserEventType(), this);
         private final CellReference<?> targetCell;
 
@@ -2330,7 +2330,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
         private Grid<?> grid;
         private final CellReference<?> targetCell;
-        private final Type<HANDLER> associatedType = new Type<HANDLER>(
+        private final Type<HANDLER> associatedType = new Type<>(
                 getBrowserEventType(), this);
 
         public AbstractGridMouseEvent(Grid<?> grid,
@@ -2408,7 +2408,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     private static final double DETAILS_ROW_INITIAL_HEIGHT = 50;
 
-    private EventCellReference<T> eventCell = new EventCellReference<T>(this);
+    private EventCellReference<T> eventCell = new EventCellReference<>(this);
     private GridKeyDownEvent keyDown = new GridKeyDownEvent(this, eventCell);
     private GridKeyUpEvent keyUp = new GridKeyUpEvent(this, eventCell);
     private GridKeyPressEvent keyPress = new GridKeyPressEvent(this, eventCell);
@@ -2882,7 +2882,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                             public void onValueChange(
                                     ValueChangeEvent<Boolean> event) {
                                 if (event.getValue()) {
-                                    fireEvent(new SelectAllEvent<T>(model));
+                                    fireEvent(new SelectAllEvent<>(model));
                                     selected = true;
                                 } else {
                                     model.deselectAll();
@@ -3167,7 +3167,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                         rescheduleCount = 0;
                         Scheduler.get().scheduleDeferred(this);
                     }
-                } else if (dataIsBeingFetched) {
+                } else if (currentDataAvailable.isEmpty()
+                        && dataSource.isWaitingForData()) {
                     Scheduler.get().scheduleDeferred(this);
                 } else {
                     calculate();
@@ -3203,7 +3204,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             isScheduled = false;
             rescheduleCount = 0;
 
-            assert !dataIsBeingFetched : "Trying to calculate column widths even though data is still being fetched.";
+            assert !(currentDataAvailable.isEmpty() && dataSource
+                    .isWaitingForData()) : "Trying to calculate column widths without data while data is still being fetched.";
 
             if (columnsAreGuaranteedToBeWiderThanGrid()) {
                 applyColumnWidths();
@@ -3232,7 +3234,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
             /* Step 1: Apply all column widths as they are. */
 
-            Map<Integer, Double> selfWidths = new LinkedHashMap<Integer, Double>();
+            Map<Integer, Double> selfWidths = new LinkedHashMap<>();
             List<Column<?, T>> columns = getVisibleColumns();
             for (int index = 0; index < columns.size(); index++) {
                 selfWidths.put(index, columns.get(index).getWidth());
@@ -3246,7 +3248,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
              * violated, fix it.
              */
 
-            Map<Integer, Double> constrainedWidths = new LinkedHashMap<Integer, Double>();
+            Map<Integer, Double> constrainedWidths = new LinkedHashMap<>();
             for (int index = 0; index < columns.size(); index++) {
                 Column<?, T> column = columns.get(index);
 
@@ -3271,9 +3273,9 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             boolean defaultExpandRatios = true;
             int totalRatios = 0;
             double reservedPixels = 0;
-            final Set<Column<?, T>> columnsToExpand = new HashSet<Column<?, T>>();
-            List<Column<?, T>> nonFixedColumns = new ArrayList<Column<?, T>>();
-            Map<Integer, Double> columnSizes = new HashMap<Integer, Double>();
+            final Set<Column<?, T>> columnsToExpand = new HashSet<>();
+            List<Column<?, T>> nonFixedColumns = new ArrayList<>();
+            Map<Integer, Double> columnSizes = new HashMap<>();
             final List<Column<?, T>> visibleColumns = getVisibleColumns();
 
             /*
@@ -3536,7 +3538,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
         private static final String STRIPE_CLASSNAME = "stripe";
 
-        private final Map<Element, Widget> elementToWidgetMap = new HashMap<Element, Widget>();
+        private final Map<Element, Widget> elementToWidgetMap = new HashMap<>();
 
         @Override
         public void init(Spacer spacer) {
@@ -3918,7 +3920,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     private final class ColumnHider {
 
         /** Map from columns to their hiding toggles, component might change */
-        private HashMap<Column<?, T>, MenuItem> columnToHidingToggleMap = new HashMap<Grid.Column<?, T>, MenuItem>();
+        private HashMap<Column<?, T>, MenuItem> columnToHidingToggleMap = new HashMap<>();
 
         /**
          * When column is being hidden with a toggle, do not refresh toggles for
@@ -4017,7 +4019,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     /**
      * List of columns in the grid. Order defines the visible order.
      */
-    private List<Column<?, T>> columns = new ArrayList<Column<?, T>>();
+    private List<Column<?, T>> columns = new ArrayList<>();
 
     /**
      * The datasource currently in use. <em>Note:</em> it is <code>null</code>
@@ -4041,7 +4043,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * Current sort order. The (private) sort() method reads this list to
      * determine the order in which to present rows.
      */
-    private List<SortOrder> sortOrder = new ArrayList<SortOrder>();
+    private List<SortOrder> sortOrder = new ArrayList<>();
 
     private Renderer<Boolean> selectColumnRenderer = null;
 
@@ -4064,21 +4066,15 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
     private final Editor<T> editor = GWT.create(Editor.class);
 
-    private boolean dataIsBeingFetched = false;
-
     /**
      * The cell a click event originated from
      * <p>
      * This is a workaround to make Chrome work like Firefox. In Chrome,
      * normally if you start a drag on one cell and release on:
      * <ul>
-     * <li>that same cell, the click event is that {@code
-     *
-    <td>}.
-     * <li>a cell on that same row, the click event is the parent {@code
-     *
-    <tr>
-     * }.
+     * <li>that same cell, the click event is that <code>&lt;td></code>.
+     * <li>a cell on that same row, the click event is the parent
+     * <code>&lt;tr></code>.
      * <li>a cell on another row, the click event is the table section ancestor
      * ({@code <thead>}, {@code <tbody>} or {@code <tfoot>}).
      * </ul>
@@ -4099,7 +4095,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     private DetailsGenerator detailsGenerator = DetailsGenerator.NULL;
     private GridSpacerUpdater gridSpacerUpdater = new GridSpacerUpdater();
     /** A set keeping track of the indices of all currently open details */
-    private Set<Integer> visibleDetails = new HashSet<Integer>();
+    private Set<Integer> visibleDetails = new HashSet<>();
 
     private boolean columnReorderingAllowed;
 
@@ -4149,7 +4145,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
          * Map of possible drop positions for the column and the corresponding
          * column index.
          */
-        private final TreeMap<Double, Integer> possibleDropPositions = new TreeMap<Double, Integer>();
+        private final TreeMap<Double, Integer> possibleDropPositions = new TreeMap<>();
         /**
          * Makes sure that drag cancel doesn't cause anything unwanted like sort
          */
@@ -4348,7 +4344,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                     && latestColumnDropIndex != (draggedColumnIndex
                             + colspan)) {
                 List<Column<?, T>> columns = getColumns();
-                List<Column<?, T>> reordered = new ArrayList<Column<?, T>>();
+                List<Column<?, T>> reordered = new ArrayList<>();
                 if (draggedColumnIndex < latestColumnDropIndex) {
                     reordered.addAll(columns.subList(0, draggedColumnIndex));
                     reordered.addAll(
@@ -4476,8 +4472,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             int leftBound = -1;
             int rightBound = getColumnCount() + 1;
 
-            final HashSet<Integer> unavailableColumnDropIndices = new HashSet<Integer>();
-            final List<StaticRow<?>> rows = new ArrayList<StaticRow<?>>();
+            final HashSet<Integer> unavailableColumnDropIndices = new HashSet<>();
+            final List<StaticRow<?>> rows = new ArrayList<>();
             rows.addAll(header.getRows());
             rows.addAll(footer.getRows());
             for (StaticRow<?> row : rows) {
@@ -5063,7 +5059,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                 grid.header.updateColSpans();
                 grid.footer.updateColSpans();
                 scheduleColumnWidthRecalculator();
-                this.grid.fireEvent(new ColumnVisibilityChangeEvent<T>(this,
+                this.grid.fireEvent(new ColumnVisibilityChangeEvent<>(this,
                         hidden, userOriginated));
             }
         }
@@ -5717,7 +5713,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                                     initialWidth = col.getWidthActual();
 
                                     minCellWidth = escalator.getMinCellWidth(
-                                            getColumns().indexOf(col));
+                                            getVisibleColumns().indexOf(col));
                                     for (Column<?, T> c : getVisibleColumns()) {
                                         if (selectionColumn == c) {
                                             // Don't modify selection column.
@@ -5726,8 +5722,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
                                         if (c.getWidth() < 0) {
                                             c.setWidth(c.getWidthActual());
-                                            fireEvent(new ColumnResizeEvent<T>(
-                                                    c));
+                                            fireEvent(
+                                                    new ColumnResizeEvent<>(c));
                                         }
                                     }
 
@@ -5737,7 +5733,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
                                 @Override
                                 public void onComplete() {
-                                    fireEvent(new ColumnResizeEvent<T>(col));
+                                    fireEvent(new ColumnResizeEvent<>(col));
 
                                     WidgetUtil.setTextSelectionEnabled(
                                             getElement(), true);
@@ -5819,7 +5815,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                 escalator.getColumnConfiguration().setColumnWidth(colIndex,
                         minWidth);
 
-                fireEvent(new ColumnResizeEvent<T>(column));
+                fireEvent(new ColumnResizeEvent<>(column));
             }
         }
 
@@ -5937,7 +5933,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                     public void onRowVisibilityChange(
                             RowVisibilityChangeEvent event) {
                         if (dataSource != null && dataSource.size() != 0) {
-                            dataIsBeingFetched = true;
                             dataSource.ensureAvailability(
                                     event.getFirstVisibleRow(),
                                     event.getVisibleRowCount());
@@ -5977,12 +5972,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             }
         });
 
-        addDataAvailableHandler(new DataAvailableHandler() {
-            @Override
-            public void onDataAvailable(DataAvailableEvent event) {
-                dataIsBeingFetched = false;
-            }
-        });
     }
 
     @Override
@@ -6229,7 +6218,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         column.reapplyWidth();
 
         // Sink all renderer events
-        Set<String> events = new HashSet<String>();
+        Set<String> events = new HashSet<>();
         events.addAll(getConsumedEventsForRenderer(column.getRenderer()));
 
         if (column.isHidable()) {
@@ -6321,8 +6310,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * @return A unmodifiable list of the columns in the grid
      */
     public List<Column<?, T>> getColumns() {
-        return Collections
-                .unmodifiableList(new ArrayList<Column<?, T>>(columns));
+        return Collections.unmodifiableList(new ArrayList<>(columns));
     }
 
     /**
@@ -6334,7 +6322,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * @return A unmodifiable list of the currently visible columns in the grid
      */
     public List<Column<?, T>> getVisibleColumns() {
-        ArrayList<Column<?, T>> visible = new ArrayList<Column<?, T>>();
+        ArrayList<Column<?, T>> visible = new ArrayList<>();
         for (Column<?, T> c : columns) {
             if (!c.isHidden()) {
                 visible.add(c);
@@ -6749,8 +6737,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                         int oldSize = body.getRowCount();
 
                         // Hide all details.
-                        Set<Integer> oldDetails = new HashSet<Integer>(
-                                visibleDetails);
+                        Set<Integer> oldDetails = new HashSet<>(visibleDetails);
                         for (int i : oldDetails) {
                             setDetailsVisible(i, false);
                         }
@@ -6766,7 +6753,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                         }
 
                         if (newSize > 0) {
-                            dataIsBeingFetched = true;
                             Range visibleRowRange = escalator
                                     .getVisibleRowRange();
                             dataSource.ensureAvailability(
@@ -7123,7 +7109,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     }
 
     private Set<String> getConsumedEventsForRenderer(Renderer<?> renderer) {
-        Set<String> events = new HashSet<String>();
+        Set<String> events = new HashSet<>();
         if (renderer instanceof ComplexRenderer) {
             Collection<String> consumedEvents = ((ComplexRenderer<?>) renderer)
                     .getConsumedEvents();
@@ -7295,7 +7281,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
             w = editor.getWidget(getColumn(editor.focusedColumnIndex));
         }
 
-        EditorDomEvent<T> editorEvent = new EditorDomEvent<T>(event,
+        EditorDomEvent<T> editorEvent = new EditorDomEvent<>(event,
                 getEventCell(), w);
 
         return getEditor().getEventHandler().handleEvent(editorEvent);
@@ -7366,8 +7352,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     private Point rowEventTouchStartingPoint;
     private CellStyleGenerator<T> cellStyleGenerator;
     private RowStyleGenerator<T> rowStyleGenerator;
-    private RowReference<T> rowReference = new RowReference<T>(this);
-    private CellReference<T> cellReference = new CellReference<T>(rowReference);
+    private RowReference<T> rowReference = new RowReference<>(this);
+    private CellReference<T> cellReference = new CellReference<>(rowReference);
     private RendererCellReference rendererCellReference = new RendererCellReference(
             (RowReference<Object>) rowReference);
 
@@ -7909,7 +7895,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         Scheduler.get().scheduleFinally(new ScheduledCommand() {
             @Override
             public void execute() {
-                if (!dataIsBeingFetched) {
+                if (!dataSource.isWaitingForData()) {
                     handler.onDataAvailable(
                             new DataAvailableEvent(currentDataAvailable));
                 }
@@ -8188,8 +8174,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     private void sort(boolean userOriginated) {
         refreshHeader();
-        fireEvent(new SortEvent<T>(this,
-                Collections.unmodifiableList(sortOrder), userOriginated));
+        fireEvent(new SortEvent<>(this, Collections.unmodifiableList(sortOrder),
+                userOriginated));
     }
 
     private int getLastVisibleRowIndex() {
@@ -8230,7 +8216,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
     @Override
     public boolean isWorkPending() {
-        return escalator.isWorkPending() || dataIsBeingFetched
+        return escalator.isWorkPending() || dataSource.isWaitingForData()
                 || autoColumnWidthsRecalculator.isScheduled()
                 || editor.isWorkPending();
     }
@@ -8270,7 +8256,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         // Trigger ComplexRenderer.destroy for old content
         conf.removeColumns(0, conf.getColumnCount());
 
-        List<Column<?, T>> newOrder = new ArrayList<Column<?, T>>();
+        List<Column<?, T>> newOrder = new ArrayList<>();
         if (selectionColumn != null) {
             newOrder.add(selectionColumn);
         }
@@ -8548,7 +8534,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
 
     @Override
     protected void onDetach() {
-        Set<Integer> details = new HashSet<Integer>(visibleDetails);
+        Set<Integer> details = new HashSet<>(visibleDetails);
         for (int row : details) {
             setDetailsVisible(row, false);
         }
@@ -8958,7 +8944,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         if (container != null) {
             Cell cell = container.getCell(element);
             if (cell != null) {
-                EventCellReference<T> cellRef = new EventCellReference<T>(this);
+                EventCellReference<T> cellRef = new EventCellReference<>(this);
                 cellRef.set(cell, getSectionFromContainer(container));
                 return cellRef;
             }
index befdc269983522ea82b19d42c0c05234b1093b33..0be6b236d0163fcc0244b4781c82848bdfb97ae0 100644 (file)
@@ -635,6 +635,25 @@ public class DateField extends AbstractField<Date> implements
         }
     }
 
+    @Override
+    public void discard() {
+        Property prop = getPropertyDataSource();
+        if (prop != null) {
+            Object value = prop.getValue();
+            if (!isValid() && value == null) {
+                // If the user entered an invalid value in the date field
+                // getInternalValue() returns null.
+                // If the datasource also contains null, then
+                // updateValueFromDataSource() will then not clear the internal
+                // state
+                // and error indicators (ticket #8069).
+                setInternalValue(null);
+            } else {
+                super.discard();
+            }
+        }
+    }
+
     /*
      * only fires the event if preventValueChangeEvent flag is false
      */
index f89cf5544bb48ec2373402224bdc0c3fdd680d33..f7bcd8075f633c6955f89db2daf2b320ca84814c 100644 (file)
@@ -4560,6 +4560,11 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
 
     private Object editedItemId = null;
     private boolean editorActive = false;
+    /**
+     * True while the editor is storing the field values, i.e. commiting the
+     * field group.
+     */
+    private boolean editorSaving = false;
     private FieldGroup editorFieldGroup = new CustomFieldGroup();
 
     private CellStyleGenerator cellStyleGenerator;
@@ -6902,7 +6907,12 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
      * @see FieldGroup#commit()
      */
     public void saveEditor() throws CommitException {
-        editorFieldGroup.commit();
+        try {
+            editorSaving = true;
+            editorFieldGroup.commit();
+        } finally {
+            editorSaving = false;
+        }
     }
 
     /**
@@ -6910,6 +6920,12 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
      * possible unsaved changes in the editor fields.
      */
     public void cancelEditor() {
+        if (editorSaving) {
+            // If the editor is already saving the values, it's too late to
+            // cancel it. This prevents item set changes from propagating during
+            // save, causing discard to be run during commit.
+            return;
+        }
         if (isEditorActive()) {
             getEditorRpc()
                     .cancel(getContainerDataSource().indexOfId(editedItemId));
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/ItemSetChangeDuringEditorCommit.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/ItemSetChangeDuringEditorCommit.java
new file mode 100644 (file)
index 0000000..0a97a84
--- /dev/null
@@ -0,0 +1,106 @@
+package com.vaadin.v7.tests.server.component.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.server.ServerRpcManager.RpcInvocationException;
+import com.vaadin.server.ServerRpcMethodInvocation;
+import com.vaadin.tests.util.MockUI;
+import com.vaadin.ui.UI;
+import com.vaadin.v7.data.fieldgroup.FieldGroup;
+import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.v7.data.util.IndexedContainer;
+import com.vaadin.v7.shared.ui.grid.EditorServerRpc;
+import com.vaadin.v7.ui.Grid;
+import com.vaadin.v7.ui.TextField;
+
+public class ItemSetChangeDuringEditorCommit {
+
+    private static class IndexedContainerImpl extends IndexedContainer {
+
+        public IndexedContainerImpl() {
+        }
+
+        @Override
+        public void fireItemSetChange() {
+            super.fireItemSetChange();
+        }
+    }
+
+    @Test
+    public void itemSetChangeDoesNotInterruptCommit()
+            throws RpcInvocationException, CommitException {
+        UI ui = new MockUI();
+        final IndexedContainerImpl indexedContainer = new IndexedContainerImpl();
+        indexedContainer.addContainerProperty("firstName", String.class,
+                "first");
+        indexedContainer.addContainerProperty("lastName", String.class, "last");
+        indexedContainer.addItem();
+        indexedContainer.addItem();
+
+        Grid grid = new Grid();
+        ui.setContent(grid);
+        grid.setContainerDataSource(indexedContainer);
+        grid.setEditorEnabled(true);
+        grid.getEditorFieldGroup()
+                .addCommitHandler(new FieldGroup.CommitHandler() {
+                    @Override
+                    public void preCommit(FieldGroup.CommitEvent commitEvent)
+                            throws FieldGroup.CommitException {
+                    }
+
+                    @Override
+                    public void postCommit(FieldGroup.CommitEvent commitEvent)
+                            throws FieldGroup.CommitException {
+                        indexedContainer.fireItemSetChange();
+                    }
+                });
+
+        editItem(grid, 0);
+        ((TextField) grid.getEditorFieldGroup().getField("firstName"))
+                .setValue("New first");
+        ((TextField) grid.getEditorFieldGroup().getField("lastName"))
+                .setValue("New last");
+        grid.saveEditor();
+
+        Assert.assertEquals("New first", indexedContainer
+                .getContainerProperty(grid.getEditedItemId(), "firstName")
+                .getValue());
+        Assert.assertEquals("New last", indexedContainer
+                .getContainerProperty(grid.getEditedItemId(), "lastName")
+                .getValue());
+
+        grid.cancelEditor();
+        Assert.assertFalse(grid.isEditorActive());
+
+        editItem(grid, 0);
+        Assert.assertEquals("New first",
+                ((TextField) grid.getEditorFieldGroup().getField("firstName"))
+                        .getValue());
+        Assert.assertEquals("New last",
+                ((TextField) grid.getEditorFieldGroup().getField("lastName"))
+                        .getValue());
+        saveEditor(grid, 0);
+    }
+
+    private void editItem(Grid grid, int itemIndex)
+            throws RpcInvocationException {
+        ServerRpcMethodInvocation invocation = new ServerRpcMethodInvocation(
+                grid.getConnectorId(), EditorServerRpc.class, "bind", 1);
+        invocation.setParameters(new Object[] { itemIndex });
+        grid.getRpcManager(EditorServerRpc.class.getName())
+                .applyInvocation(invocation);
+        Assert.assertTrue(grid.isEditorActive());
+
+    }
+
+    private void saveEditor(Grid grid, int itemIndex)
+            throws RpcInvocationException {
+        ServerRpcMethodInvocation invocation = new ServerRpcMethodInvocation(
+                grid.getConnectorId(), EditorServerRpc.class, "save", 1);
+        invocation.setParameters(new Object[] { itemIndex });
+        grid.getRpcManager(EditorServerRpc.class.getName())
+                .applyInvocation(invocation);
+
+    }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 25c553bd329376c29ef7ebf1d81d8dd972da5957..442ab7fafb6211009f4f4061c38949fc0ba88765 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <version>8.0-SNAPSHOT</version>
 
     <prerequisites>
-        <maven>3.0.5</maven>
+        <maven>3.1.0</maven>
     </prerequisites>
 
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
         <!-- Used version numbers for dependencies -->
         <liferay.portal.version>6.0.2</liferay.portal.version>
@@ -43,6 +44,9 @@
 
         <!-- Dependency unpack directory -->
         <dependency.unpack.directory>${project.build.directory}/dependency-unpack</dependency.unpack.directory>
+        
+        <jetty.version>9.3.7.v20160115</jetty.version>
+        <phantomjs.version>2.1.1</phantomjs.version>
     </properties>
 
     <!-- TODO: remove this after maven plugin has been released -->
                 <groupId>com.vaadin</groupId>
                 <artifactId>vaadin-sass-compiler</artifactId>
                 <version>${vaadin.sass.version}</version>
+                <exclusions>
+                <!-- No need to have the minifier included for development 
+                    mode on-the-fly compilation -->
+                <exclusion>
+                    <groupId>com.yahoo.platform.yui</groupId>
+                    <artifactId>yuicompressor</artifactId>
+                </exclusion>
+            </exclusions>
             </dependency>
             <dependency>
                 <groupId>com.carrotsearch</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
                     <version>2.19.1</version>
                 </plugin>
+                <plugin>
+                    <artifactId>maven-failsafe-plugin</artifactId>
+                    <version>2.19.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>com.github.klieber</groupId>
+                    <artifactId>phantomjs-maven-plugin</artifactId>
+                    <version>0.7</version>
+                </plugin>
                 <plugin>
                     <artifactId>maven-antrun-plugin</artifactId>
                     <version>1.8</version>
                                         <ignore></ignore>
                                     </action>
                                 </pluginExecution>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            com.github.klieber
+                                        </groupId>
+                                        <artifactId>
+                                            phantomjs-maven-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [0.7,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>install</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
                             </pluginExecutions>
                         </lifecycleMappingMetadata>
                     </configuration>
     </build>
 
     <profiles>
+        <profile>
+            <id>slowtest</id>
+            <modules>
+                <module>test</module>
+            </modules>
+        </profile>
         <profile>
             <id>release</id>
             <activation>
index 4e4362b1df349988095728a2cc891e3c5bd8f4b7..7870e743dedd256d4470cd3b4f194c212a34e6b6 100644 (file)
@@ -18,6 +18,7 @@ from xml.etree.ElementTree import ElementTree
 demos = {
        "dashboard" : "https://github.com/vaadin/dashboard-demo.git",
        "addressbook" : "https://github.com/vaadin/addressbook.git",
+       "framework8-demo" : "https://github.com/vaadin/framework8-demo",
        "sampler" : "demos/sampler"
 #      "my-demo" : ("my_demo_url_or_path", "my-demo-dev-branch")
 }
index 8f6e2dee6065fccde0b844427f1e3fa33f323468..8a9baee6a02cba8ee6c32aa3103c8c986b3b0511 100644 (file)
@@ -77,6 +77,8 @@ def mavenValidate(artifactId, mvnCmd = mavenCmd, logFile = sys.stdout, version =
        print("Do maven clean package validate")
        cmd = [mvnCmd]
        cmd.append("-Dvaadin.version=%s" % (version))
+       # Enforcer does not always seem to take vaadin.version into account, skip until this can be resolved
+    cmd.append("-Denforcer.skip=true")
        if mavenParams is not None:
                cmd.extend(mavenParams.strip('"').split(" "))
        cmd.extend(["clean", "package", "validate"])
index 345ac25848ac1755abfd6eb4e7c00f9a6651f264..5d198a648871b3739ef3f0e56ed67b3e53ae3c12 100644 (file)
@@ -122,11 +122,14 @@ public @interface VaadinServletConfiguration {
 
     /**
      * The default widgetset to use for the servlet. The default value is
-     * <code>com.vaadin.DefaultWidgetSet</code>.
+     * <code>""</code>, which will cause
+     * <code>com.vaadin.DefaultWidgetSet</code> to be used unless overridden by
+     * an init parameter or unless an automatically generated
+     * <code>AppWidgetset</code> is used.
      *
      * @return the default widgetset name
      */
     @InitParameterName(VaadinServlet.PARAMETER_WIDGETSET)
-    public String widgetset() default VaadinServlet.DEFAULT_WIDGETSET;
+    public String widgetset() default "";
 
 }
index ce3690f9a12f10b78457f570957498c455ad8849..a652b423ff28bbb5e85f46b4b354f2d903a17ca5 100644 (file)
@@ -178,15 +178,22 @@ public abstract class UIProvider implements Serializable {
             return new WidgetsetInfoImpl(uiWidgetset.value());
         }
 
+        // Second case: We might have an init parameter, use that
+        String initParameterWidgetSet = event.getService()
+                .getDeploymentConfiguration().getWidgetset(null);
+        if (initParameterWidgetSet != null) {
+            return new WidgetsetInfoImpl(initParameterWidgetSet);
+        }
+
         // Find the class AppWidgetset in the default package if one exists
         WidgetsetInfo info = getWidgetsetClassInfo();
 
-        // Second case: we have a generated class called APP_WIDGETSET_NAME
+        // Third case: we have a generated class called APP_WIDGETSET_NAME
         if (info != null) {
             return info;
         }
 
-        // third case: we have an AppWidgetset.gwt.xml file
+        // Fourth case: we have an AppWidgetset.gwt.xml file
         else {
             InputStream resource = event.getUIClass()
                     .getResourceAsStream("/" + APP_WIDGETSET_NAME + ".gwt.xml");
@@ -195,7 +202,7 @@ public abstract class UIProvider implements Serializable {
             }
         }
 
-        // fourth case: we are using the default widgetset
+        // fifth case: we are using the default widgetset
         return null;
     }
 
index 03d47b669369108ada75bee4391cdddce95e120b..42dfde5444d29128ec7177af43dcd7644b11d09a 100644 (file)
@@ -268,6 +268,16 @@ public class VaadinServlet extends HttpServlet implements Constants {
                         stringValue = value.toString();
                     }
 
+                    if (VaadinServlet.PARAMETER_WIDGETSET.equals(name.value())
+                            && method.getDefaultValue().equals(stringValue)) {
+                        // Do not set the widgetset to anything so that the
+                        // framework can fallback to the default. Setting
+                        // anything to the init parameter will force that into
+                        // use and e.g. AppWidgetset will not be used even
+                        // though it is found.
+                        continue;
+                    }
+
                     initParameters.setProperty(name.value(), stringValue);
                 } catch (Exception e) {
                     // This should never happen
index c271aec09f9585e70e7b4195e063bb2b61aa0bca..7aec10025550ed528d8b9c014fa8de53f1708ec0 100644 (file)
@@ -223,8 +223,21 @@ public class ClassPathExplorer {
 
                 if (!widgetsets.containsKey(classname)) {
                     String packagePath = packageName.replaceAll("\\.", "/");
-                    String basePath = location.getFile()
-                            .replaceAll("/" + packagePath + "$", "");
+
+                    String basePath = location.getFile();
+                    if (basePath.endsWith("/" + packagePath)) {
+                        basePath = basePath.replaceAll("/" + packagePath + "$",
+                                "");
+                    } else if (basePath.endsWith("/" + packagePath + "/")) {
+                        basePath = basePath.replaceAll("/" + packagePath + "/$",
+                                "");
+                    } else {
+                        throw new IllegalStateException(
+                                "Error trying to find base path, location ("
+                                        + location.getFile()
+                                        + ") does not end in expected '/"
+                                        + packagePath + "'");
+                    }
                     try {
                         URL url = new URL(location.getProtocol(),
                                 location.getHost(), location.getPort(),
@@ -453,8 +466,8 @@ public class ClassPathExplorer {
                         && !dirs[i].getPath().contains(File.separator + ".")) {
                     String key = dirs[i].getCanonicalPath() + "/" + name
                             + dirs[i].getName();
-                    locations.put(key,
-                            dirs[i].getCanonicalFile().toURI().toURL());
+                    URL url = dirs[i].getCanonicalFile().toURI().toURL();
+                    locations.put(key, url);
                 }
             } catch (Exception ioe) {
                 return;
index f64b43092f894fb7929b186aa6c8c81c49cf4014..951944d8ace9861adee6105543e0bf52a4d66fa0 100644 (file)
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
 import java.io.Reader;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Collection;
 import java.util.HashSet;
@@ -44,7 +45,8 @@ import java.util.regex.Pattern;
  */
 public class WidgetSetBuilder {
 
-    public static void main(String[] args) throws IOException {
+    public static void main(String[] args)
+            throws IOException, URISyntaxException {
         if (args.length == 0) {
             printUsage();
         } else {
@@ -55,7 +57,7 @@ public class WidgetSetBuilder {
     }
 
     public static void updateWidgetSet(final String widgetset)
-            throws IOException, FileNotFoundException {
+            throws IOException, FileNotFoundException, URISyntaxException {
         boolean changed = false;
 
         Map<String, URL> availableWidgetSets = ClassPathExplorer
@@ -69,9 +71,8 @@ public class WidgetSetBuilder {
                     .getWidgetsetSourceDirectory(widgetsetFileName);
         }
 
-        String wsFullPath = sourceUrl.getFile() + "/" + widgetsetFileName;
-
-        File widgetsetFile = new File(wsFullPath);
+        File widgetsetFile = new File(new File(sourceUrl.toURI()),
+                widgetsetFileName);
         if (!widgetsetFile.exists()) {
             // create empty gwt module file
             File parent = widgetsetFile.getParentFile();
@@ -136,7 +137,7 @@ public class WidgetSetBuilder {
 
             changed = changed || !content.equals(originalContent);
             if (changed) {
-                commitChanges(wsFullPath, content);
+                commitChanges(widgetsetFile, content);
             }
         } else {
             System.out
@@ -152,11 +153,10 @@ public class WidgetSetBuilder {
         return content.replaceFirst("<inherits name=\"" + ws + "\"[^/]*/>", "");
     }
 
-    private static void commitChanges(String widgetsetfilename, String content)
+    private static void commitChanges(File widgetsetFile, String content)
             throws IOException {
         BufferedWriter bufferedWriter = new BufferedWriter(
-                new OutputStreamWriter(
-                        new FileOutputStream(widgetsetfilename)));
+                new OutputStreamWriter(new FileOutputStream(widgetsetFile)));
         bufferedWriter.write(content);
         bufferedWriter.close();
     }
diff --git a/test/addon-using-init-param-widget-set/pom.xml b/test/addon-using-init-param-widget-set/pom.xml
new file mode 100644 (file)
index 0000000..79939e6
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-addon-using-init-param-widget-set</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <!-- Included to ensure AppWidgetset is an option -->
+        <dependency>
+            <groupId>com.vaadin.addon</groupId>
+            <artifactId>vaadin-context-menu</artifactId>
+            <version>0.7.4</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-client-compiled</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.vaadin</groupId>
+                <artifactId>vaadin-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>resources</goal>
+                            <goal>update-widgetset</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/addon-using-init-param-widget-set/src/main/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetUI.java b/test/addon-using-init-param-widget-set/src/main/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetUI.java
new file mode 100644 (file)
index 0000000..41a240e
--- /dev/null
@@ -0,0 +1,25 @@
+package com.vaadin.test.addonusinginitparamwidgetset;
+
+import javax.servlet.annotation.WebInitParam;
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.addon.contextmenu.ContextMenu;
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.test.widgetset.AbstractTestWidgetSetUI;
+import com.vaadin.ui.AbstractComponent;
+
+public class AddonUsingInitParamWidgetSetUI extends AbstractTestWidgetSetUI {
+
+    @Override
+    protected void init(VaadinRequest vaadinRequest) {
+        super.init(vaadinRequest);
+        new ContextMenu((AbstractComponent) getContent(), true);
+    }
+
+    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true, initParams = @WebInitParam(name = "widgetset", value = "com.vaadin.DefaultWidgetSet"))
+    @VaadinServletConfiguration(ui = AddonUsingInitParamWidgetSetUI.class, productionMode = false)
+    public static class MyUIServlet extends VaadinServlet {
+    }
+}
\ No newline at end of file
diff --git a/test/addon-using-init-param-widget-set/src/test/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetIT.java b/test/addon-using-init-param-widget-set/src/test/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetIT.java
new file mode 100644 (file)
index 0000000..42333fb
--- /dev/null
@@ -0,0 +1,15 @@
+package com.vaadin.test.addonusinginitparamwidgetset;
+
+import org.junit.Test;
+
+import com.vaadin.test.defaultwidgetset.AbstractWidgetSetIT;
+
+public class AddonUsingInitParamWidgetSetIT extends AbstractWidgetSetIT {
+
+    @Test
+    public void appStartsUserCanInteract() {
+        testAppStartsUserCanInteract("com.vaadin.DefaultWidgetSet");
+        assertUnknownComponentShown("com.vaadin.addon.contextmenu.ContextMenu");
+    }
+
+}
\ No newline at end of file
diff --git a/test/addon-using-no-defined-widget-set/pom.xml b/test/addon-using-no-defined-widget-set/pom.xml
new file mode 100644 (file)
index 0000000..97178f9
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-addon-using-no-defined-widget-set</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin.addon</groupId>
+            <artifactId>vaadin-context-menu</artifactId>
+            <version>0.7.4</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.vaadin</groupId>
+                <artifactId>vaadin-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>resources</goal>
+                            <goal>update-widgetset</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/addon-using-no-defined-widget-set/src/main/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetUI.java b/test/addon-using-no-defined-widget-set/src/main/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetUI.java
new file mode 100644 (file)
index 0000000..1893bb4
--- /dev/null
@@ -0,0 +1,24 @@
+package com.vaadin.test.addonusingnodefinedwidgetset;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.addon.contextmenu.ContextMenu;
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.test.widgetset.AbstractTestWidgetSetUI;
+import com.vaadin.ui.AbstractComponent;
+
+public class AddonUsingNoDefinedWidgetSetUI extends AbstractTestWidgetSetUI {
+
+    @Override
+    protected void init(VaadinRequest vaadinRequest) {
+        super.init(vaadinRequest);
+        new ContextMenu((AbstractComponent) getContent(), true);
+    }
+
+    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
+    @VaadinServletConfiguration(ui = AddonUsingNoDefinedWidgetSetUI.class, productionMode = false)
+    public static class MyUIServlet extends VaadinServlet {
+    }
+}
\ No newline at end of file
diff --git a/test/addon-using-no-defined-widget-set/src/test/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetIT.java b/test/addon-using-no-defined-widget-set/src/test/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetIT.java
new file mode 100644 (file)
index 0000000..93dc5f1
--- /dev/null
@@ -0,0 +1,14 @@
+package com.vaadin.test.addonusingnodefinedwidgetset;
+
+import org.junit.Test;
+
+import com.vaadin.test.defaultwidgetset.AbstractWidgetSetIT;
+
+public class AddonUsingNoDefinedWidgetSetIT extends AbstractWidgetSetIT {
+
+    @Test
+    public void appStartsUserCanInteract() {
+        testAppStartsUserCanInteract("AppWidgetset");
+        assertNoUnknownComponentShown();
+    }
+}
\ No newline at end of file
diff --git a/test/addon-using-own-widget-set/pom.xml b/test/addon-using-own-widget-set/pom.xml
new file mode 100644 (file)
index 0000000..fc52e47
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-addon-using-own-widget-set</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin.addon</groupId>
+            <artifactId>vaadin-context-menu</artifactId>
+            <version>0.7.4</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.vaadin</groupId>
+                <artifactId>vaadin-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>resources</goal>
+                            <goal>update-widgetset</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/addon-using-own-widget-set/src/main/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetUI.java b/test/addon-using-own-widget-set/src/main/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetUI.java
new file mode 100644 (file)
index 0000000..15efad2
--- /dev/null
@@ -0,0 +1,26 @@
+package com.vaadin.test.addonusingownwidgetset;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.addon.contextmenu.ContextMenu;
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.test.widgetset.AbstractTestWidgetSetUI;
+import com.vaadin.ui.AbstractComponent;
+
+@Widgetset("com.vaadin.test.addonusingownwidgetset.AddonUsingOwnWidgetSet")
+public class AddonUsingOwnWidgetSetUI extends AbstractTestWidgetSetUI {
+
+    @Override
+    protected void init(VaadinRequest vaadinRequest) {
+        super.init(vaadinRequest);
+        new ContextMenu((AbstractComponent) getContent(), true);
+    }
+
+    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
+    @VaadinServletConfiguration(ui = AddonUsingOwnWidgetSetUI.class, productionMode = false)
+    public static class MyUIServlet extends VaadinServlet {
+    }
+}
\ No newline at end of file
diff --git a/test/addon-using-own-widget-set/src/main/resources/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSet.gwt.xml b/test/addon-using-own-widget-set/src/main/resources/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSet.gwt.xml
new file mode 100644 (file)
index 0000000..26be42e
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
+<module>
+    <inherits name="com.vaadin.DefaultWidgetSet" />
+
+    <inherits name="com.vaadin.addon.contextmenu.WidgetSet" />
+</module>
diff --git a/test/addon-using-own-widget-set/src/test/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetIT.java b/test/addon-using-own-widget-set/src/test/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetIT.java
new file mode 100644 (file)
index 0000000..c22dbf8
--- /dev/null
@@ -0,0 +1,15 @@
+package com.vaadin.test.addonusingownwidgetset;
+
+import org.junit.Test;
+
+import com.vaadin.test.defaultwidgetset.AbstractWidgetSetIT;
+
+public class AddonUsingOwnWidgetSetIT extends AbstractWidgetSetIT {
+
+    @Test
+    public void appStartsUserCanInteract() {
+        testAppStartsUserCanInteract(
+                "com.vaadin.test.addonusingownwidgetset.AddonUsingOwnWidgetSet");
+        assertNoUnknownComponentShown();
+    }
+}
\ No newline at end of file
diff --git a/test/default-widget-set/pom.xml b/test/default-widget-set/pom.xml
new file mode 100644 (file)
index 0000000..68ee894
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-default-widget-set</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-client-compiled</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+
+</project>
\ No newline at end of file
diff --git a/test/default-widget-set/src/main/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetUI.java b/test/default-widget-set/src/main/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetUI.java
new file mode 100644 (file)
index 0000000..fb58389
--- /dev/null
@@ -0,0 +1,15 @@
+package com.vaadin.test.defaultwidgetset;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.test.widgetset.AbstractTestWidgetSetUI;
+
+public class DefaultWidgetSetUI extends AbstractTestWidgetSetUI {
+
+    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
+    @VaadinServletConfiguration(ui = DefaultWidgetSetUI.class, productionMode = false)
+    public static class MyUIServlet extends VaadinServlet {
+    }
+}
\ No newline at end of file
diff --git a/test/default-widget-set/src/test/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetIT.java b/test/default-widget-set/src/test/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetIT.java
new file mode 100644 (file)
index 0000000..8fda581
--- /dev/null
@@ -0,0 +1,11 @@
+package com.vaadin.test.defaultwidgetset;
+
+import org.junit.Test;
+
+public abstract class DefaultWidgetSetIT extends AbstractWidgetSetIT {
+
+    @Test
+    public void appStartsUserCanInteract() {
+        testAppStartsUserCanInteract("com.vaadin.DefaultWidgetSet");
+    }
+}
\ No newline at end of file
diff --git a/test/own-widget-set/pom.xml b/test/own-widget-set/pom.xml
new file mode 100644 (file)
index 0000000..6ce65c8
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-own-widget-set</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.vaadin</groupId>
+                <artifactId>vaadin-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>resources</goal>
+                            <goal>update-widgetset</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/own-widget-set/src/main/java/com/vaadin/test/ownwidgetset/OwnWidgetSetUI.java b/test/own-widget-set/src/main/java/com/vaadin/test/ownwidgetset/OwnWidgetSetUI.java
new file mode 100644 (file)
index 0000000..8801dac
--- /dev/null
@@ -0,0 +1,17 @@
+package com.vaadin.test.ownwidgetset;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.test.widgetset.AbstractTestWidgetSetUI;
+
+@Widgetset("com.vaadin.test.ownwidgetset.OwnWidgetSet")
+public class OwnWidgetSetUI extends AbstractTestWidgetSetUI {
+
+    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
+    @VaadinServletConfiguration(ui = OwnWidgetSetUI.class, productionMode = false)
+    public static class MyUIServlet extends VaadinServlet {
+    }
+}
\ No newline at end of file
diff --git a/test/own-widget-set/src/test/java/com/vaadin/test/ownwidgetset/OwnWidgetSetIT.java b/test/own-widget-set/src/test/java/com/vaadin/test/ownwidgetset/OwnWidgetSetIT.java
new file mode 100644 (file)
index 0000000..7501fba
--- /dev/null
@@ -0,0 +1,14 @@
+package com.vaadin.test.ownwidgetset;
+
+import org.junit.Test;
+
+import com.vaadin.test.defaultwidgetset.AbstractWidgetSetIT;
+
+public class OwnWidgetSetIT extends AbstractWidgetSetIT {
+
+    @Test
+    public void appStartsUserCanInteract() {
+        testAppStartsUserCanInteract(
+                "com.vaadin.test.ownwidgetset.OwnWidgetSet");
+    }
+}
\ No newline at end of file
diff --git a/test/pom.xml b/test/pom.xml
new file mode 100644 (file)
index 0000000..b1ee2fb
--- /dev/null
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-root</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test</artifactId>
+    <name>vaadin-test</name>
+    <packaging>pom</packaging>
+    <properties>
+        <failOnMissingWebXml>false</failOnMissingWebXml>
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>vaadin-addons</id>
+            <url>http://maven.vaadin.com/vaadin-addons</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+
+        <!-- API DEPENDENCIES -->
+        <!-- Project modules -->
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-server</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-themes</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <!-- Servlet 3.0 API -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+
+        <!-- Testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-testbench</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <modules>
+        <module>widget-set-testutil</module>
+        <module>default-widget-set</module>
+        <module>own-widget-set</module>
+        <module>addon-using-own-widget-set</module>
+        <module>addon-using-no-defined-widget-set</module>
+        <module>addon-using-init-param-widget-set</module>
+        <module>space in directory</module>
+        <module>vaadinservletconfiguration-widget-set</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-maven-plugin</artifactId>
+                <version>${jetty.version}</version>
+                <configuration>
+                    <scanIntervalSeconds>-1</scanIntervalSeconds>
+                    <stopPort>8081</stopPort>
+                    <stopWait>5</stopWait>
+                    <stopKey>foo</stopKey>
+                </configuration>
+                <executions>
+                    <!-- start and stop jetty (running our app) when running 
+                        integration tests -->
+                    <execution>
+                        <id>start-jetty</id>
+                        <phase>pre-integration-test</phase>
+                        <goals>
+                            <goal>start</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>stop-jetty</id>
+                        <phase>post-integration-test</phase>
+                        <goals>
+                            <goal>stop</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.github.klieber</groupId>
+                <artifactId>phantomjs-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>install</goal>
+                        </goals>
+                        <configuration>
+                            <version>${phantomjs.version}</version>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <systemPropertyVariables>
+                        <phantomjs.binary.path>${phantomjs.binary}</phantomjs.binary.path>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/test/space in directory/pom.xml b/test/space in directory/pom.xml
new file mode 100644 (file)
index 0000000..65c3574
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-space-in-directory</artifactId>
+    <packaging>war</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.vaadin</groupId>
+                <artifactId>vaadin-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>resources</goal>
+                            <goal>update-widgetset</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/space in directory/src/main/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryUI.java b/test/space in directory/src/main/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryUI.java
new file mode 100644 (file)
index 0000000..ccf023c
--- /dev/null
@@ -0,0 +1,17 @@
+package com.vaadin.test.spaceindirectory;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.test.widgetset.AbstractTestWidgetSetUI;
+
+@Widgetset("com.vaadin.test.spaceindirectory.SpaceInDirectory")
+public class SpaceInDirectoryUI extends AbstractTestWidgetSetUI {
+
+    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
+    @VaadinServletConfiguration(ui = SpaceInDirectoryUI.class, productionMode = false)
+    public static class MyUIServlet extends VaadinServlet {
+    }
+}
\ No newline at end of file
diff --git a/test/space in directory/src/main/resources/com/vaadin/test/spaceindirectory/SpaceInDirectory.gwt.xml b/test/space in directory/src/main/resources/com/vaadin/test/spaceindirectory/SpaceInDirectory.gwt.xml
new file mode 100644 (file)
index 0000000..ad42d08
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
+<module>
+    <inherits name="com.vaadin.DefaultWidgetSet" />
+</module>
\ No newline at end of file
diff --git a/test/space in directory/src/test/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryIT.java b/test/space in directory/src/test/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryIT.java
new file mode 100644 (file)
index 0000000..f8fbfb6
--- /dev/null
@@ -0,0 +1,15 @@
+package com.vaadin.test.spaceindirectory;
+
+import org.junit.Test;
+
+import com.vaadin.test.defaultwidgetset.AbstractWidgetSetIT;
+
+public class SpaceInDirectoryIT extends AbstractWidgetSetIT {
+
+    @Test
+    public void appStartsUserCanInteract() {
+        testAppStartsUserCanInteract(
+                "com.vaadin.test.spaceindirectory.SpaceInDirectory");
+
+    }
+}
\ No newline at end of file
diff --git a/test/vaadinservletconfiguration-widget-set/pom.xml b/test/vaadinservletconfiguration-widget-set/pom.xml
new file mode 100644 (file)
index 0000000..96a9a94
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-vaadinservletconfiguration-widget-set</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.vaadin</groupId>
+            <artifactId>vaadin-test-widget-set-testutil</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.vaadin</groupId>
+                <artifactId>vaadin-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>resources</goal>
+                            <goal>update-widgetset</goal>
+                            <goal>compile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/vaadinservletconfiguration-widget-set/src/main/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetUI.java b/test/vaadinservletconfiguration-widget-set/src/main/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetUI.java
new file mode 100644 (file)
index 0000000..e607df3
--- /dev/null
@@ -0,0 +1,16 @@
+package com.vaadin.test.vaadinservletconfigurationwidgetset;
+
+import javax.servlet.annotation.WebServlet;
+
+import com.vaadin.annotations.VaadinServletConfiguration;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.test.widgetset.AbstractTestWidgetSetUI;
+
+public class VaadinServletConfigurationWidgetSetUI
+        extends AbstractTestWidgetSetUI {
+
+    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
+    @VaadinServletConfiguration(ui = VaadinServletConfigurationWidgetSetUI.class, productionMode = false, widgetset = "com.vaadin.test.vaadinservletconfigurationwidgetset.VaadinServletConfigurationWidgetSet")
+    public static class MyUIServlet extends VaadinServlet {
+    }
+}
\ No newline at end of file
diff --git a/test/vaadinservletconfiguration-widget-set/src/main/resources/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSet.gwt.xml b/test/vaadinservletconfiguration-widget-set/src/main/resources/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSet.gwt.xml
new file mode 100644 (file)
index 0000000..ad42d08
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
+<module>
+    <inherits name="com.vaadin.DefaultWidgetSet" />
+</module>
\ No newline at end of file
diff --git a/test/vaadinservletconfiguration-widget-set/src/test/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetIT.java b/test/vaadinservletconfiguration-widget-set/src/test/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetIT.java
new file mode 100644 (file)
index 0000000..6727cef
--- /dev/null
@@ -0,0 +1,14 @@
+package com.vaadin.test.vaadinservletconfigurationwidgetset;
+
+import org.junit.Test;
+
+import com.vaadin.test.defaultwidgetset.AbstractWidgetSetIT;
+
+public class VaadinServletConfigurationWidgetSetIT extends AbstractWidgetSetIT {
+
+    @Test
+    public void appStartsUserCanInteract() {
+        testAppStartsUserCanInteract(
+                "com.vaadin.test.vaadinservletconfigurationwidgetset.VaadinServletConfigurationWidgetSet");
+    }
+}
\ No newline at end of file
diff --git a/test/widget-set-testutil/pom.xml b/test/widget-set-testutil/pom.xml
new file mode 100644 (file)
index 0000000..3dcc6db
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.vaadin</groupId>
+        <artifactId>vaadin-test</artifactId>
+        <version>8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>vaadin-test-widget-set-testutil</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/widget-set-testutil/src/main/java/com/vaadin/test/widgetset/AbstractTestWidgetSetUI.java b/test/widget-set-testutil/src/main/java/com/vaadin/test/widgetset/AbstractTestWidgetSetUI.java
new file mode 100644 (file)
index 0000000..c036455
--- /dev/null
@@ -0,0 +1,39 @@
+package com.vaadin.test.widgetset;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+public abstract class AbstractTestWidgetSetUI extends UI {
+
+    @Override
+    protected void init(VaadinRequest vaadinRequest) {
+        final VerticalLayout layout = new VerticalLayout();
+        final Label widgetsetInfo = new Label();
+        widgetsetInfo.setId("widgetsetinfo");
+        final TextField name = new TextField();
+        name.setCaption("Type your name here:");
+
+        Button button = new Button("Click Me");
+        button.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent clickEvent) {
+                layout.addComponent(
+                        new Label("Thanks " + name.getValue() + ", it works!"));
+            }
+        });
+
+        getPage().getJavaScript().execute(
+                "widgetsetinfo.innerText=document.querySelector('iframe').id;");
+        layout.addComponents(widgetsetInfo, name, button);
+        layout.setMargin(true);
+        layout.setSpacing(true);
+
+        setContent(layout);
+    }
+
+}
\ No newline at end of file
diff --git a/test/widget-set-testutil/src/test/java/com/vaadin/test/defaultwidgetset/AbstractWidgetSetIT.java b/test/widget-set-testutil/src/test/java/com/vaadin/test/defaultwidgetset/AbstractWidgetSetIT.java
new file mode 100644 (file)
index 0000000..e842968
--- /dev/null
@@ -0,0 +1,59 @@
+package com.vaadin.test.defaultwidgetset;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.phantomjs.PhantomJSDriver;
+
+import com.vaadin.testbench.ScreenshotOnFailureRule;
+import com.vaadin.testbench.TestBenchTestCase;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.TextFieldElement;
+
+public abstract class AbstractWidgetSetIT extends TestBenchTestCase {
+
+    @Rule
+    public ScreenshotOnFailureRule rule = new ScreenshotOnFailureRule(this,
+            true);
+
+    @Before
+    public void setup() {
+        // Screenshot rule tears down the driver
+        setDriver(new PhantomJSDriver());
+    }
+
+    protected void testAppStartsUserCanInteract(String expectedWidgetSet) {
+        getDriver().get("http://localhost:8080");
+
+        TextFieldElement nameInput = $(TextFieldElement.class).first();
+        nameInput.setValue("John Dåe");
+
+        $(ButtonElement.class).first().click();
+
+        Assert.assertEquals("Label shown", 2,
+                $(LabelElement.class).all().size());
+
+        Assert.assertEquals("Thanks John Dåe, it works!",
+                $(LabelElement.class).get(1).getText());
+
+        Assert.assertEquals(expectedWidgetSet,
+                findElement(By.id("widgetsetinfo")).getText());
+
+    }
+
+    protected void assertNoUnknownComponentShown() {
+        Assert.assertEquals(0,
+                findElements(By.className("vaadin-unknown-caption")).size());
+    }
+
+    protected void assertUnknownComponentShown(String componentClass) {
+        WebElement unknownComponentCaption = findElement(
+                By.className("vaadin-unknown-caption"));
+        Assert.assertTrue(unknownComponentCaption.getText().contains(
+                "does not contain implementation for " + componentClass));
+    }
+
+}
\ No newline at end of file
index 4985bc7e93c218e49bc5633729f775d154ba317e..dce2c77db05446eb8e0c4f4f5315c020a5f7ecc1 100644 (file)
@@ -1015,17 +1015,12 @@ public abstract class AbstractTB3Test extends ParallelTest {
         return loadingIndicator.isDisplayed();
     }
 
-    protected void waitUntilLoadingIndicatorNotVisible() {
-        waitUntil(new ExpectedCondition<Boolean>() {
-
-            @Override
-            public Boolean apply(WebDriver input) {
-                WebElement loadingIndicator = input
-                        .findElement(By.className("v-loading-indicator"));
+    protected void waitUntilLoadingIndicatorVisible() {
+        waitUntil(input -> isLoadingIndicatorVisible());
+    }
 
-                return !loadingIndicator.isDisplayed();
-            }
-        });
+    protected void waitUntilLoadingIndicatorNotVisible() {
+        waitUntil(input -> !isLoadingIndicatorVisible());
     }
 
     /**
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDown.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDown.java
new file mode 100644 (file)
index 0000000..72a53d2
--- /dev/null
@@ -0,0 +1,44 @@
+package com.vaadin.tests.components.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.data.DataSource;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Grid;
+
+@Theme("valo")
+public class GridApplyFilterWhenScrolledDown extends AbstractTestUI {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        Grid<String> grid = new Grid<>();
+
+        grid.addColumn("Name", Function.identity());
+
+        List<String> data = new ArrayList<>();
+        for (int i = 0; i < 1000; i++) {
+            data.add("Name " + i);
+        }
+
+        data.add("Test");
+        grid.setItems(data);
+
+        addComponent(grid);
+        Button button = new Button("Filter Test item",
+                event -> filter(grid.getDataSource(), data));
+        addComponent(button);
+    }
+
+    private void filter(DataSource<String> dataSource, List<String> data) {
+        String last = data.get(data.size() - 1);
+        data.clear();
+        data.add(last);
+        dataSource.refreshAll();
+    }
+
+}
\ No newline at end of file
index 7fa86b6522c9585a2acf54a8d7c0efb537ff8312..0abf48baeb88a96185d6bb442bb895482a6c9b9e 100644 (file)
@@ -41,10 +41,14 @@ public class GridColumnHiding extends AbstractTestUI {
         grid.addColumnVisibilityChangeListener(event -> visibilityChangeLabel
                 .setValue(event.getColumn().isHidden() + ""));
 
+        Button toggleHidden = new Button("Toggle all column hidden state",
+                event -> grid.getColumns().forEach(
+                        column -> column.setHidden(!column.isHidden())));
+
         grid.setItems(Arrays.asList(Person.createTestPerson1(),
                 Person.createTestPerson2()));
 
         addComponents(grid, toggleNameColumn, toggleAgeColumn,
-                toggleEmailColumn, visibilityChangeLabel);
+                toggleEmailColumn, visibilityChangeLabel, toggleHidden);
     }
 }
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/InitiallyDisabledGrid.java b/uitest/src/main/java/com/vaadin/tests/components/grid/InitiallyDisabledGrid.java
new file mode 100644 (file)
index 0000000..74f69ef
--- /dev/null
@@ -0,0 +1,58 @@
+package com.vaadin.tests.components.grid;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+public class InitiallyDisabledGrid extends UI {
+
+    @Override
+    protected void init(VaadinRequest request) {
+        VerticalLayout layout = new VerticalLayout();
+        setContent(layout);
+        layout.setSizeFull();
+        layout.setWidth("600px");
+        layout.setHeight("600px");
+        final Grid<Person> grid = createGrid();
+        Button button = new Button("Enable/Disable",
+                event -> grid.setEnabled(!grid.isEnabled()));
+
+        layout.addComponent(button);
+        VerticalLayout l = new VerticalLayout();
+        l.setSizeFull();
+        l.addComponent(grid);
+
+        layout.addComponent(l);
+        layout.setExpandRatio(l, 1.0f);
+    }
+
+    private Grid<Person> createGrid() {
+        // Have some data
+        Collection<Person> people = new ArrayList<>();
+        for (int i = 0; i < 100; i++) {
+            Person person = new Person();
+            person.setFirstName("First " + i);
+            person.setLastName("Last " + i);
+            people.add(person);
+        }
+        // Have a container of some type to contain the data
+
+        // Create a grid bound to the container
+        Grid<Person> grid = new Grid<>();
+        grid.setSizeFull();
+        grid.setItems(people);
+        grid.addColumn("firstName", Person::getFirstName);
+        grid.addColumn("lastNAme", Person::getLastName);
+
+        grid.setEnabled(false);
+
+        return grid;
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicator.java b/uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicator.java
new file mode 100644 (file)
index 0000000..d318b7e
--- /dev/null
@@ -0,0 +1,38 @@
+package com.vaadin.tests.components.javascriptcomponent;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.AbstractJavaScriptComponent;
+import com.vaadin.ui.JavaScriptFunction;
+import com.vaadin.ui.Label;
+
+import elemental.json.JsonArray;
+
+public class JSComponentLoadingIndicator extends AbstractTestUI {
+
+    @JavaScript({ "JSComponent.js" })
+    public class JSComponent extends AbstractJavaScriptComponent {
+        public JSComponent() {
+            addFunction("test", new JavaScriptFunction() {
+                @Override
+                public void call(JsonArray arguments) {
+                    try {
+                        Thread.sleep(1000);
+                        Label label = new Label("pong");
+                        label.addStyleName("pong");
+                        addComponent(label);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        addComponent(new JSComponent());
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/main/java/com/vaadin/tests/core/SpecialCharactersEncodingUI.java b/uitest/src/main/java/com/vaadin/tests/core/SpecialCharactersEncodingUI.java
new file mode 100644 (file)
index 0000000..974d94c
--- /dev/null
@@ -0,0 +1,30 @@
+package com.vaadin.tests.core;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.MenuBar;
+import com.vaadin.ui.TextField;
+
+public class SpecialCharactersEncodingUI extends AbstractTestUI {
+
+    public static String textWithZwnj = "\ufeffछुट्‌याउनेछन्  क्ष  क्‌ष  क्‍ष";
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        MenuBar menubar = new MenuBar();
+        menubar.setId("menubar");
+        addComponent(menubar);
+        menubar.addItem(textWithZwnj, null);
+
+        Label label = new Label(textWithZwnj);
+        label.setId("label");
+        addComponent(label);
+
+        TextField f = new TextField("Textfield", textWithZwnj);
+        f.setId("textfield");
+        addComponent(f);
+
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/main/java/com/vaadin/tests/resources/DownloadWithPush.java b/uitest/src/main/java/com/vaadin/tests/resources/DownloadWithPush.java
new file mode 100644 (file)
index 0000000..f3d2195
--- /dev/null
@@ -0,0 +1,93 @@
+package com.vaadin.tests.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.vaadin.annotations.Push;
+import com.vaadin.server.DownloadStream;
+import com.vaadin.server.Resource;
+import com.vaadin.server.StreamResource;
+import com.vaadin.server.StreamResource.StreamSource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+
+@Push
+public class DownloadWithPush extends AbstractTestUIWithLog {
+
+    private static class GeneratedStream extends InputStream {
+        int read = 0;
+        int next = 'a';
+        private final int size;
+
+        public GeneratedStream(int size) {
+            this.size = size;
+        }
+
+        @Override
+        public int read() throws IOException {
+            if (available() == 0) {
+                return -1;
+            }
+
+            read++;
+            next++;
+            if (next > 'z') {
+                next = 'a';
+            }
+            return next;
+        }
+
+        @Override
+        public int available() throws IOException {
+            return size - read;
+        }
+    }
+
+    private final class DownloadResoure extends StreamResource {
+        private DownloadResoure(StreamSource streamSource, String filename) {
+            super(streamSource, filename);
+        }
+
+        @Override
+        public DownloadStream getStream() {
+            DownloadStream ds = super.getStream();
+            ds.setParameter("Content-Disposition",
+                    "attachment; filename=" + getFilename() + ";");
+            return ds;
+        }
+    }
+
+    private Resource hugeFileResource = createResource();;
+    private int fileSize = 300 * (1024 * 1024);
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        Button b = new Button("Download a "
+                + String.format("%.1f", fileSize / 1024.0 / 1024.0) + "MB file",
+                new Button.ClickListener() {
+                    @Override
+                    public void buttonClick(ClickEvent event) {
+                        getUI().getPage().open(hugeFileResource, "", false);
+                    }
+                });
+        addComponent(b);
+    }
+
+    private Resource createResource() {
+        Resource hugeFileResource = new DownloadResoure(new StreamSource() {
+            @Override
+            public InputStream getStream() {
+                return new GeneratedStream(fileSize);
+            }
+        }, "hugefile.txt");
+        return hugeFileResource;
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 19709;
+    }
+
+}
\ No newline at end of file
index 0fe861f7235edddab1e07e1540da39dc42dca082..d2dbf78739dad07dcf0c467c4cb97fc9eaafa996 100644 (file)
@@ -81,6 +81,11 @@ public class GridCellFocusOnResetSizeWidget
             }
             handler.resetDataAndSize(size);
         }
+
+        @Override
+        public boolean isWaitingForData() {
+            return false;
+        }
     }
 
     private class Col extends Grid.Column<String, String[]> {
index 904ecbf1d5ba7b7ea1b752328f478cdb13c5aef5..e4dce67da8978e75ff49fef11fff790efe47310e 100644 (file)
@@ -69,6 +69,7 @@ public class GridClientColumnRendererConnector
         private int numberOfRows;
         private DataChangeHandler dataChangeHandler;
         private int latency;
+        private Timer timer;
 
         public DelayedDataSource(DataSource<String> ds, int latency) {
             this.ds = ds;
@@ -78,7 +79,7 @@ public class GridClientColumnRendererConnector
         @Override
         public void ensureAvailability(final int firstRowIndex,
                 final int numberOfRows) {
-            new Timer() {
+            timer = new Timer() {
 
                 @Override
                 public void run() {
@@ -87,8 +88,10 @@ public class GridClientColumnRendererConnector
                     dataChangeHandler.dataUpdated(firstRowIndex, numberOfRows);
                     dataChangeHandler.dataAvailable(firstRowIndex,
                             numberOfRows);
+                    timer = null;
                 }
-            }.schedule(latency);
+            };
+            timer.schedule(latency);
         }
 
         @Override
@@ -117,6 +120,11 @@ public class GridClientColumnRendererConnector
             // TODO Auto-generated method stub (henrik paul: 17.6.)
             return null;
         }
+
+        @Override
+        public boolean isWaitingForData() {
+            return timer != null;
+        }
     }
 
     @Override
@@ -211,8 +219,7 @@ public class GridClientColumnRendererConnector
                     @SuppressWarnings("unchecked")
                     public void triggerClientSortingTest() {
                         Grid<String> grid = getWidget();
-                        ListSorter<String> sorter = new ListSorter<>(
-                                grid);
+                        ListSorter<String> sorter = new ListSorter<>(grid);
 
                         // Make sorter sort the numbers in natural order
                         sorter.setComparator(
@@ -236,8 +243,7 @@ public class GridClientColumnRendererConnector
                     @SuppressWarnings("unchecked")
                     public void shuffle() {
                         Grid<String> grid = getWidget();
-                        ListSorter<String> shuffler = new ListSorter<>(
-                                grid);
+                        ListSorter<String> shuffler = new ListSorter<>(grid);
 
                         // Make shuffler return random order
                         shuffler.setComparator(
diff --git a/uitest/src/main/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValue.java b/uitest/src/main/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValue.java
new file mode 100644 (file)
index 0000000..2119b9f
--- /dev/null
@@ -0,0 +1,99 @@
+package com.vaadin.v7.tests.components.datefield;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+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.HorizontalLayout;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.v7.data.util.ObjectProperty;
+import com.vaadin.v7.ui.DateField;
+
+/**
+ * Test to demonstrate how discarding of field value works with various valid
+ * and invalid data sources. Previously (Ticket #8069) the case where the
+ * content of the datasource was null was not handled correctly. This value is a
+ * valid data source value for the field, but discard did not actually discard
+ * the value or remove error markers in this cases.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public class DateFieldDiscardValue extends AbstractTestUI {
+
+    public static final String PROP_NONULL = "A field with a valid date in the data source property";
+    public static final String PROP_NULL_VALUE = "A field with a null value in the data source property";
+    public static final String PROP_NULL = "A field with a null datasource property";
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        String dateFormat = "dd/MM/yy";
+
+        final DateField df = new DateField(PROP_NONULL);
+        df.setDateFormat(dateFormat);
+        df.setBuffered(true);
+        Date date = null;
+        try {
+            date = new SimpleDateFormat(dateFormat).parse("25/07/16");
+        } catch (ParseException e1) {
+            // This cannot happen
+        }
+        ObjectProperty<Date> prop = new ObjectProperty<>(date, Date.class);
+        df.setPropertyDataSource(prop);
+        Button button = new Button("Discard 1");
+        button.addClickListener(new ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                df.discard();
+            }
+
+        });
+        VerticalLayout layout = new VerticalLayout();
+        HorizontalLayout hLayout = new HorizontalLayout(df, button);
+        layout.addComponent(hLayout);
+
+        final DateField df1 = new DateField(PROP_NULL_VALUE);
+        df1.setDateFormat(dateFormat);
+        df1.setBuffered(true);
+
+        prop = new ObjectProperty<>(null, Date.class);
+        df1.setPropertyDataSource(prop);
+        button = new Button("Discard 2");
+        button.addClickListener(new ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                df1.discard();
+            }
+
+        });
+        hLayout = new HorizontalLayout(df1, button);
+        layout.addComponent(hLayout);
+
+        final DateField df2 = new DateField(PROP_NULL);
+        df2.setDateFormat(dateFormat);
+        df2.setBuffered(true);
+        df2.setPropertyDataSource(null);
+        button = new Button("Discard 3");
+        button.addClickListener(new ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                df2.discard();
+            }
+
+        });
+        hLayout = new HorizontalLayout(df2, button);
+        layout.addComponent(hLayout);
+
+        setContent(layout);
+
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDown.java b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDown.java
new file mode 100644 (file)
index 0000000..08a621c
--- /dev/null
@@ -0,0 +1,64 @@
+package com.vaadin.v7.tests.components.grid;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.themes.ValoTheme;
+import com.vaadin.v7.data.Container.Filterable;
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.util.filter.SimpleStringFilter;
+import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
+import com.vaadin.v7.event.FieldEvents.TextChangeListener;
+import com.vaadin.v7.ui.Grid;
+import com.vaadin.v7.ui.Grid.HeaderRow;
+import com.vaadin.v7.ui.TextField;
+
+@Theme("valo")
+public class GridApplyFilterWhenScrolledDown extends UI {
+
+    private Grid grid = new Grid();
+
+    @Override
+    protected void init(VaadinRequest vaadinRequest) {
+
+        grid.addColumn("Name", String.class);
+
+        HeaderRow appendHeaderRow = grid.appendHeaderRow();
+        TextField filter = getColumnFilter("Name");
+        appendHeaderRow.getCell("Name").setComponent(filter);
+
+        for (int i = 0; i < 1000; i++) {
+            Item addItem = grid.getContainerDataSource().addItem(i);
+            addItem.getItemProperty("Name").setValue("Name " + i);
+
+        }
+
+        Item addItem = grid.getContainerDataSource().addItem(1000);
+        addItem.getItemProperty("Name").setValue("Test");
+
+        // grid.scrollToStart();
+        setContent(grid);
+    }
+
+    private TextField getColumnFilter(final Object columnId) {
+        TextField filter = new TextField();
+        filter.setWidth("100%");
+        filter.addStyleName(ValoTheme.TEXTFIELD_TINY);
+        filter.addTextChangeListener(new TextChangeListener() {
+            SimpleStringFilter filter = null;
+
+            @Override
+            public void textChange(TextChangeEvent event) {
+                Filterable f = (Filterable) grid.getContainerDataSource();
+                if (filter != null) {
+                    f.removeContainerFilter(filter);
+                }
+                filter = new SimpleStringFilter(columnId, event.getText(), true,
+                        true);
+                f.addContainerFilter(filter);
+            }
+        });
+        return filter;
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/main/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGrid.java b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGrid.java
new file mode 100644 (file)
index 0000000..53e5851
--- /dev/null
@@ -0,0 +1,60 @@
+package com.vaadin.v7.tests.components.grid;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.v7.data.util.BeanItemContainer;
+import com.vaadin.v7.ui.Grid;
+
+public class InitiallyDisabledGrid extends UI {
+
+    @Override
+    protected void init(VaadinRequest request) {
+        VerticalLayout layout = new VerticalLayout();
+        setContent(layout);
+        layout.setSizeFull();
+        layout.setWidth("600px");
+        layout.setHeight("600px");
+        final Grid grid = createGrid();
+        Button button = new Button("Enable/Disable",
+                event -> grid.setEnabled(!grid.isEnabled()));
+
+        layout.addComponent(button);
+        VerticalLayout l = new VerticalLayout();
+        l.setSizeFull();
+        l.addComponent(grid);
+
+        layout.addComponent(l);
+        layout.setExpandRatio(l, 1.0f);
+    }
+
+    private Grid createGrid() {
+        // Have some data
+        Collection<Person> people = new ArrayList<>();
+        for (int i = 0; i < 100; i++) {
+            Person person = new Person();
+            person.setFirstName("First " + i);
+            person.setLastName("Last " + i);
+            people.add(person);
+        }
+        // Have a container of some type to contain the data
+        BeanItemContainer<Person> container = new BeanItemContainer<>(
+                Person.class, people);
+
+        // Create a grid bound to the container
+        Grid grid = new Grid(container);
+        grid.setSizeFull();
+        grid.setColumns("firstName", "lastName");
+
+        grid.setEnabled(false);
+
+        return grid;
+
+    }
+
+}
\ No newline at end of file
index a534074da01cd527d567f626519b80e8b20abe23..6349405f9b35db4882cb47a03b756e23e81a1636 100644 (file)
@@ -1233,6 +1233,15 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
 
                     }
                 });
+        createBooleanAction("Toggle all column hidden state", "Columns", false,
+                new Command<Grid, Boolean>() {
+                    @Override
+                    public void execute(Grid c, Boolean value, Object data) {
+                        for (Column col : grid.getColumns()) {
+                            col.setHidden(!col.isHidden());
+                        }
+                    }
+                });
         createBooleanAction("All columns resizable", "Columns", false,
                 new Command<Grid, Boolean>() {
 
diff --git a/uitest/src/main/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUI.java b/uitest/src/main/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUI.java
new file mode 100644 (file)
index 0000000..17aa718
--- /dev/null
@@ -0,0 +1,30 @@
+package com.vaadin.v7.tests.core;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.MenuBar;
+import com.vaadin.ui.TextField;
+
+public class SpecialCharactersEncodingUI extends AbstractTestUI {
+
+    public static String textWithZwnj = "\ufeffछुट्‌याउनेछन्  क्ष  क्‌ष  क्‍ष";
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        MenuBar menubar = new MenuBar();
+        menubar.setId("menubar");
+        addComponent(menubar);
+        menubar.addItem(textWithZwnj, null);
+
+        Label label = new Label(textWithZwnj);
+        label.setId("label");
+        addComponent(label);
+
+        TextField f = new TextField("Textfield", textWithZwnj);
+        f.setId("textfield");
+        addComponent(f);
+
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JSComponent.js b/uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JSComponent.js
new file mode 100644 (file)
index 0000000..522654a
--- /dev/null
@@ -0,0 +1,11 @@
+com_vaadin_tests_components_javascriptcomponent_JSComponentLoadingIndicator_JSComponent = function()
+{
+       var connector = this;
+       var e = this.getElement();
+
+       e.innerText="click me to ping server";
+       e.id="js";
+       e.addEventListener("click", function() {
+               connector.test();
+       });
+}
\ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java
new file mode 100644 (file)
index 0000000..8e18aee
--- /dev/null
@@ -0,0 +1,44 @@
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+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.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridApplyFilterWhenScrolledDownTest extends MultiBrowserTest {
+
+    @Test
+    public void scrolledCorrectly() throws InterruptedException {
+        openTestURL();
+        final GridElement grid = $(GridElement.class).first();
+        grid.scrollToRow(50);
+        $(ButtonElement.class).first().click();
+        final TestBenchElement gridBody = grid.getBody();
+        // Can't use element API because it scrolls
+        waitUntil(new ExpectedCondition<Boolean>() {
+
+            @Override
+            public Boolean apply(WebDriver input) {
+                return gridBody.findElements(By.className("v-grid-row"))
+                        .size() == 1;
+            }
+        });
+        WebElement cell = gridBody.findElements(By.className("v-grid-cell"))
+                .get(0);
+        Assert.assertEquals("Test", cell.getText());
+
+        int gridHeight = grid.getSize().getHeight();
+        int scrollerHeight = grid.getVerticalScroller().getSize().getHeight();
+        Assert.assertTrue(
+                "Scroller height is " + scrollerHeight
+                        + ", should be smaller than grid height: " + gridHeight,
+                scrollerHeight < gridHeight);
+    }
+}
\ No newline at end of file
index e0ec3edbd818f8808c1d4b4b8c69e50ad17790ca..dca31e52495f31beb7239c952e1b1f9124f18e4b 100644 (file)
  */
 package com.vaadin.tests.components.grid;
 
+import static org.junit.Assert.assertEquals;
+
 import java.util.List;
 
 import org.junit.Assert;
 import org.junit.Test;
+import org.openqa.selenium.Dimension;
 import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
 
 import com.vaadin.testbench.By;
 import com.vaadin.testbench.customelements.GridElement;
 import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
 import com.vaadin.testbench.elements.LabelElement;
 import com.vaadin.tests.tb3.MultiBrowserTest;
 
@@ -119,6 +124,30 @@ public class GridColumnHidingTest extends MultiBrowserTest {
                 "custom age column caption".equals(elements.get(1).getText()));
     }
 
+    @Test
+    public void testShrinkColumnToZeroWithHiddenColumn() {
+        openTestURL();
+
+        // hide all
+        $(ButtonElement.class).get(3).click();
+
+        ButtonElement toggleNameColumn = $(ButtonElement.class).get(0);
+        ButtonElement toggleEmailColumn = $(ButtonElement.class).get(2);
+
+        // Show
+        toggleNameColumn.click();
+        toggleEmailColumn.click();
+
+        GridElement gridElement = $(GridElement.class).first();
+
+        GridCellElement cell = gridElement.getCell(0, 1);
+        dragResizeColumn(1, 0, -cell.getSize().getWidth());
+        assertGreaterOrEqual("Cell got too small.", cell.getSize().getWidth(),
+                10);
+        assertEquals(gridElement.getCell(0, 0).getLocation().getY(),
+                gridElement.getCell(0, 1).getLocation().getY());
+    }
+
     protected WebElement getSidebarOpenButton(GridElement grid) {
         List<WebElement> elements = grid
                 .findElements(By.className("v-grid-sidebar-button"));
@@ -146,4 +175,15 @@ public class GridColumnHidingTest extends MultiBrowserTest {
                 By.className("v-grid-sidebar-popup"));
         return elements.isEmpty() ? null : elements.get(0);
     }
+
+    private void dragResizeColumn(int columnIndex, int posX, int offset) {
+        GridElement gridElement = $(GridElement.class).first();
+
+        GridCellElement headerCell = gridElement.getHeaderCell(0, columnIndex);
+        Dimension size = headerCell.getSize();
+        new Actions(getDriver())
+                .moveToElement(headerCell, size.getWidth() + posX,
+                        size.getHeight() / 2)
+                .clickAndHold().moveByOffset(offset, 0).release().perform();
+    }
 }
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/InitiallyDisabledGridTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/InitiallyDisabledGridTest.java
new file mode 100644 (file)
index 0000000..e57b8d3
--- /dev/null
@@ -0,0 +1,45 @@
+package com.vaadin.tests.components.grid;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.customelements.GridElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class InitiallyDisabledGridTest extends SingleBrowserTest {
+
+    @Test
+    public void columnsExpanded() {
+        openTestURL();
+
+        List<WebElement> cells = findElements(By.className("v-grid-cell"));
+        WebElement col0 = cells.get(0);
+        WebElement col1 = cells.get(1);
+        Assert.assertTrue(col0.getSize().getWidth() > 250);
+        Assert.assertTrue(col1.getSize().getWidth() > 250);
+    }
+
+    @Test
+    @Ignore
+    /*
+     * The test fails at the moment because of issues related (or exactly the
+     * same) as https://github.com/vaadin/framework8-issues/issues/286. It
+     * should be enabled once it's fixed.
+     */
+    public void worksWhenEnabled() {
+        openTestURL();
+        $(ButtonElement.class).first().click();
+
+        GridElement grid = $(GridElement.class).first();
+        grid.scrollToRow(80);
+        GridCellElement col0 = grid.getCell(80, 0);
+        Assert.assertEquals("First 80", col0.getText());
+    }
+}
\ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicatorTest.java b/uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicatorTest.java
new file mode 100644 (file)
index 0000000..4532b22
--- /dev/null
@@ -0,0 +1,29 @@
+package com.vaadin.tests.components.javascriptcomponent;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class JSComponentLoadingIndicatorTest extends SingleBrowserTest {
+
+    @Test
+    public void ensureLoadingIndicatorShown() {
+        openTestURL();
+        testBench().disableWaitForVaadin();
+
+        WebElement js = findElement(By.id("js"));
+        js.click();
+        waitUntilLoadingIndicatorVisible();
+        waitUntilLoadingIndicatorNotVisible();
+        Assert.assertEquals(1, findElements(By.className("pong")).size());
+
+        js.click();
+        waitUntilLoadingIndicatorVisible();
+        waitUntilLoadingIndicatorNotVisible();
+        Assert.assertEquals(2, findElements(By.className("pong")).size());
+    }
+
+}
\ No newline at end of file
index 57e27141055bacb40142f827e5c9199148ea94b9..074d952889667a503e5e0eba508e48372bc9a1ee 100644 (file)
@@ -21,13 +21,24 @@ import org.junit.Assert;
 import org.junit.Test;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebElement;
+import org.openqa.selenium.remote.DesiredCapabilities;
 
 import com.vaadin.testbench.elements.ButtonElement;
 import com.vaadin.testbench.elements.TabSheetElement;
+import com.vaadin.testbench.parallel.Browser;
 import com.vaadin.tests.tb3.MultiBrowserTest;
 
 public class TabsheetScrollIntoViewTest extends MultiBrowserTest {
 
+    @Override
+    public List<DesiredCapabilities> getBrowsersToTest() {
+        List<DesiredCapabilities> browsers = super.getBrowsersToTest();
+        // For whatever reason, IE8 never returns from the
+        // $(TabSheetElement.class).first() call
+        browsers.remove(Browser.IE8.getDesiredCapabilities());
+        return browsers;
+    }
+
     @Test
     public void scrollIntoView() {
         openTestURL();
diff --git a/uitest/src/test/java/com/vaadin/tests/core/SpecialCharactersEncodingUITest.java b/uitest/src/test/java/com/vaadin/tests/core/SpecialCharactersEncodingUITest.java
new file mode 100644 (file)
index 0000000..03a4416
--- /dev/null
@@ -0,0 +1,37 @@
+package com.vaadin.tests.core;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.MenuBarElement;
+import com.vaadin.testbench.elements.TextFieldElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class SpecialCharactersEncodingUITest extends SingleBrowserTest {
+
+    @Test
+    public void checkEncoding() {
+        openTestURL();
+        String textFieldValue = $(TextFieldElement.class).id("textfield")
+                .getValue();
+        Assert.assertEquals(SpecialCharactersEncodingUI.textWithZwnj,
+                textFieldValue);
+        LabelElement label = $(LabelElement.class).id("label");
+        String labelValue = getHtml(label); // getText() strips some characters
+        Assert.assertEquals(SpecialCharactersEncodingUI.textWithZwnj,
+                labelValue);
+
+        MenuBarElement menubar = $(MenuBarElement.class).first();
+        WebElement menuItem = menubar
+                .findElement(By.className("v-menubar-menuitem-caption"));
+        Assert.assertEquals(SpecialCharactersEncodingUI.textWithZwnj,
+                getHtml(menuItem));
+    }
+
+    private String getHtml(WebElement element) {
+        return element.getAttribute("innerHTML");
+    }
+}
\ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValueTest.java b/uitest/src/test/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValueTest.java
new file mode 100644 (file)
index 0000000..e215370
--- /dev/null
@@ -0,0 +1,85 @@
+package com.vaadin.v7.tests.components.datefield;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+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.DateFieldElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class DateFieldDiscardValueTest extends SingleBrowserTest {
+
+    @Test
+    public void discardWhenDatasourceContentNonNullInvalidValue() {
+        discardWorks(DateFieldDiscardValue.PROP_NONULL, "1", "123", "25/07/16");
+    }
+
+    @Test
+    public void discardWhenDatasourceContentNonNullValidValue() {
+        discardWorks(DateFieldDiscardValue.PROP_NONULL, "1", "24/07/16",
+                "25/07/16");
+    }
+
+    @Test
+    public void discardWhenDatasourceContentNullInvalidValue() {
+        discardWorks(DateFieldDiscardValue.PROP_NULL_VALUE, "2", "123", "");
+    }
+
+    @Test
+    public void discardWhenDatasourceContentNullValidValue() {
+        discardWorks(DateFieldDiscardValue.PROP_NULL_VALUE, "2", "24/07/16",
+                "");
+    }
+
+    @Test
+    public void discardWhenDatasourceNull() {
+        // If the data source is null, discard should do nothing.
+        discardDoesntWork(DateFieldDiscardValue.PROP_NULL, "3", "123");
+    }
+
+    private void discardWorks(String caption, String id, String dateValue,
+            String resultValue) {
+        openTestURL();
+
+        ButtonElement discardButton = $(ButtonElement.class)
+                .caption("Discard " + id).first();
+        DateFieldElement dateField = $(DateFieldElement.class).caption(caption)
+                .first();
+        dateField.setValue(dateValue);
+
+        discardButton.click();
+
+        assertEquals(resultValue, dateField.getValue());
+
+        List<WebElement> elements = driver
+                .findElements(By.className("v-errorindicator"));
+
+        assertEquals(0, elements.size());
+    }
+
+    private void discardDoesntWork(String caption, String id,
+            String dateValue) {
+        openTestURL();
+
+        ButtonElement discardButton = $(ButtonElement.class)
+                .caption("Discard " + id).first();
+        DateFieldElement dateField = $(DateFieldElement.class).caption(caption)
+                .first();
+        dateField.setValue(dateValue);
+
+        discardButton.click();
+
+        assertEquals(dateValue, dateField.getValue());
+
+        List<WebElement> elements = driver
+                .findElements(By.className("v-errorindicator"));
+
+        assertEquals(1, elements.size());
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java
new file mode 100644 (file)
index 0000000..9a14c01
--- /dev/null
@@ -0,0 +1,44 @@
+package com.vaadin.v7.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+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.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.TextFieldElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridApplyFilterWhenScrolledDownTest extends MultiBrowserTest {
+
+    @Test
+    public void scrolledCorrectly() throws InterruptedException {
+        openTestURL();
+        final GridElement grid = $(GridElement.class).first();
+        grid.scrollToRow(50);
+        $(TextFieldElement.class).first().setValue("Test");
+        final TestBenchElement gridBody = grid.getBody();
+        // Can't use element API because it scrolls
+        waitUntil(new ExpectedCondition<Boolean>() {
+
+            @Override
+            public Boolean apply(WebDriver input) {
+                return gridBody.findElements(By.className("v-grid-row"))
+                        .size() == 1;
+            }
+        });
+        WebElement cell = gridBody.findElements(By.className("v-grid-cell"))
+                .get(0);
+        Assert.assertEquals("Test", cell.getText());
+
+        int gridHeight = grid.getSize().getHeight();
+        int scrollerHeight = grid.getVerticalScroller().getSize().getHeight();
+        Assert.assertTrue(
+                "Scroller height is " + scrollerHeight
+                        + ", should be smaller than grid height: " + gridHeight,
+                scrollerHeight < gridHeight);
+    }
+}
\ No newline at end of file
diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGridTest.java b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGridTest.java
new file mode 100644 (file)
index 0000000..8f012ee
--- /dev/null
@@ -0,0 +1,34 @@
+package com.vaadin.v7.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class InitiallyDisabledGridTest extends SingleBrowserTest {
+
+    @Test
+    public void columnsExpanded() {
+        openTestURL();
+
+        GridElement grid = $(GridElement.class).first();
+        GridCellElement col0 = grid.getCell(0, 0);
+        GridCellElement col1 = grid.getCell(0, 1);
+        Assert.assertTrue(col0.getSize().getWidth() > 250);
+        Assert.assertTrue(col1.getSize().getWidth() > 250);
+    }
+
+    @Test
+    public void worksWhenEnabled() {
+        openTestURL();
+        $(ButtonElement.class).first().click();
+
+        GridElement grid = $(GridElement.class).first();
+        grid.scrollToRow(80);
+        GridCellElement col0 = grid.getCell(80, 0);
+        Assert.assertEquals("First 80", col0.getText());
+    }
+}
\ No newline at end of file
index 22bea4f9f53d8f8b734b9c75a490bbfffbb3ec9f..fda42e77396dcc18e026a94d56d8af6f80cbe3d0 100644 (file)
@@ -146,4 +146,25 @@ public class GridColumnResizeTest extends GridBasicFeaturesTest {
         assertGreaterOrEqual("Cell got too small.", cell.getSize().getWidth(),
                 10);
     }
+
+    @Test
+    public void testShrinkColumnToZeroWithHiddenColumn() {
+        openTestURL();
+        selectMenuPath("Component", "Columns",
+                "Toggle all column hidden state");
+        // Hides although already hidden
+        selectMenuPath("Component", "Columns", "Column 0", "Hidden");
+        // Shows
+        selectMenuPath("Component", "Columns", "Column 0", "Hidden");
+        // Hides although already hidden
+        selectMenuPath("Component", "Columns", "Column 2", "Hidden");
+        // Shows
+        selectMenuPath("Component", "Columns", "Column 2", "Hidden");
+        GridCellElement cell = getGridElement().getCell(0, 1);
+        dragResizeColumn(1, 0, -cell.getSize().getWidth());
+        assertGreaterOrEqual("Cell got too small.", cell.getSize().getWidth(),
+                10);
+        assertEquals(getGridElement().getCell(0, 0).getLocation().getY(),
+                getGridElement().getCell(0, 1).getLocation().getY());
+    }
 }
index 65fe0e7dee1d75161f1c69d5af6918928f264b27..b63da5ce30a6e3260f248dd11f54337a34059455 100644 (file)
@@ -21,9 +21,11 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.vaadin.testbench.elements.GridElement;
 import com.vaadin.testbench.parallel.TestCategory;
 import com.vaadin.v7.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
 
@@ -295,6 +297,35 @@ public class GridColumnVisibilityTest extends GridBasicFeaturesTest {
         verifyColumnNotFrozen(2);
     }
 
+    @Test
+    public void showColumnAndScrollbarWhenScrolledDownAndVisibleRowsChange()
+            throws Exception {
+        // Set a (un)suitable height
+        selectMenuPath("Component", "Size", "HeightMode Row");
+        selectMenuPath("Component", "Size", "Height by Rows", "4.33 rows");
+
+        toggleAllColumnsHidable();
+
+        // Hide all but the first 3
+        getSidebarOpenButton().click();
+        for (int i = 3; i < 12; i++) {
+            getColumnHidingToggle(i).click();
+        }
+
+        getSidebarOpenButton().click();
+
+        // Scroll all the way to the end
+        $(GridElement.class).first().scrollToRow(999);
+
+        // Show the fourth column
+        getSidebarOpenButton().click();
+        getColumnHidingToggle(3).click();
+
+        // Make sure that the new column contains the data it should
+        Assert.assertEquals("(999, 3)",
+                getGridElement().getCell(999, 3).getText());
+    }
+
     private void verifyColumnFrozen(int index) {
         assertTrue(getGridElement().getHeaderCell(0, index).isFrozen());
     }
@@ -307,6 +338,10 @@ public class GridColumnVisibilityTest extends GridBasicFeaturesTest {
         selectMenuPath("Component", "Columns", "Column " + index, "Hidable");
     }
 
+    private void toggleAllColumnsHidable() {
+        selectMenuPath("Component", "Columns", "All columns hidable");
+    }
+
     private void addRemoveColumn(int index) {
         selectMenuPath("Component", "Columns", "Column " + index,
                 "Add / Remove");
diff --git a/uitest/src/test/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUITest.java b/uitest/src/test/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUITest.java
new file mode 100644 (file)
index 0000000..02cad36
--- /dev/null
@@ -0,0 +1,37 @@
+package com.vaadin.v7.tests.core;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.MenuBarElement;
+import com.vaadin.testbench.elements.TextFieldElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class SpecialCharactersEncodingUITest extends SingleBrowserTest {
+
+    @Test
+    public void checkEncoding() {
+        openTestURL();
+        String textFieldValue = $(TextFieldElement.class).id("textfield")
+                .getValue();
+        Assert.assertEquals(SpecialCharactersEncodingUI.textWithZwnj,
+                textFieldValue);
+        LabelElement label = $(LabelElement.class).id("label");
+        String labelValue = getHtml(label); // getText() strips some characters
+        Assert.assertEquals(SpecialCharactersEncodingUI.textWithZwnj,
+                labelValue);
+
+        MenuBarElement menubar = $(MenuBarElement.class).first();
+        WebElement menuItem = menubar
+                .findElement(By.className("v-menubar-menuitem-caption"));
+        Assert.assertEquals(SpecialCharactersEncodingUI.textWithZwnj,
+                getHtml(menuItem));
+    }
+
+    private String getHtml(WebElement element) {
+        return element.getAttribute("innerHTML");
+    }
+}
\ No newline at end of file