diff options
author | Denis Anisimov <denis@vaadin.com> | 2016-09-28 13:24:42 +0300 |
---|---|---|
committer | Denis Anisimov <denis@vaadin.com> | 2016-10-03 09:00:48 +0300 |
commit | 43bb825f0e7fbaa3a1382f85c9b2f6f6c4fe3ac4 (patch) | |
tree | 6ba789759db22c0d8042c4ede8d91593b648ed7e | |
parent | d6967afcbc87836464b39b22b2d424a336403952 (diff) | |
download | vaadin-framework-43bb825f0e7fbaa3a1382f85c9b2f6f6c4fe3ac4.tar.gz vaadin-framework-43bb825f0e7fbaa3a1382f85c9b2f6f6c4fe3ac4.zip |
Migrating 7.7.1, 7.7.2, 7.7.3 to V8.
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, 2401 insertions, 197 deletions
diff --git a/client/src/main/java/com/vaadin/client/AnimationUtil.java b/client/src/main/java/com/vaadin/client/AnimationUtil.java index bbefcffbdd..e2cf9e690a 100644 --- a/client/src/main/java/com/vaadin/client/AnimationUtil.java +++ b/client/src/main/java/com/vaadin/client/AnimationUtil.java @@ -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]; diff --git a/client/src/main/java/com/vaadin/client/LayoutManager.java b/client/src/main/java/com/vaadin/client/LayoutManager.java index 841eead561..ad0a3f8c38 100644 --- a/client/src/main/java/com/vaadin/client/LayoutManager.java +++ b/client/src/main/java/com/vaadin/client/LayoutManager.java @@ -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"); } diff --git a/client/src/main/java/com/vaadin/client/communication/ServerRpcQueue.java b/client/src/main/java/com/vaadin/client/communication/ServerRpcQueue.java index 35d6f48565..ce07fc0baf 100644 --- a/client/src/main/java/com/vaadin/client/communication/ServerRpcQueue.java +++ b/client/src/main/java/com/vaadin/client/communication/ServerRpcQueue.java @@ -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)) { diff --git a/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java b/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java index 33f96e009c..9dd1a504ab 100644 --- a/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java +++ b/client/src/main/java/com/vaadin/client/data/AbstractRemoteDataSource.java @@ -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; + } } diff --git a/client/src/main/java/com/vaadin/client/data/DataSource.java b/client/src/main/java/com/vaadin/client/data/DataSource.java index fdec4b9a38..4645957111 100644 --- a/client/src/main/java/com/vaadin/client/data/DataSource.java +++ b/client/src/main/java/com/vaadin/client/data/DataSource.java @@ -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(); } diff --git a/client/src/main/java/com/vaadin/client/widget/escalator/ScrollbarBundle.java b/client/src/main/java/com/vaadin/client/widget/escalator/ScrollbarBundle.java index 7e11c6c0d9..c62c5f032f 100644 --- a/client/src/main/java/com/vaadin/client/widget/escalator/ScrollbarBundle.java +++ b/client/src/main/java/com/vaadin/client/widget/escalator/ScrollbarBundle.java @@ -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; } } diff --git a/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java b/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java index 9767a230bb..355840d4ce 100644 --- a/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java +++ b/client/src/main/java/com/vaadin/client/widget/grid/datasources/ListDataSource.java @@ -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(); diff --git a/client/src/main/java/com/vaadin/client/widgets/Escalator.java b/client/src/main/java/com/vaadin/client/widgets/Escalator.java index 77afccdb30..fdd4c22645 100644 --- a/client/src/main/java/com/vaadin/client/widgets/Escalator.java +++ b/client/src/main/java/com/vaadin/client/widgets/Escalator.java @@ -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) { diff --git a/client/src/main/java/com/vaadin/client/widgets/Grid.java b/client/src/main/java/com/vaadin/client/widgets/Grid.java index 9a87d82363..eac958fdce 100644 --- a/client/src/main/java/com/vaadin/client/widgets/Grid.java +++ b/client/src/main/java/com/vaadin/client/widgets/Grid.java @@ -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><td></code>. + * <li>a cell on that same row, the click event is the parent + * <code><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(); } diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/connectors/RpcDataSourceConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/connectors/RpcDataSourceConnector.java index 363d3c047d..f800300440 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/connectors/RpcDataSourceConnector.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/connectors/RpcDataSourceConnector.java @@ -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(); diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/widget/escalator/ScrollbarBundle.java b/compatibility-client/src/main/java/com/vaadin/v7/client/widget/escalator/ScrollbarBundle.java index bdd4240818..20b1e5d1b9 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/widget/escalator/ScrollbarBundle.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/widget/escalator/ScrollbarBundle.java @@ -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; } } diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/datasources/ListDataSource.java b/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/datasources/ListDataSource.java index 994e8059eb..d80cdad3c9 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/datasources/ListDataSource.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/datasources/ListDataSource.java @@ -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(); diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java b/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java index e79237702b..afc9cd8a45 100644 --- a/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java +++ b/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java @@ -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><td></code>. + * <li>a cell on that same row, the click event is the parent + * <code><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; } diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java index befdc26998..0be6b236d0 100644 --- a/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java +++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/DateField.java @@ -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 */ diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java index f89cf5544b..f7bcd8075f 100644 --- a/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java +++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java @@ -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 index 0000000000..0a97a84999 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/ItemSetChangeDuringEditorCommit.java @@ -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 @@ -13,13 +13,14 @@ <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 --> @@ -135,6 +139,14 @@ <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> @@ -340,6 +352,15 @@ <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> </plugin> @@ -436,6 +457,25 @@ <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> @@ -503,6 +543,12 @@ <profiles> <profile> + <id>slowtest</id> + <modules> + <module>test</module> + </modules> + </profile> + <profile> <id>release</id> <activation> <activeByDefault>false</activeByDefault> diff --git a/scripts/BuildDemos.py b/scripts/BuildDemos.py index 4e4362b1df..7870e743de 100644 --- a/scripts/BuildDemos.py +++ b/scripts/BuildDemos.py @@ -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") } diff --git a/scripts/BuildHelpers.py b/scripts/BuildHelpers.py index 8f6e2dee60..8a9baee6a0 100644 --- a/scripts/BuildHelpers.py +++ b/scripts/BuildHelpers.py @@ -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"]) diff --git a/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java b/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java index 345ac25848..5d198a6488 100644 --- a/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java +++ b/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java @@ -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 ""; } diff --git a/server/src/main/java/com/vaadin/server/UIProvider.java b/server/src/main/java/com/vaadin/server/UIProvider.java index ce3690f9a1..a652b423ff 100644 --- a/server/src/main/java/com/vaadin/server/UIProvider.java +++ b/server/src/main/java/com/vaadin/server/UIProvider.java @@ -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; } diff --git a/server/src/main/java/com/vaadin/server/VaadinServlet.java b/server/src/main/java/com/vaadin/server/VaadinServlet.java index 03d47b6693..42dfde5444 100644 --- a/server/src/main/java/com/vaadin/server/VaadinServlet.java +++ b/server/src/main/java/com/vaadin/server/VaadinServlet.java @@ -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 diff --git a/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java b/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java index c271aec09f..7aec100255 100644 --- a/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java +++ b/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java @@ -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; diff --git a/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java b/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java index f64b43092f..951944d8ac 100644 --- a/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java +++ b/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java @@ -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 index 0000000000..79939e6b1b --- /dev/null +++ b/test/addon-using-init-param-widget-set/pom.xml @@ -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 index 0000000000..41a240e006 --- /dev/null +++ b/test/addon-using-init-param-widget-set/src/main/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetUI.java @@ -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 index 0000000000..42333fb2c7 --- /dev/null +++ b/test/addon-using-init-param-widget-set/src/test/java/com/vaadin/test/addonusinginitparamwidgetset/AddonUsingInitParamWidgetSetIT.java @@ -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 index 0000000000..97178f94f8 --- /dev/null +++ b/test/addon-using-no-defined-widget-set/pom.xml @@ -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 index 0000000000..1893bb46e1 --- /dev/null +++ b/test/addon-using-no-defined-widget-set/src/main/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetUI.java @@ -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 index 0000000000..93dc5f1e77 --- /dev/null +++ b/test/addon-using-no-defined-widget-set/src/test/java/com/vaadin/test/addonusingnodefinedwidgetset/AddonUsingNoDefinedWidgetSetIT.java @@ -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 index 0000000000..fc52e47f4f --- /dev/null +++ b/test/addon-using-own-widget-set/pom.xml @@ -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 index 0000000000..15efad2295 --- /dev/null +++ b/test/addon-using-own-widget-set/src/main/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetUI.java @@ -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 index 0000000000..26be42e65b --- /dev/null +++ b/test/addon-using-own-widget-set/src/main/resources/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSet.gwt.xml @@ -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 index 0000000000..c22dbf8eb9 --- /dev/null +++ b/test/addon-using-own-widget-set/src/test/java/com/vaadin/test/addonusingownwidgetset/AddonUsingOwnWidgetSetIT.java @@ -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 index 0000000000..68ee894911 --- /dev/null +++ b/test/default-widget-set/pom.xml @@ -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 index 0000000000..fb58389ece --- /dev/null +++ b/test/default-widget-set/src/main/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetUI.java @@ -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 index 0000000000..8fda5812d0 --- /dev/null +++ b/test/default-widget-set/src/test/java/com/vaadin/test/defaultwidgetset/DefaultWidgetSetIT.java @@ -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 index 0000000000..6ce65c868f --- /dev/null +++ b/test/own-widget-set/pom.xml @@ -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 index 0000000000..8801dacbae --- /dev/null +++ b/test/own-widget-set/src/main/java/com/vaadin/test/ownwidgetset/OwnWidgetSetUI.java @@ -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 index 0000000000..7501fbabbb --- /dev/null +++ b/test/own-widget-set/src/test/java/com/vaadin/test/ownwidgetset/OwnWidgetSetIT.java @@ -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 index 0000000000..b1ee2fb074 --- /dev/null +++ b/test/pom.xml @@ -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 index 0000000000..65c3574ead --- /dev/null +++ b/test/space in directory/pom.xml @@ -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 index 0000000000..ccf023c871 --- /dev/null +++ b/test/space in directory/src/main/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryUI.java @@ -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 index 0000000000..ad42d087ce --- /dev/null +++ b/test/space in directory/src/main/resources/com/vaadin/test/spaceindirectory/SpaceInDirectory.gwt.xml @@ -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 index 0000000000..f8fbfb6f8a --- /dev/null +++ b/test/space in directory/src/test/java/com/vaadin/test/spaceindirectory/SpaceInDirectoryIT.java @@ -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 index 0000000000..96a9a94d7f --- /dev/null +++ b/test/vaadinservletconfiguration-widget-set/pom.xml @@ -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 index 0000000000..e607df30c2 --- /dev/null +++ b/test/vaadinservletconfiguration-widget-set/src/main/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetUI.java @@ -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 index 0000000000..ad42d087ce --- /dev/null +++ b/test/vaadinservletconfiguration-widget-set/src/main/resources/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSet.gwt.xml @@ -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 index 0000000000..6727cef4c7 --- /dev/null +++ b/test/vaadinservletconfiguration-widget-set/src/test/java/com/vaadin/test/vaadinservletconfigurationwidgetset/VaadinServletConfigurationWidgetSetIT.java @@ -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 index 0000000000..3dcc6db865 --- /dev/null +++ b/test/widget-set-testutil/pom.xml @@ -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 index 0000000000..c03645517a --- /dev/null +++ b/test/widget-set-testutil/src/main/java/com/vaadin/test/widgetset/AbstractTestWidgetSetUI.java @@ -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 index 0000000000..e84296819c --- /dev/null +++ b/test/widget-set-testutil/src/test/java/com/vaadin/test/defaultwidgetset/AbstractWidgetSetIT.java @@ -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 diff --git a/uitest-common/src/main/java/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest-common/src/main/java/com/vaadin/tests/tb3/AbstractTB3Test.java index 4985bc7e93..dce2c77db0 100644 --- a/uitest-common/src/main/java/com/vaadin/tests/tb3/AbstractTB3Test.java +++ b/uitest-common/src/main/java/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -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 index 0000000000..72a53d2f0c --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDown.java @@ -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 diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridColumnHiding.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridColumnHiding.java index 7fa86b6522..0abf48baeb 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/GridColumnHiding.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridColumnHiding.java @@ -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 index 0000000000..74f69ef7ab --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/InitiallyDisabledGrid.java @@ -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 index 0000000000..d318b7e5b0 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicator.java @@ -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 index 0000000000..974d94c03b --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/core/SpecialCharactersEncodingUI.java @@ -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 index 0000000000..f3d21950f9 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/resources/DownloadWithPush.java @@ -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 diff --git a/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridCellFocusOnResetSizeWidget.java b/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridCellFocusOnResetSizeWidget.java index 0fe861f723..d2dbf78739 100644 --- a/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridCellFocusOnResetSizeWidget.java +++ b/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridCellFocusOnResetSizeWidget.java @@ -81,6 +81,11 @@ public class GridCellFocusOnResetSizeWidget } handler.resetDataAndSize(size); } + + @Override + public boolean isWaitingForData() { + return false; + } } private class Col extends Grid.Column<String, String[]> { diff --git a/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridClientColumnRendererConnector.java b/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridClientColumnRendererConnector.java index 904ecbf1d5..e4dce67da8 100644 --- a/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridClientColumnRendererConnector.java +++ b/uitest/src/main/java/com/vaadin/tests/widgetset/client/v7/grid/GridClientColumnRendererConnector.java @@ -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 index 0000000000..2119b9f21e --- /dev/null +++ b/uitest/src/main/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValue.java @@ -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 index 0000000000..08a621c937 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDown.java @@ -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 index 0000000000..53e585120e --- /dev/null +++ b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGrid.java @@ -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 diff --git a/uitest/src/main/java/com/vaadin/v7/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/basicfeatures/GridBasicFeatures.java index a534074da0..6349405f9b 100644 --- a/uitest/src/main/java/com/vaadin/v7/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -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 index 0000000000..17aa7185fb --- /dev/null +++ b/uitest/src/main/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUI.java @@ -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 index 0000000000..522654a930 --- /dev/null +++ b/uitest/src/main/resources/com/vaadin/tests/components/javascriptcomponent/JSComponent.js @@ -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 index 0000000000..8e18aeedd1 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java @@ -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 diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridColumnHidingTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridColumnHidingTest.java index e0ec3edbd8..dca31e5249 100644 --- a/uitest/src/test/java/com/vaadin/tests/components/grid/GridColumnHidingTest.java +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridColumnHidingTest.java @@ -15,15 +15,20 @@ */ 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 index 0000000000..e57b8d3efe --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/InitiallyDisabledGridTest.java @@ -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 index 0000000000..4532b22937 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/javascriptcomponent/JSComponentLoadingIndicatorTest.java @@ -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 diff --git a/uitest/src/test/java/com/vaadin/tests/components/tabsheet/TabsheetScrollIntoViewTest.java b/uitest/src/test/java/com/vaadin/tests/components/tabsheet/TabsheetScrollIntoViewTest.java index 57e2714105..074d952889 100644 --- a/uitest/src/test/java/com/vaadin/tests/components/tabsheet/TabsheetScrollIntoViewTest.java +++ b/uitest/src/test/java/com/vaadin/tests/components/tabsheet/TabsheetScrollIntoViewTest.java @@ -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 index 0000000000..03a441623b --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/core/SpecialCharactersEncodingUITest.java @@ -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 index 0000000000..e215370560 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/v7/tests/components/datefield/DateFieldDiscardValueTest.java @@ -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 index 0000000000..9a14c01146 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/GridApplyFilterWhenScrolledDownTest.java @@ -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 index 0000000000..8f012eed25 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/InitiallyDisabledGridTest.java @@ -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 diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java index 22bea4f9f5..fda42e7739 100644 --- a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java +++ b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java @@ -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()); + } } diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java index 65fe0e7dee..b63da5ce30 100644 --- a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java +++ b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java @@ -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 index 0000000000..02cad362eb --- /dev/null +++ b/uitest/src/test/java/com/vaadin/v7/tests/core/SpecialCharactersEncodingUITest.java @@ -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 |