summaryrefslogtreecommitdiffstats
path: root/uitest
diff options
context:
space:
mode:
Diffstat (limited to 'uitest')
-rw-r--r--uitest/build.xml132
-rw-r--r--uitest/src/com/vaadin/testbench/elements/GridElement.java325
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java109
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java76
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java63
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInit.java62
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInitTest.java46
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridAddRow.java49
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridAddRowTest.java50
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java292
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColspans.java102
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java101
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidth.java63
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClient.java33
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClientTest.java27
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthServerTest.java27
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColumnExpand.java159
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridEditorUI.java49
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridEditorUITest.java63
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridGeneratedProperties.java165
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridGeneratedPropertiesTest.java90
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNames.java111
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java158
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridInTabSheet.java69
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridInTabSheetTest.java61
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInit.java34
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInitTest.java35
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridScrolling.java112
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java60
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java47
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridThemeChange.java59
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridThemeChangeTest.java51
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverter.java37
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverterTest.java25
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridWithoutRenderer.java34
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridWithoutRendererTest.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumns.java41
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumnsTest.java42
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java24
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderers.java75
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java46
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java34
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java33
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/SelectDuringInit.java40
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/SelectDuringInitTest.java35
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/WidgetRenderers.java117
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/WidgetRenderersTest.java132
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeatures.java36
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java262
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUi.java33
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java39
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java92
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java1026
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java135
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesValo.java28
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSources.java32
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSourcesTest.java180
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInit.java20
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInitTest.java19
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRenderer.java32
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRendererTest.java68
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInit.java50
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInitTest.java20
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicators.java65
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicatorsTest.java39
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/DisabledGridClientTest.java58
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridCellStyleGeneratorTest.java131
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java128
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeEditorTest.java13
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeFooterTest.java11
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeHeaderTest.java11
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeKeyEventsTest.java12
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeSelectionTest.java11
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java132
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java102
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientStructureTest.java37
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java155
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java219
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java281
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridRowHandleRefreshTest.java65
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java90
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java114
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java64
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColspanTest.java80
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColumnFreezingTest.java111
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorRowColumnTest.java316
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorScrollTest.java95
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorUpdaterUiTest.java151
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/DisabledGridTest.java58
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellFocusAdjustmentTest.java86
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java121
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java259
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridItemClickTest.java57
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java221
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridMultiSortingTest.java70
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridRowAddRemoveTest.java57
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java292
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java375
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java71
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java485
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java86
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/myBeanJsRenderer.js16
-rw-r--r--uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeer.java32
-rw-r--r--uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeerTest.java28
-rw-r--r--uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRuno.java32
-rw-r--r--uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRunoTest.java28
-rw-r--r--uitest/src/com/vaadin/tests/serialization/NoLayout.java101
-rw-r--r--uitest/src/com/vaadin/tests/serialization/NoLayoutTest.java84
-rw-r--r--uitest/src/com/vaadin/tests/serialization/SerializerTest.java21
-rw-r--r--uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java6
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml6
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/BasicExtensionTestConnector.java5
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/CustomUIConnector.java3
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/LayoutDetectorConnector.java61
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java11
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/NoLayoutRpc.java26
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java2
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java33
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java5
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/SerializerTestState.java7
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/TestWidgetConnector.java100
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java702
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java218
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java1173
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java386
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererRpc.java48
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientDataSourcesWidget.java219
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridColumnAutoWidthClientWidget.java71
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridDefaultTextRendererWidget.java64
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridHeightByRowOnInitWidget.java32
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java46
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java308
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java78
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java144
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/LayoutDetector.java26
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/TestWidgetComponent.java67
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/grid/GridClientColumnRenderers.java158
137 files changed, 14728 insertions, 58 deletions
diff --git a/uitest/build.xml b/uitest/build.xml
index 02b97fb3a0..e6c68a90aa 100644
--- a/uitest/build.xml
+++ b/uitest/build.xml
@@ -1,6 +1,7 @@
<?xml version="1.0"?>
-<project name="vaadin-uitest" basedir="." default="publish-local" xmlns:ivy="antlib:org.apache.ivy.ant">
+<project name="vaadin-uitest" basedir="." default="publish-local"
+ xmlns:ivy="antlib:org.apache.ivy.ant">
<description>
Provides a uitest WAR containing Vaadin UI tests
</description>
@@ -12,20 +13,24 @@
<property name="uitest.dir" location="${vaadin.basedir}/uitest" />
<property name="result.dir" value="result" />
<property name="theme.result.dir" value="${result.dir}/VAADIN/themes" />
- <property name="result.war" location="${result.dir}/lib/${module.name}-${vaadin.version}.war" />
+ <property name="result.war"
+ location="${result.dir}/lib/${module.name}-${vaadin.version}.war" />
<path id="classpath.compile.custom">
</path>
<target name="dependencies">
- <!-- This is copied from common.xml to be able to add server.test.source
+ <!-- This is copied from common.xml to be able to add server.test.source
to the source path -->
- <ivy:resolve log="download-only" resolveid="common" conf="build, build-provided" />
- <ivy:cachepath pathid="classpath.compile.dependencies" conf="build, build-provided" />
+ <ivy:resolve log="download-only" resolveid="common"
+ conf="build, build-provided" />
+ <ivy:cachepath pathid="classpath.compile.dependencies"
+ conf="build, build-provided" />
</target>
- <target name="compile" description="Compiles the module" depends="dependencies">
+ <target name="compile" description="Compiles the module"
+ depends="dependencies">
<fail unless="module.name" message="No module name given" />
<property name="result.dir" location="result" />
@@ -35,16 +40,21 @@
<mkdir dir="${classes}" />
<!-- TODO: Get rid of this -->
- <javac destdir="${classes}" source="${vaadin.java.version}" target="${vaadin.java.version}" debug="true" encoding="UTF-8" includeantruntime="false">
+ <javac destdir="${classes}" source="${vaadin.java.version}"
+ target="${vaadin.java.version}" debug="true" encoding="UTF-8"
+ includeantruntime="false">
<src path="${server.test.sources}" />
<include name="com/vaadin/tests/data/bean/**" />
<include name="com/vaadin/tests/VaadinClasses.java" />
- <include name="com/vaadin/data/util/sqlcontainer/SQLTestsConstants.java" />
+ <include
+ name="com/vaadin/data/util/sqlcontainer/SQLTestsConstants.java" />
<classpath refid="classpath.compile.dependencies" />
<classpath refid="classpath.compile.custom" />
</javac>
- <javac destdir="${classes}" source="${vaadin.java.version}" target="${vaadin.java.version}" debug="true" encoding="UTF-8" includeantruntime="false">
+ <javac destdir="${classes}" source="${vaadin.java.version}"
+ target="${vaadin.java.version}" debug="true" encoding="UTF-8"
+ includeantruntime="false">
<src path="${src}" />
<classpath location="${classes}" />
<classpath refid="classpath.compile.dependencies" />
@@ -53,7 +63,8 @@
</target>
<target name="testing-widgetset" depends="dependencies,compile">
- <property name="module" value="com.vaadin.tests.widgetset.TestingWidgetSet" />
+ <property name="module"
+ value="com.vaadin.tests.widgetset.TestingWidgetSet" />
<property name="style" value="OBF" />
<property name="localWorkers" value="6" />
<property name="extraParams" value="" />
@@ -65,7 +76,8 @@
<echo>Compiling ${module} to ${module.output.dir}</echo>
<!-- compile the module -->
- <java classname="com.google.gwt.dev.Compiler" classpathref="classpath.compile.dependencies" failonerror="yes" fork="yes" maxmemory="512m">
+ <java classname="com.google.gwt.dev.Compiler" classpathref="classpath.compile.dependencies"
+ failonerror="yes" fork="yes" maxmemory="512m">
<classpath location="src" />
<classpath location="${classes}" />
<arg value="-workDir" />
@@ -92,15 +104,18 @@
</target>
- <target name="war" depends="dependencies, compile, compile-test-themes, testing-widgetset">
+ <target name="war"
+ depends="dependencies, compile, compile-test-themes, testing-widgetset">
<property name="result.dir" location="result" />
<property name="classes" location="${result.dir}/classes" />
<property name="WebContent.dir" location="${vaadin.basedir}/WebContent" />
<property name="deps.dir" location="${result.dir}/deps" />
<property name="src" location="${result.dir}/../src" />
- <ivy:resolve log="download-only" resolveid="common" conf="build" />
- <ivy:cachepath pathid="classpath.runtime.dependencies" conf="build" />
+ <ivy:resolve log="download-only" resolveid="common"
+ conf="build" />
+ <ivy:cachepath pathid="classpath.runtime.dependencies"
+ conf="build" />
<delete dir="${deps.dir}" />
<mkdir dir="${deps.dir}" />
@@ -110,16 +125,14 @@
</copy>
<delete>
- <!-- Avoid including some potentially conflicting jars in the war -->
+ <!-- Avoid including some potentially conflicting jars in the
+ war -->
<fileset dir="${deps.dir}" includes="jetty-*.jar" />
<fileset dir="${deps.dir}" includes="servlet-api-*.jar" />
</delete>
- <!-- Ensure filtered webcontent files are available -->
- <antcall target="common.filter.webcontent" />
-
<war destfile="${result.war}" duplicate="fail" index="true">
- <fileset refid="common.files.for.all.jars" />
+ <fileset dir="${common.jarfiles.dir}" />
<fileset dir="${result.dir}">
<include name="VAADIN/widgetsets/**/*" />
<include name="VAADIN/themes/tests-valo*/**" />
@@ -156,38 +169,45 @@
<target name="test" depends="checkstyle">
</target>
- <target name="test-testbench" depends="clean-testbench-errors" description="Run all TestBench based tests, including server tests">
+ <target name="test-testbench" depends="clean-testbench-errors"
+ description="Run all TestBench based tests, including server tests">
<parallel>
<daemons>
<!-- Start server -->
- <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" />
+ <ant antfile="${uitest.dir}/vaadin-server.xml"
+ inheritall="true" inheritrefs="true" target="deploy-and-start" />
</daemons>
<sequential>
<!-- Server tests -->
- <!-- Sleep before running integration tests so testbench 2
- tests have time to compile and start -->
+ <!-- Sleep before running integration tests so testbench
+ 2 tests have time to compile and start -->
<sleep minutes="4" />
- <ant antfile="${uitest.dir}/integration_tests.xml" target="integration-test-all" inheritall="false" inheritrefs="false">
+ <ant antfile="${uitest.dir}/integration_tests.xml"
+ target="integration-test-all" inheritall="false"
+ inheritrefs="false">
<property name="demo.war" value="${war.file}" />
</ant>
</sequential>
<sequential>
<!-- Wait for server to start -->
- <ant antfile="${uitest.dir}/vaadin-server.xml" target="wait-for-startup" />
+ <ant antfile="${uitest.dir}/vaadin-server.xml"
+ target="wait-for-startup" />
<!-- Run all different kinds of TestBench tests in parallel -->
<parallel>
<!-- Legacy TestBench 2 tests -->
<sequential>
- <ant antfile="${uitest.dir}/test.xml" target="tb2-tests" />
+ <ant antfile="${uitest.dir}/test.xml"
+ target="tb2-tests" />
<echo message="TestBench 2 tests complete" />
</sequential>
<!-- TestBench 3 tests -->
<sequential>
- <ant antfile="${uitest.dir}/tb3test.xml" target="run-all-tb3-tests" inheritall="true" />
+ <ant antfile="${uitest.dir}/tb3test.xml"
+ target="run-all-tb3-tests" inheritall="true" />
<echo message="TestBench 3 tests complete" />
</sequential>
</parallel>
@@ -196,13 +216,17 @@
</target>
<target name="test-server" depends="clean-testbench-errors">
- <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" />
+ <property name="war.file"
+ location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" />
<parallel>
<daemons>
- <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" />
+ <ant antfile="${uitest.dir}/vaadin-server.xml"
+ inheritall="true" inheritrefs="true" target="deploy-and-start" />
</daemons>
<sequential>
- <ant antfile="${uitest.dir}/integration_tests.xml" target="integration-test-all" inheritall="false" inheritrefs="false">
+ <ant antfile="${uitest.dir}/integration_tests.xml"
+ target="integration-test-all" inheritall="false"
+ inheritrefs="false">
<property name="demo.war" value="${war.file}" />
</ant>
</sequential>
@@ -210,36 +234,45 @@
</target>
<target name="test-tb2" depends="clean-testbench-errors">
- <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" />
+ <property name="war.file"
+ location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" />
<parallel>
<daemons>
- <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" />
+ <ant antfile="${uitest.dir}/vaadin-server.xml"
+ inheritall="true" inheritrefs="true" target="deploy-and-start" />
</daemons>
<sequential>
- <ant antfile="${uitest.dir}/vaadin-server.xml" target="wait-for-startup" />
+ <ant antfile="${uitest.dir}/vaadin-server.xml"
+ target="wait-for-startup" />
<ant antfile="${uitest.dir}/test.xml" target="tb2-tests" />
</sequential>
</parallel>
</target>
<target name="test-tb3" depends="clean-testbench-errors">
- <property name="war.file" location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" />
+ <property name="war.file"
+ location="${vaadin.basedir}/result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" />
<parallel>
<daemons>
- <ant antfile="${uitest.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" />
+ <ant antfile="${uitest.dir}/vaadin-server.xml"
+ inheritall="true" inheritrefs="true" target="deploy-and-start" />
</daemons>
<sequential>
- <ant antfile="${uitest.dir}/vaadin-server.xml" target="wait-for-startup" />
- <ant antfile="${uitest.dir}/tb3test.xml" target="run-all-tb3-tests" inheritall="true" />
+ <ant antfile="${uitest.dir}/vaadin-server.xml"
+ target="wait-for-startup" />
+ <ant antfile="${uitest.dir}/tb3test.xml" target="run-all-tb3-tests"
+ inheritall="true" />
</sequential>
</parallel>
</target>
<target name="clean-testbench-errors">
- <fail unless="com.vaadin.testbench.screenshot.directory" message="Define screenshot directory using -Dcom.vaadin.testbench.screenshot.directory" />
+ <fail unless="com.vaadin.testbench.screenshot.directory"
+ message="Define screenshot directory using -Dcom.vaadin.testbench.screenshot.directory" />
<mkdir dir="${com.vaadin.testbench.screenshot.directory}/errors" />
<delete>
- <fileset dir="${com.vaadin.testbench.screenshot.directory}/errors">
+ <fileset
+ dir="${com.vaadin.testbench.screenshot.directory}/errors">
<include name="*" />
</fileset>
</delete>
@@ -268,22 +301,28 @@
<param name="theme" value="tests-valo-blueprint" />
</antcall>
<antcall target="compile-theme">
- <param name="theme" value="tests-valo-light" />
+ <param name="theme" value="tests-valo-light" />
</antcall>
</target>
<target name="compile-theme" depends="copy-theme">
- <fail unless="theme" message="You must give the theme name to compile in the 'theme' parameter" />
+ <fail unless="theme"
+ message="You must give the theme name to compile in the 'theme' parameter" />
- <ivy:resolve log="download-only" resolveid="common" conf="compile-theme" />
- <ivy:cachepath pathid="classpath.compile.theme" conf="compile-theme" />
- <ivy:cachepath pathid="classpath.runtime.theme" conf="build" />
+ <ivy:resolve log="download-only" resolveid="common"
+ conf="compile-theme" />
+ <ivy:cachepath pathid="classpath.compile.theme"
+ conf="compile-theme" />
+ <ivy:cachepath pathid="classpath.runtime.theme"
+ conf="build" />
<echo>Compiling ${theme}</echo>
<mkdir dir="${theme.result.dir}" />
<!-- compile the theme -->
- <java classname="com.vaadin.buildhelpers.CompileTheme" classpathref="classpath.compile.theme" failonerror="yes" fork="yes" maxmemory="512m">
+ <java classname="com.vaadin.buildhelpers.CompileTheme"
+ classpathref="classpath.compile.theme" failonerror="yes"
+ fork="yes" maxmemory="512m">
<arg value="--theme" />
<arg value="${theme}" />
<arg value="--theme-folder" />
@@ -298,7 +337,8 @@
</target>
<target name="copy-theme">
- <fail unless="theme" message="You must give the theme name to copy n the 'theme' parameter" />
+ <fail unless="theme"
+ message="You must give the theme name to copy n the 'theme' parameter" />
<property name="theme.source.dir" location="../WebContent/VAADIN/themes" />
<copy todir="${theme.result.dir}">
diff --git a/uitest/src/com/vaadin/testbench/elements/GridElement.java b/uitest/src/com/vaadin/testbench/elements/GridElement.java
new file mode 100644
index 0000000000..0c94c1dd88
--- /dev/null
+++ b/uitest/src/com/vaadin/testbench/elements/GridElement.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testbench.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+
+/**
+ * TestBench Element API for Grid
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@ServerClass("com.vaadin.ui.Grid")
+public class GridElement extends AbstractComponentElement {
+
+ public static class GridCellElement extends AbstractElement {
+
+ private static final String FOCUSED_CELL_CLASS_NAME = "-cell-focused";
+ private static final String FROZEN_CLASS_NAME = "frozen";
+
+ public boolean isFocused() {
+ return getAttribute("class").contains(FOCUSED_CELL_CLASS_NAME);
+ }
+
+ public boolean isFrozen() {
+ return getAttribute("class").contains(FROZEN_CLASS_NAME);
+ }
+ }
+
+ public static class GridRowElement extends AbstractElement {
+
+ private static final String FOCUSED_CLASS_NAME = "-row-focused";
+ private static final String SELECTED_CLASS_NAME = "-row-selected";
+
+ public boolean isFocused() {
+ return getAttribute("class").contains(FOCUSED_CLASS_NAME);
+ }
+
+ @Override
+ public boolean isSelected() {
+ return getAttribute("class").contains(SELECTED_CLASS_NAME);
+ }
+ }
+
+ public static class GridEditorElement extends AbstractElement {
+
+ private GridElement grid;
+
+ private GridEditorElement setGrid(GridElement grid) {
+ this.grid = grid;
+ return this;
+ }
+
+ /**
+ * Gets the editor field for column in given index.
+ *
+ * @param colIndex
+ * column index
+ * @return the editor field for given location
+ */
+ public TestBenchElement getField(int colIndex) {
+ return grid.getSubPart("#editor[" + colIndex + "]");
+ }
+
+ /**
+ * Saves the fields of this editor.
+ * <p>
+ * <em>Note:</em> that this closes the editor making this element
+ * useless.
+ */
+ public void save() {
+ getField(0);
+ List<WebElement> buttons = findElements(By.xpath("./button"));
+ buttons.get(0).click();
+ }
+
+ /**
+ * Cancels this editor.
+ * <p>
+ * <em>Note:</em> that this closes the editor making this element
+ * useless.
+ */
+ public void cancel() {
+ getField(0);
+ List<WebElement> buttons = findElements(By.xpath("./button"));
+ buttons.get(1).click();
+ }
+ }
+
+ /**
+ * Scrolls Grid element so that wanted row is displayed
+ *
+ * @param index
+ * Target row
+ */
+ public void scrollToRow(int index) {
+ try {
+ getSubPart("#cell[" + index + "]");
+ } catch (NoSuchElementException e) {
+ // Expected, ignore it.
+ }
+ }
+
+ /**
+ * Gets cell element with given row and column index.
+ *
+ * @param rowIndex
+ * Row index
+ * @param colIndex
+ * Column index
+ * @return Cell element with given indices.
+ */
+ public GridCellElement getCell(int rowIndex, int colIndex) {
+ scrollToRow(rowIndex);
+ return getSubPart("#cell[" + rowIndex + "][" + colIndex + "]").wrap(
+ GridCellElement.class);
+ }
+
+ /**
+ * Gets row element with given row index.
+ *
+ * @param index
+ * Row index
+ * @return Row element with given index.
+ */
+ public GridRowElement getRow(int index) {
+ scrollToRow(index);
+ return getSubPart("#cell[" + index + "]").wrap(GridRowElement.class);
+ }
+
+ /**
+ * Gets header cell element with given row and column index.
+ *
+ * @param rowIndex
+ * Row index
+ * @param colIndex
+ * Column index
+ * @return Header cell element with given indices.
+ */
+ public GridCellElement getHeaderCell(int rowIndex, int colIndex) {
+ return getSubPart("#header[" + rowIndex + "][" + colIndex + "]").wrap(
+ GridCellElement.class);
+ }
+
+ /**
+ * Gets footer cell element with given row and column index.
+ *
+ * @param rowIndex
+ * Row index
+ * @param colIndex
+ * Column index
+ * @return Footer cell element with given indices.
+ */
+ public GridCellElement getFooterCell(int rowIndex, int colIndex) {
+ return getSubPart("#footer[" + rowIndex + "][" + colIndex + "]").wrap(
+ GridCellElement.class);
+ }
+
+ /**
+ * Gets list of header cell elements on given row.
+ *
+ * @param rowIndex
+ * Row index
+ * @return Header cell elements on given row.
+ */
+ public List<GridCellElement> getHeaderCells(int rowIndex) {
+ List<GridCellElement> headers = new ArrayList<GridCellElement>();
+ for (TestBenchElement e : TestBenchElement.wrapElements(
+ getSubPart("#header[" + rowIndex + "]").findElements(
+ By.xpath("./th")), getCommandExecutor())) {
+ headers.add(e.wrap(GridCellElement.class));
+ }
+ return headers;
+ }
+
+ /**
+ * Gets list of header cell elements on given row.
+ *
+ * @param rowIndex
+ * Row index
+ * @return Header cell elements on given row.
+ */
+ public List<GridCellElement> getFooterCells(int rowIndex) {
+ List<GridCellElement> footers = new ArrayList<GridCellElement>();
+ for (TestBenchElement e : TestBenchElement.wrapElements(
+ getSubPart("#footer[" + rowIndex + "]").findElements(
+ By.xpath("./td")), getCommandExecutor())) {
+ footers.add(e.wrap(GridCellElement.class));
+ }
+ return footers;
+ }
+
+ /**
+ * Get header row count
+ *
+ * @return Header row count
+ */
+ public int getHeaderCount() {
+ return getSubPart("#header").findElements(By.xpath("./tr")).size();
+ }
+
+ /**
+ * Get footer row count
+ *
+ * @return Footer row count
+ */
+ public int getFooterCount() {
+ return getSubPart("#footer").findElements(By.xpath("./tr")).size();
+ }
+
+ /**
+ * Get a header row by index
+ *
+ * @param rowIndex
+ * Row index
+ * @return The th element of the row
+ */
+ public WebElement getHeaderRow(int rowIndex) {
+ return getSubPart("#header[" + rowIndex + "]");
+ }
+
+ /**
+ * Get a footer row by index
+ *
+ * @param rowIndex
+ * Row index
+ * @return The tr element of the row
+ */
+ public WebElement getFooterRow(int rowIndex) {
+ return getSubPart("#footer[" + rowIndex + "]");
+ }
+
+ /**
+ * Get the vertical scroll element
+ *
+ * @return The element representing the vertical scrollbar
+ */
+ public WebElement getVerticalScroller() {
+ List<WebElement> rootElements = findElements(By.xpath("./div"));
+ return rootElements.get(0);
+ }
+
+ /**
+ * Get the horizontal scroll element
+ *
+ * @return The element representing the horizontal scrollbar
+ */
+ public WebElement getHorizontalScroller() {
+ List<WebElement> rootElements = findElements(By.xpath("./div"));
+ return rootElements.get(1);
+ }
+
+ /**
+ * Get the header element
+ *
+ * @return The thead element
+ */
+ public WebElement getHeader() {
+ return getSubPart("#header");
+ }
+
+ /**
+ * Get the body element
+ *
+ * @return the tbody element
+ */
+ public WebElement getBody() {
+ return getSubPart("#cell");
+ }
+
+ /**
+ * Get the footer element
+ *
+ * @return the tfoot element
+ */
+ public WebElement getFooter() {
+ return getSubPart("#footer");
+ }
+
+ /**
+ * Get the element wrapping the table element
+ *
+ * @return The element that wraps the table element
+ */
+ public WebElement getTableWrapper() {
+ List<WebElement> rootElements = findElements(By.xpath("./div"));
+ return rootElements.get(2);
+ }
+
+ public GridEditorElement getEditor() {
+ return getSubPart("#editor").wrap(GridEditorElement.class)
+ .setGrid(this);
+ }
+
+ /**
+ * Helper function to get Grid subparts wrapped correctly
+ *
+ * @param subPartSelector
+ * SubPart to be used in ComponentLocator
+ * @return SubPart element wrapped in TestBenchElement class
+ */
+ private TestBenchElement getSubPart(String subPartSelector) {
+ return (TestBenchElement) findElement(By.vaadin(subPartSelector));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java b/uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java
new file mode 100644
index 0000000000..cc5be455cd
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@SuppressWarnings("boxing")
+@TestCategory("grid")
+public abstract class AbstractGridColumnAutoWidthTest extends MultiBrowserTest {
+
+ public static final int TOTAL_MARGIN_PX = 13;
+
+ @Before
+ public void before() {
+ openTestURL();
+ }
+
+ @Test
+ public void testNarrowHeaderWideBody() {
+ WebElement[] col = getColumn(1);
+ int headerWidth = col[0].getSize().getWidth();
+ int bodyWidth = col[1].getSize().getWidth();
+ int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX;
+
+ assertLessThan("header should've been narrower than body", headerWidth,
+ bodyWidth);
+ assertEquals("column should've been roughly as wide as the body",
+ bodyWidth, colWidth, 5);
+ }
+
+ @Test
+ public void testWideHeaderNarrowBody() {
+ WebElement[] col = getColumn(2);
+ int headerWidth = col[0].getSize().getWidth();
+ int bodyWidth = col[1].getSize().getWidth();
+ int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX;
+
+ assertGreater("header should've been wider than body", headerWidth,
+ bodyWidth);
+ assertEquals("column should've been roughly as wide as the header",
+ headerWidth, colWidth, 5);
+
+ }
+
+ @Test
+ public void testTooNarrowColumn() {
+ if (BrowserUtil.isIE(getDesiredCapabilities())) {
+ // IE can't deal with overflow nicely.
+ return;
+ }
+
+ WebElement[] col = getColumn(3);
+ int headerWidth = col[0].getSize().getWidth();
+ int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX;
+
+ assertLessThan("column should've been narrower than content", colWidth,
+ headerWidth);
+ }
+
+ @Test
+ public void testTooWideColumn() {
+ WebElement[] col = getColumn(4);
+ int headerWidth = col[0].getSize().getWidth();
+ int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX;
+
+ assertGreater("column should've been wider than content", colWidth,
+ headerWidth);
+ }
+
+ @Test
+ public void testColumnsRenderCorrectly() throws IOException {
+ compareScreen("initialRender");
+ }
+
+ private WebElement[] getColumn(int i) {
+ WebElement[] col = new WebElement[3];
+ col[0] = getDriver().findElement(
+ By.xpath("//thead//th[" + (i + 1) + "]/span"));
+ col[1] = getDriver().findElement(
+ By.xpath("//tbody//td[" + (i + 1) + "]/span"));
+ col[2] = getDriver().findElement(
+ By.xpath("//tbody//td[" + (i + 1) + "]"));
+ return col;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java b/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java
new file mode 100644
index 0000000000..f7d14bbff6
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.Label;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class CustomRenderer extends AbstractTestUI {
+
+ private static final Object INT_ARRAY_PROPERTY = "int array";
+ private static final Object VOID_PROPERTY = "void";
+
+ static final Object ITEM_ID = "itemId1";
+ static final String DEBUG_LABEL_ID = "debuglabel";
+ static final String INIT_DEBUG_LABEL_CAPTION = "Debug label placeholder";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ IndexedContainer container = new IndexedContainer();
+ container.addContainerProperty(INT_ARRAY_PROPERTY, int[].class,
+ new int[] {});
+ container.addContainerProperty(VOID_PROPERTY, Void.class, null);
+
+ Item item = container.addItem(ITEM_ID);
+
+ @SuppressWarnings("unchecked")
+ Property<int[]> propertyIntArray = item
+ .getItemProperty(INT_ARRAY_PROPERTY);
+ propertyIntArray.setValue(new int[] { 1, 1, 2, 3, 5, 8, 13 });
+
+ Label debugLabel = new Label(INIT_DEBUG_LABEL_CAPTION);
+ debugLabel.setId(DEBUG_LABEL_ID);
+
+ Grid grid = new Grid(container);
+ grid.getColumn(INT_ARRAY_PROPERTY).setRenderer(new IntArrayRenderer());
+ grid.getColumn(VOID_PROPERTY).setRenderer(
+ new RowAwareRenderer(debugLabel));
+ grid.setSelectionMode(SelectionMode.NONE);
+ addComponent(grid);
+ addComponent(debugLabel);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Verifies that renderers operating on other data than "
+ + "just Strings also work ";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(13334);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java b/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java
new file mode 100644
index 0000000000..1c00574f9c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class CustomRendererTest extends MultiBrowserTest {
+ @Test
+ public void testIntArrayIsRendered() throws Exception {
+ openTestURL();
+
+ GridElement grid = findGrid();
+ assertEquals("1 :: 1 :: 2 :: 3 :: 5 :: 8 :: 13", grid.getCell(0, 0)
+ .getText());
+ }
+
+ @Test
+ public void testRowAwareRenderer() throws Exception {
+ openTestURL();
+
+ GridElement grid = findGrid();
+ assertEquals("Click me!", grid.getCell(0, 1).getText());
+ assertEquals(CustomRenderer.INIT_DEBUG_LABEL_CAPTION, findDebugLabel()
+ .getText());
+
+ grid.getCell(0, 1).click();
+ assertEquals("row: 0, key: 0", grid.getCell(0, 1).getText());
+ assertEquals("key: 0, itemId: " + CustomRenderer.ITEM_ID,
+ findDebugLabel().getText());
+ }
+
+ private GridElement findGrid() {
+ List<GridElement> elements = $(GridElement.class).all();
+ return elements.get(0);
+ }
+
+ private LabelElement findDebugLabel() {
+ return $(LabelElement.class).id(CustomRenderer.DEBUG_LABEL_ID);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInit.java b/uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInit.java
new file mode 100644
index 0000000000..36d92d79a0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInit.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Container.Indexed;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+
+public class GridAddAndRemoveDataOnInit extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid gridAdd = new Grid();
+ gridAdd.setHeight("240px");
+ gridAdd.setWidth("140px");
+ addComponent(gridAdd);
+ Indexed dataSource = gridAdd.getContainerDataSource();
+ dataSource.addContainerProperty("foo", Integer.class, 0);
+ for (int i = 0; i < 10; ++i) {
+ Object id = dataSource.addItem();
+ dataSource.getItem(id).getItemProperty("foo").setValue(i);
+ }
+ dataSource = new IndexedContainer();
+ dataSource.addContainerProperty("bar", Integer.class, 0);
+ for (int i = 0; i < 10; ++i) {
+ Object id = dataSource.addItem();
+ dataSource.getItem(id).getItemProperty("bar").setValue(i);
+ }
+ Grid gridRemove = new Grid(dataSource);
+ gridRemove.setHeight("150px");
+ gridRemove.setWidth("140px");
+ addComponent(gridRemove);
+ for (int i = 0; i < 5; ++i) {
+ dataSource.removeItem(dataSource.getIdByIndex(i));
+ }
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Foo";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 13334;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInitTest.java b/uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInitTest.java
new file mode 100644
index 0000000000..ceaceb661d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridAddAndRemoveDataOnInitTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridAddAndRemoveDataOnInitTest extends MultiBrowserTest {
+
+ @Test
+ public void verifyGridSizes() {
+ openTestURL();
+
+ GridElement gridAdd = $(GridElement.class).first();
+ if (!gridAdd.isElementPresent(By.vaadin("#cell[9][0]"))
+ || gridAdd.isElementPresent(By.vaadin("#cell[10][0]"))) {
+ Assert.fail("Grid with added data contained incorrect rows");
+ }
+
+ GridElement gridRemove = $(GridElement.class).get(1);
+ if (!gridRemove.isElementPresent(By.vaadin("#cell[4][0]"))
+ || gridRemove.isElementPresent(By.vaadin("#cell[5][0]"))) {
+ Assert.fail("Grid with removed data contained incorrect rows");
+ }
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridAddRow.java b/uitest/src/com/vaadin/tests/components/grid/GridAddRow.java
new file mode 100644
index 0000000000..fa2d7b5399
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridAddRow.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+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.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+
+public class GridAddRow extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ final Grid grid = new Grid();
+ grid.setSelectionMode(SelectionMode.MULTI);
+ grid.addColumn("firstName");
+ grid.addColumn("age", Integer.class);
+
+ grid.addRow("Lorem", Integer.valueOf(1));
+ grid.addRow("Ipsum", Integer.valueOf(2));
+
+ addComponent(grid);
+
+ addComponent(new Button("Add new row", new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.addRow("Dolor", Integer.valueOf(3));
+ }
+ }));
+
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridAddRowTest.java b/uitest/src/com/vaadin/tests/components/grid/GridAddRowTest.java
new file mode 100644
index 0000000000..46f085686d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridAddRowTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridAddRowTest extends MultiBrowserTest {
+ @Test
+ public void testAddRow() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+
+ Assert.assertEquals("Lorem", grid.getCell(0, 1).getText());
+ Assert.assertEquals("2", grid.getCell(1, 2).getText());
+
+ addRow();
+
+ Assert.assertEquals("Dolor", grid.getCell(2, 1).getText());
+
+ addRow();
+
+ Assert.assertEquals("Dolor", grid.getCell(3, 1).getText());
+ }
+
+ private void addRow() {
+ $(ButtonElement.class).caption("Add new row").first().click();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java b/uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java
new file mode 100644
index 0000000000..00db02bef3
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.NativeButtonElement;
+import com.vaadin.testbench.elements.NativeSelectElement;
+import com.vaadin.testbench.elements.ServerClass;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererConnector.Renderers;
+import com.vaadin.tests.widgetset.server.grid.GridClientColumnRenderers;
+
+/**
+ * Tests Grid client side renderers
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@TestCategory("grid")
+public class GridClientRenderers extends MultiBrowserTest {
+
+ private static final double SLEEP_MULTIPLIER = 1.2;
+ private int latency = 0;
+
+ @Override
+ protected Class<?> getUIClass() {
+ return GridClientColumnRenderers.class;
+ }
+
+ @Override
+ protected String getDeploymentPath() {
+ String path = super.getDeploymentPath();
+ if (latency > 0) {
+ path += (path.contains("?") ? "&" : "?") + "latency=" + latency;
+ }
+ return path;
+ }
+
+ @ServerClass("com.vaadin.tests.widgetset.server.grid.GridClientColumnRenderers.GridController")
+ public static class MyClientGridElement extends GridElement {
+ }
+
+ @Override
+ public void setup() throws Exception {
+ latency = 0; // reset
+ super.setup();
+ }
+
+ @Test
+ public void addWidgetRenderer() throws Exception {
+ openTestURL();
+
+ // Add widget renderer column
+ $(NativeSelectElement.class).first().selectByText(
+ Renderers.WIDGET_RENDERER.toString());
+ $(NativeButtonElement.class).caption("Add").first().click();
+
+ // Click the button in cell 1,1
+ TestBenchElement cell = getGrid().getCell(1, 2);
+ WebElement gwtButton = cell.findElement(By.tagName("button"));
+ gwtButton.click();
+
+ // Should be an alert visible
+ assertEquals("Button did not contain text \"Clicked\"", "Clicked",
+ gwtButton.getText());
+ }
+
+ @Test
+ public void detachAndAttachGrid() {
+ openTestURL();
+
+ // Add widget renderer column
+ $(NativeSelectElement.class).first().selectByText(
+ Renderers.WIDGET_RENDERER.toString());
+ $(NativeButtonElement.class).caption("Add").first().click();
+
+ // Detach and re-attach the Grid
+ $(NativeButtonElement.class).caption("DetachAttach").first().click();
+
+ // Click the button in cell 1,1
+ TestBenchElement cell = getGrid().getCell(1, 2);
+ WebElement gwtButton = cell.findElement(By.tagName("button"));
+ gwtButton.click();
+
+ // Should be an alert visible
+ assertEquals("Button did not contain text \"Clicked\"",
+ gwtButton.getText(), "Clicked");
+ }
+
+ @Test
+ public void rowsWithDataHasStyleName() throws Exception {
+
+ testBench().disableWaitForVaadin();
+
+ // Simulate network latency with 2000ms
+ latency = 2000;
+
+ openTestURL();
+
+ sleep((int) (latency * SLEEP_MULTIPLIER));
+
+ TestBenchElement row = getGrid().getRow(51);
+ String className = row.getAttribute("class");
+ assertFalse(
+ "Row should not yet contain style name v-grid-row-has-data",
+ className.contains("v-grid-row-has-data"));
+
+ // Wait for data to arrive
+ sleep((int) (latency * SLEEP_MULTIPLIER));
+
+ row = getGrid().getRow(51);
+ className = row.getAttribute("class");
+ assertTrue("Row should now contain style name v-grid-row-has-data",
+ className.contains("v-grid-row-has-data"));
+ }
+
+ @Test
+ public void complexRendererSetVisibleContent() throws Exception {
+
+ DesiredCapabilities desiredCapabilities = getDesiredCapabilities();
+
+ // Simulate network latency with 2000ms
+ latency = 2000;
+ if (BrowserUtil.isIE8(desiredCapabilities)) {
+ // IE8 is slower than other browsers. Bigger latency is needed for
+ // stability in this test.
+ latency = 3000;
+ }
+
+ // Chrome uses RGB instead of RGBA
+ String colorRed = "rgba(255, 0, 0, 1)";
+ String colorWhite = "rgba(255, 255, 255, 1)";
+ String colorDark = "rgba(239, 240, 241, 1)";
+ if (BrowserUtil.isChrome(desiredCapabilities)) {
+ colorRed = "rgb(255, 0, 0)";
+ colorWhite = "rgb(255, 255, 255)";
+ colorDark = "rgb(239, 240, 241)";
+ }
+
+ openTestURL();
+
+ getGrid();
+
+ testBench().disableWaitForVaadin();
+
+ // Test initial renderering with contentVisible = False
+ TestBenchElement cell = getGrid().getCell(51, 1);
+ String backgroundColor = cell.getCssValue("backgroundColor");
+ assertEquals("Background color was not red.", colorRed, backgroundColor);
+
+ // data arrives...
+ sleep((int) (latency * SLEEP_MULTIPLIER));
+
+ // Content becomes visible
+ cell = getGrid().getCell(51, 1);
+ backgroundColor = cell.getCssValue("backgroundColor");
+ assertNotEquals("Background color was red.", colorRed, backgroundColor);
+
+ // scroll down, new cells becomes contentVisible = False
+ getGrid().scrollToRow(60);
+
+ // Cell should be red (setContentVisible set cell red)
+ cell = getGrid().getCell(55, 1);
+ backgroundColor = cell.getCssValue("backgroundColor");
+ assertEquals("Background color was not red.", colorRed, backgroundColor);
+
+ // data arrives...
+ sleep((int) (latency * SLEEP_MULTIPLIER));
+
+ // Cell should no longer be red
+ backgroundColor = cell.getCssValue("backgroundColor");
+ assertTrue(
+ "Background color was not reset",
+ backgroundColor.equals(colorWhite)
+ || backgroundColor.equals(colorDark));
+ }
+
+ @Test
+ public void testSortingEvent() throws Exception {
+ openTestURL();
+
+ $(NativeButtonElement.class).caption("Trigger sorting event").first()
+ .click();
+
+ String consoleText = $(LabelElement.class).id("testDebugConsole")
+ .getText();
+
+ assertTrue("Console text as expected",
+ consoleText.contains("Columns: 1, order: Column 1: ASCENDING"));
+
+ }
+
+ @Test
+ public void testListSorter() throws Exception {
+ openTestURL();
+
+ $(NativeButtonElement.class).caption("Shuffle").first().click();
+
+ GridElement gridElem = $(MyClientGridElement.class).first();
+
+ // XXX: DANGER! We'll need to know how many rows the Grid has!
+ // XXX: Currently, this is impossible; hence the hardcoded value of 70.
+
+ boolean shuffled = false;
+ for (int i = 1, l = 70; i < l; ++i) {
+
+ String str_a = gridElem.getCell(i - 1, 0).getAttribute("innerHTML");
+ String str_b = gridElem.getCell(i, 0).getAttribute("innerHTML");
+
+ int value_a = Integer.parseInt(str_a);
+ int value_b = Integer.parseInt(str_b);
+
+ if (value_a > value_b) {
+ shuffled = true;
+ break;
+ }
+ }
+ assertTrue("Grid shuffled", shuffled);
+
+ $(NativeButtonElement.class).caption("Test sorting").first().click();
+
+ for (int i = 1, l = 70; i < l; ++i) {
+
+ String str_a = gridElem.getCell(i - 1, 0).getAttribute("innerHTML");
+ String str_b = gridElem.getCell(i, 0).getAttribute("innerHTML");
+
+ int value_a = Integer.parseInt(str_a);
+ int value_b = Integer.parseInt(str_b);
+
+ if (value_a > value_b) {
+ assertTrue("Grid sorted", false);
+ }
+ }
+ }
+
+ @Test
+ public void testComplexRendererOnActivate() {
+ openTestURL();
+
+ GridCellElement cell = getGrid().getCell(3, 1);
+ cell.click();
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+
+ assertEquals("onActivate was not called on KeyDown Enter.",
+ "Activated!", cell.getText());
+
+ cell = getGrid().getCell(4, 1);
+ cell.click();
+ new Actions(getDriver()).moveToElement(cell).doubleClick().perform();
+ assertEquals("onActivate was not called on double click.",
+ "Activated!", cell.getText());
+ }
+
+ private GridElement getGrid() {
+ return $(MyClientGridElement.class).first();
+ }
+
+ private void addColumn(Renderers renderer) {
+ // Add widget renderer column
+ $(NativeSelectElement.class).first().selectByText(renderer.toString());
+ $(NativeButtonElement.class).caption("Add").first().click();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColspans.java b/uitest/src/com/vaadin/tests/components/grid/GridColspans.java
new file mode 100644
index 0000000000..80337971b6
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColspans.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Container.Indexed;
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+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.Grid;
+import com.vaadin.ui.Grid.FooterRow;
+import com.vaadin.ui.Grid.HeaderRow;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.renderer.NumberRenderer;
+
+public class GridColspans extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Indexed dataSource = new IndexedContainer();
+ final Grid grid;
+
+ dataSource.addContainerProperty("firstName", String.class, "");
+ dataSource.addContainerProperty("lastName", String.class, "");
+ dataSource.addContainerProperty("streetAddress", String.class, "");
+ dataSource.addContainerProperty("zipCode", Integer.class, null);
+ dataSource.addContainerProperty("city", String.class, "");
+ Item i = dataSource.addItem(0);
+ i.getItemProperty("firstName").setValue("Rudolph");
+ i.getItemProperty("lastName").setValue("Reindeer");
+ i.getItemProperty("streetAddress").setValue("Ruukinkatu 2-4");
+ i.getItemProperty("zipCode").setValue(20540);
+ i.getItemProperty("city").setValue("Turku");
+ grid = new Grid(dataSource);
+ grid.setWidth("600px");
+ grid.getColumn("zipCode").setRenderer(new NumberRenderer());
+ grid.setSelectionMode(SelectionMode.MULTI);
+ addComponent(grid);
+
+ HeaderRow row = grid.prependHeaderRow();
+ row.join("firstName", "lastName").setText("Full Name");
+ row.join("streetAddress", "zipCode", "city").setText("Address");
+ grid.prependHeaderRow()
+ .join(dataSource.getContainerPropertyIds().toArray())
+ .setText("All the stuff");
+
+ FooterRow footerRow = grid.appendFooterRow();
+ footerRow.join("firstName", "lastName").setText("Full Name");
+ footerRow.join("streetAddress", "zipCode", "city").setText("Address");
+ grid.appendFooterRow()
+ .join(dataSource.getContainerPropertyIds().toArray())
+ .setText("All the stuff");
+
+ addComponent(new Button("Show/Hide firstName",
+ new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (grid.getColumn("firstName") != null) {
+ grid.removeColumn("firstName");
+ } else {
+ grid.addColumn("firstName");
+ }
+ }
+ }));
+
+ addComponent(new Button("Change column order",
+ new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.setColumnOrder("zipCode", "firstName");
+ }
+ }));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Grid header and footer colspans";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 13334;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
new file mode 100644
index 0000000000..6b50b64732
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridColspansTest extends MultiBrowserTest {
+
+ @Before
+ public void setUp() {
+ setDebug(true);
+ }
+
+ @Test
+ public void testHeaderColSpans() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ assertEquals("5", grid.getHeaderCell(0, 1).getAttribute("colspan"));
+ assertEquals("2", grid.getHeaderCell(1, 1).getAttribute("colspan"));
+ assertEquals("3", grid.getHeaderCell(1, 3).getAttribute("colspan"));
+ }
+
+ @Test
+ public void testFooterColSpans() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ assertEquals("5", grid.getFooterCell(1, 1).getAttribute("colspan"));
+ assertEquals("2", grid.getFooterCell(0, 1).getAttribute("colspan"));
+ assertEquals("3", grid.getFooterCell(0, 3).getAttribute("colspan"));
+ }
+
+ @Test
+ public void testHideFirstColumnOfColspan() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ assertEquals("Failed initial condition.", "all the stuff", grid
+ .getHeaderCell(0, 1).getText().toLowerCase());
+ assertEquals("Failed initial condition.", "first name", grid
+ .getHeaderCell(2, 1).getText().toLowerCase());
+ $(ButtonElement.class).caption("Show/Hide firstName").first().click();
+ assertEquals("Header text changed on column hide.", "all the stuff",
+ grid.getHeaderCell(0, 1).getText().toLowerCase());
+ assertEquals("Failed initial condition.", "last name", grid
+ .getHeaderCell(2, 1).getText().toLowerCase());
+ }
+
+ @Test
+ public void testSplittingMergedHeaders() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ GridCellElement headerCell = grid.getHeaderCell(1, 1);
+ assertEquals("Failed initial condition.", "full name", headerCell
+ .getText().toLowerCase());
+ assertEquals("Failed initial condition.", "first name", grid
+ .getHeaderCell(2, 1).getText().toLowerCase());
+ $(ButtonElement.class).get(1).click();
+ headerCell = grid.getHeaderCell(1, 1);
+ assertEquals("Header text not changed on column reorder.", "address",
+ headerCell.getText().toLowerCase());
+ assertEquals("Unexpected colspan", "1",
+ headerCell.getAttribute("colspan"));
+ headerCell = grid.getHeaderCell(1, 2);
+ assertEquals("Header text not changed on column reorder", "full name",
+ headerCell.getText().toLowerCase());
+ assertEquals("Unexpected colspan", "2",
+ headerCell.getAttribute("colspan"));
+
+ assertTrue("Error indicator not present",
+ isElementPresent(By.className("v-errorindicator")));
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidth.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidth.java
new file mode 100644
index 0000000000..98fa1ab6fd
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidth.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.renderer.HtmlRenderer;
+
+public class GridColumnAutoWidth extends AbstractTestUI {
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid grid = new Grid(createContainer());
+ grid.getColumn("fixed width narrow").setWidth(50);
+ grid.getColumn("fixed width wide").setWidth(200);
+
+ for (Object propertyId : grid.getContainerDataSource()
+ .getContainerPropertyIds()) {
+ Column column = grid.getColumn(propertyId);
+ column.setExpandRatio(0);
+ column.setRenderer(new HtmlRenderer());
+ grid.getHeaderRow(0).getCell(propertyId)
+ .setHtml("<span>" + column.getHeaderCaption() + "</span>");
+ }
+
+ grid.setSelectionMode(SelectionMode.NONE);
+ grid.setWidth("700px");
+ addComponent(grid);
+ }
+
+ private static Container.Indexed createContainer() {
+ IndexedContainer c = new IndexedContainer();
+ c.addContainerProperty("equal width", String.class,
+ "<span>equal width</span>");
+ c.addContainerProperty("short", String.class,
+ "<span>a very long cell content</span>");
+ c.addContainerProperty("a very long header content", String.class,
+ "<span>short</span>");
+ c.addContainerProperty("fixed width narrow", String.class,
+ "<span>fixed width narrow</span>");
+ c.addContainerProperty("fixed width wide", String.class,
+ "<span>fixed width wide</span>");
+ c.addItem();
+ return c;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClient.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClient.java
new file mode 100644
index 0000000000..0829e09de9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClient.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.GridColumnAutoWidthClientWidget;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class GridColumnAutoWidthClient extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ addComponent(new TestWidgetComponent(
+ GridColumnAutoWidthClientWidget.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClientTest.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClientTest.java
new file mode 100644
index 0000000000..dcc14a967d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.tests.annotations.TestCategory;
+
+@TestCategory("grid")
+public class GridColumnAutoWidthClientTest extends
+ AbstractGridColumnAutoWidthTest {
+ @Override
+ protected Class<?> getUIClass() {
+ return GridColumnAutoWidthClient.class;
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthServerTest.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthServerTest.java
new file mode 100644
index 0000000000..2f42b89eb1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColumnAutoWidthServerTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.tests.annotations.TestCategory;
+
+@TestCategory("grid")
+public class GridColumnAutoWidthServerTest extends
+ AbstractGridColumnAutoWidthTest {
+ @Override
+ protected Class<?> getUIClass() {
+ return GridColumnAutoWidth.class;
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnExpand.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnExpand.java
new file mode 100644
index 0000000000..f8338f991a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColumnExpand.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.util.PersonContainer;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.themes.Reindeer;
+
+@Theme(Reindeer.THEME_NAME)
+public class GridColumnExpand extends AbstractTestUI {
+ private Grid grid;
+ private Label firstInfo = new Label();
+ private Label secondInfo = new Label();
+ private Column firstColumn;
+ private Column secondColumn;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ grid = new Grid(PersonContainer.createWithTestData());
+ grid.removeAllColumns();
+ grid.addColumn("address.streetAddress");
+ grid.addColumn("lastName");
+ firstColumn = grid.getColumns().get(0);
+ secondColumn = grid.getColumns().get(1);
+
+ updateInfoLabels();
+ addComponent(grid);
+ addComponent(firstInfo);
+ addComponent(secondInfo);
+ addButtons();
+ }
+
+ private void addButtons() {
+ HorizontalLayout layout = new HorizontalLayout();
+ layout.addComponent(createButtons(firstColumn));
+ layout.addComponent(createButtons(secondColumn));
+ layout.setExpandRatio(layout.getComponent(1), 1);
+ addComponent(layout);
+ }
+
+ private Component createButtons(Column column) {
+ CssLayout layout = new CssLayout();
+ layout.addComponent(new Label("Column 1"));
+
+ CssLayout widthLayout = new CssLayout();
+ layout.addComponent(widthLayout);
+ widthLayout.addComponent(new Label("Width"));
+ widthLayout.addComponent(createWidthButton(column, -1));
+ widthLayout.addComponent(createWidthButton(column, 50));
+ widthLayout.addComponent(createWidthButton(column, 200));
+
+ CssLayout minLayout = new CssLayout();
+ layout.addComponent(minLayout);
+ minLayout.addComponent(new Label("Min width"));
+ minLayout.addComponent(createMinButton(column, -1));
+ minLayout.addComponent(createMinButton(column, 50));
+ minLayout.addComponent(createMinButton(column, 200));
+
+ CssLayout maxLayout = new CssLayout();
+ maxLayout.addComponent(new Label("Max width"));
+ maxLayout.addComponent(createMaxButton(column, -1));
+ maxLayout.addComponent(createMaxButton(column, 50));
+ maxLayout.addComponent(createMaxButton(column, 200));
+ layout.addComponent(maxLayout);
+
+ CssLayout expandLayout = new CssLayout();
+ expandLayout.addComponent(new Label("Expand ratio"));
+ expandLayout.addComponent(createExpandButton(column, -1));
+ expandLayout.addComponent(createExpandButton(column, 0));
+ expandLayout.addComponent(createExpandButton(column, 1));
+ expandLayout.addComponent(createExpandButton(column, 2));
+ layout.addComponent(expandLayout);
+
+ return layout;
+ }
+
+ private Component createWidthButton(final Column column, final double width) {
+ return new Button("" + width, new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (width >= 0) {
+ column.setWidth(width);
+ } else {
+ column.setWidthUndefined();
+ }
+ updateInfoLabels();
+ }
+ });
+ }
+
+ private Component createMinButton(final Column column, final double width) {
+ return new Button("" + width, new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ column.setMinimumWidth(width);
+ updateInfoLabels();
+ }
+ });
+ }
+
+ private Component createMaxButton(final Column column, final double width) {
+ return new Button("" + width, new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ column.setMaximumWidth(width);
+ updateInfoLabels();
+ }
+ });
+ }
+
+ private Component createExpandButton(final Column column, final int ratio) {
+ return new Button("" + ratio, new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ column.setExpandRatio(ratio);
+ updateInfoLabels();
+ }
+ });
+ }
+
+ private void updateInfoLabels() {
+ updateLabel(firstInfo, firstColumn);
+ updateLabel(secondInfo, secondColumn);
+ }
+
+ private void updateLabel(Label label, Column column) {
+ int expandRatio = column.getExpandRatio();
+ double minimumWidth = Math.round(column.getMinimumWidth() * 100) / 100;
+ double maximumWidth = Math.round(column.getMaximumWidth() * 100) / 100;
+ double width = Math.round(column.getWidth() * 100) / 100;
+ Object propertyId = column.getPropertyId();
+ label.setValue(String.format(
+ "[%s] Expand ratio: %s - min: %s - max: %s - width: %s",
+ propertyId, expandRatio, minimumWidth, maximumWidth, width));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridEditorUI.java b/uitest/src/com/vaadin/tests/components/grid/GridEditorUI.java
new file mode 100644
index 0000000000..fe4b4342a2
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridEditorUI.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.util.PersonContainer;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.PasswordField;
+import com.vaadin.ui.TextField;
+
+public class GridEditorUI extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ PersonContainer container = PersonContainer.createWithTestData();
+
+ Grid grid = new Grid(container);
+
+ // Don't use address since there's no converter
+ grid.removeColumn("address");
+
+ grid.setEditorEnabled(true);
+
+ grid.setEditorField("firstName", new PasswordField());
+
+ TextField lastNameField = (TextField) grid
+ .getEditorField("lastName");
+ lastNameField.setMaxLength(50);
+
+ grid.getEditorField("phoneNumber").setReadOnly(true);
+
+ addComponent(grid);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridEditorUITest.java b/uitest/src/com/vaadin/tests/components/grid/GridEditorUITest.java
new file mode 100644
index 0000000000..6c386eec03
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridEditorUITest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.testbench.elements.PasswordFieldElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridEditorUITest extends MultiBrowserTest {
+
+ @Test
+ public void testEditor() {
+ setDebug(true);
+ openTestURL();
+
+ assertFalse("Sanity check",
+ isElementPresent(PasswordFieldElement.class));
+
+ openEditor(5);
+ new Actions(getDriver()).sendKeys(Keys.ESCAPE).perform();
+
+ openEditor(10);
+
+ assertTrue("Edtor should be opened with a password field",
+ isElementPresent(PasswordFieldElement.class));
+
+ assertFalse("Notification was present",
+ isElementPresent(NotificationElement.class));
+ }
+
+ private void openEditor(int rowIndex) {
+ GridElement grid = $(GridElement.class).first();
+
+ GridCellElement cell = grid.getCell(rowIndex, 1);
+
+ new Actions(driver).moveToElement(cell).doubleClick().build().perform();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridGeneratedProperties.java b/uitest/src/com/vaadin/tests/components/grid/GridGeneratedProperties.java
new file mode 100644
index 0000000000..2782a5fc6c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridGeneratedProperties.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Container.Filter;
+import com.vaadin.data.Container.Filterable;
+import com.vaadin.data.Container.Indexed;
+import com.vaadin.data.Item;
+import com.vaadin.data.sort.Sort;
+import com.vaadin.data.sort.SortOrder;
+import com.vaadin.data.util.GeneratedPropertyContainer;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.data.util.PropertyValueGenerator;
+import com.vaadin.data.util.filter.Compare;
+import com.vaadin.data.util.filter.UnsupportedFilterException;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.data.sort.SortDirection;
+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.Grid;
+
+public class GridGeneratedProperties extends AbstractTestUI {
+
+ private GeneratedPropertyContainer container;
+ static double MILES_CONVERSION = 0.6214d;
+ private Filter filter = new Compare.Greater("miles", 1d);
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ container = new GeneratedPropertyContainer(createContainer());
+ Grid grid = new Grid(container);
+ addComponent(grid);
+
+ container.addGeneratedProperty("miles",
+ new PropertyValueGenerator<Double>() {
+
+ @Override
+ public Double getValue(Item item, Object itemId,
+ Object propertyId) {
+ return (Double) item.getItemProperty("km").getValue()
+ * MILES_CONVERSION;
+ }
+
+ @Override
+ public Class<Double> getType() {
+ return Double.class;
+ }
+
+ @Override
+ public Filter modifyFilter(Filter filter)
+ throws UnsupportedFilterException {
+ if (filter instanceof Compare.Greater) {
+ Double value = (Double) ((Compare.Greater) filter)
+ .getValue();
+ value = value / MILES_CONVERSION;
+ return new Compare.Greater("km", value);
+ }
+ return super.modifyFilter(filter);
+ }
+ });
+
+ final Button filterButton = new Button("Add filter");
+ filterButton.addClickListener(new ClickListener() {
+
+ boolean active = false;
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if (active) {
+ ((Filterable) container).removeContainerFilter(filter);
+ filterButton.setCaption("Add filter");
+ active = false;
+ return;
+ }
+ ((Filterable) container).addContainerFilter(filter);
+ filterButton.setCaption("Remove filter");
+ active = true;
+ }
+ });
+
+ container.addGeneratedProperty("foo",
+ new PropertyValueGenerator<String>() {
+
+ @Override
+ public String getValue(Item item, Object itemId,
+ Object propertyId) {
+ return item.getItemProperty("foo").getValue() + " "
+ + item.getItemProperty("bar").getValue();
+ }
+
+ @Override
+ public Class<String> getType() {
+ return String.class;
+ }
+ });
+ container.removeContainerProperty("bar");
+ container.addGeneratedProperty("baz",
+ new PropertyValueGenerator<Integer>() {
+
+ @Override
+ public Integer getValue(Item item, Object itemId,
+ Object propertyId) {
+ return (Integer) item.getItemProperty("bar").getValue();
+ }
+
+ @Override
+ public Class<Integer> getType() {
+ return Integer.class;
+ }
+
+ @Override
+ public SortOrder[] getSortProperties(SortOrder order) {
+ return Sort.by("bar", order.getDirection()).build()
+ .toArray(new SortOrder[1]);
+ }
+ });
+
+ addComponent(filterButton);
+ grid.sort(Sort.by("km").then("bar", SortDirection.DESCENDING));
+ }
+
+ private Indexed createContainer() {
+ Indexed container = new IndexedContainer();
+ container.addContainerProperty("foo", String.class, "foo");
+ container.addContainerProperty("bar", Integer.class, 0);
+ // km contains double values from 0.0 to 2.0
+ container.addContainerProperty("km", Double.class, 0);
+
+ for (int i = 0; i <= 100; ++i) {
+ Object itemId = container.addItem();
+ Item item = container.getItem(itemId);
+ item.getItemProperty("foo").setValue("foo");
+ item.getItemProperty("bar").setValue(i);
+ item.getItemProperty("km").setValue(i / 5.0d);
+ }
+
+ return container;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "A Grid with GeneratedPropertyContainer";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 13334;
+ }
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridGeneratedPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/GridGeneratedPropertiesTest.java
new file mode 100644
index 0000000000..ffcd4c448f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridGeneratedPropertiesTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridGeneratedPropertiesTest extends MultiBrowserTest {
+
+ @Test
+ public void testMilesColumnExists() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+ assertEquals("Miles header wasn't present.", "miles", grid
+ .getHeaderCell(0, 2).getText().toLowerCase());
+ }
+
+ @Test
+ public void testUnsortableGeneratedProperty() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+
+ // Overwritten foo property should not be sortable
+ GridCellElement fooHeader = grid.getHeaderCell(0, 0);
+ fooHeader.click();
+ assertFalse("Column foo was unexpectedly sorted.", fooHeader
+ .getAttribute("class").contains("sort"));
+
+ // Generated property miles is not sortable
+ GridCellElement milesHeader = grid.getHeaderCell(0, 2);
+ milesHeader.click();
+ assertFalse("Column miles was unexpectedly sorted.", milesHeader
+ .getAttribute("class").contains("sort"));
+ }
+
+ @Test
+ public void testSortableGeneratedProperty() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+
+ // Generated property baz is sortable
+ GridCellElement bazHeader = grid.getHeaderCell(0, 3);
+ bazHeader.click();
+ assertTrue("Column baz was not sorted ascending", bazHeader
+ .getAttribute("class").contains("sort-asc"));
+ bazHeader.click();
+ assertTrue("Column baz was not sorted descending", bazHeader
+ .getAttribute("class").contains("sort-desc"));
+ }
+
+ @Test
+ public void testInitialSorting() {
+ // Grid is sorted in this case by one visible and one nonexistent
+ // column. There should be no sort indicator.
+ setDebug(true);
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+
+ GridCellElement kmHeader = grid.getHeaderCell(0, 1);
+ assertFalse("Column km was unexpectedly sorted",
+ kmHeader.getAttribute("class").contains("sort-asc")
+ || kmHeader.getAttribute("class").contains("sort-desc"));
+ assertFalse("Unexpected client-side exception was visible",
+ isElementPresent(NotificationElement.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNames.java b/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNames.java
new file mode 100644
index 0000000000..765cd01812
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNames.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.tests.components.beanitemcontainer.BeanItemContainerGenerator;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.FooterCell;
+import com.vaadin.ui.Grid.FooterRow;
+import com.vaadin.ui.Grid.HeaderCell;
+import com.vaadin.ui.Grid.HeaderRow;
+import com.vaadin.ui.Grid.SelectionMode;
+
+@Theme("valo")
+public class GridHeaderStyleNames extends AbstractTestUIWithLog {
+
+ private HeaderCell ageHeaderCell;
+ private HeaderCell mergedCityCountryCell;
+ private FooterCell ageFooterCell;
+ private HeaderRow headerRow;
+ private FooterRow footerRow;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid grid = new Grid();
+ grid.setSelectionMode(SelectionMode.MULTI);
+ grid.setContainerDataSource(BeanItemContainerGenerator
+ .createContainer(100));
+
+ ageHeaderCell = grid.getDefaultHeaderRow().getCell("age");
+
+ headerRow = grid.prependHeaderRow();
+ mergedCityCountryCell = headerRow.join("city", "country");
+ mergedCityCountryCell.setText("Merged cell");
+ addComponent(grid);
+
+ footerRow = grid.appendFooterRow();
+ ageFooterCell = footerRow.getCell("age");
+
+ getPage()
+ .getStyles()
+ .add(".age {background-image: linear-gradient(to bottom,green 2%, #efefef 98%) !important;}");
+ getPage()
+ .getStyles()
+ .add(".valo .v-grid-header .v-grid-cell.city-country {background-image: linear-gradient(to bottom,yellow 2%, #efefef 98%) !important;}");
+ getPage()
+ .getStyles()
+ .add(".valo .v-grid-footer .v-grid-cell.age-footer {background-image: linear-gradient(to bottom,blue 2%, #efefef 98%) !important;}");
+ getPage()
+ .getStyles()
+ .add(".valo .v-grid .v-grid-row.custom-row > * {background-image: linear-gradient(to bottom,purple 2%, #efefef 98%);}");
+
+ setCellStyles(true);
+ setRowStyles(true);
+
+ Button b = new Button("Toggle styles");
+ b.addClickListener(new ClickListener() {
+ private boolean stylesOn = true;
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ setCellStyles(!stylesOn);
+ setRowStyles(!stylesOn);
+ stylesOn = !stylesOn;
+ }
+ });
+ addComponent(b);
+ }
+
+ protected void setCellStyles(boolean set) {
+ if (set) {
+ ageHeaderCell.setStyleName("age");
+ ageFooterCell.setStyleName("age-footer");
+ mergedCityCountryCell.setStyleName("city-country");
+ } else {
+ ageHeaderCell.setStyleName(null);
+ ageFooterCell.setStyleName(null);
+ mergedCityCountryCell.setStyleName(null);
+ }
+
+ }
+
+ protected void setRowStyles(boolean set) {
+ if (set) {
+ headerRow.setStyleName("custom-row");
+ footerRow.setStyleName("custom-row");
+ } else {
+ headerRow.setStyleName(null);
+ footerRow.setStyleName(null);
+ }
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java b/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java
new file mode 100644
index 0000000000..0f70d66ad4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+@TestCategory("grid")
+public class GridHeaderStyleNamesTest extends SingleBrowserTest {
+
+ private GridElement grid;
+
+ @Before
+ public void findGridCells() {
+ openTestURL();
+ grid = $(GridElement.class).first();
+ }
+
+ private GridCellElement getMergedHeaderCell() {
+ return grid.getHeaderCell(0, 3);
+ }
+
+ private GridCellElement getAgeFooterCell() {
+ return grid.getFooterCell(0, 2);
+ }
+
+ @Test
+ public void cellStyleNamesCanBeAddedAndRemoved() {
+ ButtonElement toggleStyles = $(ButtonElement.class).caption(
+ "Toggle styles").first();
+
+ assertStylesSet(true);
+ toggleStyles.click();
+ assertStylesSet(false);
+ toggleStyles.click();
+ assertStylesSet(true);
+ }
+
+ @Test
+ public void rowStyleNamesCanBeAddedAndRemoved() {
+ ButtonElement toggleStyles = $(ButtonElement.class).caption(
+ "Toggle styles").first();
+
+ assertRowStylesSet(true);
+ toggleStyles.click();
+ assertRowStylesSet(false);
+ toggleStyles.click();
+ assertRowStylesSet(true);
+
+ }
+
+ private void assertStylesSet(boolean set) {
+ if (set) {
+ assertHasStyleName(
+ "Footer cell should have the assigned 'age-footer' class name",
+ getAgeFooterCell(), "age-footer");
+ assertHasStyleName(
+ "Header cell should have the assigned 'age' class name",
+ getAgeHeaderCell(), "age");
+ assertHasStyleName(
+ "The merged header cell should have the assigned 'city-country' class name",
+ getMergedHeaderCell(), "city-country");
+ } else {
+ assertHasNotStyleName(
+ "Footer cell should not have the removed 'age-footer' class name",
+ getAgeFooterCell(), "age-footer");
+ assertHasNotStyleName(
+ "Header cell should not have the removed 'age' class name",
+ getAgeHeaderCell(), "age");
+ assertHasNotStyleName(
+ "Ther merged header cell should not have the removed 'city-country' class name",
+ getMergedHeaderCell(), "city-country");
+ }
+ assertHasStyleName(
+ "The default v-grid-cell style name should not be removed from the header cell",
+ getAgeHeaderCell(), "v-grid-cell");
+ assertHasStyleName(
+ "The default v-grid-cell style name should not be removed from the footer cell",
+ getAgeFooterCell(), "v-grid-cell");
+ assertHasStyleName(
+ "The default v-grid-cell style name should not be removed from the merged header cell",
+ getMergedHeaderCell(), "v-grid-cell");
+
+ }
+
+ private void assertRowStylesSet(boolean set) {
+ if (set) {
+ assertHasStyleName(
+ "Footer row should have the assigned 'custom-row' class name",
+ getFooterRow(), "custom-row");
+ assertHasStyleName(
+ "Header row should have the assigned 'custom-row' class name",
+ getHeaderRow(), "custom-row");
+ } else {
+ assertHasNotStyleName(
+ "Footer row should not have the removed 'custom-row' class name",
+ getFooterRow(), "custom-row");
+ assertHasNotStyleName(
+ "Header row should not have the removed 'custom-row' class name",
+ getHeaderRow(), "custom-row");
+ }
+ assertHasStyleName(
+ "The default v-grid-row style name should not be removed from the header row",
+ getHeaderRow(), "v-grid-row");
+ assertHasStyleName(
+ "The default v-grid-row style name should not be removed from the footer row",
+ getFooterRow(), "v-grid-row");
+
+ }
+
+ private WebElement getAgeHeaderCell() {
+ return grid.getHeaderCell(1, 2);
+ }
+
+ private WebElement getFooterRow() {
+ return grid.getFooterRow(0);
+ }
+
+ private WebElement getHeaderRow() {
+ return grid.getHeaderRow(0);
+ }
+
+ private void assertHasStyleName(String message, WebElement element,
+ String stylename) {
+ if (!hasCssClass(element, stylename)) {
+ Assert.fail(message);
+ }
+ }
+
+ private void assertHasNotStyleName(String message, WebElement element,
+ String stylename) {
+ if (hasCssClass(element, stylename)) {
+ Assert.fail(message);
+ }
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridInTabSheet.java b/uitest/src/com/vaadin/tests/components/grid/GridInTabSheet.java
new file mode 100644
index 0000000000..6c7f254a0d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridInTabSheet.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TabSheet;
+
+public class GridInTabSheet extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ TabSheet sheet = new TabSheet();
+ final Grid grid = new Grid();
+ grid.setSelectionMode(SelectionMode.MULTI);
+ grid.addColumn("count", Integer.class);
+ for (Integer i = 0; i < 3; ++i) {
+ grid.addRow(i);
+ }
+
+ sheet.addTab(grid);
+ sheet.addTab(new Label("Hidden"));
+
+ addComponent(sheet);
+ addComponent(new Button("Add row to Grid", new Button.ClickListener() {
+
+ private Integer k = 0;
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.addRow(100 + (k++));
+ }
+ }));
+ addComponent(new Button("Remove row from Grid",
+ new Button.ClickListener() {
+
+ private Integer k = 0;
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ Object firstItemId = grid.getContainerDataSource()
+ .firstItemId();
+ if (firstItemId != null) {
+ grid.getContainerDataSource().removeItem(
+ firstItemId);
+ }
+ }
+ }));
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridInTabSheetTest.java b/uitest/src/com/vaadin/tests/components/grid/GridInTabSheetTest.java
new file mode 100644
index 0000000000..cd165e4678
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridInTabSheetTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridInTabSheetTest extends MultiBrowserTest {
+
+ @Test
+ public void testRemoveAllRowsAndAddThreeNewOnes() {
+ setDebug(true);
+ openTestURL();
+
+ for (int i = 0; i < 3; ++i) {
+ removeGridRow();
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ addGridRow();
+ assertEquals("" + (100 + i), getGridElement().getCell(i, 1)
+ .getText());
+ }
+ assertFalse("There was an unexpected error notification",
+ isElementPresent(NotificationElement.class));
+ }
+
+ private void removeGridRow() {
+ $(ButtonElement.class).caption("Remove row from Grid").first().click();
+ }
+
+ private void addGridRow() {
+ $(ButtonElement.class).caption("Add row to Grid").first().click();
+ }
+
+ private GridElement getGridElement() {
+ return $(GridElement.class).first();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInit.java b/uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInit.java
new file mode 100644
index 0000000000..10d4977623
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInit.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+
+public class GridMultiSelectionOnInit extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid grid = new Grid();
+ grid.addColumn("foo", String.class);
+ grid.addRow("Foo 1");
+ grid.addRow("Foo 2");
+ grid.setSelectionMode(SelectionMode.MULTI);
+ addComponent(grid);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInitTest.java b/uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInitTest.java
new file mode 100644
index 0000000000..5f5b4df8de
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridMultiSelectionOnInitTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridMultiSelectionOnInitTest extends MultiBrowserTest {
+
+ @Test
+ public void testSelectAllCheckBoxExists() {
+ openTestURL();
+ assertTrue("The select all checkbox was missing.",
+ $(GridElement.class).first().getHeaderCell(0, 0)
+ .isElementPresent(By.tagName("input")));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridScrolling.java b/uitest/src/com/vaadin/tests/components/grid/GridScrolling.java
new file mode 100644
index 0000000000..ce64b3e9f3
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridScrolling.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.grid.ScrollDestination;
+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.Grid;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.VerticalLayout;
+
+@SuppressWarnings("serial")
+public class GridScrolling extends AbstractTestUI {
+
+ private Grid grid;
+
+ private IndexedContainer ds;
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void setup(VaadinRequest request) {
+ // Build data source
+ ds = new IndexedContainer();
+
+ for (int col = 0; col < 5; col++) {
+ ds.addContainerProperty("col" + col, String.class, "");
+ }
+
+ for (int row = 0; row < 65536; row++) {
+ Item item = ds.addItem(Integer.valueOf(row));
+ for (int col = 0; col < 5; col++) {
+ item.getItemProperty("col" + col).setValue(
+ "(" + row + ", " + col + ")");
+ }
+ }
+
+ grid = new Grid(ds);
+
+ HorizontalLayout hl = new HorizontalLayout();
+ hl.addComponent(grid);
+ hl.setMargin(true);
+ hl.setSpacing(true);
+
+ VerticalLayout vl = new VerticalLayout();
+ vl.setSpacing(true);
+
+ // Add scroll buttons
+ Button scrollUpButton = new Button("Top", new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.scrollToStart();
+ }
+ });
+ scrollUpButton.setSizeFull();
+ vl.addComponent(scrollUpButton);
+
+ for (int i = 1; i < 7; ++i) {
+ final int row = (ds.size() / 7) * i;
+ Button scrollButton = new Button("Scroll to row " + row,
+ new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.scrollTo(Integer.valueOf(row),
+ ScrollDestination.MIDDLE);
+ }
+ });
+ scrollButton.setSizeFull();
+ vl.addComponent(scrollButton);
+ }
+
+ Button scrollDownButton = new Button("Bottom", new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.scrollToEnd();
+ }
+ });
+ scrollDownButton.setSizeFull();
+ vl.addComponent(scrollDownButton);
+
+ hl.addComponent(vl);
+ addComponent(hl);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test Grid programmatic scrolling features";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 13327;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java
new file mode 100644
index 0000000000..2ab0282102
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.SelectionMode;
+
+public class GridSingleColumn extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+
+ IndexedContainer indexedContainer = new IndexedContainer();
+ indexedContainer.addContainerProperty("column1", String.class, "");
+
+ for (int i = 0; i < 100; i++) {
+ Item addItem = indexedContainer.addItem(i);
+ addItem.getItemProperty("column1").setValue("cell");
+ }
+
+ Grid grid = new Grid(indexedContainer);
+ grid.setSelectionMode(SelectionMode.NONE);
+
+ Column column = grid.getColumn("column1");
+
+ column.setHeaderCaption("Header");
+
+ addComponent(grid);
+ grid.scrollTo(grid.getContainerDataSource().getIdByIndex(50));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Tests a single column grid";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return null;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java
new file mode 100644
index 0000000000..42eb2197bf
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridSingleColumnTest extends MultiBrowserTest {
+
+ @Test
+ public void testHeaderIsVisible() {
+ openTestURL();
+
+ GridCellElement cell = $(GridElement.class).first().getHeaderCell(0, 0);
+ Assert.assertTrue("No header available", cell.getText()
+ .equalsIgnoreCase("header"));
+ }
+
+ @Test
+ public void testScrollDidNotThrow() {
+ setDebug(true);
+ openTestURL();
+
+ Assert.assertFalse("Exception when scrolling on init",
+ isElementPresent(NotificationElement.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridThemeChange.java b/uitest/src/com/vaadin/tests/components/grid/GridThemeChange.java
new file mode 100644
index 0000000000..76f7e22ee0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridThemeChange.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.vaadin.event.SelectionEvent;
+import com.vaadin.event.SelectionEvent.SelectionListener;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+
+public class GridThemeChange extends AbstractTestUI {
+ private final List<String> themes = Arrays.asList("valo", "reindeer",
+ "runo", "chameleon", "base");
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Grid grid = new Grid();
+ grid.setSelectionMode(SelectionMode.SINGLE);
+
+ grid.addColumn("Theme");
+ for (String theme : themes) {
+ Object itemId = grid.addRow(theme);
+ if (theme.equals(getTheme())) {
+ grid.select(itemId);
+ }
+ }
+
+ grid.addSelectionListener(new SelectionListener() {
+ @Override
+ public void select(SelectionEvent event) {
+ Object selectedItemId = grid.getSelectedRow();
+ Object theme = grid.getContainerDataSource()
+ .getItem(selectedItemId).getItemProperty("Theme")
+ .getValue();
+ setTheme(String.valueOf(theme));
+ }
+ });
+
+ addComponent(grid);
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridThemeChangeTest.java b/uitest/src/com/vaadin/tests/components/grid/GridThemeChangeTest.java
new file mode 100644
index 0000000000..5a21705b55
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridThemeChangeTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridThemeChangeTest extends MultiBrowserTest {
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+ // Seems like stylesheet onload is not fired on PhantomJS
+ // https://github.com/ariya/phantomjs/issues/12332
+ return super.getBrowsersExcludingPhantomJS();
+ }
+
+ @Test
+ public void testThemeChange() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+
+ int reindeerHeight = grid.getRow(0).getSize().getHeight();
+
+ grid.getCell(0, 0).click();
+
+ int valoHeight = grid.getRow(0).getSize().getHeight();
+
+ Assert.assertTrue(
+ "Row height should increase when changing from Reindeer to Valo",
+ valoHeight > reindeerHeight);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverter.java b/uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverter.java
new file mode 100644
index 0000000000..fba2bbf698
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverter.java
@@ -0,0 +1,37 @@
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+
+public class GridUndefinedObjectConverter extends AbstractTestUI {
+ private static class Pojo {
+ private final String content;
+
+ public Pojo(String content) {
+ this.content = content;
+ }
+
+ @Override
+ public String toString() {
+ return "Pojo:" + content;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("all")
+ protected void setup(VaadinRequest request) {
+ IndexedContainer container = new IndexedContainer();
+ container.addContainerProperty("pojo", Pojo.class, new Pojo("foo"));
+ container.addContainerProperty("pojo object ", Object.class, new Pojo(
+ "bar"));
+ container.addContainerProperty("int", Integer.class, 1);
+ container.addContainerProperty("int object", Object.class, 2);
+ container.addContainerProperty("string", String.class, "foo");
+ container.addContainerProperty("string object", Object.class, "bar");
+ container.addItem();
+
+ addComponent(new Grid(container));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverterTest.java b/uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverterTest.java
new file mode 100644
index 0000000000..401bfda885
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridUndefinedObjectConverterTest.java
@@ -0,0 +1,25 @@
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridUndefinedObjectConverterTest extends MultiBrowserTest {
+ @Test
+ public void testDefaultToStringRendering() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ assertEquals("pojo", "Pojo:foo", grid.getCell(0, 0).getText());
+ assertEquals("pojo object", "Pojo:bar", grid.getCell(0, 1).getText());
+ assertEquals("int", "1", grid.getCell(0, 2).getText());
+ assertEquals("int object", "2", grid.getCell(0, 3).getText());
+ assertEquals("string", "foo", grid.getCell(0, 4).getText());
+ assertEquals("string object", "bar", grid.getCell(0, 5).getText());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridWithoutRenderer.java b/uitest/src/com/vaadin/tests/components/grid/GridWithoutRenderer.java
new file mode 100644
index 0000000000..fd5e6fdc01
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridWithoutRenderer.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.util.PersonContainer;
+import com.vaadin.ui.Grid;
+
+@Theme("valo")
+public class GridWithoutRenderer extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid grid = new Grid();
+ grid.setContainerDataSource(PersonContainer.createWithTestData());
+ addComponent(grid);
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridWithoutRendererTest.java b/uitest/src/com/vaadin/tests/components/grid/GridWithoutRendererTest.java
new file mode 100644
index 0000000000..5d6ffbd8a7
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridWithoutRendererTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+@TestCategory("grid")
+public class GridWithoutRendererTest extends SingleBrowserTest {
+
+ @Test
+ public void ensureNoError() {
+ openTestURL();
+ // WebElement errorIndicator = findElement(By
+ // .cssSelector("v-error-indicator"));
+ // System.out.println(errorIndicator);
+ List<WebElement> errorIndicator = findElements(By
+ .xpath("//span[@class='v-errorindicator']"));
+ Assert.assertTrue("There should not be an error indicator",
+ errorIndicator.isEmpty());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumns.java b/uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumns.java
new file mode 100644
index 0000000000..b6da30d314
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumns.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+
+public class InitialFrozenColumns extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid grid = new Grid();
+ grid.setSelectionMode(SelectionMode.NONE);
+
+ grid.addColumn("foo").setWidth(200);
+ grid.addColumn("bar").setWidth(200);
+ grid.addColumn("baz").setWidth(200);
+
+ grid.addRow("a", "b", "c");
+
+ grid.setFrozenColumnCount(2);
+
+ addComponent(grid);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumnsTest.java b/uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumnsTest.java
new file mode 100644
index 0000000000..7a6d37d089
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/InitialFrozenColumnsTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class InitialFrozenColumnsTest extends MultiBrowserTest {
+ @Test
+ public void testInitialFrozenColumns() {
+ setDebug(true);
+ openTestURL();
+
+ Assert.assertFalse("Notification was present",
+ isElementPresent(NotificationElement.class));
+
+ WebElement cell = $(GridElement.class).first().getCell(0, 0);
+ assertTrue(cell.getAttribute("class").contains("frozen"));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java
new file mode 100644
index 0000000000..ce15676b60
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.ui.Grid.AbstractRenderer;
+
+public class IntArrayRenderer extends AbstractRenderer<int[]> {
+ public IntArrayRenderer() {
+ super(int[].class);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderers.java b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderers.java
new file mode 100644
index 0000000000..4bfa244c22
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderers.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+
+public class JavaScriptRenderers extends AbstractTestUI {
+
+ public static class MyBean {
+ private int integer;
+ private String string;
+
+ public MyBean(int integer, String string) {
+ super();
+ this.integer = integer;
+ this.string = string;
+ }
+
+ public int getInteger() {
+ return integer;
+ }
+
+ public void setInteger(int integer) {
+ this.integer = integer;
+ }
+
+ public String getString() {
+ return string;
+ }
+
+ public void setString(String string) {
+ this.string = string;
+ }
+ }
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ IndexedContainer container = new IndexedContainer();
+ container.addContainerProperty("id", Integer.class, Integer.valueOf(0));
+ container.addContainerProperty("bean", MyBean.class, null);
+
+ for (int i = 0; i < 1000; i++) {
+ Integer itemId = Integer.valueOf(i);
+ Item item = container.addItem(itemId);
+ item.getItemProperty("id").setValue(itemId);
+ item.getItemProperty("bean").setValue(
+ new MyBean(i + 1, Integer.toString(i - 1)));
+ }
+
+ Grid grid = new Grid(container);
+
+ grid.getColumn("bean").setRenderer(new MyBeanJSRenderer());
+ grid.getColumn("bean").setWidth(250);
+
+ addComponent(grid);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java
new file mode 100644
index 0000000000..96fd672ab1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/JavaScriptRenderersTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class JavaScriptRenderersTest extends MultiBrowserTest {
+
+ @Test
+ public void testJavaScriptRenderer() {
+ setDebug(true);
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ GridCellElement cell_1_1 = grid.getCell(1, 1);
+
+ // Verify render functionality
+ Assert.assertEquals("Bean(2, 0)", cell_1_1.getText());
+
+ // Verify init functionality
+ Assert.assertEquals("1", cell_1_1.getAttribute("column"));
+
+ // Verify onbrowserevent
+ cell_1_1.click();
+ Assert.assertTrue(cell_1_1.getText().startsWith(
+ "Clicked 1 with key 1 at"));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java b/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java
new file mode 100644
index 0000000000..ccb94f5d2d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.tests.components.grid.JavaScriptRenderers.MyBean;
+import com.vaadin.ui.renderer.AbstractJavaScriptRenderer;
+
+/**
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@JavaScript("myBeanJsRenderer.js")
+public class MyBeanJSRenderer extends AbstractJavaScriptRenderer<MyBean> {
+
+ public MyBeanJSRenderer() {
+ super(MyBean.class);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java
new file mode 100644
index 0000000000..7b3390a7e7
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.tests.widgetset.client.grid.RowAwareRendererConnector.RowAwareRendererRpc;
+import com.vaadin.ui.Grid.AbstractRenderer;
+import com.vaadin.ui.Label;
+
+public class RowAwareRenderer extends AbstractRenderer<Void> {
+ public RowAwareRenderer(final Label debugLabel) {
+ super(Void.class);
+ registerRpc(new RowAwareRendererRpc() {
+ @Override
+ public void clicky(String key) {
+ Object itemId = getItemId(key);
+ debugLabel.setValue("key: " + key + ", itemId: " + itemId);
+ }
+ });
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/SelectDuringInit.java b/uitest/src/com/vaadin/tests/components/grid/SelectDuringInit.java
new file mode 100644
index 0000000000..d8394acd19
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/SelectDuringInit.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+
+public class SelectDuringInit extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid grid = new Grid();
+ grid.setSelectionMode(SelectionMode.MULTI);
+
+ grid.addColumn("value");
+ grid.addRow("row 1");
+ grid.addRow("row 2");
+ grid.addRow("row 3");
+
+ grid.select(Integer.valueOf(2));
+
+ addComponent(grid);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/SelectDuringInitTest.java b/uitest/src/com/vaadin/tests/components/grid/SelectDuringInitTest.java
new file mode 100644
index 0000000000..edfc8031a8
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/SelectDuringInitTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class SelectDuringInitTest extends SingleBrowserTest {
+
+ @Test
+ public void testSelectDuringInit() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+
+ Assert.assertTrue(grid.getRow(1).isSelected());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/WidgetRenderers.java b/uitest/src/com/vaadin/tests/components/grid/WidgetRenderers.java
new file mode 100644
index 0000000000..0d51558cd1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/WidgetRenderers.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.Resource;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.renderer.ButtonRenderer;
+import com.vaadin.ui.renderer.ClickableRenderer.RendererClickEvent;
+import com.vaadin.ui.renderer.ClickableRenderer.RendererClickListener;
+import com.vaadin.ui.renderer.ImageRenderer;
+import com.vaadin.ui.renderer.ProgressBarRenderer;
+
+@SuppressWarnings("all")
+public class WidgetRenderers extends AbstractTestUI {
+
+ static final String PROPERTY_ID = "property id";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ IndexedContainer container = new IndexedContainer();
+
+ container.addContainerProperty(ProgressBarRenderer.class, Double.class,
+ null);
+ container
+ .addContainerProperty(ButtonRenderer.class, String.class, null);
+ container.addContainerProperty(ImageRenderer.class, Resource.class,
+ null);
+ container.addContainerProperty(PROPERTY_ID, String.class, null);
+
+ final Item item = container.getItem(container.addItem());
+
+ item.getItemProperty(ProgressBarRenderer.class).setValue(0.3);
+ item.getItemProperty(ButtonRenderer.class).setValue("Click");
+ item.getItemProperty(ImageRenderer.class).setValue(
+ new ThemeResource("window/img/close.png"));
+ item.getItemProperty(PROPERTY_ID).setValue("Click");
+
+ final Grid grid = new Grid(container);
+
+ grid.setId("test-grid");
+ grid.setSelectionMode(SelectionMode.NONE);
+
+ grid.getColumn(ProgressBarRenderer.class).setRenderer(
+ new ProgressBarRenderer());
+
+ grid.getColumn(ButtonRenderer.class).setRenderer(
+ new ButtonRenderer(new RendererClickListener() {
+ @Override
+ public void click(RendererClickEvent event) {
+ item.getItemProperty(ButtonRenderer.class).setValue(
+ "Clicked!");
+ }
+ }));
+
+ grid.getColumn(ImageRenderer.class).setRenderer(
+ new ImageRenderer(new RendererClickListener() {
+
+ @Override
+ public void click(RendererClickEvent event) {
+ item.getItemProperty(ImageRenderer.class).setValue(
+ new ThemeResource("window/img/maximize.png"));
+ }
+ }));
+
+ grid.getColumn(PROPERTY_ID).setRenderer(
+ new ButtonRenderer(new RendererClickListener() {
+ @Override
+ public void click(RendererClickEvent event) {
+ item.getItemProperty(PROPERTY_ID).setValue(
+ event.getPropertyId());
+ }
+ }));
+
+ addComponent(grid);
+
+ addComponent(new NativeButton("Change column order",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.setColumnOrder(ImageRenderer.class,
+ ProgressBarRenderer.class, ButtonRenderer.class);
+ }
+ }));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Tests the functionality of widget-based renderers";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(13334);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/WidgetRenderersTest.java b/uitest/src/com/vaadin/tests/components/grid/WidgetRenderersTest.java
new file mode 100644
index 0000000000..5da92b2034
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/WidgetRenderersTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * TB tests for the various builtin widget-based renderers.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@TestCategory("grid")
+public class WidgetRenderersTest extends MultiBrowserTest {
+
+ @Test
+ public void testProgressBarRenderer() {
+ openTestURL();
+
+ assertTrue(getGridCell(0, 0).isElementPresent(
+ By.className("v-progressbar")));
+ }
+
+ @Test
+ public void testButtonRenderer() {
+ openTestURL();
+
+ WebElement button = getGridCell(0, 1).findElement(
+ By.className("v-nativebutton"));
+
+ button.click();
+
+ assertEquals("Clicked!", button.getText());
+ }
+
+ @Test
+ public void testButtonRendererAfterCellBeingFocused() {
+ openTestURL();
+
+ GridCellElement buttonCell = getGridCell(0, 1);
+ assertFalse("cell should not be focused before focusing",
+ buttonCell.isFocused());
+
+ // avoid clicking on the button
+ buttonCell.click(buttonCell.getSize().getWidth() - 10, 5);
+ assertTrue("cell should be focused after focusing",
+ buttonCell.isFocused());
+
+ WebElement button = buttonCell.findElement(By
+ .className("v-nativebutton"));
+ assertNotEquals("Button should not be clicked before click",
+ "Clicked!", button.getText());
+
+ new Actions(getDriver()).moveToElement(button).click().perform();
+ assertEquals("Button should be clicked after click", "Clicked!",
+ button.getText());
+ }
+
+ @Test
+ public void testImageRenderer() {
+ openTestURL();
+
+ WebElement image = getGridCell(0, 2).findElement(
+ By.className("gwt-Image"));
+
+ assertTrue(image.getAttribute("src").endsWith("window/img/close.png"));
+
+ image.click();
+
+ assertTrue(image.getAttribute("src")
+ .endsWith("window/img/maximize.png"));
+ }
+
+ @Test
+ public void testColumnReorder() {
+ setDebug(true);
+ openTestURL();
+
+ $(ButtonElement.class).caption("Change column order").first().click();
+
+ assertFalse("Notification was present",
+ isElementPresent(NotificationElement.class));
+
+ assertTrue(getGridCell(0, 0)
+ .isElementPresent(By.className("gwt-Image")));
+ assertTrue(getGridCell(0, 1).isElementPresent(
+ By.className("v-progressbar")));
+ assertTrue(getGridCell(0, 2).isElementPresent(
+ By.className("v-nativebutton")));
+ }
+
+ @Test
+ public void testPropertyIdInEvent() {
+ openTestURL();
+ WebElement button = getGridCell(0, 3).findElement(
+ By.className("v-nativebutton"));
+ button.click();
+ assertEquals(WidgetRenderers.PROPERTY_ID, button.getText());
+ }
+
+ GridCellElement getGridCell(int row, int col) {
+ return $(GridElement.class).first().getCell(row, col);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeatures.java
new file mode 100644
index 0000000000..8e1a80a830
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeatures.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Title;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.EscalatorBasicClientFeaturesWidget;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+import com.vaadin.ui.UI;
+
+@Widgetset(TestingWidgetSet.NAME)
+@Title("Escalator basic client features")
+public class EscalatorBasicClientFeatures extends UI {
+
+ @Override
+ public void init(VaadinRequest request) {
+ setContent(new TestWidgetComponent(
+ EscalatorBasicClientFeaturesWidget.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java
new file mode 100644
index 0000000000..92c7f3e6a6
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.Dimension;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("escalator")
+public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest {
+ protected static final String COLUMNS_AND_ROWS = "Columns and Rows";
+
+ protected static final String COLUMNS = "Columns";
+ protected static final String ADD_ONE_COLUMN_TO_BEGINNING = "Add one column to beginning";
+ protected static final String ADD_ONE_ROW_TO_BEGINNING = "Add one row to beginning";
+ protected static final String REMOVE_ONE_COLUMN_FROM_BEGINNING = "Remove one column from beginning";
+ protected static final String REMOVE_ONE_ROW_FROM_BEGINNING = "Remove one row from beginning";
+ protected static final String REMOVE_50_ROWS_FROM_BOTTOM = "Remove 50 rows from bottom";
+ protected static final String REMOVE_50_ROWS_FROM_ALMOST_BOTTOM = "Remove 50 rows from almost bottom";
+ protected static final String ADD_ONE_OF_EACH_ROW = "Add one of each row";
+ protected static final String RESIZE_FIRST_COLUMN_TO_MAX_WIDTH = "Resize first column to max width";
+ protected static final String RESIZE_FIRST_COLUMN_TO_100PX = "Resize first column to 100 px";
+
+ protected static final String HEADER_ROWS = "Header Rows";
+ protected static final String BODY_ROWS = "Body Rows";
+ protected static final String FOOTER_ROWS = "Footer Rows";
+
+ protected static final String REMOVE_ALL_INSERT_SCROLL = "Remove all, insert 30 and scroll 40px";
+
+ protected static final String GENERAL = "General";
+ protected static final String DETACH_ESCALATOR = "Detach Escalator";
+ protected static final String POPULATE_COLUMN_ROW = "Populate Escalator (columns, then rows)";
+ protected static final String POPULATE_ROW_COLUMN = "Populate Escalator (rows, then columns)";
+ protected static final String CLEAR_COLUMN_ROW = "Clear (columns, then rows)";
+ protected static final String CLEAR_ROW_COLUMN = "Clear (rows, then columns)";
+
+ protected static final String FEATURES = "Features";
+ protected static final String FROZEN_COLUMNS = "Frozen columns";
+ protected static final String FREEZE_1_COLUMN = "Freeze 1 column";
+ protected static final String FREEZE_0_COLUMNS = "Freeze 0 columns";
+ protected static final String COLUMN_SPANNING = "Column spanning";
+ protected static final String COLSPAN_NORMAL = "Apply normal colspan";
+ protected static final String COLSPAN_NONE = "Apply no colspan";
+
+ @Override
+ protected Class<?> getUIClass() {
+ return EscalatorBasicClientFeatures.class;
+ }
+
+ protected TestBenchElement getEscalator() {
+ By className = By.className("v-escalator");
+ if (isElementPresent(className)) {
+ return (TestBenchElement) findElement(className);
+ }
+ return null;
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ protected TestBenchElement getHeaderRow(int row) {
+ return getRow("thead", row);
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ protected TestBenchElement getBodyRow(int row) {
+ return getRow("tbody", row);
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ protected TestBenchElement getFooterRow(int row) {
+ return getRow("tfoot", row);
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ protected TestBenchElement getHeaderCell(int row, int col) {
+ return getCell("thead", row, col);
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ protected TestBenchElement getBodyCell(int row, int col) {
+ return getCell("tbody", row, col);
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ protected TestBenchElement getFooterCell(int row, int col) {
+ return getCell("tfoot", row, col);
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ private TestBenchElement getCell(String sectionTag, int row, int col) {
+ TestBenchElement rowElement = getRow(sectionTag, row);
+ By xpath = By.xpath("*[" + (col + 1) + "]");
+ if (rowElement != null && rowElement.isElementPresent(xpath)) {
+ return (TestBenchElement) rowElement.findElement(xpath);
+ }
+ return null;
+ }
+
+ /**
+ * @param row
+ * the index of the row element in the section. If negative, the
+ * calculation starts from the end (-1 is the last, -2 is the
+ * second-to-last etc)
+ */
+ private TestBenchElement getRow(String sectionTag, int row) {
+ TestBenchElement escalator = getEscalator();
+ WebElement tableSection = escalator.findElement(By.tagName(sectionTag));
+ By xpath;
+
+ if (row >= 0) {
+ int fromFirst = row + 1;
+ xpath = By.xpath("tr[" + fromFirst + "]");
+ } else {
+ int fromLast = Math.abs(row + 1);
+ xpath = By.xpath("tr[last() - " + fromLast + "]");
+ }
+ if (tableSection != null
+ && ((TestBenchElement) tableSection).isElementPresent(xpath)) {
+ return (TestBenchElement) tableSection.findElement(xpath);
+ }
+ return null;
+ }
+
+ protected void selectMenu(String menuCaption) {
+ TestBenchElement menuElement = getMenuElement(menuCaption);
+ Dimension size = menuElement.getSize();
+ new Actions(getDriver()).moveToElement(menuElement, size.width - 10,
+ size.height / 2).perform();
+ }
+
+ private TestBenchElement getMenuElement(String menuCaption) {
+ return (TestBenchElement) findElement(By.xpath("//td[text() = '"
+ + menuCaption + "']"));
+ }
+
+ protected void selectMenuPath(String... menuCaptions) {
+ new Actions(getDriver()).moveToElement(getMenuElement(menuCaptions[0]))
+ .click().perform();
+ for (int i = 1; i < menuCaptions.length - 1; ++i) {
+ selectMenu(menuCaptions[i]);
+ new Actions(getDriver()).moveByOffset(20, 0).perform();
+ }
+ new Actions(getDriver())
+ .moveToElement(
+ getMenuElement(menuCaptions[menuCaptions.length - 1]))
+ .click().perform();
+ }
+
+ protected void assertLogContains(String substring) {
+ assertTrue("log should've contained, but didn't: " + substring,
+ getLogText().contains(substring));
+ }
+
+ protected void assertLogDoesNotContain(String substring) {
+ assertFalse("log shouldn't have contained, but did: " + substring,
+ getLogText().contains(substring));
+ }
+
+ private String getLogText() {
+ WebElement log = findElement(By.cssSelector("#log"));
+ return log.getText();
+ }
+
+ protected void assertLogContainsInOrder(String... substrings) {
+ String log = getLogText();
+ int cursor = 0;
+ for (String substring : substrings) {
+ String remainingLog = log.substring(cursor, log.length());
+ int substringIndex = remainingLog.indexOf(substring);
+ if (substringIndex == -1) {
+ fail("substring \"" + substring
+ + "\" was not found in order from log.");
+ }
+
+ cursor += substringIndex + substring.length();
+ }
+ }
+
+ protected void scrollVerticallyTo(int px) {
+ executeScript("arguments[0].scrollTop = " + px, getVeticalScrollbar());
+ }
+
+ private TestBenchElement getVeticalScrollbar() {
+ return (TestBenchElement) getEscalator().findElement(
+ By.className("v-escalator-scroller-vertical"));
+ }
+
+ protected void scrollHorizontallyTo(int px) {
+ executeScript("arguments[0].scrollLeft = " + px,
+ getHorizontalScrollbar());
+ }
+
+ private TestBenchElement getHorizontalScrollbar() {
+ return (TestBenchElement) getEscalator().findElement(
+ By.className("v-escalator-scroller-horizontal"));
+ }
+
+ protected Object executeScript(String script, Object... args) {
+ return ((JavascriptExecutor) getDriver()).executeScript(script, args);
+ }
+
+ protected void populate() {
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUi.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUi.java
new file mode 100644
index 0000000000..ef997b3cae
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUi.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.EscalatorBasicClientFeaturesWidget;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+import com.vaadin.ui.UI;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class EscalatorUpdaterUi extends UI {
+
+ @Override
+ protected void init(VaadinRequest request) {
+ setContent(new TestWidgetComponent(
+ EscalatorBasicClientFeaturesWidget.UpdaterLifetimeWidget.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java
new file mode 100644
index 0000000000..429f15bb47
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+import com.vaadin.ui.UI;
+
+/**
+ * Initializer shell for GridClientBasicFeatures test application
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+@Widgetset(TestingWidgetSet.NAME)
+public class GridBasicClientFeatures extends UI {
+
+ @Override
+ protected void init(VaadinRequest request) {
+ setContent(new TestWidgetComponent(GridBasicClientFeaturesWidget.class));
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java
new file mode 100644
index 0000000000..d0e076fd3b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+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.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement;
+
+/**
+ * Variant of GridBasicFeaturesTest to be used with GridBasicClientFeatures.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest {
+
+ private boolean composite = false;
+
+ @Override
+ protected Class<?> getUIClass() {
+ return GridBasicClientFeatures.class;
+ }
+
+ @Override
+ protected String getDeploymentPath() {
+ String path = super.getDeploymentPath();
+ if (composite) {
+ path += (path.contains("?") ? "&" : "?") + "composite";
+ }
+ return path;
+ }
+
+ protected void setUseComposite(boolean useComposite) {
+ composite = useComposite;
+ }
+
+ @Override
+ protected void selectMenu(String menuCaption) {
+ WebElement menuElement = getMenuElement(menuCaption);
+ Dimension size = menuElement.getSize();
+ new Actions(getDriver()).moveToElement(menuElement, size.width - 10,
+ size.height / 2).perform();
+ }
+
+ private WebElement getMenuElement(String menuCaption) {
+ return getDriver().findElement(
+ By.xpath("//td[text() = '" + menuCaption + "']"));
+ }
+
+ @Override
+ protected void selectMenuPath(String... menuCaptions) {
+ new Actions(getDriver()).moveToElement(getMenuElement(menuCaptions[0]))
+ .click().perform();
+ for (int i = 1; i < menuCaptions.length - 1; ++i) {
+ selectMenu(menuCaptions[i]);
+ new Actions(getDriver()).moveByOffset(20, 0).perform();
+ }
+ new Actions(getDriver())
+ .moveToElement(
+ getMenuElement(menuCaptions[menuCaptions.length - 1]))
+ .click().perform();
+ }
+
+ @Override
+ protected GridElement getGridElement() {
+ if (composite) {
+ // Composite requires the basic client features widget for subparts
+ return ((TestBenchElement) findElement(By
+ .vaadin("//TestWidgetComponent")))
+ .wrap(GridElement.class);
+ } else {
+ return super.getGridElement();
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
new file mode 100644
index 0000000000..7a625e2f25
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -0,0 +1,1026 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Random;
+
+import com.vaadin.data.Container.Filter;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
+import com.vaadin.data.sort.Sort;
+import com.vaadin.data.sort.SortOrder;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.event.ItemClickEvent;
+import com.vaadin.event.ItemClickEvent.ItemClickListener;
+import com.vaadin.event.SelectionEvent;
+import com.vaadin.event.SelectionEvent.SelectionListener;
+import com.vaadin.event.SortEvent;
+import com.vaadin.event.SortEvent.SortListener;
+import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.shared.ui.grid.GridStaticCellType;
+import com.vaadin.shared.ui.grid.HeightMode;
+import com.vaadin.tests.components.AbstractComponentTest;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.CellReference;
+import com.vaadin.ui.Grid.CellStyleGenerator;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.FooterCell;
+import com.vaadin.ui.Grid.HeaderCell;
+import com.vaadin.ui.Grid.HeaderRow;
+import com.vaadin.ui.Grid.MultiSelectionModel;
+import com.vaadin.ui.Grid.RowReference;
+import com.vaadin.ui.Grid.RowStyleGenerator;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.renderer.DateRenderer;
+import com.vaadin.ui.renderer.HtmlRenderer;
+import com.vaadin.ui.renderer.NumberRenderer;
+
+/**
+ * Tests the basic features like columns, footers and headers
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridBasicFeatures extends AbstractComponentTest<Grid> {
+
+ public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4 = "Row numbers for 3/4";
+ public static final String ROW_STYLE_GENERATOR_NONE = "None";
+ public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS = "Row numbers";
+ public static final String CELL_STYLE_GENERATOR_NONE = "None";
+ public static final String CELL_STYLE_GENERATOR_PROPERTY_TO_STRING = "Property to string";
+ public static final String CELL_STYLE_GENERATOR_SPECIAL = "Special for 1/4 Column 1";
+ private static final int MANUALLY_FORMATTED_COLUMNS = 5;
+ public static final int COLUMNS = 12;
+ public static final int ROWS = 1000;
+
+ private int containerDelay = 0;
+
+ private IndexedContainer ds;
+ private Grid grid;
+ private SelectionListener selectionListener = new SelectionListener() {
+
+ @Override
+ public void select(SelectionEvent event) {
+ Iterator<Object> iter = event.getAdded().iterator();
+ Object addedRow = (iter.hasNext() ? iter.next() : "none");
+ iter = event.getRemoved().iterator();
+ Object removedRow = (iter.hasNext() ? iter.next() : "none");
+ log("SelectionEvent: Added " + addedRow + ", Removed " + removedRow);
+ }
+ };
+
+ private ItemClickListener itemClickListener = new ItemClickListener() {
+
+ @Override
+ public void itemClick(ItemClickEvent event) {
+ log("Item " + (event.isDoubleClick() ? "double " : "")
+ + "click on " + event.getPropertyId() + ", item "
+ + event.getItemId());
+ }
+ };
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected Grid constructComponent() {
+
+ // Build data source
+ ds = new IndexedContainer() {
+ @Override
+ public List<Object> getItemIds(int startIndex, int numberOfIds) {
+ log("Requested items " + startIndex + " - "
+ + (startIndex + numberOfIds));
+ if (containerDelay > 0) {
+ try {
+ Thread.sleep(containerDelay);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return super.getItemIds(startIndex, numberOfIds);
+ }
+ };
+
+ {
+ int col = 0;
+ for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) {
+ ds.addContainerProperty(getColumnProperty(col), String.class,
+ "");
+ }
+
+ ds.addContainerProperty(getColumnProperty(col++), Integer.class,
+ Integer.valueOf(0));
+ ds.addContainerProperty(getColumnProperty(col++), Date.class,
+ new Date());
+ ds.addContainerProperty(getColumnProperty(col++), String.class, "");
+
+ // Random numbers
+ ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0);
+ ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0);
+
+ }
+
+ {
+ Random rand = new Random();
+ rand.setSeed(13334);
+ long timestamp = 0;
+ for (int row = 0; row < ROWS; row++) {
+ Item item = ds.addItem(Integer.valueOf(row));
+ int col = 0;
+ for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) {
+ item.getItemProperty(getColumnProperty(col)).setValue(
+ "(" + row + ", " + col + ")");
+ }
+ item.getItemProperty(getColumnProperty(1)).setReadOnly(true);
+
+ item.getItemProperty(getColumnProperty(col++)).setValue(
+ Integer.valueOf(row));
+ item.getItemProperty(getColumnProperty(col++)).setValue(
+ new Date(timestamp));
+ timestamp += 91250000; // a bit over a day, just to get
+ // variation
+ item.getItemProperty(getColumnProperty(col++)).setValue(
+ "<b>" + row + "</b>");
+
+ // Random numbers
+ item.getItemProperty(getColumnProperty(col++)).setValue(
+ rand.nextInt());
+ // Random between 0 - 5 to test multisorting
+ item.getItemProperty(getColumnProperty(col++)).setValue(
+ rand.nextInt(5));
+ }
+ }
+
+ // Create grid
+ Grid grid = new Grid(ds);
+
+ {
+ int col = grid.getContainerDataSource().getContainerPropertyIds()
+ .size()
+ - MANUALLY_FORMATTED_COLUMNS;
+ grid.getColumn(getColumnProperty(col++)).setRenderer(
+ new NumberRenderer(new DecimalFormat("0,000.00",
+ DecimalFormatSymbols.getInstance(new Locale("fi",
+ "FI")))));
+ grid.getColumn(getColumnProperty(col++)).setRenderer(
+ new DateRenderer(new SimpleDateFormat("dd.MM.yy HH:mm")));
+ grid.getColumn(getColumnProperty(col++)).setRenderer(
+ new HtmlRenderer());
+ grid.getColumn(getColumnProperty(col++)).setRenderer(
+ new NumberRenderer());
+ grid.getColumn(getColumnProperty(col++)).setRenderer(
+ new NumberRenderer());
+ }
+
+ // Create footer
+ grid.appendFooterRow();
+ grid.setFooterVisible(false);
+
+ // Add footer values (header values are automatically created)
+ for (int col = 0; col < COLUMNS; col++) {
+ grid.getFooterRow(0).getCell(getColumnProperty(col))
+ .setText("Footer " + col);
+ }
+
+ // Set varying column widths
+ for (int col = 0; col < COLUMNS; col++) {
+ grid.getColumn(getColumnProperty(col)).setWidth(100 + col * 50);
+ }
+
+ grid.addSortListener(new SortListener() {
+ @Override
+ public void sort(SortEvent event) {
+
+ log("SortOrderChangeEvent: isUserOriginated? "
+ + event.isUserOriginated());
+ }
+ });
+
+ grid.setSelectionMode(SelectionMode.NONE);
+
+ grid.getEditorField(getColumnProperty(3)).setReadOnly(true);
+
+ createGridActions();
+
+ createColumnActions();
+
+ createPropertyActions();
+
+ createHeaderActions();
+
+ createFooterActions();
+
+ createRowActions();
+
+ createEditorActions();
+
+ addHeightActions();
+
+ addFilterActions();
+
+ this.grid = grid;
+ return grid;
+ }
+
+ private void addFilterActions() {
+ createClickAction("Column 1 starts with \"(23\"", "Filter",
+ new Command<Grid, Void>() {
+ @Override
+ public void execute(Grid grid, Void value, Object data) {
+ ds.addContainerFilter(new Filter() {
+
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedOperationException {
+ return item.getItemProperty("Column 1")
+ .getValue().toString()
+ .startsWith("(23");
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return propertyId.equals("Column 1");
+ }
+ });
+ }
+ }, null);
+
+ createClickAction("Add impassable filter", "Filter",
+ new Command<Grid, Void>() {
+ @Override
+ public void execute(Grid c, Void value, Object data) {
+ ds.addContainerFilter(new Filter() {
+ @Override
+ public boolean passesFilter(Object itemId, Item item)
+ throws UnsupportedOperationException {
+ return false;
+ }
+
+ @Override
+ public boolean appliesToProperty(Object propertyId) {
+ return true;
+ }
+ });
+ }
+ }, null);
+ }
+
+ protected void createGridActions() {
+ LinkedHashMap<String, String> primaryStyleNames = new LinkedHashMap<String, String>();
+ primaryStyleNames.put("v-grid", "v-grid");
+ primaryStyleNames.put("v-escalator", "v-escalator");
+ primaryStyleNames.put("my-grid", "my-grid");
+
+ createMultiClickAction("Primary style name", "State",
+ primaryStyleNames, new Command<Grid, String>() {
+
+ @Override
+ public void execute(Grid grid, String value, Object data) {
+ grid.setPrimaryStyleName(value);
+
+ }
+ }, primaryStyleNames.get("v-grid"));
+
+ LinkedHashMap<String, SelectionMode> selectionModes = new LinkedHashMap<String, Grid.SelectionMode>();
+ selectionModes.put("single", SelectionMode.SINGLE);
+ selectionModes.put("multi", SelectionMode.MULTI);
+ selectionModes.put("none", SelectionMode.NONE);
+ createSelectAction("Selection mode", "State", selectionModes, "none",
+ new Command<Grid, Grid.SelectionMode>() {
+ @Override
+ public void execute(Grid grid, SelectionMode selectionMode,
+ Object data) {
+ grid.setSelectionMode(selectionMode);
+ if (selectionMode == SelectionMode.SINGLE) {
+ grid.addSelectionListener(selectionListener);
+ } else {
+ grid.removeSelectionListener(selectionListener);
+ }
+ }
+ });
+
+ LinkedHashMap<String, Integer> selectionLimits = new LinkedHashMap<String, Integer>();
+ selectionLimits.put("2", Integer.valueOf(2));
+ selectionLimits.put("1000", Integer.valueOf(1000));
+ selectionLimits.put("Integer.MAX_VALUE",
+ Integer.valueOf(Integer.MAX_VALUE));
+ createSelectAction("Selection limit", "State", selectionLimits, "1000",
+ new Command<Grid, Integer>() {
+ @Override
+ public void execute(Grid grid, Integer limit, Object data) {
+ if (!(grid.getSelectionModel() instanceof MultiSelectionModel)) {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ }
+
+ ((MultiSelectionModel) grid.getSelectionModel())
+ .setSelectionLimit(limit.intValue());
+ }
+ });
+
+ LinkedHashMap<String, List<SortOrder>> sortableProperties = new LinkedHashMap<String, List<SortOrder>>();
+ for (Object propertyId : ds.getSortableContainerPropertyIds()) {
+ sortableProperties.put(propertyId + ", ASC", Sort.by(propertyId)
+ .build());
+ sortableProperties.put(propertyId + ", DESC",
+ Sort.by(propertyId, SortDirection.DESCENDING).build());
+ }
+ createSelectAction("Sort by column", "State", sortableProperties,
+ "Column 9, ascending", new Command<Grid, List<SortOrder>>() {
+ @Override
+ public void execute(Grid grid, List<SortOrder> sortOrder,
+ Object data) {
+ grid.setSortOrder(sortOrder);
+ }
+ });
+
+ createBooleanAction("Reverse Grid Columns", "State", false,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ List<Object> ids = new ArrayList<Object>();
+ ids.addAll(ds.getContainerPropertyIds());
+ if (!value) {
+ c.setColumnOrder(ids.toArray());
+ } else {
+ Object[] idsArray = new Object[ids.size()];
+ for (int i = 0; i < ids.size(); ++i) {
+ idsArray[i] = ids.get((ids.size() - 1) - i);
+ }
+ c.setColumnOrder(idsArray);
+ }
+ }
+ });
+
+ LinkedHashMap<String, CellStyleGenerator> cellStyleGenerators = new LinkedHashMap<String, CellStyleGenerator>();
+ LinkedHashMap<String, RowStyleGenerator> rowStyleGenerators = new LinkedHashMap<String, RowStyleGenerator>();
+ rowStyleGenerators.put(ROW_STYLE_GENERATOR_NONE, null);
+ rowStyleGenerators.put(ROW_STYLE_GENERATOR_ROW_NUMBERS,
+ new RowStyleGenerator() {
+ @Override
+ public String getStyle(RowReference rowReference) {
+ return "row" + rowReference.getItemId();
+ }
+ });
+ rowStyleGenerators.put(ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4,
+ new RowStyleGenerator() {
+ @Override
+ public String getStyle(RowReference rowReference) {
+ int rowIndex = ((Integer) rowReference.getItemId())
+ .intValue();
+
+ if (rowIndex % 4 == 0) {
+ return null;
+ } else {
+ return "row" + rowReference.getItemId();
+ }
+ }
+ });
+ cellStyleGenerators.put(CELL_STYLE_GENERATOR_NONE, null);
+ cellStyleGenerators.put(CELL_STYLE_GENERATOR_PROPERTY_TO_STRING,
+ new CellStyleGenerator() {
+ @Override
+ public String getStyle(CellReference cellReference) {
+ return cellReference.getPropertyId().toString()
+ .replace(' ', '-');
+ }
+ });
+ cellStyleGenerators.put(CELL_STYLE_GENERATOR_SPECIAL,
+ new CellStyleGenerator() {
+ @Override
+ public String getStyle(CellReference cellReference) {
+ int rowIndex = ((Integer) cellReference.getItemId())
+ .intValue();
+ Object propertyId = cellReference.getPropertyId();
+ if (rowIndex % 4 == 1) {
+ return null;
+ } else if (rowIndex % 4 == 3
+ && "Column 1".equals(propertyId)) {
+ return null;
+ }
+ return propertyId.toString().replace(' ', '_');
+ }
+ });
+
+ createSelectAction("Row style generator", "State", rowStyleGenerators,
+ CELL_STYLE_GENERATOR_NONE,
+ new Command<Grid, RowStyleGenerator>() {
+ @Override
+ public void execute(Grid grid, RowStyleGenerator generator,
+ Object data) {
+ grid.setRowStyleGenerator(generator);
+ }
+ });
+
+ createSelectAction("Cell style generator", "State",
+ cellStyleGenerators, CELL_STYLE_GENERATOR_NONE,
+ new Command<Grid, CellStyleGenerator>() {
+ @Override
+ public void execute(Grid grid,
+ CellStyleGenerator generator, Object data) {
+ grid.setCellStyleGenerator(generator);
+ }
+ });
+
+ LinkedHashMap<String, Integer> frozenOptions = new LinkedHashMap<String, Integer>();
+ for (int i = -1; i <= COLUMNS; i++) {
+ frozenOptions.put(String.valueOf(i), Integer.valueOf(i));
+ }
+ createSelectAction("Frozen column count", "State", frozenOptions, "0",
+ new Command<Grid, Integer>() {
+ @Override
+ public void execute(Grid c, Integer value, Object data) {
+ c.setFrozenColumnCount(value.intValue());
+ }
+ });
+
+ LinkedHashMap<String, Integer> containerDelayValues = new LinkedHashMap<String, Integer>();
+ for (int delay : new int[] { 0, 500, 2000, 10000 }) {
+ containerDelayValues.put(String.valueOf(delay),
+ Integer.valueOf(delay));
+ }
+
+ createSelectAction("Container delay", "State", containerDelayValues,
+ "0", new Command<Grid, Integer>() {
+ @Override
+ public void execute(Grid grid, Integer delay, Object data) {
+ containerDelay = delay.intValue();
+ }
+ });
+
+ createBooleanAction("ItemClickListener", "State", false,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ if (!value) {
+ c.removeItemClickListener(itemClickListener);
+ } else {
+ c.addItemClickListener(itemClickListener);
+ }
+ }
+
+ });
+ }
+
+ protected void createHeaderActions() {
+ createCategory("Header", null);
+
+ createBooleanAction("Visible", "Header", true,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid grid, Boolean value, Object data) {
+ grid.setHeaderVisible(value);
+ }
+ });
+
+ LinkedHashMap<String, String> defaultRows = new LinkedHashMap<String, String>();
+ defaultRows.put("Top", "Top");
+ defaultRows.put("Bottom", "Bottom");
+ defaultRows.put("Unset", "Unset");
+
+ createMultiClickAction("Default row", "Header", defaultRows,
+ new Command<Grid, String>() {
+
+ @Override
+ public void execute(Grid grid, String value, Object data) {
+ HeaderRow defaultRow = null;
+ if (value.equals("Top")) {
+ defaultRow = grid.getHeaderRow(0);
+ } else if (value.equals("Bottom")) {
+ defaultRow = grid.getHeaderRow(grid
+ .getHeaderRowCount() - 1);
+ }
+ grid.setDefaultHeaderRow(defaultRow);
+ }
+
+ }, defaultRows.get("Top"));
+
+ createClickAction("Prepend row", "Header", new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.prependHeaderRow();
+ }
+
+ }, null);
+ createClickAction("Append row", "Header", new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.appendHeaderRow();
+ }
+
+ }, null);
+
+ createClickAction("Remove top row", "Header",
+ new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.removeHeaderRow(0);
+ }
+
+ }, null);
+ createClickAction("Remove bottom row", "Header",
+ new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.removeHeaderRow(grid.getHeaderRowCount() - 1);
+ }
+
+ }, null);
+ }
+
+ protected void createFooterActions() {
+ createCategory("Footer", null);
+
+ createBooleanAction("Visible", "Footer", false,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid grid, Boolean value, Object data) {
+ grid.setFooterVisible(value);
+ }
+ });
+
+ createClickAction("Prepend row", "Footer", new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.prependFooterRow();
+ }
+
+ }, null);
+ createClickAction("Append row", "Footer", new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.appendFooterRow();
+ }
+
+ }, null);
+
+ createClickAction("Remove top row", "Footer",
+ new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.removeFooterRow(0);
+ }
+
+ }, null);
+ createClickAction("Remove bottom row", "Footer",
+ new Command<Grid, Object>() {
+
+ @Override
+ public void execute(Grid grid, Object value, Object data) {
+ grid.removeFooterRow(grid.getFooterRowCount() - 1);
+ }
+
+ }, null);
+ }
+
+ protected void createColumnActions() {
+ createCategory("Columns", null);
+
+ for (int c = 0; c < COLUMNS; c++) {
+ final int index = c;
+ createCategory(getColumnProperty(c), "Columns");
+
+ createClickAction("Add / Remove", getColumnProperty(c),
+ new Command<Grid, String>() {
+
+ @Override
+ public void execute(Grid grid, String value, Object data) {
+ String columnProperty = getColumnProperty((Integer) data);
+ if (grid.getColumn(columnProperty) == null) {
+ grid.addColumn(columnProperty);
+ } else {
+ grid.removeColumn(columnProperty);
+ }
+ }
+ }, null, c);
+
+ createBooleanAction("Sortable", getColumnProperty(c), true,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid grid, Boolean value,
+ Object columnIndex) {
+ Object propertyId = getColumnProperty((Integer) columnIndex);
+ Column column = grid.getColumn(propertyId);
+ column.setSortable(value);
+ }
+ }, c);
+
+ createCategory("Column " + c + " Width", getColumnProperty(c));
+
+ createClickAction("Auto", "Column " + c + " Width",
+ new Command<Grid, Integer>() {
+
+ @Override
+ public void execute(Grid grid, Integer value,
+ Object columnIndex) {
+ Object propertyId = getColumnProperty((Integer) columnIndex);
+ Column column = grid.getColumn(propertyId);
+ column.setWidthUndefined();
+ }
+ }, -1, c);
+
+ createClickAction("25.5px", "Column " + c + " Width",
+ new Command<Grid, Void>() {
+ @Override
+ @SuppressWarnings("boxing")
+ public void execute(Grid grid, Void value,
+ Object columnIndex) {
+ grid.getColumns().get((Integer) columnIndex)
+ .setWidth(25.5);
+ }
+ }, null, c);
+
+ for (int w = 50; w < 300; w += 50) {
+ createClickAction(w + "px", "Column " + c + " Width",
+ new Command<Grid, Integer>() {
+
+ @Override
+ public void execute(Grid grid, Integer value,
+ Object columnIndex) {
+ Object propertyId = getColumnProperty((Integer) columnIndex);
+ Column column = grid.getColumn(propertyId);
+ column.setWidth(value);
+ }
+ }, w, c);
+ }
+
+ LinkedHashMap<String, GridStaticCellType> defaultRows = new LinkedHashMap<String, GridStaticCellType>();
+ defaultRows.put("Text Header", GridStaticCellType.TEXT);
+ defaultRows.put("Html Header ", GridStaticCellType.HTML);
+ defaultRows.put("Widget Header", GridStaticCellType.WIDGET);
+
+ createMultiClickAction("Header Type", getColumnProperty(c),
+ defaultRows, new Command<Grid, GridStaticCellType>() {
+
+ @Override
+ public void execute(Grid grid,
+ GridStaticCellType value, Object columnIndex) {
+ final Object propertyId = getColumnProperty((Integer) columnIndex);
+ final HeaderCell cell = grid.getDefaultHeaderRow()
+ .getCell(propertyId);
+ switch (value) {
+ case TEXT:
+ cell.setText("Text Header");
+ break;
+ case HTML:
+ cell.setHtml("HTML Header");
+ break;
+ case WIDGET:
+ cell.setComponent(new Button("Button Header",
+ new ClickListener() {
+
+ @Override
+ public void buttonClick(
+ ClickEvent event) {
+ log("Button clicked!");
+ }
+ }));
+ default:
+ break;
+ }
+ }
+
+ }, c);
+
+ defaultRows = new LinkedHashMap<String, GridStaticCellType>();
+ defaultRows.put("Text Footer", GridStaticCellType.TEXT);
+ defaultRows.put("Html Footer", GridStaticCellType.HTML);
+ defaultRows.put("Widget Footer", GridStaticCellType.WIDGET);
+
+ createMultiClickAction("Footer Type", getColumnProperty(c),
+ defaultRows, new Command<Grid, GridStaticCellType>() {
+
+ @Override
+ public void execute(Grid grid,
+ GridStaticCellType value, Object columnIndex) {
+ final Object propertyId = getColumnProperty((Integer) columnIndex);
+ final FooterCell cell = grid.getFooterRow(0)
+ .getCell(propertyId);
+ switch (value) {
+ case TEXT:
+ cell.setText("Text Footer");
+ break;
+ case HTML:
+ cell.setHtml("HTML Footer");
+ break;
+ case WIDGET:
+ cell.setComponent(new Button("Button Footer",
+ new ClickListener() {
+
+ @Override
+ public void buttonClick(
+ ClickEvent event) {
+ log("Button clicked!");
+ }
+ }));
+ default:
+ break;
+ }
+ }
+
+ }, c);
+ }
+ }
+
+ private static String getColumnProperty(int c) {
+ return "Column " + c;
+ }
+
+ protected void createPropertyActions() {
+ createCategory("Properties", null);
+
+ createBooleanAction("Prepend property", "Properties", false,
+ new Command<Grid, Boolean>() {
+ private final Object propertyId = new Object();
+
+ @Override
+ public void execute(Grid c, Boolean enable, Object data) {
+ if (enable.booleanValue()) {
+ ds.addContainerProperty(propertyId, String.class,
+ "property value");
+ grid.getColumn(propertyId).setHeaderCaption(
+ "new property");
+ grid.setColumnOrder(propertyId);
+ } else {
+ ds.removeContainerProperty(propertyId);
+ }
+ }
+ }, null);
+ }
+
+ protected void createRowActions() {
+ createCategory("Body rows", null);
+
+ class NewRowCommand implements Command<Grid, String> {
+ private final int index;
+
+ public NewRowCommand() {
+ this(0);
+ }
+
+ public NewRowCommand(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ Item item = ds.addItemAt(index, new Object());
+ for (int i = 0; i < COLUMNS; i++) {
+ Class<?> type = ds.getType(getColumnProperty(i));
+ if (String.class.isAssignableFrom(type)) {
+ Property<String> itemProperty = getProperty(item, i);
+ itemProperty.setValue("newcell: " + i);
+ } else if (Integer.class.isAssignableFrom(type)) {
+ Property<Integer> itemProperty = getProperty(item, i);
+ itemProperty.setValue(Integer.valueOf(i));
+ } else {
+ // let the default value be taken implicitly.
+ }
+ }
+ }
+
+ private <T extends Object> Property<T> getProperty(Item item, int i) {
+ @SuppressWarnings("unchecked")
+ Property<T> itemProperty = item
+ .getItemProperty(getColumnProperty(i));
+ return itemProperty;
+ }
+ }
+ final NewRowCommand newRowCommand = new NewRowCommand();
+
+ createClickAction("Add 18 rows", "Body rows",
+ new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ for (int i = 0; i < 18; i++) {
+ newRowCommand.execute(c, value, data);
+ }
+ }
+ }, null);
+
+ createClickAction("Add first row", "Body rows", newRowCommand, null);
+
+ createClickAction("Add third row", "Body rows", new NewRowCommand(2),
+ null);
+
+ createClickAction("Remove first row", "Body rows",
+ new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ Object firstItemId = ds.getIdByIndex(0);
+ ds.removeItem(firstItemId);
+ }
+ }, null);
+
+ createClickAction("Remove 18 first rows", "Body rows",
+ new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ for (int i = 0; i < 18; i++) {
+ Object firstItemId = ds.getIdByIndex(0);
+ ds.removeItem(firstItemId);
+ }
+ }
+ }, null);
+
+ createClickAction("Modify first row (getItemProperty)", "Body rows",
+ new Command<Grid, String>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ Object firstItemId = ds.getIdByIndex(0);
+ Item item = ds.getItem(firstItemId);
+ for (int i = 0; i < COLUMNS; i++) {
+ Property<?> property = item
+ .getItemProperty(getColumnProperty(i));
+ if (property.getType().equals(String.class)) {
+ ((Property<String>) property)
+ .setValue("modified: " + i);
+ }
+ }
+ }
+ }, null);
+
+ createClickAction("Modify first row (getContainerProperty)",
+ "Body rows", new Command<Grid, String>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ Object firstItemId = ds.getIdByIndex(0);
+ for (Object containerPropertyId : ds
+ .getContainerPropertyIds()) {
+ Property<?> property = ds.getContainerProperty(
+ firstItemId, containerPropertyId);
+ if (property.getType().equals(String.class)) {
+ ((Property<String>) property)
+ .setValue("modified: "
+ + containerPropertyId);
+ }
+ }
+ }
+ }, null);
+
+ createBooleanAction("Select first row", "Body rows", false,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid grid, Boolean select, Object data) {
+ final Object firstItemId = grid
+ .getContainerDataSource().firstItemId();
+ if (select.booleanValue()) {
+ grid.select(firstItemId);
+ } else {
+ grid.deselect(firstItemId);
+ }
+ }
+ });
+
+ createClickAction("Remove all rows", "Body rows",
+ new Command<Grid, String>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ ds.removeAllItems();
+ }
+ }, null);
+ }
+
+ protected void createEditorActions() {
+ createBooleanAction("Enabled", "Editor", false,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ c.setEditorEnabled(value);
+ }
+ });
+
+ createClickAction("Edit item 5", "Editor", new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ c.editItem(5);
+ }
+ }, null);
+
+ createClickAction("Edit item 100", "Editor",
+ new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ c.editItem(100);
+ }
+ }, null);
+ createClickAction("Save", "Editor", new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ try {
+ c.saveEditor();
+ } catch (CommitException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }, null);
+ createClickAction("Cancel edit", "Editor", new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ c.cancelEditor();
+ }
+ }, null);
+ }
+
+ @SuppressWarnings("boxing")
+ protected void addHeightActions() {
+ createCategory("Height by Rows", "Size");
+
+ createBooleanAction("HeightMode Row", "Size", false,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean heightModeByRows,
+ Object data) {
+ c.setHeightMode(heightModeByRows ? HeightMode.ROW
+ : HeightMode.CSS);
+ }
+ }, null);
+
+ addActionForHeightByRows(1d / 3d);
+ addActionForHeightByRows(2d / 3d);
+
+ for (double i = 1; i < 5; i++) {
+ addActionForHeightByRows(i);
+ addActionForHeightByRows(i + 1d / 3d);
+ addActionForHeightByRows(i + 2d / 3d);
+ }
+
+ Command<Grid, String> sizeCommand = new Command<Grid, String>() {
+ @Override
+ public void execute(Grid grid, String height, Object data) {
+ grid.setHeight(height);
+ }
+ };
+
+ createCategory("Height", "Size");
+ // header 20px + scrollbar 16px = 36px baseline
+ createClickAction("86px (no drag scroll select)", "Height",
+ sizeCommand, "86px");
+ createClickAction("96px (drag scroll select limit)", "Height",
+ sizeCommand, "96px");
+ createClickAction("106px (drag scroll select enabled)", "Height",
+ sizeCommand, "106px");
+ }
+
+ private void addActionForHeightByRows(final Double i) {
+ DecimalFormat df = new DecimalFormat("0.00");
+ createClickAction(df.format(i) + " rows", "Height by Rows",
+ new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ c.setHeightByRows(i);
+ }
+ }, null);
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 12829;
+ }
+
+ @Override
+ protected Class<Grid> getTestClass() {
+ return Grid.class;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java
new file mode 100644
index 0000000000..0e339ec0ae
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public abstract class GridBasicFeaturesTest extends MultiBrowserTest {
+
+ @Override
+ protected DesiredCapabilities getDesiredCapabilities() {
+ DesiredCapabilities dCap = super.getDesiredCapabilities();
+ if (BrowserUtil.isIE(dCap)) {
+ dCap.setCapability("requireWindowFocus", true);
+ }
+ return super.getDesiredCapabilities();
+ }
+
+ @Override
+ protected Class<?> getUIClass() {
+ return GridBasicFeatures.class;
+ }
+
+ protected void selectSubMenu(String menuCaption) {
+ selectMenu(menuCaption);
+ new Actions(getDriver()).moveByOffset(100, 0).build().perform();
+ }
+
+ protected void selectMenu(String menuCaption) {
+ getDriver().findElement(
+ By.xpath("//span[text() = '" + menuCaption + "']")).click();
+ }
+
+ protected void selectMenuPath(String... menuCaptions) {
+ selectMenu(menuCaptions[0]);
+ for (int i = 1; i < menuCaptions.length; i++) {
+ selectSubMenu(menuCaptions[i]);
+ }
+ }
+
+ protected GridElement getGridElement() {
+ return ((TestBenchElement) findElement(By.id("testComponent")))
+ .wrap(GridElement.class);
+ }
+
+ protected void scrollGridVerticallyTo(double px) {
+ executeScript("arguments[0].scrollTop = " + px,
+ getGridVerticalScrollbar());
+ }
+
+ protected int getGridVerticalScrollPos() {
+ return ((Number) executeScript("return arguments[0].scrollTop",
+ getGridVerticalScrollbar())).intValue();
+ }
+
+ protected List<TestBenchElement> getGridHeaderRowCells() {
+ List<TestBenchElement> headerCells = new ArrayList<TestBenchElement>();
+ for (int i = 0; i < getGridElement().getHeaderCount(); ++i) {
+ headerCells.addAll(getGridElement().getHeaderCells(i));
+ }
+ return headerCells;
+ }
+
+ protected List<TestBenchElement> getGridFooterRowCells() {
+ List<TestBenchElement> footerCells = new ArrayList<TestBenchElement>();
+ for (int i = 0; i < getGridElement().getFooterCount(); ++i) {
+ footerCells.addAll(getGridElement().getFooterCells(i));
+ }
+ return footerCells;
+ }
+
+ protected WebElement getEditor() {
+ List<WebElement> elems = getGridElement().findElements(
+ By.className("v-grid-editor"));
+
+ assertLessThanOrEqual("number of editors", elems.size(), 1);
+
+ return elems.isEmpty() ? null : elems.get(0);
+ }
+
+ private Object executeScript(String script, WebElement element) {
+ final WebDriver driver = getDriver();
+ if (driver instanceof JavascriptExecutor) {
+ final JavascriptExecutor je = (JavascriptExecutor) driver;
+ return je.executeScript(script, element);
+ } else {
+ throw new IllegalStateException("current driver "
+ + getDriver().getClass().getName() + " is not a "
+ + JavascriptExecutor.class.getSimpleName());
+ }
+ }
+
+ protected WebElement getGridVerticalScrollbar() {
+ return getDriver()
+ .findElement(
+ By.xpath("//div[contains(@class, \"v-grid-scroller-vertical\")]"));
+ }
+
+ /**
+ * Reloads the page without restartApplication. This occasionally breaks
+ * stuff.
+ */
+ protected void reopenTestURL() {
+ String testUrl = getTestUrl();
+ testUrl = testUrl.replace("?restartApplication", "?");
+ testUrl = testUrl.replace("?&", "?");
+ driver.get(testUrl);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesValo.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesValo.java
new file mode 100644
index 0000000000..aef353fe93
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesValo.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.ui.themes.ValoTheme;
+
+@Theme(ValoTheme.THEME_NAME)
+public class GridBasicFeaturesValo extends GridBasicFeatures {
+ @Override
+ @Deprecated
+ public String getTheme() {
+ return ValoTheme.THEME_NAME;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSources.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSources.java
new file mode 100644
index 0000000000..3f84d40b01
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSources.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.GridClientDataSourcesWidget;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+import com.vaadin.ui.UI;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class GridClientDataSources extends UI {
+
+ @Override
+ protected void init(VaadinRequest request) {
+ setContent(new TestWidgetComponent(GridClientDataSourcesWidget.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSourcesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSourcesTest.java
new file mode 100644
index 0000000000..30d6541344
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientDataSourcesTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Dimension;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridClientDataSourcesTest extends MultiBrowserTest {
+
+ @Before
+ public void before() {
+ openTestURL();
+ }
+
+ @Test
+ public void normalRestishDatasource() throws Exception {
+ selectMenuPath("DataSources", "RESTish", "Use");
+ assertCellPresent("cell 0 #0");
+
+ scrollToBottom();
+ assertCellPresent("cell 199 #0");
+ assertCellNotPresent("cell 200 #0");
+ }
+
+ @Test
+ public void growOnRequestRestishDatasource() throws Exception {
+ selectMenuPath("DataSources", "RESTish", "Use");
+ selectMenuPath("DataSources", "RESTish", "Next request +10");
+
+ scrollToBottom();
+ /* second scroll needed because of scrollsize change after scrolling */
+ scrollToBottom();
+
+ assertCellPresent("cell 209 #1");
+ assertCellNotPresent("cell 210 #1");
+ }
+
+ @Test
+ public void shrinkOnRequestRestishDatasource() throws Exception {
+ selectMenuPath("DataSources", "RESTish", "Use");
+ scrollToBottom();
+
+ selectMenuPath("DataSources", "RESTish", "Next request -10");
+ scrollToTop();
+
+ assertCellPresent("cell 0 #1");
+ }
+
+ @Test
+ public void pushChangeRestishDatasource() throws Exception {
+ selectMenuPath("DataSources", "RESTish", "Use");
+ selectMenuPath("DataSources", "RESTish", "Push data change");
+ assertCellPresent("cell 0 #1");
+ assertCellNotPresent("cell 0 #0");
+ }
+
+ @Test
+ public void growOnPushRestishDatasource() throws Exception {
+ selectMenuPath("DataSources", "RESTish", "Use");
+ selectMenuPath("DataSources", "RESTish", "Push data change +10");
+ assertCellPresent("cell 0 #1");
+ assertCellNotPresent("cell 0 #0");
+ scrollToBottom();
+ assertCellPresent("cell 209 #1");
+ }
+
+ @Test
+ public void shrinkOnPushRestishDatasource() throws Exception {
+ selectMenuPath("DataSources", "RESTish", "Use");
+ scrollToBottom();
+
+ selectMenuPath("DataSources", "RESTish", "Push data change -10");
+ assertCellPresent("cell 189 #1");
+ assertCellNotPresent("cell 189 #0");
+ assertCellNotPresent("cell 199 #1");
+ assertCellNotPresent("cell 199 #0");
+ }
+
+ private void assertCellPresent(String content) {
+ assertNotNull("A cell with content \"" + content
+ + "\" should've been found", findByXPath("//td[text()='"
+ + content + "']"));
+ }
+
+ private void assertCellNotPresent(String content) {
+ assertNull("A cell with content \"" + content
+ + "\" should've not been found", findByXPath("//td[text()='"
+ + content + "']"));
+ }
+
+ private void scrollToTop() {
+ scrollVerticallyTo(0);
+ }
+
+ private void scrollToBottom() {
+ scrollVerticallyTo(9999);
+ }
+
+ private WebElement findByXPath(String string) {
+ if (isElementPresent(By.xpath(string))) {
+ return findElement(By.xpath(string));
+ } else {
+ return null;
+ }
+ }
+
+ private void scrollVerticallyTo(int px) {
+ executeScript("arguments[0].scrollTop = " + px, findVerticalScrollbar());
+ }
+
+ private Object executeScript(String script, Object args) {
+ final WebDriver driver = getDriver();
+ if (driver instanceof JavascriptExecutor) {
+ final JavascriptExecutor je = (JavascriptExecutor) driver;
+ return je.executeScript(script, args);
+ } else {
+ throw new IllegalStateException("current driver "
+ + getDriver().getClass().getName() + " is not a "
+ + JavascriptExecutor.class.getSimpleName());
+ }
+ }
+
+ private WebElement findVerticalScrollbar() {
+ return getDriver().findElement(
+ By.xpath("//div[contains(@class, "
+ + "\"v-grid-scroller-vertical\")]"));
+ }
+
+ private void selectMenu(String menuCaption) {
+ WebElement menuElement = getMenuElement(menuCaption);
+ Dimension size = menuElement.getSize();
+ new Actions(getDriver()).moveToElement(menuElement, size.width - 10,
+ size.height / 2).perform();
+ }
+
+ private WebElement getMenuElement(String menuCaption) {
+ return getDriver().findElement(
+ By.xpath("//td[text() = '" + menuCaption + "']"));
+ }
+
+ private void selectMenuPath(String... menuCaptions) {
+ new Actions(getDriver()).moveToElement(getMenuElement(menuCaptions[0]))
+ .click().perform();
+ for (int i = 1; i < menuCaptions.length - 1; ++i) {
+ selectMenu(menuCaptions[i]);
+ new Actions(getDriver()).moveByOffset(20, 0).perform();
+ }
+ new Actions(getDriver())
+ .moveToElement(
+ getMenuElement(menuCaptions[menuCaptions.length - 1]))
+ .click().perform();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInit.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInit.java
new file mode 100644
index 0000000000..afbe3fcbbb
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInit.java
@@ -0,0 +1,20 @@
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Title;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.GridHeightByRowOnInitWidget;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+import com.vaadin.ui.UI;
+
+@Theme("valo")
+@Title("Client Grid height by row on init")
+@Widgetset(TestingWidgetSet.NAME)
+public class GridClientHeightByRowOnInit extends UI {
+ @Override
+ protected void init(VaadinRequest request) {
+ setContent(new TestWidgetComponent(GridHeightByRowOnInitWidget.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInitTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInitTest.java
new file mode 100644
index 0000000000..dadaff0eaa
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientHeightByRowOnInitTest.java
@@ -0,0 +1,19 @@
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@SuppressWarnings("all")
+@TestCategory("grid")
+public class GridClientHeightByRowOnInitTest extends MultiBrowserTest {
+ @Test
+ public void gridHeightIsMoreThanACoupleOfRows() {
+ openTestURL();
+ int height = findElement(By.className("v-grid")).getSize().getHeight();
+ assertGreater("Grid should be much taller than 150px (was " + height
+ + "px)", height, 150);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRenderer.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRenderer.java
new file mode 100644
index 0000000000..5c4ccfae89
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRenderer.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.GridDefaultTextRendererWidget;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+import com.vaadin.ui.UI;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class GridDefaultTextRenderer extends UI {
+
+ @Override
+ protected void init(VaadinRequest request) {
+ setContent(new TestWidgetComponent(GridDefaultTextRendererWidget.class));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRendererTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRendererTest.java
new file mode 100644
index 0000000000..79eadd03d8
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridDefaultTextRendererTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.testbench.elements.ServerClass;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridDefaultTextRendererTest extends MultiBrowserTest {
+
+ @ServerClass("com.vaadin.tests.widgetset.server.TestWidgetComponent")
+ public static class MyGridElement extends GridElement {
+ // empty
+ }
+
+ private GridElement grid;
+
+ @Before
+ public void init() {
+ setDebug(true);
+ openTestURL();
+ grid = $(MyGridElement.class).first();
+ assertFalse("There was an unexpected notification during init",
+ $(NotificationElement.class).exists());
+ }
+
+ @Test
+ public void testNullIsRenderedAsEmptyStringByDefaultTextRenderer() {
+ assertTrue("First cell should've been empty", grid.getCell(0, 0)
+ .getText().isEmpty());
+ }
+
+ @Test
+ public void testStringIsRenderedAsStringByDefaultTextRenderer() {
+ assertEquals("Second cell should've been populated ", "string", grid
+ .getCell(1, 0).getText());
+ }
+
+ @Test
+ public void testWarningShouldNotBeInDebugLog() {
+ assertFalse("Warning visible with string content.",
+ isElementPresent(By.xpath("//span[contains(.,'attached:#1')]")));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInit.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInit.java
new file mode 100644
index 0000000000..0b6e6c36dd
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInit.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Title;
+import com.vaadin.data.Container;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.grid.HeightMode;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.themes.ValoTheme;
+
+@Title("Server Grid height by row on init")
+@Theme(ValoTheme.THEME_NAME)
+public class GridHeightByRowOnInit extends UI {
+
+ private static final String PROPERTY = "Property";
+
+ @Override
+ protected void init(VaadinRequest request) {
+ final Grid grid = new Grid();
+ Container.Indexed container = grid.getContainerDataSource();
+ container.addContainerProperty(PROPERTY, String.class, "");
+
+ container.addItem("A").getItemProperty(PROPERTY).setValue("A");
+ container.addItem("B").getItemProperty(PROPERTY).setValue("B");
+ container.addItem("C").getItemProperty(PROPERTY).setValue("C");
+ container.addItem("D").getItemProperty(PROPERTY).setValue("D");
+ container.addItem("E").getItemProperty(PROPERTY).setValue("E");
+
+ grid.setHeightMode(HeightMode.ROW);
+ grid.setHeightByRows(5);
+
+ setContent(grid);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInitTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInitTest.java
new file mode 100644
index 0000000000..15a1cd6c85
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeightByRowOnInitTest.java
@@ -0,0 +1,20 @@
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@SuppressWarnings("all")
+@TestCategory("grid")
+public class GridHeightByRowOnInitTest extends MultiBrowserTest {
+
+ @Test
+ public void gridHeightIsMoreThanACoupleOfRows() {
+ openTestURL();
+ int height = $(GridElement.class).first().getSize().getHeight();
+ assertGreater("Grid should be much taller than 150px (was " + height
+ + "px)", height, 150);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicators.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicators.java
new file mode 100644
index 0000000000..6d602baf06
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicators.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.sort.Sort;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Grid;
+
+public class GridSortingIndicators extends AbstractTestUI {
+
+ private static int FOO_MIN = 4;
+ private static int BAR_MULTIPLIER = 3;
+ private static int BAZ_MAX = 132;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Grid grid = new Grid(createContainer());
+ addComponent(grid);
+ grid.sort(Sort.by("foo").then("bar", SortDirection.DESCENDING)
+ .then("baz"));
+
+ addComponent(new Button("Reverse sorting", new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.sort(Sort.by("baz", SortDirection.DESCENDING).then("bar")
+ .then("foo", SortDirection.DESCENDING));
+ }
+ }));
+ }
+
+ private Container.Indexed createContainer() {
+ IndexedContainer container = new IndexedContainer();
+ container.addContainerProperty("foo", Integer.class, 0);
+ container.addContainerProperty("bar", Integer.class, 0);
+ container.addContainerProperty("baz", Integer.class, 0);
+ for (int i = 0; i < 10; ++i) {
+ Item item = container.getItem(container.addItem());
+ item.getItemProperty("foo").setValue(FOO_MIN + i);
+ item.getItemProperty("baz").setValue(BAZ_MAX - i);
+ item.getItemProperty("bar").setValue(BAR_MULTIPLIER * i);
+ }
+ return container;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicatorsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicatorsTest.java
new file mode 100644
index 0000000000..6a5360f152
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingIndicatorsTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridSortingIndicatorsTest extends MultiBrowserTest {
+
+ @Test
+ public void testSortingIndicators() throws IOException {
+ openTestURL();
+ compareScreen("initialSort");
+
+ $(ButtonElement.class).first().click();
+
+ compareScreen("reversedSort");
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/DisabledGridClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/DisabledGridClientTest.java
new file mode 100644
index 0000000000..63d031bc85
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/DisabledGridClientTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+
+public class DisabledGridClientTest extends GridBasicClientFeaturesTest {
+
+ @Before
+ public void setUp() {
+ openTestURL();
+ selectMenuPath("Component", "State", "Enabled");
+ }
+
+ @Test
+ public void testSelection() {
+ selectMenuPath("Component", "State", "Selection mode", "single");
+
+ GridRowElement row = getGridElement().getRow(0);
+ row.click();
+ assertFalse("disabled row should not be selected", row.isSelected());
+
+ }
+
+ @Test
+ public void testEditorOpening() {
+ selectMenuPath("Component", "Editor", "Enabled");
+
+ GridRowElement row = getGridElement().getRow(0);
+ row.click();
+ assertNull("Editor should not open", getEditor());
+
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+ assertNull("Editor should not open", getEditor());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridCellStyleGeneratorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridCellStyleGeneratorTest.java
new file mode 100644
index 0000000000..8188553e61
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridCellStyleGeneratorTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget;
+
+public class GridCellStyleGeneratorTest extends GridBasicClientFeaturesTest {
+
+ @Test
+ public void testStyleNameGeneratorScrolling() throws Exception {
+ openTestURL();
+
+ selectCellStyleNameGenerator(GridBasicClientFeaturesWidget.CELL_STYLE_GENERATOR_COL_INDEX);
+ selectRowStyleNameGenerator(GridBasicClientFeaturesWidget.ROW_STYLE_GENERATOR_ROW_INDEX);
+
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell4_2 = getGridElement().getCell(4, 2);
+
+ Assert.assertTrue(hasCssClass(row2, "2"));
+ Assert.assertTrue(hasCssClass(cell4_2, "4_2"));
+
+ // Scroll down and verify that the old elements don't have the
+ // stylename any more
+
+ getGridElement().getRow(350);
+
+ Assert.assertFalse(hasCssClass(row2, "2"));
+ Assert.assertFalse(hasCssClass(cell4_2, "4_2"));
+ }
+
+ @Test
+ public void testDisableStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectCellStyleNameGenerator(GridBasicClientFeaturesWidget.CELL_STYLE_GENERATOR_COL_INDEX);
+ selectRowStyleNameGenerator(GridBasicClientFeaturesWidget.ROW_STYLE_GENERATOR_ROW_INDEX);
+
+ // Just verify that change was effective
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell4_2 = getGridElement().getCell(4, 2);
+
+ Assert.assertTrue(hasCssClass(row2, "2"));
+ Assert.assertTrue(hasCssClass(cell4_2, "4_2"));
+
+ // Disable the generator and check again
+ selectCellStyleNameGenerator(GridBasicClientFeaturesWidget.CELL_STYLE_GENERATOR_NONE);
+ selectRowStyleNameGenerator(GridBasicClientFeaturesWidget.ROW_STYLE_GENERATOR_NONE);
+
+ Assert.assertFalse(hasCssClass(row2, "2"));
+ Assert.assertFalse(hasCssClass(cell4_2, "4_2"));
+ }
+
+ @Test
+ public void testChangeStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectCellStyleNameGenerator(GridBasicClientFeaturesWidget.CELL_STYLE_GENERATOR_COL_INDEX);
+ selectRowStyleNameGenerator(GridBasicClientFeaturesWidget.ROW_STYLE_GENERATOR_ROW_INDEX);
+
+ // Just verify that change was effective
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell4_2 = getGridElement().getCell(4, 2);
+
+ Assert.assertTrue(hasCssClass(row2, "2"));
+ Assert.assertTrue(hasCssClass(cell4_2, "4_2"));
+
+ // Change the generator and check again
+ selectRowStyleNameGenerator(GridBasicClientFeaturesWidget.ROW_STYLE_GENERATOR_NONE);
+ selectCellStyleNameGenerator(GridBasicClientFeaturesWidget.CELL_STYLE_GENERATOR_SIMPLE);
+
+ // Old styles removed?
+ Assert.assertFalse(hasCssClass(row2, "2"));
+ Assert.assertFalse(hasCssClass(cell4_2, "4_2"));
+
+ // New style present?
+ Assert.assertTrue(hasCssClass(cell4_2, "two"));
+ }
+
+ @Test
+ public void testStyleNameGeneratorChangePrimary() throws Exception {
+ openTestURL();
+
+ selectCellStyleNameGenerator(GridBasicClientFeaturesWidget.CELL_STYLE_GENERATOR_COL_INDEX);
+ selectRowStyleNameGenerator(GridBasicClientFeaturesWidget.ROW_STYLE_GENERATOR_ROW_INDEX);
+
+ // Just verify that change was effective
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell4_2 = getGridElement().getCell(4, 2);
+
+ Assert.assertTrue(hasCssClass(row2, "2"));
+ Assert.assertTrue(hasCssClass(cell4_2, "4_2"));
+
+ // Change primary stylename
+ selectMenuPath("Component", "State", "Primary Stylename", "v-escalator");
+
+ // Styles still present
+ Assert.assertTrue(hasCssClass(row2, "2"));
+ Assert.assertTrue(hasCssClass(cell4_2, "4_2"));
+
+ // New styles present?
+ Assert.assertFalse(hasCssClass(row2, "v-escalator-row-2"));
+ Assert.assertFalse(hasCssClass(cell4_2, "v-escalator-cell-content-4_2"));
+ }
+
+ private void selectCellStyleNameGenerator(String name) {
+ selectMenuPath("Component", "State", "Cell style generator", name);
+ }
+
+ private void selectRowStyleNameGenerator(String name) {
+ selectMenuPath("Component", "State", "Row style generator", name);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java
new file mode 100644
index 0000000000..82bf349096
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget;
+
+public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest {
+
+ @Test
+ public void initialColumnWidths() {
+ openTestURL();
+
+ for (int col = 0; col < GridBasicClientFeaturesWidget.COLUMNS; col++) {
+ int width = getGridElement().getCell(0, col).getSize().getWidth();
+ if (col <= 6) {
+ // Growing column widths
+ int expectedWidth = 50 + col * 25;
+ assertEquals("column " + col + " has incorrect width",
+ expectedWidth, width);
+ }
+ }
+ }
+
+ @Test
+ public void testChangingColumnWidth() {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 0", "Width", "50px");
+ int width = getGridElement().getCell(0, 0).getSize().getWidth();
+ assertEquals(50, width);
+
+ selectMenuPath("Component", "Columns", "Column 0", "Width", "200px");
+ width = getGridElement().getCell(0, 0).getSize().getWidth();
+ assertEquals(200, width);
+
+ selectMenuPath("Component", "Columns", "Column 0", "Width", "auto");
+ int autoWidth = getGridElement().getCell(0, 0).getSize().getWidth();
+ assertLessThan("Automatic sizing should've shrunk the column",
+ autoWidth, width);
+ }
+
+ @Test
+ public void testFrozenColumns() {
+ openTestURL();
+
+ assertFalse(cellIsFrozen(0, 0));
+ assertFalse(cellIsFrozen(0, 1));
+
+ selectMenuPath("Component", "State", "Frozen column count", "1 columns");
+
+ assertTrue(cellIsFrozen(1, 0));
+ assertFalse(cellIsFrozen(1, 1));
+
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+
+ assertTrue(cellIsFrozen(1, 1));
+ assertFalse(cellIsFrozen(1, 2));
+
+ selectMenuPath("Component", "State", "Frozen column count", "0 columns");
+
+ assertTrue(cellIsFrozen(1, 0));
+ assertFalse(cellIsFrozen(1, 1));
+
+ selectMenuPath("Component", "State", "Frozen column count",
+ "-1 columns");
+
+ assertFalse(cellIsFrozen(1, 0));
+ }
+
+ @Test
+ public void testBrokenRenderer() {
+ setDebug(true);
+ openTestURL();
+
+ GridElement gridElement = getGridElement();
+
+ // Scroll first row out of view
+ gridElement.getRow(50);
+
+ // Enable broken renderer for the first row
+ selectMenuPath("Component", "Columns", "Column 0", "Broken renderer");
+
+ // Shouldn't have an error notification yet
+ assertFalse("Notification was present",
+ isElementPresent(NotificationElement.class));
+
+ // Scroll broken row into view and enjoy the chaos
+ gridElement.getRow(0);
+
+ assertTrue("Notification was not present",
+ isElementPresent(NotificationElement.class));
+
+ assertFalse("Text in broken cell should have old value",
+ "(0, 0)".equals(gridElement.getCell(0, 0).getText()));
+
+ assertEquals("Neighbour cell should be updated", "(0, 1)", gridElement
+ .getCell(0, 1).getText());
+
+ assertEquals("Neighbour cell should be updated", "(1, 0)", gridElement
+ .getCell(1, 0).getText());
+ }
+
+ private boolean cellIsFrozen(int row, int col) {
+ return getGridElement().getCell(row, col).isFrozen();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeEditorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeEditorTest.java
new file mode 100644
index 0000000000..29e6fed68c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeEditorTest.java
@@ -0,0 +1,13 @@
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import org.junit.Before;
+
+public class GridClientCompositeEditorTest extends GridEditorClientTest {
+
+ @Override
+ @Before
+ public void setUp() {
+ setUseComposite(true);
+ super.setUp();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeFooterTest.java
new file mode 100644
index 0000000000..26ae7320b0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeFooterTest.java
@@ -0,0 +1,11 @@
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import org.junit.Before;
+
+public class GridClientCompositeFooterTest extends GridFooterTest {
+
+ @Before
+ public void setUp() {
+ setUseComposite(true);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeHeaderTest.java
new file mode 100644
index 0000000000..c0ed833ab2
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeHeaderTest.java
@@ -0,0 +1,11 @@
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import org.junit.Before;
+
+public class GridClientCompositeHeaderTest extends GridHeaderTest {
+
+ @Before
+ public void setUp() {
+ setUseComposite(true);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeKeyEventsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeKeyEventsTest.java
new file mode 100644
index 0000000000..a09a31830f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeKeyEventsTest.java
@@ -0,0 +1,12 @@
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import org.junit.Before;
+
+public class GridClientCompositeKeyEventsTest extends
+ GridClientKeyEventsTest {
+
+ @Before
+ public void setUp() {
+ setUseComposite(true);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeSelectionTest.java
new file mode 100644
index 0000000000..7a79a114b8
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientCompositeSelectionTest.java
@@ -0,0 +1,11 @@
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import org.junit.Before;
+
+public class GridClientCompositeSelectionTest extends GridClientSelectionTest {
+
+ @Before
+ public void setUp() {
+ setUseComposite(true);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java
new file mode 100644
index 0000000000..dc4dedd3a0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+
+public class GridClientKeyEventsTest extends GridBasicClientFeaturesTest {
+
+ private List<String> eventOrder = Arrays.asList("Down", "Up", "Press");
+
+ @Test
+ public void testBodyKeyEvents() throws IOException {
+ openTestURL();
+
+ getGridElement().getCell(2, 2).click();
+
+ new Actions(getDriver()).sendKeys("a").perform();
+
+ for (int i = 0; i < 3; ++i) {
+ assertEquals("Body key event handler was not called.",
+ "(2, 2) event: GridKey" + eventOrder.get(i) + "Event:["
+ + (eventOrder.get(i).equals("Press") ? "a" : 65)
+ + "]",
+ findElements(By.className("v-label")).get(i * 3).getText());
+
+ assertTrue("Header key event handler got called unexpectedly.",
+ findElements(By.className("v-label")).get(i * 3 + 1)
+ .getText().isEmpty());
+ assertTrue("Footer key event handler got called unexpectedly.",
+ findElements(By.className("v-label")).get(i * 3 + 2)
+ .getText().isEmpty());
+ }
+
+ }
+
+ @Test
+ public void testHeaderKeyEvents() throws IOException {
+ openTestURL();
+
+ getGridElement().getHeaderCell(0, 2).click();
+
+ new Actions(getDriver()).sendKeys("a").perform();
+
+ for (int i = 0; i < 3; ++i) {
+ assertEquals("Header key event handler was not called.",
+ "(0, 2) event: GridKey" + eventOrder.get(i) + "Event:["
+ + (eventOrder.get(i).equals("Press") ? "a" : 65)
+ + "]",
+ findElements(By.className("v-label")).get(i * 3 + 1)
+ .getText());
+
+ assertTrue("Body key event handler got called unexpectedly.",
+ findElements(By.className("v-label")).get(i * 3).getText()
+ .isEmpty());
+ assertTrue("Footer key event handler got called unexpectedly.",
+ findElements(By.className("v-label")).get(i * 3 + 2)
+ .getText().isEmpty());
+ }
+ }
+
+ @Test
+ public void testFooterKeyEvents() throws IOException {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+ getGridElement().getFooterCell(0, 2).click();
+
+ new Actions(getDriver()).sendKeys("a").perform();
+
+ for (int i = 0; i < 3; ++i) {
+ assertEquals("Footer key event handler was not called.",
+ "(0, 2) event: GridKey" + eventOrder.get(i) + "Event:["
+ + (eventOrder.get(i).equals("Press") ? "a" : 65)
+ + "]",
+ findElements(By.className("v-label")).get(i * 3 + 2)
+ .getText());
+
+ assertTrue("Body key event handler got called unexpectedly.",
+ findElements(By.className("v-label")).get(i * 3).getText()
+ .isEmpty());
+ assertTrue("Header key event handler got called unexpectedly.",
+ findElements(By.className("v-label")).get(i * 3 + 1)
+ .getText().isEmpty());
+
+ }
+ }
+
+ @Test
+ public void testNoKeyEventsFromWidget() {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 2", "Header Type",
+ "Widget Header");
+ GridCellElement header = getGridElement().getHeaderCell(0, 2);
+ header.findElement(By.tagName("button")).click();
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+
+ for (int i = 0; i < 3; ++i) {
+ assertTrue("Header key event handler got called unexpectedly.",
+ findElements(By.className("v-label")).get(i * 3 + 1)
+ .getText().isEmpty());
+
+ }
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java
new file mode 100644
index 0000000000..d4c10da626
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+
+public class GridClientSelectionTest extends GridBasicClientFeaturesTest {
+
+ @Test
+ public void testChangeSelectionMode() {
+ openTestURL();
+
+ setSelectionModelNone();
+ assertTrue("First column was selection column", getGridElement()
+ .getCell(0, 0).getText().equals("(0, 0)"));
+ setSelectionModelMulti();
+ assertTrue("First column was not selection column", getGridElement()
+ .getCell(0, 1).getText().equals("(0, 0)"));
+ }
+
+ @Test
+ public void testSelectAllCheckbox() {
+ openTestURL();
+
+ setSelectionModelMulti();
+ selectMenuPath("Component", "DataSource", "Reset with 100 rows of Data");
+ GridCellElement header = getGridElement().getHeaderCell(0, 0);
+
+ assertTrue("No checkbox", header.isElementPresent(By.tagName("input")));
+ header.findElement(By.tagName("input")).click();
+
+ for (int i = 0; i < 100; i += 10) {
+ assertTrue("Row " + i + " was not selected.", getGridElement()
+ .getRow(i).isSelected());
+ }
+
+ header.findElement(By.tagName("input")).click();
+ assertFalse("Row 52 was still selected", getGridElement().getRow(52)
+ .isSelected());
+ }
+
+ @Test
+ public void testSelectAllCheckboxWhenChangingModels() {
+ openTestURL();
+
+ GridCellElement header;
+ header = getGridElement().getHeaderCell(0, 0);
+ assertFalse(
+ "Check box shouldn't have been in header for None Selection Model",
+ header.isElementPresent(By.tagName("input")));
+
+ setSelectionModelMulti();
+ header = getGridElement().getHeaderCell(0, 0);
+ assertTrue("Multi Selection Model should have select all checkbox",
+ header.isElementPresent(By.tagName("input")));
+
+ setSelectionModelSingle();
+ header = getGridElement().getHeaderCell(0, 0);
+ assertFalse(
+ "Check box shouldn't have been in header for Single Selection Model",
+ header.isElementPresent(By.tagName("input")));
+
+ setSelectionModelNone();
+ header = getGridElement().getHeaderCell(0, 0);
+ assertFalse(
+ "Check box shouldn't have been in header for None Selection Model",
+ header.isElementPresent(By.tagName("input")));
+
+ }
+
+ private void setSelectionModelMulti() {
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+ }
+
+ private void setSelectionModelSingle() {
+ selectMenuPath("Component", "State", "Selection mode", "single");
+ }
+
+ private void setSelectionModelNone() {
+ selectMenuPath("Component", "State", "Selection mode", "none");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientStructureTest.java
new file mode 100644
index 0000000000..74cf368da9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientStructureTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+
+@SuppressWarnings("all")
+public class GridClientStructureTest extends GridBasicClientFeaturesTest {
+ @Test
+ public void haederDecoSizeShouldBeRecalculated() {
+ // it's easier to notice with valo
+ openTestURL("theme=valo");
+
+ WebElement topDeco = getGridElement().findElement(
+ By.className("v-grid-header-deco"));
+ assertGreater(
+ "The header deco in Valo hasn't been recalculated after initial rendering",
+ topDeco.getSize().getHeight(), 20);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java
new file mode 100644
index 0000000000..a67b901198
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+
+public class GridEditorClientTest extends GridBasicClientFeaturesTest {
+
+ @Before
+ public void setUp() {
+ openTestURL();
+ selectMenuPath("Component", "Editor", "Enabled");
+ }
+
+ @Test
+ public void testProgrammaticOpeningClosing() {
+ selectMenuPath("Component", "Editor", "Edit row 5");
+ assertNotNull(getEditor());
+
+ selectMenuPath("Component", "Editor", "Cancel edit");
+ assertNull(getEditor());
+ assertEquals("Row 5 edit cancelled",
+ findElement(By.className("grid-editor-log")).getText());
+ }
+
+ @Test
+ public void testProgrammaticOpeningWithScroll() {
+ selectMenuPath("Component", "Editor", "Edit row 100");
+ assertNotNull(getEditor());
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void testVerticalScrollLocking() {
+ selectMenuPath("Component", "Editor", "Edit row 5");
+ getGridElement().getCell(200, 0);
+ }
+
+ @Test
+ public void testKeyboardOpeningClosing() {
+
+ getGridElement().getCell(4, 0).click();
+
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+
+ assertNotNull(getEditor());
+
+ new Actions(getDriver()).sendKeys(Keys.ESCAPE).perform();
+ assertNull(getEditor());
+ assertEquals("Row 4 edit cancelled",
+ findElement(By.className("grid-editor-log")).getText());
+
+ // Disable editor
+ selectMenuPath("Component", "Editor", "Enabled");
+
+ getGridElement().getCell(5, 0).click();
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+ assertNull(getEditor());
+ }
+
+ @Test
+ public void testWidgetBinding() throws Exception {
+ selectMenuPath("Component", "Editor", "Edit row 100");
+ WebElement editor = getEditor();
+
+ List<WebElement> widgets = editor.findElements(By
+ .className("gwt-TextBox"));
+
+ assertEquals(GridBasicFeatures.COLUMNS, widgets.size());
+
+ assertEquals("(100, 0)", widgets.get(0).getAttribute("value"));
+ assertEquals("(100, 1)", widgets.get(1).getAttribute("value"));
+ assertEquals("(100, 2)", widgets.get(2).getAttribute("value"));
+
+ assertEquals("100", widgets.get(7).getAttribute("value"));
+ assertEquals("<b>100</b>", widgets.get(9).getAttribute("value"));
+ }
+
+ @Test
+ public void testWithSelectionColumn() throws Exception {
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+ selectMenuPath("Component", "State", "Editor", "Edit row 5");
+
+ WebElement editor = getEditor();
+ List<WebElement> selectorDivs = editor.findElements(By
+ .cssSelector("div"));
+
+ assertTrue("selector column cell should've been empty", selectorDivs
+ .get(0).getAttribute("innerHTML").isEmpty());
+ assertFalse("normal column cell shoul've had contents", selectorDivs
+ .get(1).getAttribute("innerHTML").isEmpty());
+ }
+
+ @Test
+ public void testSave() {
+ selectMenuPath("Component", "Editor", "Edit row 100");
+
+ WebElement textField = getEditor().findElements(
+ By.className("gwt-TextBox")).get(0);
+
+ textField.clear();
+ textField.sendKeys("Changed");
+
+ WebElement saveButton = getEditor().findElement(
+ By.className("v-grid-editor-save"));
+
+ saveButton.click();
+
+ assertEquals("Changed", getGridElement().getCell(100, 0).getText());
+ }
+
+ @Test
+ public void testProgrammaticSave() {
+ selectMenuPath("Component", "Editor", "Edit row 100");
+
+ WebElement textField = getEditor().findElements(
+ By.className("gwt-TextBox")).get(0);
+
+ textField.clear();
+ textField.sendKeys("Changed");
+
+ selectMenuPath("Component", "Editor", "Save");
+
+ assertEquals("Changed", getGridElement().getCell(100, 0).getText());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java
new file mode 100644
index 0000000000..8b65ba315b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+
+public class GridFooterTest extends GridStaticSectionTest {
+
+ @Test
+ public void testDefaultFooter() {
+ openTestURL();
+
+ // Footer should have zero rows by default
+ assertFooterCount(0);
+ }
+
+ @Test
+ public void testFooterVisibility() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Visible");
+
+ assertFooterCount(0);
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ assertFooterCount(0);
+
+ selectMenuPath("Component", "Footer", "Visible");
+
+ assertFooterCount(1);
+ }
+
+ @Test
+ public void testAddRows() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ assertFooterCount(1);
+ assertFooterTexts(0, 0);
+
+ selectMenuPath("Component", "Footer", "Prepend row");
+
+ assertFooterCount(2);
+ assertFooterTexts(1, 0);
+ assertFooterTexts(0, 1);
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ assertFooterCount(3);
+ assertFooterTexts(1, 0);
+ assertFooterTexts(0, 1);
+ assertFooterTexts(2, 2);
+ }
+
+ @Test
+ public void testRemoveRows() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Prepend row");
+ selectMenuPath("Component", "Footer", "Append row");
+
+ selectMenuPath("Component", "Footer", "Remove top row");
+
+ assertFooterCount(1);
+ assertFooterTexts(1, 0);
+
+ selectMenuPath("Component", "Footer", "Remove bottom row");
+ assertFooterCount(0);
+ }
+
+ @Test
+ public void joinColumnsByCells() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ selectMenuPath("Component", "Footer", "Row 1", "Join column cells 0, 1");
+
+ GridCellElement spannedCell = getGridElement().getFooterCell(0, 0);
+ assertTrue(spannedCell.isDisplayed());
+ assertEquals("2", spannedCell.getAttribute("colspan"));
+
+ // TestBench returns the spanned cell for all columns
+ assertEquals(spannedCell.getText(), getGridElement()
+ .getFooterCell(0, 1).getText());
+ }
+
+ @Test
+ public void joinColumnsByColumns() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2");
+
+ GridCellElement spannedCell = getGridElement().getFooterCell(0, 1);
+ assertTrue(spannedCell.isDisplayed());
+ assertEquals("2", spannedCell.getAttribute("colspan"));
+
+ // TestBench returns the spanned cell for all columns
+ assertEquals(spannedCell.getText(), getGridElement()
+ .getFooterCell(0, 2).getText());
+ }
+
+ @Test
+ public void joinAllColumnsInRow() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ selectMenuPath("Component", "Footer", "Row 1", "Join all columns");
+
+ GridCellElement spannedCell = getGridElement().getFooterCell(0, 0);
+ assertTrue(spannedCell.isDisplayed());
+ assertEquals("" + GridBasicFeatures.COLUMNS,
+ spannedCell.getAttribute("colspan"));
+
+ for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) {
+ GridCellElement hiddenCell = getGridElement().getFooterCell(0,
+ columnIndex);
+ // TestBench returns the spanned cell for all columns
+ assertEquals(spannedCell.getText(), hiddenCell.getText());
+ }
+ }
+
+ @Test
+ public void testInitialCellTypes() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ GridCellElement textCell = getGridElement().getFooterCell(0, 0);
+ /*
+ * Reindeer has a CSS text transformation that changes the casing so
+ * that we can't rely on it being what we set
+ */
+ assertEquals("footer (0,0)", textCell.getText().toLowerCase());
+
+ GridCellElement widgetCell = getGridElement().getFooterCell(0, 1);
+ assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML")));
+
+ GridCellElement htmlCell = getGridElement().getFooterCell(0, 2);
+ assertHTML("<b>Footer (0,2)</b>", htmlCell);
+ }
+
+ @Test
+ public void testDynamicallyChangingCellType() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ selectMenuPath("Component", "Columns", "Column 0", "Footer Type",
+ "Widget Footer");
+ GridCellElement widgetCell = getGridElement().getFooterCell(0, 0);
+ assertTrue(widgetCell.isElementPresent(By.className("gwt-Button")));
+
+ selectMenuPath("Component", "Columns", "Column 1", "Footer Type",
+ "HTML Footer");
+ GridCellElement htmlCell = getGridElement().getFooterCell(0, 1);
+ assertHTML("<b>HTML Footer</b>", htmlCell);
+
+ selectMenuPath("Component", "Columns", "Column 2", "Footer Type",
+ "Text Footer");
+ GridCellElement textCell = getGridElement().getFooterCell(0, 2);
+
+ /*
+ * Reindeer has a CSS text transformation that changes the casing so
+ * that we can't rely on it being what we set
+ */
+ assertEquals("text footer", textCell.getText().toLowerCase());
+ }
+
+ @Test
+ public void testCellWidgetInteraction() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Append row");
+
+ selectMenuPath("Component", "Columns", "Column 0", "Footer Type",
+ "Widget Footer");
+ GridCellElement widgetCell = getGridElement().getFooterCell(0, 0);
+ WebElement button = widgetCell.findElement(By.className("gwt-Button"));
+
+ assertNotEquals("clicked", button.getText().toLowerCase());
+
+ new Actions(getDriver()).moveToElement(button, 5, 5).click().perform();
+
+ assertEquals("clicked", button.getText().toLowerCase());
+ }
+
+ private void assertFooterCount(int count) {
+ assertEquals("footer count", count, getGridElement().getFooterCount());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java
new file mode 100644
index 0000000000..8cf7f7374f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+
+public class GridHeaderTest extends GridStaticSectionTest {
+
+ @Test
+ public void testDefaultHeader() throws Exception {
+ openTestURL();
+
+ assertHeaderCount(1);
+ assertHeaderTexts(0, 0);
+ }
+
+ @Test
+ public void testHeaderVisibility() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Header", "Visible");
+
+ assertHeaderCount(0);
+
+ selectMenuPath("Component", "Header", "Append row");
+
+ assertHeaderCount(0);
+
+ selectMenuPath("Component", "Header", "Visible");
+
+ assertHeaderCount(2);
+ }
+
+ @Test
+ public void testHeaderCaptions() throws Exception {
+ openTestURL();
+
+ assertHeaderTexts(0, 0);
+ }
+
+ @Test
+ public void testAddRows() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Header", "Append row");
+
+ assertHeaderCount(2);
+ assertHeaderTexts(0, 0);
+ assertHeaderTexts(1, 1);
+
+ selectMenuPath("Component", "Header", "Prepend row");
+
+ assertHeaderCount(3);
+ assertHeaderTexts(2, 0);
+ assertHeaderTexts(0, 1);
+ assertHeaderTexts(1, 2);
+
+ selectMenuPath("Component", "Header", "Append row");
+
+ assertHeaderCount(4);
+ assertHeaderTexts(2, 0);
+ assertHeaderTexts(0, 1);
+ assertHeaderTexts(1, 2);
+ assertHeaderTexts(3, 3);
+ }
+
+ @Test
+ public void testRemoveRows() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Header", "Prepend row");
+ selectMenuPath("Component", "Header", "Append row");
+
+ selectMenuPath("Component", "Header", "Remove top row");
+
+ assertHeaderCount(2);
+ assertHeaderTexts(0, 0);
+ assertHeaderTexts(2, 1);
+
+ selectMenuPath("Component", "Header", "Remove bottom row");
+ assertHeaderCount(1);
+ assertHeaderTexts(0, 0);
+ }
+
+ @Test
+ public void testDefaultRow() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 0", "Sortable");
+
+ GridCellElement headerCell = getGridElement().getHeaderCell(0, 0);
+
+ headerCell.click();
+
+ assertTrue(hasClassName(headerCell, "sort-asc"));
+
+ headerCell.click();
+
+ assertFalse(hasClassName(headerCell, "sort-asc"));
+ assertTrue(hasClassName(headerCell, "sort-desc"));
+
+ selectMenuPath("Component", "Header", "Prepend row");
+ selectMenuPath("Component", "Header", "Default row", "Top");
+
+ assertFalse(hasClassName(headerCell, "sort-desc"));
+ headerCell = getGridElement().getHeaderCell(0, 0);
+ assertTrue(hasClassName(headerCell, "sort-desc"));
+
+ selectMenuPath("Component", "Header", "Default row", "Unset");
+
+ assertFalse(hasClassName(headerCell, "sort-desc"));
+ }
+
+ @Test
+ public void joinHeaderColumnsByCells() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Header", "Append row");
+
+ selectMenuPath("Component", "Header", "Row 2", "Join column cells 0, 1");
+
+ GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0);
+ assertTrue(spannedCell.isDisplayed());
+ assertEquals("2", spannedCell.getAttribute("colspan"));
+
+ // TestBench returns the spanned cell for all spanned columns
+ GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 1);
+ assertEquals(spannedCell.getText(), hiddenCell.getText());
+ }
+
+ @Test
+ public void joinHeaderColumnsByColumns() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Header", "Append row");
+
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+
+ GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1);
+ assertTrue(spannedCell.isDisplayed());
+ assertEquals("2", spannedCell.getAttribute("colspan"));
+
+ // TestBench returns the spanned cell for all spanned columns
+ GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 2);
+ assertEquals(spannedCell.getText(), hiddenCell.getText());
+ }
+
+ @Test
+ public void joinAllColumnsInHeaderRow() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Header", "Append row");
+
+ selectMenuPath("Component", "Header", "Row 2", "Join all columns");
+
+ GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0);
+ assertTrue(spannedCell.isDisplayed());
+ assertEquals("" + GridBasicFeatures.COLUMNS,
+ spannedCell.getAttribute("colspan"));
+
+ for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) {
+ // TestBench returns the spanned cell for all spanned columns
+ GridCellElement hiddenCell = getGridElement().getHeaderCell(1,
+ columnIndex);
+ assertEquals(spannedCell.getText(), hiddenCell.getText());
+ }
+ }
+
+ @Test
+ public void testInitialCellTypes() throws Exception {
+ openTestURL();
+
+ GridCellElement textCell = getGridElement().getHeaderCell(0, 0);
+
+ /*
+ * Reindeer has a CSS text transformation that changes the casing so
+ * that we can't rely on it being what we set
+ */
+ assertEquals("header (0,0)", textCell.getText().toLowerCase());
+
+ GridCellElement widgetCell = getGridElement().getHeaderCell(0, 1);
+ assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML")));
+
+ GridCellElement htmlCell = getGridElement().getHeaderCell(0, 2);
+ assertHTML("<b>Header (0,2)</b>", htmlCell);
+ }
+
+ @Test
+ public void testDynamicallyChangingCellType() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 0", "Header Type",
+ "Widget Header");
+ GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0);
+ assertTrue(widgetCell.isElementPresent(By.className("gwt-Button")));
+
+ selectMenuPath("Component", "Columns", "Column 1", "Header Type",
+ "HTML Header");
+ GridCellElement htmlCell = getGridElement().getHeaderCell(0, 1);
+ assertHTML("<b>HTML Header</b>", htmlCell);
+
+ selectMenuPath("Component", "Columns", "Column 2", "Header Type",
+ "Text Header");
+ GridCellElement textCell = getGridElement().getHeaderCell(0, 2);
+
+ /*
+ * Reindeer has a CSS text transformation that changes the casing so
+ * that we can't rely on it being what we set
+ */
+ assertEquals("text header", textCell.getText().toLowerCase());
+ }
+
+ @Test
+ public void testCellWidgetInteraction() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 0", "Header Type",
+ "Widget Header");
+ GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0);
+ WebElement button = widgetCell.findElement(By.className("gwt-Button"));
+
+ new Actions(getDriver()).moveToElement(button, 5, 5).click().perform();
+
+ assertEquals("clicked", button.getText().toLowerCase());
+ }
+
+ @Test
+ public void widgetInSortableCellInteraction() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 0", "Header Type",
+ "Widget Header");
+
+ selectMenuPath("Component", "Columns", "Column 0", "Sortable");
+
+ GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0);
+ WebElement button = widgetCell.findElement(By.className("gwt-Button"));
+
+ assertNotEquals("clicked", button.getText().toLowerCase());
+
+ new Actions(getDriver()).moveToElement(button, 5, 5).click().perform();
+
+ assertEquals("clicked", button.getText().toLowerCase());
+ }
+
+ private void assertHeaderCount(int count) {
+ assertEquals("header count", count, getGridElement().getHeaderCount());
+ }
+
+ private boolean hasClassName(TestBenchElement element, String name) {
+ return Arrays.asList(element.getAttribute("class").split(" "))
+ .contains(name);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridRowHandleRefreshTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridRowHandleRefreshTest.java
new file mode 100644
index 0000000000..c7a509da45
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridRowHandleRefreshTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+
+public class GridRowHandleRefreshTest extends GridBasicClientFeaturesTest {
+
+ @Test
+ public void testRefreshingThroughRowHandle() {
+ openTestURL();
+
+ assertEquals("Unexpected initial state", "(0, 0)", getGridElement()
+ .getCell(0, 0).getText());
+ selectMenuPath("Component", "State", "Edit and refresh Row 0");
+ assertEquals("Cell contents did not update correctly", "Foo",
+ getGridElement().getCell(0, 0).getText());
+ }
+
+ @Test
+ public void testDelayedRefreshingThroughRowHandle()
+ throws InterruptedException {
+ openTestURL();
+
+ assertEquals("Unexpected initial state", "(0, 0)", getGridElement()
+ .getCell(0, 0).getText());
+ selectMenuPath("Component", "State", "Delayed edit of Row 0");
+ // Still the same data
+ assertEquals("Cell contents did not update correctly", "(0, 0)",
+ getGridElement().getCell(0, 0).getText());
+ sleep(5000);
+ // Data should be updated
+ assertEquals("Cell contents did not update correctly", "Bar",
+ getGridElement().getCell(0, 0).getText());
+ }
+
+ @Test
+ public void testRefreshingWhenNotInViewThroughRowHandle() {
+ openTestURL();
+
+ assertEquals("Unexpected initial state", "(0, 0)", getGridElement()
+ .getCell(0, 0).getText());
+ getGridElement().scrollToRow(100);
+ selectMenuPath("Component", "State", "Edit and refresh Row 0");
+ assertEquals("Cell contents did not update correctly", "Foo",
+ getGridElement().getCell(0, 0).getText());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java
new file mode 100644
index 0000000000..cc801bf870
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+
+/**
+ * Abstract base class for header and footer tests.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest {
+
+ protected void assertHeaderTexts(int headerId, int rowIndex) {
+ int i = 0;
+ for (TestBenchElement cell : getGridElement().getHeaderCells(rowIndex)) {
+
+ if (i % 3 == 0) {
+ assertText(String.format("Header (%d,%d)", headerId, i), cell);
+ } else if (i % 2 == 0) {
+ assertHTML(String.format("<b>Header (%d,%d)</b>", headerId, i),
+ cell);
+ } else {
+ assertHTML(String.format(
+ "<div class=\"gwt-HTML\">Header (%d,%d)</div>",
+ headerId, i), cell);
+ }
+
+ i++;
+ }
+ assertEquals("number of header columns", GridBasicFeatures.COLUMNS, i);
+ }
+
+ protected void assertFooterTexts(int footerId, int rowIndex) {
+ int i = 0;
+ for (TestBenchElement cell : getGridElement().getFooterCells(rowIndex)) {
+ if (i % 3 == 0) {
+ assertText(String.format("Footer (%d,%d)", footerId, i), cell);
+ } else if (i % 2 == 0) {
+ assertHTML(String.format("<b>Footer (%d,%d)</b>", footerId, i),
+ cell);
+ } else {
+ assertHTML(String.format(
+ "<div class=\"gwt-HTML\">Footer (%d,%d)</div>",
+ footerId, i), cell);
+ }
+ i++;
+ }
+ assertEquals("number of footer columns", GridBasicFeatures.COLUMNS, i);
+ }
+
+ protected static void assertText(String text, TestBenchElement e) {
+ // TBE.getText returns "" if the element is scrolled out of view
+ assertEquals(text, e.getAttribute("innerHTML"));
+ }
+
+ protected static void assertHTML(String text, TestBenchElement e) {
+ String html = e.getAttribute("innerHTML");
+
+ // IE 8 returns tags as upper case while other browsers do not, make the
+ // comparison non-casesensive
+ html = html.toLowerCase();
+ text = text.toLowerCase();
+
+ // IE 8 returns attributes without quotes, make the comparison without
+ // quotes
+ html = html.replaceAll("\"", "");
+ text = html.replaceAll("\"", "");
+
+ assertEquals(text, html);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java
new file mode 100644
index 0000000000..cbf27a69d9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+
+public class GridStylingTest extends GridStaticSectionTest {
+
+ @Test
+ public void testGridPrimaryStyle() throws Exception {
+ openTestURL();
+
+ validateStylenames("v-grid");
+ }
+
+ @Test
+ public void testChangingPrimaryStyleName() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "State", "Primary Stylename",
+ "v-custom-style");
+
+ validateStylenames("v-custom-style");
+ }
+
+ private void validateStylenames(String stylename) {
+
+ String classNames = getGridElement().getAttribute("class");
+ assertEquals(stylename, classNames);
+
+ classNames = getGridElement().getVerticalScroller().getAttribute(
+ "class");
+ assertTrue(classNames.contains(stylename + "-scroller"));
+ assertTrue(classNames.contains(stylename + "-scroller-vertical"));
+
+ classNames = getGridElement().getHorizontalScroller().getAttribute(
+ "class");
+ assertTrue(classNames.contains(stylename + "-scroller"));
+ assertTrue(classNames.contains(stylename + "-scroller-horizontal"));
+
+ classNames = getGridElement().getTableWrapper().getAttribute("class");
+ assertEquals(stylename + "-tablewrapper", classNames);
+
+ classNames = getGridElement().getHeader().getAttribute("class");
+ assertEquals(stylename + "-header", classNames);
+
+ for (int row = 0; row < getGridElement().getHeaderCount(); row++) {
+ classNames = getGridElement().getHeaderRow(row).getAttribute(
+ "class");
+ assertEquals(stylename + "-row", classNames);
+
+ for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) {
+ classNames = getGridElement().getHeaderCell(row, col)
+ .getAttribute("class");
+ assertTrue(classNames.contains(stylename + "-cell"));
+ }
+ }
+
+ classNames = getGridElement().getBody().getAttribute("class");
+ assertEquals(stylename + "-body", classNames);
+
+ int rowsInBody = getGridElement().getBody()
+ .findElements(By.tagName("tr")).size();
+ for (int row = 0; row < rowsInBody; row++) {
+ classNames = getGridElement().getRow(row).getAttribute("class");
+ assertTrue(classNames.contains(stylename + "-row"));
+ assertTrue(classNames.contains(stylename + "-row-has-data"));
+
+ for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) {
+ classNames = getGridElement().getCell(row, col).getAttribute(
+ "class");
+ assertTrue(classNames.contains(stylename + "-cell"));
+
+ if (row == 0 && col == 0) {
+ assertTrue(classNames.contains(stylename + "-cell-focused"));
+ }
+ }
+ }
+
+ classNames = getGridElement().getFooter().getAttribute("class");
+ assertEquals(stylename + "-footer", classNames);
+
+ for (int row = 0; row < getGridElement().getFooterCount(); row++) {
+ classNames = getGridElement().getFooterRow(row).getAttribute(
+ "class");
+ assertEquals(stylename + "-row", classNames);
+
+ for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) {
+ classNames = getGridElement().getFooterCell(row, col)
+ .getAttribute("class");
+ assertTrue(classNames.contains(stylename + "-cell"));
+ }
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java
new file mode 100644
index 0000000000..95ed6ab3ff
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.escalator;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
+
+public class EscalatorBasicsTest extends EscalatorBasicClientFeaturesTest {
+
+ @Test
+ public void testDetachingAnEmptyEscalator() {
+ setDebug(true);
+ openTestURL();
+
+ selectMenuPath(GENERAL, DETACH_ESCALATOR);
+ assertEscalatorIsRemovedCorrectly();
+ }
+
+ @Test
+ public void testDetachingASemiPopulatedEscalator() throws IOException {
+ setDebug(true);
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, ADD_ONE_OF_EACH_ROW);
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ selectMenuPath(GENERAL, DETACH_ESCALATOR);
+ assertEscalatorIsRemovedCorrectly();
+ }
+
+ @Test
+ public void testDetachingAPopulatedEscalator() {
+ setDebug(true);
+ openTestURL();
+
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+ selectMenuPath(GENERAL, DETACH_ESCALATOR);
+ assertEscalatorIsRemovedCorrectly();
+ }
+
+ private void assertEscalatorIsRemovedCorrectly() {
+ assertFalse($(NotificationElement.class).exists());
+ assertNull(getEscalator());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColspanTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColspanTest.java
new file mode 100644
index 0000000000..d9b3debbe1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColspanTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.escalator;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
+
+public class EscalatorColspanTest extends EscalatorBasicClientFeaturesTest {
+ private static final int NO_COLSPAN = 1;
+
+ @Test
+ public void testNoColspan() {
+ openTestURL();
+ populate();
+
+ assertEquals(NO_COLSPAN, getColSpan(getHeaderCell(0, 0)));
+ assertEquals(NO_COLSPAN, getColSpan(getBodyCell(0, 0)));
+ assertEquals(NO_COLSPAN, getColSpan(getFooterCell(0, 0)));
+ }
+
+ @Test
+ public void testColspan() {
+ openTestURL();
+ populate();
+
+ int firstCellWidth = getBodyCell(0, 0).getSize().getWidth();
+ int secondCellWidth = getBodyCell(0, 1).getSize().getWidth();
+ int doubleCellWidth = firstCellWidth + secondCellWidth;
+
+ selectMenuPath(FEATURES, COLUMN_SPANNING, COLSPAN_NORMAL);
+
+ WebElement bodyCell = getBodyCell(0, 0);
+ assertEquals("Cell was not spanned correctly", 2, getColSpan(bodyCell));
+ assertEquals(
+ "Spanned cell's width was not the sum of the previous cells ("
+ + firstCellWidth + " + " + secondCellWidth + ")",
+ doubleCellWidth, bodyCell.getSize().getWidth(), 1);
+ }
+
+ @Test
+ public void testColspanToggle() {
+ openTestURL();
+ populate();
+
+ int singleCellWidth = getBodyCell(0, 0).getSize().getWidth();
+
+ selectMenuPath(FEATURES, COLUMN_SPANNING, COLSPAN_NORMAL);
+ selectMenuPath(FEATURES, COLUMN_SPANNING, COLSPAN_NONE);
+
+ WebElement bodyCell = getBodyCell(0, 0);
+ assertEquals(NO_COLSPAN, getColSpan(bodyCell));
+ assertEquals(singleCellWidth, bodyCell.getSize().getWidth(), 1);
+ }
+
+ private static int getColSpan(WebElement cell) {
+ String attribute = cell.getAttribute("colspan");
+ if (attribute == null) {
+ return NO_COLSPAN;
+ } else {
+ return Integer.parseInt(attribute);
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColumnFreezingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColumnFreezingTest.java
new file mode 100644
index 0000000000..e808001cf7
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorColumnFreezingTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.escalator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
+
+public class EscalatorColumnFreezingTest extends
+ EscalatorBasicClientFeaturesTest {
+
+ private final static Pattern TRANSFORM_PATTERN = Pattern.compile(// @formatter:off
+ // any start of the string
+ ".*"
+
+ // non-capturing group for "webkitTransform: " or "transform: "
+ + "(?:webkitT|t)ransform: "
+
+ // non-capturing group for "translate" or "translate3d"
+ + "translate(?:3d)?"
+
+ // capturing the digits in e.g "(100px,"
+ + "\\((\\d+)px,"
+
+ // any end of the string
+ + ".*", Pattern.CASE_INSENSITIVE);
+
+ // @formatter:on
+
+ private final static Pattern LEFT_PATTERN = Pattern.compile(
+ ".*left: (\\d+)px.*", Pattern.CASE_INSENSITIVE);
+
+ private static final int NO_FREEZE = -1;
+
+ @Test
+ public void testNoFreeze() {
+ openTestURL();
+ populate();
+
+ WebElement bodyCell = getBodyCell(0, 0);
+ assertFalse(isFrozen(bodyCell));
+ assertEquals(NO_FREEZE, getFrozenScrollCompensation(bodyCell));
+ }
+
+ @Test
+ public void testOneFreeze() {
+ openTestURL();
+ populate();
+
+ selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_1_COLUMN);
+ int scrollPx = 60;
+ scrollHorizontallyTo(scrollPx);
+
+ WebElement bodyCell = getBodyCell(0, 0);
+ assertTrue(isFrozen(bodyCell));
+ assertEquals(scrollPx, getFrozenScrollCompensation(bodyCell));
+ }
+
+ @Test
+ public void testFreezeToggle() {
+ openTestURL();
+ populate();
+
+ selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_1_COLUMN);
+ scrollHorizontallyTo(100);
+ selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_0_COLUMNS);
+
+ WebElement bodyCell = getBodyCell(0, 0);
+ assertFalse(isFrozen(bodyCell));
+ assertEquals(NO_FREEZE, getFrozenScrollCompensation(bodyCell));
+ }
+
+ private static boolean isFrozen(WebElement cell) {
+ return cell.getAttribute("class").contains("frozen");
+ }
+
+ private static int getFrozenScrollCompensation(WebElement cell) {
+ String styleAttribute = cell.getAttribute("style");
+ Matcher transformMatcher = TRANSFORM_PATTERN.matcher(styleAttribute);
+ Matcher leftMatcher = LEFT_PATTERN.matcher(styleAttribute);
+
+ if (transformMatcher.find()) {
+ return Integer.parseInt(transformMatcher.group(1));
+ } else if (leftMatcher.find()) {
+ return Integer.parseInt(leftMatcher.group(1));
+ } else {
+ return NO_FREEZE;
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorRowColumnTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorRowColumnTest.java
new file mode 100644
index 0000000000..e72e8fae70
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorRowColumnTest.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.escalator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
+
+public class EscalatorRowColumnTest extends EscalatorBasicClientFeaturesTest {
+
+ /**
+ * The scroll position of the Escalator when scrolled all the way down, to
+ * reveal the 100:th row.
+ */
+ private static final int BOTTOM_SCROLL_POSITION = 1857;
+
+ @Test
+ public void testInit() {
+ openTestURL();
+ assertNotNull(getEscalator());
+ assertNull(getHeaderRow(0));
+ assertNull(getBodyRow(0));
+ assertNull(getFooterRow(0));
+
+ assertLogContains("Columns: 0");
+ assertLogContains("Header rows: 0");
+ assertLogContains("Body rows: 0");
+ assertLogContains("Footer rows: 0");
+ }
+
+ @Test
+ public void testInsertAColumn() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ assertNull(getHeaderRow(0));
+ assertNull(getBodyRow(0));
+ assertNull(getFooterRow(0));
+ assertLogContains("Columns: 1");
+ }
+
+ @Test
+ public void testInsertAHeaderRow() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, HEADER_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ assertNull(getHeaderCell(0, 0));
+ assertNull(getBodyCell(0, 0));
+ assertNull(getFooterCell(0, 0));
+ assertLogContains("Header rows: 1");
+ }
+
+ @Test
+ public void testInsertABodyRow() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ assertNull(getHeaderCell(0, 0));
+ assertNull(getBodyCell(0, 0));
+ assertNull(getFooterCell(0, 0));
+ assertLogContains("Body rows: 1");
+ }
+
+ @Test
+ public void testInsertAFooterRow() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, FOOTER_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ assertNull(getHeaderCell(0, 0));
+ assertNull(getBodyCell(0, 0));
+ assertNull(getFooterCell(0, 0));
+ assertLogContains("Footer rows: 1");
+ }
+
+ @Test
+ public void testInsertAColumnAndAHeaderRow() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, HEADER_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ assertNotNull(getHeaderCell(0, 0));
+ assertNull(getBodyCell(0, 0));
+ assertNull(getFooterCell(0, 0));
+ assertLogContains("Columns: 1");
+ assertLogContains("Header rows: 1");
+ }
+
+ @Test
+ public void testInsertAColumnAndABodyRow() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ assertNull(getHeaderCell(0, 0));
+ assertNotNull(getBodyCell(0, 0));
+ assertNull(getFooterCell(0, 0));
+ assertLogContains("Columns: 1");
+ assertLogContains("Body rows: 1");
+ }
+
+ @Test
+ public void testInsertAColumnAndAFooterRow() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, FOOTER_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ assertNull(getHeaderCell(0, 0));
+ assertNull(getBodyCell(0, 0));
+ assertNotNull(getFooterCell(0, 0));
+ assertLogContains("Columns: 1");
+ assertLogContains("Footer rows: 1");
+ }
+
+ @Test
+ public void testInsertAHeaderRowAndAColumn() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, HEADER_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ assertNotNull(getHeaderCell(0, 0));
+ assertNull(getBodyCell(0, 0));
+ assertNull(getFooterCell(0, 0));
+ assertLogContains("Columns: 1");
+ assertLogContains("Header rows: 1");
+ }
+
+ @Test
+ public void testInsertABodyRowAndAColumn() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ assertNull(getHeaderCell(0, 0));
+ assertNotNull(getBodyCell(0, 0));
+ assertNull(getFooterCell(0, 0));
+ assertLogContains("Columns: 1");
+ assertLogContains("Body rows: 1");
+ }
+
+ @Test
+ public void testInsertAFooterRowAndAColumn() {
+ openTestURL();
+
+ selectMenuPath(COLUMNS_AND_ROWS, FOOTER_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING);
+ assertNull(getHeaderCell(0, 0));
+ assertNull(getBodyCell(0, 0));
+ assertNotNull(getFooterCell(0, 0));
+ assertLogContains("Columns: 1");
+ assertLogContains("Footer rows: 1");
+ }
+
+ @Test
+ public void testFillColRow() {
+ openTestURL();
+
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+ scrollVerticallyTo(2000); // more like 1857, but this should be enough.
+
+ // if not found, an exception is thrown here
+ assertTrue("Wanted cell was not visible",
+ isElementPresent(By.xpath("//td[text()='Cell: 9,99']")));
+ }
+
+ @Test
+ public void testFillRowCol() {
+ openTestURL();
+
+ selectMenuPath(GENERAL, POPULATE_ROW_COLUMN);
+ scrollVerticallyTo(2000); // more like 1857, but this should be enough.
+
+ // if not found, an exception is thrown here
+ assertTrue("Wanted cell was not visible",
+ isElementPresent(By.xpath("//td[text()='Cell: 9,99']")));
+ }
+
+ @Test
+ public void testClearColRow() {
+ openTestURL();
+
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+ selectMenuPath(GENERAL, CLEAR_COLUMN_ROW);
+
+ assertNull(getBodyCell(0, 0));
+ }
+
+ @Test
+ public void testClearRowCol() {
+ openTestURL();
+
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+ selectMenuPath(GENERAL, CLEAR_ROW_COLUMN);
+
+ assertNull(getBodyCell(0, 0));
+ }
+
+ @Test
+ public void testResizeColToFit() {
+ openTestURL();
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, RESIZE_FIRST_COLUMN_TO_100PX);
+ int originalWidth = getBodyCell(0, 0).getSize().getWidth();
+
+ assertEquals(100, originalWidth);
+
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS,
+ RESIZE_FIRST_COLUMN_TO_MAX_WIDTH);
+ int newWidth = getBodyCell(0, 0).getSize().getWidth();
+ assertNotEquals("Column width should've changed", originalWidth,
+ newWidth);
+ }
+
+ @Test
+ public void testRemoveMoreThanPagefulAtBottomWhileScrolledToBottom()
+ throws Exception {
+ openTestURL();
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+
+ scrollVerticallyTo(BOTTOM_SCROLL_POSITION);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_50_ROWS_FROM_BOTTOM);
+ assertEquals("Row 49: 0,49", getBodyCell(-1, 0).getText());
+
+ scrollVerticallyTo(0);
+
+ // let the DOM organize itself
+ Thread.sleep(500);
+
+ // if something goes wrong, it'll explode before this.
+ assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText());
+ }
+
+ @Test
+ public void testRemoveMoreThanPagefulAtBottomWhileScrolledAlmostToBottom()
+ throws Exception {
+ openTestURL();
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+
+ // bottom minus 15 rows.
+ scrollVerticallyTo(BOTTOM_SCROLL_POSITION - 15 * 20);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_50_ROWS_FROM_BOTTOM);
+ assertEquals("Row 49: 0,49", getBodyCell(-1, 0).getText());
+
+ scrollVerticallyTo(0);
+
+ // let the DOM organize itself
+ Thread.sleep(500);
+
+ // if something goes wrong, it'll explode before this.
+ assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText());
+ }
+
+ @Test
+ public void testRemoveMoreThanPagefulNearBottomWhileScrolledToBottom()
+ throws Exception {
+ openTestURL();
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+
+ scrollVerticallyTo(BOTTOM_SCROLL_POSITION);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS,
+ REMOVE_50_ROWS_FROM_ALMOST_BOTTOM);
+ assertEquals("Row 49: 0,99", getBodyCell(-1, 0).getText());
+
+ scrollVerticallyTo(0);
+
+ // let the DOM organize itself
+ Thread.sleep(500);
+
+ // if something goes wrong, it'll explode before this.
+ assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText());
+ }
+
+ @Test
+ public void testRemoveMoreThanPagefulNearBottomWhileScrolledAlmostToBottom()
+ throws Exception {
+ openTestURL();
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+
+ // bottom minus 15 rows.
+ scrollVerticallyTo(BOTTOM_SCROLL_POSITION - 15 * 20);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS,
+ REMOVE_50_ROWS_FROM_ALMOST_BOTTOM);
+
+ // let the DOM organize itself
+ Thread.sleep(500);
+ assertEquals("Row 49: 0,99", getBodyCell(-1, 0).getText());
+
+ scrollVerticallyTo(0);
+
+ // let the DOM organize itself
+ Thread.sleep(500);
+
+ // if something goes wrong, it'll explode before this.
+ assertEquals("Row 0: 0,0", getBodyCell(0, 0).getText());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorScrollTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorScrollTest.java
new file mode 100644
index 0000000000..41ad370b98
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorScrollTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.escalator;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
+
+@SuppressWarnings("all")
+public class EscalatorScrollTest extends EscalatorBasicClientFeaturesTest {
+
+ @Before
+ public void setUp() {
+ openTestURL();
+ populate();
+ }
+
+ /**
+ * Before the fix, removing and adding rows and also scrolling would put the
+ * scroll state in an internally inconsistent state. The scrollbar would've
+ * been scrolled correctly, but the body wasn't.
+ *
+ * This was due to optimizations that didn't keep up with the promises, so
+ * to say. So the optimizations were removed.
+ */
+ @Test
+ public void testScrollRaceCondition() {
+ scrollVerticallyTo(40);
+ String originalStyle = getTBodyStyle();
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_ALL_INSERT_SCROLL);
+
+ // body should be scrolled to exactly the same spot. (not 0)
+ assertEquals(originalStyle, getTBodyStyle());
+ }
+
+ @Test
+ public void scrollToBottomAndRemoveHeader() throws Exception {
+ scrollVerticallyTo(999999); // to bottom
+
+ /*
+ * apparently the scroll event isn't fired by the time the next assert
+ * would've been done.
+ */
+ Thread.sleep(50);
+
+ assertEquals("Unexpected last row cell before header removal",
+ "Row 99: 0,99", getBodyCell(-1, 0).getText());
+ selectMenuPath(COLUMNS_AND_ROWS, HEADER_ROWS,
+ REMOVE_ONE_ROW_FROM_BEGINNING);
+ assertEquals("Unexpected last row cell after header removal",
+ "Row 99: 0,99", getBodyCell(-1, 0).getText());
+
+ }
+
+ @Test
+ public void scrollToBottomAndRemoveFooter() throws Exception {
+ scrollVerticallyTo(999999); // to bottom
+
+ /*
+ * apparently the scroll event isn't fired by the time the next assert
+ * would've been done.
+ */
+ Thread.sleep(50);
+
+ assertEquals("Unexpected last row cell before footer removal",
+ "Row 99: 0,99", getBodyCell(-1, 0).getText());
+ selectMenuPath(COLUMNS_AND_ROWS, FOOTER_ROWS,
+ REMOVE_ONE_ROW_FROM_BEGINNING);
+ assertEquals("Unexpected last row cell after footer removal",
+ "Row 99: 0,99", getBodyCell(-1, 0).getText());
+ }
+
+ private String getTBodyStyle() {
+ WebElement tbody = getEscalator().findElement(By.tagName("tbody"));
+ return tbody.getAttribute("style");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorUpdaterUiTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorUpdaterUiTest.java
new file mode 100644
index 0000000000..85d3fc0bac
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorUpdaterUiTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.escalator;
+
+import org.junit.Test;
+
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorUpdaterUi;
+
+public class EscalatorUpdaterUiTest extends EscalatorBasicClientFeaturesTest {
+ @Override
+ protected Class<?> getUIClass() {
+ return EscalatorUpdaterUi.class;
+ }
+
+ @Test
+ public void testHeaderPaintOrderRowColRowCol() {
+ boolean addColumnFirst = false;
+ boolean removeColumnFirst = false;
+ testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testHeaderPaintOrderRowColColRow() {
+ boolean addColumnFirst = false;
+ boolean removeColumnFirst = true;
+ testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testHeaderPaintOrderColRowColRow() {
+ boolean addColumnFirst = true;
+ boolean removeColumnFirst = true;
+ testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testHeaderPaintOrderColRowRowCol() {
+ boolean addColumnFirst = true;
+ boolean removeColumnFirst = false;
+ testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testBodyPaintOrderRowColRowCol() {
+ boolean addColumnFirst = false;
+ boolean removeColumnFirst = false;
+ testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testBodyPaintOrderRowColColRow() {
+ boolean addColumnFirst = false;
+ boolean removeColumnFirst = true;
+ testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testBodyPaintOrderColRowColRow() {
+ boolean addColumnFirst = true;
+ boolean removeColumnFirst = true;
+ testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testBodyPaintOrderColRowRowCol() {
+ boolean addColumnFirst = true;
+ boolean removeColumnFirst = false;
+ testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testFooterPaintOrderRowColRowCol() {
+ boolean addColumnFirst = false;
+ boolean removeColumnFirst = false;
+ testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testFooterPaintOrderRowColColRow() {
+ boolean addColumnFirst = false;
+ boolean removeColumnFirst = true;
+ testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testFooterPaintOrderColRowColRow() {
+ boolean addColumnFirst = true;
+ boolean removeColumnFirst = true;
+ testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ @Test
+ public void testFooterPaintOrderColRowRowCol() {
+ boolean addColumnFirst = true;
+ boolean removeColumnFirst = false;
+ testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst);
+ }
+
+ private void testPaintOrder(String tableSection, boolean addColumnFirst,
+ boolean removeColumnFirst) {
+ openTestURL();
+
+ if (addColumnFirst) {
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS,
+ ADD_ONE_COLUMN_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, tableSection,
+ ADD_ONE_ROW_TO_BEGINNING);
+ } else {
+ selectMenuPath(COLUMNS_AND_ROWS, tableSection,
+ ADD_ONE_ROW_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS,
+ ADD_ONE_COLUMN_TO_BEGINNING);
+ }
+
+ assertLogContainsInOrder("preAttach: elementIsAttached == false",
+ "postAttach: elementIsAttached == true",
+ "update: elementIsAttached == true");
+ assertLogDoesNotContain("preDetach");
+ assertLogDoesNotContain("postDetach");
+
+ if (removeColumnFirst) {
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS,
+ REMOVE_ONE_COLUMN_FROM_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, tableSection,
+ REMOVE_ONE_ROW_FROM_BEGINNING);
+ } else {
+ selectMenuPath(COLUMNS_AND_ROWS, tableSection,
+ REMOVE_ONE_ROW_FROM_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, COLUMNS,
+ REMOVE_ONE_COLUMN_FROM_BEGINNING);
+ }
+
+ assertLogContainsInOrder("preDetach: elementIsAttached == true",
+ "postDetach: elementIsAttached == false");
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/DisabledGridTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/DisabledGridTest.java
new file mode 100644
index 0000000000..ed1234e608
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/DisabledGridTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class DisabledGridTest extends GridBasicFeaturesTest {
+
+ @Before
+ public void setUp() {
+ openTestURL();
+ selectMenuPath("Component", "State", "Enabled");
+ }
+
+ @Test
+ public void testSelection() {
+ selectMenuPath("Component", "State", "Selection mode", "single");
+
+ GridRowElement row = getGridElement().getRow(0);
+ row.click();
+ assertFalse("disabled row should not be selected", row.isSelected());
+
+ }
+
+ @Test
+ public void testEditorOpening() {
+ selectMenuPath("Component", "Editor", "Enabled");
+
+ GridRowElement row = getGridElement().getRow(0);
+ row.click();
+ assertNull("Editor should not open", getEditor());
+
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+ assertNull("Editor should not open", getEditor());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellFocusAdjustmentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellFocusAdjustmentTest.java
new file mode 100644
index 0000000000..0c26ceb5c9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellFocusAdjustmentTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridCellFocusAdjustmentTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testCellFocusWithAddAndRemoveRows() {
+ openTestURL();
+ GridElement grid = getGridElement();
+
+ grid.getCell(0, 0).click();
+
+ selectMenuPath("Component", "Body rows", "Add first row");
+ assertTrue("Cell focus was not moved when adding a row",
+ grid.getCell(1, 0).isFocused());
+
+ selectMenuPath("Component", "Body rows", "Add 18 rows");
+ assertTrue("Cell focus was not moved when adding multiple rows", grid
+ .getCell(19, 0).isFocused());
+
+ for (int i = 18; i <= 0; --i) {
+ selectMenuPath("Component", "Body rows", "Remove first row");
+ assertTrue("Cell focus was not moved when removing a row", grid
+ .getCell(i, 0).isFocused());
+ }
+ }
+
+ @Test
+ public void testCellFocusOffsetWhileInDifferentSection() {
+ openTestURL();
+ getGridElement().getCell(0, 0).click();
+ new Actions(getDriver()).sendKeys(Keys.UP).perform();
+ assertTrue("Header 0,0 should've become focused", getGridElement()
+ .getHeaderCell(0, 0).isFocused());
+
+ selectMenuPath("Component", "Body rows", "Add first row");
+ assertTrue("Header 0,0 should've remained focused", getGridElement()
+ .getHeaderCell(0, 0).isFocused());
+ }
+
+ @Test
+ public void testCellFocusOffsetWhileInSameSectionAndInsertedAbove() {
+ openTestURL();
+ assertTrue("Body 0,0 should've gotten focus",
+ getGridElement().getCell(0, 0).isFocused());
+
+ selectMenuPath("Component", "Body rows", "Add first row");
+ assertTrue("Body 1,0 should've gotten focus",
+ getGridElement().getCell(1, 0).isFocused());
+ }
+
+ @Test
+ public void testCellFocusOffsetWhileInSameSectionAndInsertedBelow() {
+ openTestURL();
+ assertTrue("Body 0,0 should've gotten focus",
+ getGridElement().getCell(0, 0).isFocused());
+
+ selectMenuPath("Component", "Body rows", "Add third row");
+ assertTrue("Body 0,0 should've remained focused", getGridElement()
+ .getCell(0, 0).isFocused());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java
new file mode 100644
index 0000000000..643c61d90a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridCellStyleGeneratorTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridCellStyleGeneratorTest extends GridBasicFeaturesTest {
+ @Test
+ public void testStyleNameGeneratorScrolling() throws Exception {
+ openTestURL();
+
+ selectRowStyleNameGenerator(GridBasicFeatures.ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4);
+ selectCellStyleNameGenerator(GridBasicFeatures.CELL_STYLE_GENERATOR_SPECIAL);
+
+ GridRowElement row = getGridElement().getRow(2);
+ GridCellElement cell = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(hasCssClass(row, "row2"));
+ Assert.assertTrue(hasCssClass(cell, "Column_2"));
+
+ // Scroll down and verify that the old elements don't have the
+ // stylename any more
+
+ // Carefully chosen offset to hit an index % 4 without cell style
+ row = getGridElement().getRow(352);
+ cell = getGridElement().getCell(353, 2);
+
+ Assert.assertFalse(hasCssClass(row, "row352"));
+ Assert.assertFalse(hasCssClass(cell, "Column_2"));
+ }
+
+ @Test
+ public void testDisableStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectRowStyleNameGenerator(GridBasicFeatures.ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4);
+ selectCellStyleNameGenerator(GridBasicFeatures.CELL_STYLE_GENERATOR_SPECIAL);
+
+ // Just verify that change was effective
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell3_2 = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(hasCssClass(row2, "row2"));
+ Assert.assertTrue(hasCssClass(cell3_2, "Column_2"));
+
+ // Disable the generator and check again
+ selectRowStyleNameGenerator(GridBasicFeatures.ROW_STYLE_GENERATOR_NONE);
+ selectCellStyleNameGenerator(GridBasicFeatures.CELL_STYLE_GENERATOR_NONE);
+
+ Assert.assertFalse(hasCssClass(row2, "row2"));
+ Assert.assertFalse(hasCssClass(cell3_2, "Column_2"));
+ }
+
+ @Test
+ public void testChangeStyleNameGenerator() throws Exception {
+ openTestURL();
+
+ selectRowStyleNameGenerator(GridBasicFeatures.ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4);
+ selectCellStyleNameGenerator(GridBasicFeatures.CELL_STYLE_GENERATOR_SPECIAL);
+
+ // Just verify that change was effective
+ GridRowElement row2 = getGridElement().getRow(2);
+ GridCellElement cell3_2 = getGridElement().getCell(3, 2);
+
+ Assert.assertTrue(hasCssClass(row2, "row2"));
+ Assert.assertTrue(hasCssClass(cell3_2, "Column_2"));
+
+ // Change the generator and check again
+ selectRowStyleNameGenerator(GridBasicFeatures.ROW_STYLE_GENERATOR_NONE);
+ selectCellStyleNameGenerator(GridBasicFeatures.CELL_STYLE_GENERATOR_PROPERTY_TO_STRING);
+
+ // Old styles removed?
+ Assert.assertFalse(hasCssClass(row2, "row2"));
+ Assert.assertFalse(hasCssClass(cell3_2, "Column_2"));
+
+ // New style present?
+ Assert.assertTrue(hasCssClass(cell3_2, "Column-2"));
+ }
+
+ @Test
+ public void testCellStyleGeneratorWithSelectionColumn() {
+ setDebug(true);
+ openTestURL();
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+
+ selectCellStyleNameGenerator(GridBasicFeatures.CELL_STYLE_GENERATOR_SPECIAL);
+
+ assertFalse("Error notification was present",
+ isElementPresent(NotificationElement.class));
+ }
+
+ private void selectRowStyleNameGenerator(String name) {
+ selectMenuPath("Component", "State", "Row style generator", name);
+ }
+
+ private void selectCellStyleNameGenerator(String name) {
+ selectMenuPath("Component", "State", "Cell style generator", name);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java
new file mode 100644
index 0000000000..0218fffe61
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.GridElement.GridEditorElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridEditorTest extends GridBasicFeaturesTest {
+
+ private static final String[] EDIT_ITEM_5 = new String[] { "Component",
+ "Editor", "Edit item 5" };
+ private static final String[] EDIT_ITEM_100 = new String[] { "Component",
+ "Editor", "Edit item 100" };
+ private static final String[] TOGGLE_EDIT_ENABLED = new String[] {
+ "Component", "Editor", "Enabled" };
+
+ @Before
+ public void setUp() {
+ setDebug(true);
+ openTestURL();
+ selectMenuPath(TOGGLE_EDIT_ENABLED);
+ }
+
+ @Test
+ public void testProgrammaticOpeningClosing() {
+ selectMenuPath(EDIT_ITEM_5);
+ assertEditorOpen();
+
+ selectMenuPath("Component", "Editor", "Cancel edit");
+ assertEditorClosed();
+ }
+
+ @Test
+ public void testProgrammaticOpeningWhenDisabled() {
+ selectMenuPath(TOGGLE_EDIT_ENABLED);
+ selectMenuPath(EDIT_ITEM_5);
+ assertEditorClosed();
+ boolean thrown = logContainsText("Exception occured, java.lang.IllegalStateException");
+ assertTrue("IllegalStateException thrown", thrown);
+ }
+
+ @Test
+ public void testDisablingWhileOpen() {
+ selectMenuPath(EDIT_ITEM_5);
+ selectMenuPath(TOGGLE_EDIT_ENABLED);
+ assertEditorOpen();
+ boolean thrown = logContainsText("Exception occured, java.lang.IllegalStateException");
+ assertTrue("IllegalStateException thrown", thrown);
+ }
+
+ @Test
+ public void testProgrammaticOpeningWithScroll() {
+ selectMenuPath(EDIT_ITEM_100);
+ assertEditorOpen();
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void testVerticalScrollLocking() {
+ selectMenuPath(EDIT_ITEM_5);
+ getGridElement().getCell(200, 0);
+ }
+
+ @Test
+ public void testKeyboardOpeningClosing() {
+
+ getGridElement().getCell(4, 0).click();
+ assertEditorClosed();
+
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+ assertEditorOpen();
+
+ new Actions(getDriver()).sendKeys(Keys.ESCAPE).perform();
+ assertEditorClosed();
+
+ // Disable Editor
+ selectMenuPath(TOGGLE_EDIT_ENABLED);
+ getGridElement().getCell(5, 0).click();
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+ assertEditorClosed();
+ }
+
+ @Test
+ public void testComponentBinding() {
+ selectMenuPath(EDIT_ITEM_100);
+
+ List<WebElement> widgets = getEditorWidgets();
+ assertEquals("Number of widgets", GridBasicFeatures.COLUMNS,
+ widgets.size());
+
+ assertEquals("(100, 0)", widgets.get(0).getAttribute("value"));
+ assertEquals("(100, 1)", widgets.get(1).getAttribute("value"));
+ assertEquals("(100, 2)", widgets.get(2).getAttribute("value"));
+ assertEquals("<b>100</b>", widgets.get(9).getAttribute("value"));
+ }
+
+ @Test
+ public void testSave() {
+ selectMenuPath(EDIT_ITEM_100);
+
+ WebElement textField = getEditorWidgets().get(0);
+
+ textField.click();
+
+ textField.sendKeys(" changed");
+
+ WebElement saveButton = getEditor().findElement(
+ By.className("v-grid-editor-save"));
+
+ saveButton.click();
+
+ assertEquals("(100, 0) changed", getGridElement().getCell(100, 0)
+ .getText());
+ }
+
+ @Test
+ public void testProgrammaticSave() {
+ selectMenuPath(EDIT_ITEM_100);
+
+ WebElement textField = getEditorWidgets().get(0);
+
+ textField.click();
+
+ textField.sendKeys(" changed");
+
+ selectMenuPath("Component", "Editor", "Save");
+
+ assertEquals("(100, 0) changed", getGridElement().getCell(100, 0)
+ .getText());
+ }
+
+ private void assertEditorOpen() {
+ assertNotNull("Editor is supposed to be open", getEditor());
+ assertEquals("Unexpected number of widgets", GridBasicFeatures.COLUMNS,
+ getEditorWidgets().size());
+ }
+
+ private void assertEditorClosed() {
+ assertNull("Editor is supposed to be closed", getEditor());
+ }
+
+ private List<WebElement> getEditorWidgets() {
+ assertNotNull(getEditor());
+ return getEditor().findElements(By.className("v-textfield"));
+
+ }
+
+ @Test
+ public void testInvalidEdition() {
+ selectMenuPath(EDIT_ITEM_5);
+ assertFalse(logContainsText("Exception occured, java.lang.IllegalStateException"));
+
+ GridEditorElement editor = getGridElement().getEditor();
+
+ WebElement intField = editor.getField(7);
+ intField.clear();
+ intField.sendKeys("banana phone");
+ editor.save();
+ assertTrue(
+ "No exception on invalid value.",
+ logContainsText("Exception occured, com.vaadin.data.fieldgroup.FieldGroup$CommitException: Commit failed"));
+ editor.cancel();
+
+ selectMenuPath(EDIT_ITEM_100);
+ assertFalse("Exception should not exist",
+ isElementPresent(NotificationElement.class));
+ }
+
+ @Test
+ public void testNoScrollAfterEditByAPI() {
+ int originalScrollPos = getGridVerticalScrollPos();
+
+ selectMenuPath(EDIT_ITEM_5);
+
+ scrollGridVerticallyTo(100);
+ assertEquals("Grid shouldn't scroll vertically while editing",
+ originalScrollPos, getGridVerticalScrollPos());
+ }
+
+ @Test
+ public void testNoScrollAfterEditByMouse() {
+ int originalScrollPos = getGridVerticalScrollPos();
+
+ GridCellElement cell_5_0 = getGridElement().getCell(5, 0);
+ new Actions(getDriver()).doubleClick(cell_5_0).perform();
+
+ scrollGridVerticallyTo(100);
+ assertEquals("Grid shouldn't scroll vertically while editing",
+ originalScrollPos, getGridVerticalScrollPos());
+ }
+
+ @Test
+ public void testNoScrollAfterEditByKeyboard() {
+ int originalScrollPos = getGridVerticalScrollPos();
+
+ GridCellElement cell_5_0 = getGridElement().getCell(5, 0);
+ cell_5_0.click();
+ new Actions(getDriver()).sendKeys(Keys.ENTER).perform();
+
+ scrollGridVerticallyTo(100);
+ assertEquals("Grid shouldn't scroll vertically while editing",
+ originalScrollPos, getGridVerticalScrollPos());
+ }
+
+ @Test
+ public void testEditorInDisabledGrid() {
+ int originalScrollPos = getGridVerticalScrollPos();
+
+ selectMenuPath(EDIT_ITEM_5);
+ assertEditorOpen();
+
+ selectMenuPath("Component", "State", "Enabled");
+ assertEditorOpen();
+
+ GridEditorElement editor = getGridElement().getEditor();
+ editor.save();
+ assertEditorOpen();
+
+ editor.cancel();
+ assertEditorOpen();
+
+ selectMenuPath("Component", "State", "Enabled");
+
+ scrollGridVerticallyTo(100);
+ assertEquals("Grid shouldn't scroll vertically while editing",
+ originalScrollPos, getGridVerticalScrollPos());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridItemClickTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridItemClickTest.java
new file mode 100644
index 0000000000..57fc56c995
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridItemClickTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridItemClickTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testItemClick() {
+ openTestURL();
+
+ selectMenuPath("Component", "State", "ItemClickListener");
+
+ GridCellElement cell = getGridElement().getCell(3, 2);
+ new Actions(getDriver()).moveToElement(cell).click().perform();
+
+ assertTrue("No click in log", logContainsText(itemClickOn(3, 2, false)));
+ }
+
+ @Test
+ public void testItemDoubleClick() {
+ openTestURL();
+
+ selectMenuPath("Component", "State", "ItemClickListener");
+
+ GridCellElement cell = getGridElement().getCell(3, 2);
+ new Actions(getDriver()).moveToElement(cell).doubleClick().perform();
+
+ assertTrue("No double click in log",
+ logContainsText(itemClickOn(3, 2, true)));
+ }
+
+ private String itemClickOn(int row, int column, boolean dblClick) {
+ return "Item " + (dblClick ? "double " : "") + "click on Column "
+ + column + ", item " + row;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java
new file mode 100644
index 0000000000..3f2e82793b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridKeyboardNavigationTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testCellFocusOnClick() {
+ openTestURL();
+
+ GridElement grid = getGridElement();
+ assertTrue("Body cell 0, 0 is not focused on init.", grid.getCell(0, 0)
+ .isFocused());
+ grid.getCell(5, 2).click();
+ assertFalse("Body cell 0, 0 was still focused after clicking", grid
+ .getCell(0, 0).isFocused());
+ assertTrue("Body cell 5, 2 is not focused after clicking", grid
+ .getCell(5, 2).isFocused());
+ }
+
+ @Test
+ public void testCellNotFocusedWhenRendererHandlesEvent() {
+ openTestURL();
+
+ GridElement grid = getGridElement();
+ assertTrue("Body cell 0, 0 is not focused on init.", grid.getCell(0, 0)
+ .isFocused());
+ grid.getHeaderCell(0, 3).click();
+ assertFalse("Body cell 0, 0 is focused after click on header.", grid
+ .getCell(0, 0).isFocused());
+ assertTrue("Header cell 0, 3 is not focused after click on header.",
+ grid.getHeaderCell(0, 3).isFocused());
+ }
+
+ @Test
+ public void testSimpleKeyboardNavigation() {
+ openTestURL();
+
+ GridElement grid = getGridElement();
+ grid.getCell(0, 0).click();
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform();
+ assertTrue("Body cell 1, 0 is not focused after keyboard navigation.",
+ grid.getCell(1, 0).isFocused());
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT).perform();
+ assertTrue("Body cell 1, 1 is not focused after keyboard navigation.",
+ grid.getCell(1, 1).isFocused());
+
+ int i;
+ for (i = 1; i < 40; ++i) {
+ new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform();
+ }
+
+ assertFalse("Grid has not scrolled with cell focus",
+ isElementPresent(By.xpath("//td[text() = '(0, 0)']")));
+ assertTrue("Cell focus is not visible",
+ isElementPresent(By.xpath("//td[text() = '(" + i + ", 0)']")));
+ assertTrue("Body cell " + i + ", 1 is not focused", grid.getCell(i, 1)
+ .isFocused());
+ }
+
+ @Test
+ public void testNavigateFromHeaderToBody() {
+ openTestURL();
+
+ GridElement grid = getGridElement();
+ grid.scrollToRow(300);
+ new Actions(driver).moveToElement(grid.getHeaderCell(0, 7)).click()
+ .perform();
+ grid.scrollToRow(280);
+
+ assertTrue("Header cell is not focused.", grid.getHeaderCell(0, 7)
+ .isFocused());
+ new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform();
+ assertTrue("Body cell 280, 7 is not focused", grid.getCell(280, 7)
+ .isFocused());
+ }
+
+ @Test
+ public void testNavigationFromFooterToBody() {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Visible");
+
+ GridElement grid = getGridElement();
+ grid.scrollToRow(300);
+ grid.getFooterCell(0, 2).click();
+
+ assertTrue("Footer cell does not have focus.", grid.getFooterCell(0, 2)
+ .isFocused());
+ new Actions(getDriver()).sendKeys(Keys.ARROW_UP).perform();
+ assertTrue("Body cell 300, 2 does not have focus.", grid
+ .getCell(300, 2).isFocused());
+ }
+
+ @Test
+ public void testNavigateBetweenHeaderAndBodyWithTab() {
+ openTestURL();
+
+ GridElement grid = getGridElement();
+ grid.getCell(10, 2).click();
+
+ assertTrue("Body cell 10, 2 does not have focus", grid.getCell(10, 2)
+ .isFocused());
+ new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB)
+ .keyUp(Keys.SHIFT).perform();
+ assertTrue("Header cell 0, 2 does not have focus",
+ grid.getHeaderCell(0, 2).isFocused());
+ new Actions(getDriver()).sendKeys(Keys.TAB).perform();
+ assertTrue("Body cell 10, 2 does not have focus", grid.getCell(10, 2)
+ .isFocused());
+
+ // Navigate out of the Grid and try to navigate with arrow keys.
+ new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB)
+ .sendKeys(Keys.TAB).keyUp(Keys.SHIFT).sendKeys(Keys.ARROW_DOWN)
+ .perform();
+ assertTrue("Header cell 0, 2 does not have focus",
+ grid.getHeaderCell(0, 2).isFocused());
+ }
+
+ @Test
+ public void testNavigateBetweenFooterAndBodyWithTab() {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Visible");
+
+ GridElement grid = getGridElement();
+ grid.getCell(10, 2).click();
+
+ assertTrue("Body cell 10, 2 does not have focus", grid.getCell(10, 2)
+ .isFocused());
+ new Actions(getDriver()).sendKeys(Keys.TAB).perform();
+ assertTrue("Footer cell 0, 2 does not have focus",
+ grid.getFooterCell(0, 2).isFocused());
+ new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB)
+ .keyUp(Keys.SHIFT).perform();
+ assertTrue("Body cell 10, 2 does not have focus", grid.getCell(10, 2)
+ .isFocused());
+
+ // Navigate out of the Grid and try to navigate with arrow keys.
+ new Actions(getDriver()).sendKeys(Keys.TAB).sendKeys(Keys.TAB)
+ .sendKeys(Keys.ARROW_UP).perform();
+ assertTrue("Footer cell 0, 2 does not have focus",
+ grid.getFooterCell(0, 2).isFocused());
+ }
+
+ @Test
+ public void testHomeEnd() throws Exception {
+ openTestURL();
+
+ getGridElement().getCell(100, 2).click();
+
+ new Actions(getDriver()).sendKeys(Keys.HOME).perform();
+ assertTrue("First row is not visible", getGridElement().getCell(0, 2)
+ .isDisplayed());
+
+ new Actions(getDriver()).sendKeys(Keys.END).perform();
+ assertTrue("Last row cell not visible",
+ getGridElement().getCell(GridBasicFeatures.ROWS - 1, 2)
+ .isDisplayed());
+ }
+
+ @Test
+ public void testPageUpPageDown() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Size", "HeightMode Row");
+
+ getGridElement().getCell(5, 2).click();
+
+ new Actions(getDriver()).sendKeys(Keys.PAGE_DOWN).perform();
+ assertTrue("Row 20 did not become visible",
+ isElementPresent(By.xpath("//td[text() = '(20, 2)']")));
+
+ new Actions(getDriver()).sendKeys(Keys.PAGE_DOWN).perform();
+ assertTrue("Row 30 did not become visible",
+ isElementPresent(By.xpath("//td[text() = '(30, 2)']")));
+
+ assertTrue("Originally focused cell is no longer focused",
+ getGridElement().getCell(5, 2).isFocused());
+
+ getGridElement().getCell(50, 2).click();
+
+ new Actions(getDriver()).sendKeys(Keys.PAGE_UP).perform();
+ assertTrue("Row 31 did not become visible",
+ isElementPresent(By.xpath("//td[text() = '(31, 2)']")));
+
+ new Actions(getDriver()).sendKeys(Keys.PAGE_UP).perform();
+ assertTrue("Row 21 did not become visible",
+ isElementPresent(By.xpath("//td[text() = '(21, 2)']")));
+
+ assertTrue("Originally focused cell is no longer focused",
+ getGridElement().getCell(50, 2).isFocused());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridMultiSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridMultiSortingTest.java
new file mode 100644
index 0000000000..a61ed33029
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridMultiSortingTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridMultiSortingTest extends GridBasicFeaturesTest {
+
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+ List<DesiredCapabilities> browsersToTest = super.getBrowsersToTest();
+ /* FireFox and PhantomJS don't know how to press Shift key... */
+ browsersToTest.remove(Browser.FIREFOX.getDesiredCapabilities());
+ browsersToTest.remove(Browser.PHANTOMJS.getDesiredCapabilities());
+ return browsersToTest;
+ }
+
+ @Test
+ public void testUserMultiColumnSorting() {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 11", "Column 11 Width",
+ "Auto");
+
+ GridCellElement cell = getGridElement().getHeaderCell(0, 11);
+ new Actions(driver).moveToElement(cell, 5, 5).click().perform();
+ new Actions(driver).keyDown(Keys.SHIFT).perform();
+ new Actions(driver)
+ .moveToElement(getGridElement().getHeaderCell(0, 0), 5, 5)
+ .click().perform();
+ new Actions(driver).keyUp(Keys.SHIFT).perform();
+
+ String prev = getGridElement().getCell(0, 11).getAttribute("innerHTML");
+ for (int i = 1; i <= 6; ++i) {
+ assertEquals("Column 11 should contain same values.", prev,
+ getGridElement().getCell(i, 11).getAttribute("innerHTML"));
+ }
+
+ prev = getGridElement().getCell(0, 0).getText();
+ for (int i = 1; i <= 6; ++i) {
+ assertTrue(
+ "Grid is not sorted by column 0.",
+ prev.compareTo(getGridElement().getCell(i, 0).getText()) < 0);
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridRowAddRemoveTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridRowAddRemoveTest.java
new file mode 100644
index 0000000000..8535efb9ef
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridRowAddRemoveTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridRowAddRemoveTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void addRows_loadAllAtOnce() {
+ openTestURL();
+
+ selectMenuPath("Settings", "Clear log");
+ selectMenuPath("Component", "Body rows", "Remove all rows");
+ selectMenuPath("Component", "Body rows", "Add 18 rows");
+
+ Assert.assertTrue(
+ "All added rows should be fetched in the same round trip.",
+ logContainsText("Requested items 0 - 18"));
+ }
+
+ @Test
+ public void removeRows_loadAllAtOnce() {
+ openTestURL();
+
+ selectMenuPath("Component", "Size", "HeightMode Row");
+ selectMenuPath("Settings", "Clear log");
+ selectMenuPath("Component", "Body rows", "Remove 18 first rows");
+
+ Assert.assertTrue(
+ "All newly required rows should be fetched in the same round trip.",
+ logContainsText("Requested items 37 - 55"));
+
+ selectMenuPath("Settings", "Clear log");
+ selectMenuPath("Component", "Body rows", "Remove 18 first rows");
+
+ Assert.assertTrue(
+ "All newly required rows should be fetched in the same round trip.",
+ logContainsText("Requested items 37 - 55"));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
new file mode 100644
index 0000000000..3dbf613ba0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridSelectionTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testSelectOnOff() throws Exception {
+ openTestURL();
+
+ setSelectionModelMulti();
+
+ assertFalse("row shouldn't start out as selected", getRow(0)
+ .isSelected());
+ toggleFirstRowSelection();
+ assertTrue("row should become selected", getRow(0).isSelected());
+ toggleFirstRowSelection();
+ assertFalse("row shouldn't remain selected", getRow(0).isSelected());
+ }
+
+ @Test
+ public void testSelectOnScrollOffScroll() throws Exception {
+ openTestURL();
+
+ setSelectionModelMulti();
+
+ assertFalse("row shouldn't start out as selected", getRow(0)
+ .isSelected());
+ toggleFirstRowSelection();
+ assertTrue("row should become selected", getRow(0).isSelected());
+
+ scrollGridVerticallyTo(10000); // make sure the row is out of cache
+ scrollGridVerticallyTo(0); // scroll it back into view
+
+ assertTrue("row should still be selected when scrolling "
+ + "back into view", getRow(0).isSelected());
+ }
+
+ @Test
+ public void testSelectScrollOnScrollOff() throws Exception {
+ openTestURL();
+
+ setSelectionModelMulti();
+
+ assertFalse("row shouldn't start out as selected", getRow(0)
+ .isSelected());
+
+ scrollGridVerticallyTo(10000); // make sure the row is out of cache
+ toggleFirstRowSelection();
+
+ scrollGridVerticallyTo(0); // scroll it back into view
+ assertTrue("row should still be selected when scrolling "
+ + "back into view", getRow(0).isSelected());
+
+ toggleFirstRowSelection();
+ assertFalse("row shouldn't remain selected", getRow(0).isSelected());
+ }
+
+ @Test
+ public void testSelectScrollOnOffScroll() throws Exception {
+ openTestURL();
+
+ setSelectionModelMulti();
+
+ assertFalse("row shouldn't start out as selected", getRow(0)
+ .isSelected());
+
+ scrollGridVerticallyTo(10000); // make sure the row is out of cache
+ toggleFirstRowSelection();
+ toggleFirstRowSelection();
+
+ scrollGridVerticallyTo(0); // make sure the row is out of cache
+ assertFalse("row shouldn't be selected when scrolling "
+ + "back into view", getRow(0).isSelected());
+ }
+
+ @Test
+ public void testSingleSelectionUpdatesFromServer() {
+ openTestURL();
+ setSelectionModelSingle();
+
+ GridElement grid = getGridElement();
+ assertFalse("First row was selected from start", grid.getRow(0)
+ .isSelected());
+ toggleFirstRowSelection();
+ assertTrue("First row was not selected.", getRow(0).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Added 0, Removed none"));
+ grid.getCell(5, 0).click();
+ assertTrue("Fifth row was not selected.", getRow(5).isSelected());
+ assertFalse("First row was still selected.", getRow(0).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Added 5, Removed 0"));
+ grid.getCell(0, 6).click();
+ assertTrue("Selection event was not correct",
+ logContainsText("Added 0, Removed 5"));
+ toggleFirstRowSelection();
+ assertTrue("Selection event was not correct",
+ logContainsText("Added none, Removed 0"));
+ assertFalse("First row was still selected.", getRow(0).isSelected());
+ assertFalse("Fifth row was still selected.", getRow(5).isSelected());
+
+ grid.scrollToRow(600);
+ grid.getCell(595, 3).click();
+ assertTrue("Row 595 was not selected.", getRow(595).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Added 595, Removed none"));
+ toggleFirstRowSelection();
+ assertFalse("Row 595 was still selected.", getRow(595).isSelected());
+ assertTrue("First row was not selected.", getRow(0).isSelected());
+ assertTrue("Selection event was not correct",
+ logContainsText("Added 0, Removed 595"));
+ }
+
+ @Test
+ public void testKeyboardSelection() {
+ openTestURL();
+ setSelectionModelMulti();
+
+ GridElement grid = getGridElement();
+ grid.getCell(3, 1).click();
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not selected with space key.", grid
+ .getRow(3).isSelected());
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not deselected with space key.", !grid
+ .getRow(3).isSelected());
+
+ grid.scrollToRow(500);
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not selected with space key.", grid
+ .getRow(3).isSelected());
+ }
+
+ @Test
+ public void testKeyboardWithSingleSelection() {
+ openTestURL();
+ setSelectionModelSingle();
+
+ GridElement grid = getGridElement();
+ grid.getCell(3, 1).click();
+
+ assertTrue("Grid row 3 was not selected with clicking.", grid.getRow(3)
+ .isSelected());
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not deselected with space key.", !grid
+ .getRow(3).isSelected());
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not selected with space key.", grid
+ .getRow(3).isSelected());
+
+ grid.scrollToRow(500);
+
+ new Actions(getDriver()).sendKeys(Keys.SPACE).perform();
+
+ assertTrue("Grid row 3 was not deselected with space key.", !grid
+ .getRow(3).isSelected());
+ }
+
+ @Test
+ public void testSelectAllCheckbox() {
+ openTestURL();
+
+ setSelectionModelMulti();
+ GridCellElement header = getGridElement().getHeaderCell(0, 0);
+
+ assertTrue("No checkbox", header.isElementPresent(By.tagName("input")));
+ header.findElement(By.tagName("input")).click();
+
+ for (int i = 0; i < GridBasicFeatures.ROWS; i += 100) {
+ assertTrue("Row " + i + " was not selected.", getGridElement()
+ .getRow(i).isSelected());
+ }
+
+ header.findElement(By.tagName("input")).click();
+ assertFalse("Row 100 was still selected", getGridElement().getRow(100)
+ .isSelected());
+ }
+
+ @Test
+ public void testSelectAllAndSort() {
+ openTestURL();
+
+ setSelectionModelMulti();
+ GridCellElement header = getGridElement().getHeaderCell(0, 0);
+
+ header.findElement(By.tagName("input")).click();
+
+ getGridElement().getHeaderCell(0, 1).click();
+
+ WebElement selectionBox = getGridElement().getCell(4, 0).findElement(
+ By.tagName("input"));
+ selectionBox.click();
+ selectionBox.click();
+
+ assertFalse(
+ "Exception occured on row reselection.",
+ logContainsText("Exception occured, java.lang.IllegalStateException: No item id for key 101 found."));
+ }
+
+ @Test
+ public void testSelectAllCheckboxWhenChangingModels() {
+ openTestURL();
+
+ GridCellElement header;
+ header = getGridElement().getHeaderCell(0, 0);
+ assertFalse(
+ "Check box shouldn't have been in header for None Selection Model",
+ header.isElementPresent(By.tagName("input")));
+
+ setSelectionModelMulti();
+ header = getGridElement().getHeaderCell(0, 0);
+ assertTrue("Multi Selection Model should have select all checkbox",
+ header.isElementPresent(By.tagName("input")));
+
+ setSelectionModelSingle();
+ header = getGridElement().getHeaderCell(0, 0);
+ assertFalse(
+ "Check box shouldn't have been in header for Single Selection Model",
+ header.isElementPresent(By.tagName("input")));
+
+ // Single selection model shouldn't have selection column to begin with
+ assertFalse(
+ "Selection columnn shouldn't have been in grid for Single Selection Model",
+ getGridElement().getCell(0, 1).isElementPresent(
+ By.tagName("input")));
+
+ setSelectionModelNone();
+ header = getGridElement().getHeaderCell(0, 0);
+ assertFalse(
+ "Check box shouldn't have been in header for None Selection Model",
+ header.isElementPresent(By.tagName("input")));
+
+ }
+
+ private void setSelectionModelMulti() {
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+ }
+
+ private void setSelectionModelSingle() {
+ selectMenuPath("Component", "State", "Selection mode", "single");
+ }
+
+ private void setSelectionModelNone() {
+ selectMenuPath("Component", "State", "Selection mode", "none");
+ }
+
+ private void toggleFirstRowSelection() {
+ selectMenuPath("Component", "Body rows", "Select first row");
+ }
+
+ private GridRowElement getRow(int i) {
+ return getGridElement().getRow(i);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java
new file mode 100644
index 0000000000..7e805595c6
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+@TestCategory("grid")
+public class GridSortingTest extends GridBasicFeaturesTest {
+
+ private static class SortInfo {
+ public final int sortOrder;
+ public final SortDirection sortDirection;
+
+ private SortInfo(int sortOrder, SortDirection sortDirection) {
+ this.sortOrder = sortOrder;
+ this.sortDirection = sortDirection;
+ }
+ }
+
+ private static class SortInfoWithColumn extends SortInfo {
+ public final int columnIndex;
+
+ private SortInfoWithColumn(int columnIndex, int sortOrder,
+ SortDirection sortDirection) {
+ super(sortOrder, sortDirection);
+ this.columnIndex = columnIndex;
+ }
+ }
+
+ private static SortInfo _(int sortOrder, SortDirection sortDirection) {
+ return new SortInfo(sortOrder, sortDirection);
+ }
+
+ private static SortInfoWithColumn _(int columnIndex, int sortOrder,
+ SortDirection sortDirection) {
+ return new SortInfoWithColumn(columnIndex, sortOrder, sortDirection);
+ }
+
+ @Test
+ public void testProgrammaticSorting() throws Exception {
+ openTestURL();
+
+ // Sorting by column 9 is sorting by row index that is represented as a
+ // String.
+ // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0)
+ sortBy("Column 9, DESC");
+ assertLastSortIsUserOriginated(false);
+
+ // Verify that programmatic sorting calls are identified as originating
+ // from API
+ assertColumnsAreSortedAs(_(9, 1, SortDirection.DESCENDING));
+
+ String row = "";
+ for (int i = 0; i < 3; ++i) {
+ row += "9";
+ String expected = "(" + row + ", 0)";
+ String cellValue = getGridElement().getCell(i, 0).getText();
+ assertEquals("Grid is not sorted by Column 9 "
+ + "using descending direction.", expected, cellValue);
+ }
+
+ // Column 10 is random numbers from Random with seed 13334
+ sortBy("Column 10, ASC");
+
+ assertFalse("Column 9 should no longer have the sort-desc stylename",
+ getGridElement().getHeaderCell(0, 9).getAttribute("class")
+ .contains("sort-desc"));
+
+ assertColumnsAreSortedAs(_(10, 1, SortDirection.ASCENDING));
+
+ for (int i = 0; i < 5; ++i) {
+ Integer firstRow = Integer.valueOf(getGridElement().getCell(i + 1,
+ 10).getText());
+ Integer secondRow = Integer.valueOf(getGridElement().getCell(i, 10)
+ .getText());
+ assertGreater("Grid is not sorted by Column 10 using"
+ + " ascending direction", firstRow, secondRow);
+
+ }
+
+ // Column 7 is row index as a number. Last three row are original rows
+ // 2, 1 and 0.
+ sortBy("Column 7, DESC");
+ for (int i = 0; i < 3; ++i) {
+ String expected = "(" + i + ", 0)";
+ String cellContent = getGridElement().getCell(
+ GridBasicFeatures.ROWS - (i + 1), 0).getText();
+ assertEquals("Grid is not sorted by Column 7 using "
+ + "descending direction", expected, cellContent);
+ }
+
+ assertFalse("Column 10 should no longer have the sort-asc stylename",
+ getGridElement().getHeaderCell(0, 10).getAttribute("class")
+ .contains("sort-asc"));
+
+ assertColumnsAreSortedAs(_(7, 1, SortDirection.DESCENDING));
+ }
+
+ @Test
+ public void testMouseSorting() throws Exception {
+ setDebug(true);
+ openTestURL();
+
+ GridElement grid = getGridElement();
+
+ selectMenuPath("Component", "Columns", "Column 9", "Column 9 Width",
+ "Auto");
+
+ // Sorting by column 9 is sorting by row index that is represented as a
+ // String.
+
+ // Click header twice to sort descending
+ GridCellElement header = grid.getHeaderCell(0, 9);
+ header.click();
+ assertLastSortIsUserOriginated(true);
+
+ assertColumnsAreSortedAs(_(9, 1, SortDirection.ASCENDING));
+ grid.getHeaderCell(0, 9).click();
+ assertColumnsAreSortedAs(_(9, 1, SortDirection.DESCENDING));
+
+ // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0)
+ String row = "";
+ for (int i = 0; i < 3; ++i) {
+ row += "9";
+ String expected = "(" + row + ", 0)";
+ String actual = grid.getCell(i, 0).getText();
+ assertEquals("Grid is not sorted by Column 9"
+ + " using descending direction.", expected, actual);
+ }
+
+ selectMenuPath("Component", "Columns", "Column 10", "Column 10 Width",
+ "Auto");
+ // Column 10 is random numbers from Random with seed 13334
+ // Click header to sort ascending
+ grid.getHeaderCell(0, 10).click();
+ assertColumnsAreSortedAs(_(10, 1, SortDirection.ASCENDING));
+
+ for (int i = 0; i < 5; ++i) {
+ Integer firstRow = Integer.valueOf(grid.getCell(i + 1, 10)
+ .getText());
+ Integer secondRow = Integer.valueOf(grid.getCell(i, 10).getText());
+ assertGreater(
+ "Grid is not sorted by Column 10 using ascending direction",
+ firstRow, secondRow);
+
+ }
+
+ selectMenuPath("Component", "Columns", "Column 7", "Column 7 Width",
+ "Auto");
+ // Column 7 is row index as a number. Last three row are original rows
+ // 2, 1 and 0.
+ // Click header twice to sort descending
+ grid.getHeaderCell(0, 7).click();
+ assertColumnsAreSortedAs(_(7, 1, SortDirection.ASCENDING));
+ grid.getHeaderCell(0, 7).click();
+ assertColumnsAreSortedAs(_(7, 1, SortDirection.DESCENDING));
+
+ for (int i = 0; i < 3; ++i) {
+ assertEquals(
+ "Grid is not sorted by Column 7 using descending direction",
+ "(" + i + ", 0)",
+ grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText());
+ }
+
+ }
+
+ private void sendKey(Keys seq) {
+ new Actions(getDriver()).sendKeys(seq).perform();
+ }
+
+ private void holdKey(Keys key) {
+ new Actions(getDriver()).keyDown(key).perform();
+ }
+
+ private void releaseKey(Keys key) {
+ new Actions(getDriver()).keyUp(key).perform();
+ }
+
+ @Test
+ public void testKeyboardSorting() {
+ openTestURL();
+
+ /*
+ * We can't click on the header directly, since it will sort the header
+ * immediately. We need to focus some other column first, and only then
+ * navigate there.
+ */
+ getGridElement().getCell(0, 0).click();
+ sendKey(Keys.ARROW_UP);
+
+ // Sort ASCENDING on first column
+ sendKey(Keys.ENTER);
+ assertLastSortIsUserOriginated(true);
+ assertColumnsAreSortedAs(_(1, SortDirection.ASCENDING));
+
+ // Move to next column
+ sendKey(Keys.RIGHT);
+
+ // Add this column to the existing sorting group
+ holdKey(Keys.SHIFT);
+ sendKey(Keys.ENTER);
+ releaseKey(Keys.SHIFT);
+ assertColumnsAreSortedAs(_(1, SortDirection.ASCENDING),
+ _(2, SortDirection.ASCENDING));
+
+ // Move to next column
+ sendKey(Keys.RIGHT);
+
+ // Add a third column to the sorting group
+ holdKey(Keys.SHIFT);
+ sendKey(Keys.ENTER);
+ releaseKey(Keys.SHIFT);
+ assertColumnsAreSortedAs(_(1, SortDirection.ASCENDING),
+ _(2, SortDirection.ASCENDING), _(3, SortDirection.ASCENDING));
+
+ // Move back to the second column
+ sendKey(Keys.LEFT);
+
+ // Change sort direction of the second column to DESCENDING
+ holdKey(Keys.SHIFT);
+ sendKey(Keys.ENTER);
+ releaseKey(Keys.SHIFT);
+ assertColumnsAreSortedAs(_(1, SortDirection.ASCENDING),
+ _(2, SortDirection.DESCENDING), _(3, SortDirection.ASCENDING));
+
+ // Move back to the third column
+ sendKey(Keys.RIGHT);
+
+ // Set sorting to third column, ASCENDING
+ sendKey(Keys.ENTER);
+ assertColumnsAreSortedAs(_(2, 1, SortDirection.ASCENDING));
+
+ // Move to the fourth column
+ sendKey(Keys.RIGHT);
+
+ // Make sure that single-column sorting also works as expected
+ sendKey(Keys.ENTER);
+ assertColumnsAreSortedAs(_(3, 1, SortDirection.ASCENDING));
+
+ }
+
+ private void assertColumnsAreSortedAs(SortInfoWithColumn... sortInfos) {
+ for (SortInfoWithColumn sortInfo : sortInfos) {
+ assertSort(sortInfo, sortInfo.columnIndex,
+ onlyOneColumnIsSorted(sortInfos));
+ }
+ }
+
+ /**
+ * @param sortDirections
+ * <code>null</code> if not interested in that index, otherwise a
+ * direction that the column needs to be sorted as
+ */
+ private void assertColumnsAreSortedAs(SortInfo... sortInfos) {
+ for (int column = 0; column < sortInfos.length; column++) {
+ SortInfo sortInfo = sortInfos[column];
+ assertSort(sortInfo, column, onlyOneColumnIsSorted(sortInfos));
+ }
+ }
+
+ private void assertSort(SortInfo sortInfo, int column,
+ boolean onlyOneColumnIsSorted) {
+ if (sortInfo == null) {
+ return;
+ }
+
+ GridCellElement headerCell = getGridElement().getHeaderCell(0, column);
+ String classValue = headerCell.getAttribute("class");
+
+ boolean isSortedAscending = sortInfo.sortDirection == SortDirection.ASCENDING
+ && classValue.contains("sort-asc");
+ boolean isSortedDescending = sortInfo.sortDirection == SortDirection.DESCENDING
+ && classValue.contains("sort-desc");
+
+ if (isSortedAscending || isSortedDescending) {
+ String sortOrderAttribute = headerCell.getAttribute("sort-order");
+
+ if (sortOrderAttribute == null) {
+ if (!(sortInfo.sortOrder == 1 && onlyOneColumnIsSorted)) {
+ fail("missing sort-order element attribute from column "
+ + column);
+ }
+ } else {
+ assertEquals("sort order was not as expected",
+ String.valueOf(sortInfo.sortOrder), sortOrderAttribute);
+ }
+ } else {
+ fail("column index " + column + " was not sorted as "
+ + sortInfo.sortDirection + " (class: " + classValue + ")");
+ }
+ }
+
+ private static boolean onlyOneColumnIsSorted(SortInfo[] sortInfos) {
+
+ boolean foundSortedColumn = false;
+ for (SortInfo sortInfo : sortInfos) {
+ if (sortInfo == null) {
+ continue;
+ }
+
+ if (!foundSortedColumn) {
+ foundSortedColumn = true;
+ } else {
+ // two columns were sorted
+ return false;
+ }
+ }
+ return foundSortedColumn;
+ }
+
+ private void sortBy(String column) {
+ selectMenuPath("Component", "State", "Sort by column", column);
+ }
+
+ private void assertLastSortIsUserOriginated(boolean isUserOriginated) {
+ List<WebElement> userOriginatedMessages = getDriver()
+ .findElements(
+ By.xpath("//*[contains(text(),'SortOrderChangeEvent: isUserOriginated')]"));
+
+ Collections.sort(userOriginatedMessages, new Comparator<WebElement>() {
+ @Override
+ public int compare(WebElement o1, WebElement o2) {
+ return o1.getText().compareTo(o2.getText());
+ }
+ });
+
+ String newestEntry = userOriginatedMessages.get(
+ userOriginatedMessages.size() - 1).getText();
+
+ String[] parts = newestEntry.split(" ");
+ boolean wasUserOriginated = Boolean
+ .parseBoolean(parts[parts.length - 1]);
+ if (isUserOriginated) {
+ assertTrue("expected the sort to be user originated, but wasn't",
+ wasUserOriginated);
+ } else {
+ assertFalse(
+ "expected the sort not to be user originated, but it was",
+ wasUserOriginated);
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java
new file mode 100644
index 0000000000..2fbaa58cab
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridStaticSectionComponentTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testNativeButtonInHeader() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 1", "Header Type",
+ "Widget Header");
+
+ getGridElement().$(ButtonElement.class).first().click();
+
+ assertTrue("Button click should be logged",
+ logContainsText("Button clicked!"));
+ }
+
+ @Test
+ public void testNativeButtonInFooter() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Footer", "Visible");
+ selectMenuPath("Component", "Footer", "Append row");
+ selectMenuPath("Component", "Columns", "Column 1", "Footer Type",
+ "Widget Footer");
+
+ getGridElement().$(ButtonElement.class).first().click();
+
+ assertTrue("Button click should be logged",
+ logContainsText("Button clicked!"));
+ }
+
+ @Test
+ public void testRemoveComponentFromHeader() throws Exception {
+ openTestURL();
+ selectMenuPath("Component", "Columns", "Column 1", "Header Type",
+ "Widget Header");
+ selectMenuPath("Component", "Columns", "Column 1", "Header Type",
+ "Text Header");
+ assertTrue("No notifications should've been shown",
+ !$(NotificationElement.class).exists());
+ assertEquals("Header should've been reverted back to text header",
+ "text header", getGridElement().getHeaderCell(0, 1).getText()
+ .toLowerCase());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java
new file mode 100644
index 0000000000..08f903b3fe
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridStructureTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testRemovingAllColumns() {
+ setDebug(true);
+ openTestURL();
+ for (int i = 0; i < GridBasicFeatures.COLUMNS; ++i) {
+ selectMenuPath("Component", "Columns", "Column " + i,
+ "Add / Remove");
+ assertFalse(isElementPresent(NotificationElement.class));
+ }
+
+ assertEquals("Headers still visible.", 0, getGridHeaderRowCells()
+ .size());
+ }
+
+ @Test
+ public void testRemoveAndAddColumn() {
+ setDebug(true);
+ openTestURL();
+
+ assertEquals("column 0", getGridElement().getHeaderCell(0, 0).getText()
+ .toLowerCase());
+ selectMenuPath("Component", "Columns", "Column 0", "Add / Remove");
+ assertEquals("column 1", getGridElement().getHeaderCell(0, 0).getText()
+ .toLowerCase());
+ selectMenuPath("Component", "Columns", "Column 0", "Add / Remove");
+ // Column 0 is appended to the end of grid
+ assertEquals("column 0", getGridElement().getHeaderCell(0, 11)
+ .getText().toLowerCase());
+ }
+
+ @Test
+ public void testRemovingColumn() throws Exception {
+ openTestURL();
+
+ // Column 0 should be visible
+ List<TestBenchElement> cells = getGridHeaderRowCells();
+ assertEquals("column 0", cells.get(0).getText().toLowerCase());
+
+ // Hide column 0
+ selectMenuPath("Component", "Columns", "Column 0", "Add / Remove");
+
+ // Column 1 should now be the first cell
+ cells = getGridHeaderRowCells();
+ assertEquals("column 1", cells.get(0).getText().toLowerCase());
+ }
+
+ @Test
+ public void testDataLoadingAfterRowRemoval() throws Exception {
+ openTestURL();
+
+ // Remove columns 2,3,4
+ selectMenuPath("Component", "Columns", "Column 2", "Add / Remove");
+ selectMenuPath("Component", "Columns", "Column 3", "Add / Remove");
+ selectMenuPath("Component", "Columns", "Column 4", "Add / Remove");
+
+ // Scroll so new data is lazy loaded
+ scrollGridVerticallyTo(1000);
+
+ // Let lazy loading do its job
+ sleep(1000);
+
+ // Check that row is loaded
+ assertThat(getGridElement().getCell(11, 0).getText(), not("..."));
+ }
+
+ @Test
+ public void testFreezingColumn() throws Exception {
+ openTestURL();
+
+ // Freeze column 1
+ selectMenuPath("Component", "State", "Frozen column count", "1");
+
+ WebElement cell = getGridElement().getCell(0, 0);
+ assertTrue(cell.getAttribute("class").contains("frozen"));
+
+ cell = getGridElement().getCell(0, 1);
+ assertFalse(cell.getAttribute("class").contains("frozen"));
+ }
+
+ @Test
+ public void testInitialColumnWidths() throws Exception {
+ openTestURL();
+
+ WebElement cell = getGridElement().getCell(0, 0);
+ assertEquals(100, cell.getSize().getWidth());
+
+ cell = getGridElement().getCell(0, 1);
+ assertEquals(150, cell.getSize().getWidth());
+
+ cell = getGridElement().getCell(0, 2);
+ assertEquals(200, cell.getSize().getWidth());
+ }
+
+ @Test
+ public void testColumnWidths() throws Exception {
+ openTestURL();
+
+ // Default column width is 100px
+ WebElement cell = getGridElement().getCell(0, 0);
+ assertEquals(100, cell.getSize().getWidth());
+
+ // Set first column to be 200px wide
+ selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width",
+ "200px");
+
+ cell = getGridElement().getCell(0, 0);
+ assertEquals(200, cell.getSize().getWidth());
+
+ // Set second column to be 150px wide
+ selectMenuPath("Component", "Columns", "Column 1", "Column 1 Width",
+ "150px");
+ cell = getGridElement().getCell(0, 1);
+ assertEquals(150, cell.getSize().getWidth());
+
+ selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width",
+ "Auto");
+
+ // since the column 0 was previously 200, it should've shrunk when
+ // autoresizing.
+ cell = getGridElement().getCell(0, 0);
+ assertLessThan("", cell.getSize().getWidth(), 200);
+ }
+
+ @Test
+ public void testPrimaryStyleNames() throws Exception {
+ openTestURL();
+
+ // v-grid is default primary style namea
+ assertPrimaryStylename("v-grid");
+
+ selectMenuPath("Component", "State", "Primary style name",
+ "v-escalator");
+ assertPrimaryStylename("v-escalator");
+
+ selectMenuPath("Component", "State", "Primary style name", "my-grid");
+ assertPrimaryStylename("my-grid");
+
+ selectMenuPath("Component", "State", "Primary style name", "v-grid");
+ assertPrimaryStylename("v-grid");
+ }
+
+ /**
+ * Test that the current view is updated when a server-side container change
+ * occurs (without scrolling back and forth)
+ */
+ @Test
+ public void testItemSetChangeEvent() throws Exception {
+ openTestURL();
+
+ final org.openqa.selenium.By newRow = By
+ .xpath("//td[text()='newcell: 0']");
+
+ assertTrue("Unexpected initial state", !isElementPresent(newRow));
+
+ selectMenuPath("Component", "Body rows", "Add first row");
+ assertTrue("Add row failed", isElementPresent(newRow));
+
+ selectMenuPath("Component", "Body rows", "Remove first row");
+ assertTrue("Remove row failed", !isElementPresent(newRow));
+ }
+
+ /**
+ * Test that the current view is updated when a property's value is reflect
+ * to the client, when the value is modified server-side.
+ */
+ @Test
+ public void testPropertyValueChangeEvent() throws Exception {
+ openTestURL();
+
+ assertEquals("Unexpected cell initial state", "(0, 0)",
+ getGridElement().getCell(0, 0).getText());
+
+ selectMenuPath("Component", "Body rows",
+ "Modify first row (getItemProperty)");
+ assertEquals("(First) modification with getItemProperty failed",
+ "modified: 0", getGridElement().getCell(0, 0).getText());
+
+ selectMenuPath("Component", "Body rows",
+ "Modify first row (getContainerProperty)");
+ assertEquals("(Second) modification with getItemProperty failed",
+ "modified: Column 0", getGridElement().getCell(0, 0).getText());
+ }
+
+ @Test
+ public void testRemovingAllItems() throws Exception {
+ openTestURL();
+
+ selectMenuPath("Component", "Body rows", "Remove all rows");
+
+ assertEquals(0, getGridElement().findElement(By.tagName("tbody"))
+ .findElements(By.tagName("tr")).size());
+ }
+
+ @Test
+ public void testVerticalScrollBarVisibilityWhenEnoughRows()
+ throws Exception {
+ openTestURL();
+
+ assertTrue(verticalScrollbarIsPresent());
+
+ selectMenuPath("Component", "Body rows", "Remove all rows");
+ assertFalse(verticalScrollbarIsPresent());
+
+ selectMenuPath("Component", "Size", "HeightMode Row");
+ selectMenuPath("Component", "Size", "Height by Rows", "2.33 rows");
+ selectMenuPath("Component", "Body rows", "Add first row");
+ selectMenuPath("Component", "Body rows", "Add first row");
+ assertFalse(verticalScrollbarIsPresent());
+
+ selectMenuPath("Component", "Body rows", "Add first row");
+ assertTrue(verticalScrollbarIsPresent());
+ }
+
+ @Test
+ public void testBareItemSetChange() throws Exception {
+ openTestURL();
+ filterSomeAndAssert();
+ }
+
+ @Test
+ public void testBareItemSetChangeRemovingAllRows() throws Exception {
+ openTestURL();
+ selectMenuPath("Component", "Filter", "Add impassable filter");
+ assertFalse("A notification shouldn't have been displayed",
+ $(NotificationElement.class).exists());
+ assertTrue("No body cells should've been found", getGridElement()
+ .getBody().findElements(By.tagName("td")).isEmpty());
+ }
+
+ @Test
+ public void testBareItemSetChangeWithMidScroll() throws Exception {
+ openTestURL();
+ getGridElement().scrollToRow(GridBasicFeatures.ROWS / 2);
+ filterSomeAndAssert();
+ }
+
+ @Test
+ public void testBareItemSetChangeWithBottomScroll() throws Exception {
+ openTestURL();
+ getGridElement().scrollToRow(GridBasicFeatures.ROWS);
+ filterSomeAndAssert();
+ }
+
+ private void filterSomeAndAssert() {
+ selectMenuPath("Component", "Filter", "Column 1 starts with \"(23\"");
+ boolean foundElements = false;
+ for (int row = 0; row < 100; row++) {
+ try {
+ GridCellElement cell = getGridElement().getCell(row, 1);
+ foundElements = true;
+ assertTrue("Unexpected cell contents. "
+ + "Did the ItemSetChange work after all?", cell
+ .getText().startsWith("(23"));
+ } catch (NoSuchElementException e) {
+ assertTrue("No rows were found", foundElements);
+ return;
+ }
+ }
+ fail("unexpected amount of rows post-filter. Did the ItemSetChange work after all?");
+ }
+
+ @Test
+ public void testRemoveLastColumn() {
+ setDebug(true);
+ openTestURL();
+
+ String columnName = "Column " + (GridBasicFeatures.COLUMNS - 1);
+ assertTrue(columnName + " was not present in DOM",
+ isElementPresent(By.xpath("//th[text()='" + columnName + "']")));
+ selectMenuPath("Component", "Columns", columnName, "Add / Remove");
+ assertFalse(isElementPresent(NotificationElement.class));
+ assertFalse(columnName + " was still present in DOM",
+ isElementPresent(By.xpath("//th[text()='" + columnName + "']")));
+ }
+
+ @Test
+ public void testReverseColumns() {
+ openTestURL();
+
+ String[] gridData = new String[GridBasicFeatures.COLUMNS];
+ GridElement grid = getGridElement();
+ for (int i = 0; i < gridData.length; ++i) {
+ gridData[i] = grid.getCell(0, i).getAttribute("innerHTML");
+ }
+
+ selectMenuPath("Component", "State", "Reverse Grid Columns");
+
+ // Compare with reversed order
+ for (int i = 0; i < gridData.length; ++i) {
+ final int column = gridData.length - 1 - i;
+ final String newText = grid.getCell(0, column).getAttribute(
+ "innerHTML");
+ assertEquals("Grid contained unexpected values. (0, " + column
+ + ")", gridData[i], newText);
+ }
+ }
+
+ @Test
+ public void testAddingProperty() {
+ setDebug(true);
+ openTestURL();
+
+ assertNotEquals("property value", getGridElement().getCell(0, 0)
+ .getText());
+ selectMenuPath("Component", "Properties", "Prepend property");
+ assertEquals("property value", getGridElement().getCell(0, 0).getText());
+ }
+
+ @Test
+ public void testRemovingAddedProperty() {
+ openTestURL();
+
+ assertEquals("(0, 0)", getGridElement().getCell(0, 0).getText());
+ assertNotEquals("property value", getGridElement().getCell(0, 0)
+ .getText());
+
+ selectMenuPath("Component", "Properties", "Prepend property");
+ selectMenuPath("Component", "Properties", "Prepend property");
+
+ assertNotEquals("property value", getGridElement().getCell(0, 0)
+ .getText());
+ assertEquals("(0, 0)", getGridElement().getCell(0, 0).getText());
+ }
+
+ private boolean verticalScrollbarIsPresent() {
+ return "scroll".equals(getGridVerticalScrollbar().getCssValue(
+ "overflow-y"));
+ }
+
+ @Test
+ public void testAddRowAboveViewport() {
+ setDebug(true);
+ openTestURL();
+
+ GridCellElement cell = getGridElement().getCell(500, 1);
+ String cellContent = cell.getText();
+ selectMenuPath("Component", "Body rows", "Add first row");
+
+ assertFalse("Error notification was present",
+ isElementPresent(NotificationElement.class));
+
+ assertEquals("Grid scrolled unexpectedly", cellContent, cell.getText());
+ }
+
+ @Test
+ public void testRemoveAndAddRowAboveViewport() {
+ setDebug(true);
+ openTestURL();
+
+ GridCellElement cell = getGridElement().getCell(500, 1);
+ String cellContent = cell.getText();
+ selectMenuPath("Component", "Body rows", "Remove first row");
+
+ assertFalse("Error notification was present after removing row",
+ isElementPresent(NotificationElement.class));
+
+ assertEquals("Grid scrolled unexpectedly", cellContent, cell.getText());
+
+ selectMenuPath("Component", "Body rows", "Add first row");
+
+ assertFalse("Error notification was present after adding row",
+ isElementPresent(NotificationElement.class));
+
+ assertEquals("Grid scrolled unexpectedly", cellContent, cell.getText());
+ }
+
+ @Test
+ public void testScrollAndRemoveAll() {
+ setDebug(true);
+ openTestURL();
+
+ getGridElement().scrollToRow(500);
+ selectMenuPath("Component", "Body rows", "Remove all rows");
+
+ assertFalse("Error notification was present after removing all rows",
+ isElementPresent(NotificationElement.class));
+
+ assertFalse(getGridElement().isElementPresent(By.vaadin("#cell[0][0]")));
+ }
+
+ private void assertPrimaryStylename(String stylename) {
+ assertTrue(getGridElement().getAttribute("class").contains(stylename));
+
+ String tableWrapperStyleName = getGridElement().getTableWrapper()
+ .getAttribute("class");
+ assertTrue(tableWrapperStyleName.contains(stylename + "-tablewrapper"));
+
+ String hscrollStyleName = getGridElement().getHorizontalScroller()
+ .getAttribute("class");
+ assertTrue(hscrollStyleName.contains(stylename + "-scroller"));
+ assertTrue(hscrollStyleName
+ .contains(stylename + "-scroller-horizontal"));
+
+ String vscrollStyleName = getGridElement().getVerticalScroller()
+ .getAttribute("class");
+ assertTrue(vscrollStyleName.contains(stylename + "-scroller"));
+ assertTrue(vscrollStyleName.contains(stylename + "-scroller-vertical"));
+ }
+
+ @Test
+ public void testScrollPosDoesNotChangeAfterStateChange() {
+ openTestURL();
+ scrollGridVerticallyTo(1000);
+ int scrollPos = getGridVerticalScrollPos();
+ selectMenuPath("Component", "Editor", "Enabled");
+ assertEquals("Scroll position should've not have changed", scrollPos,
+ getGridVerticalScrollPos());
+ }
+
+ @Test
+ public void testReloadPage() throws InterruptedException {
+ setDebug(true);
+ openTestURL();
+
+ reopenTestURL();
+
+ // After opening the URL Grid can be stuck in a state where it thinks it
+ // should wait for something that's not going to happen.
+ testBench().disableWaitForVaadin();
+
+ // Wait until page is loaded completely.
+ int count = 0;
+ while (!isElementPresent(GridElement.class)) {
+ if (count == 100) {
+ fail("Reloading page failed");
+ }
+ sleep(100);
+ ++count;
+ }
+
+ // Wait a bit more for notification to occur.
+ sleep(1000);
+
+ assertFalse("Exception occurred when reloading page",
+ isElementPresent(NotificationElement.class));
+ }
+
+ @Test
+ public void testAddThirdRowToGrid() {
+ openTestURL();
+ selectMenuPath("Component", "Body rows", "Add third row");
+ assertFalse(logContainsText("Exception occured"));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java
new file mode 100644
index 0000000000..b122eb02e9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class LoadingIndicatorTest extends GridBasicFeaturesTest {
+ @Test
+ public void testLoadingIndicator() throws InterruptedException {
+ setDebug(true);
+ openTestURL();
+
+ selectMenuPath("Component", "State", "Container delay", "2000");
+
+ GridElement gridElement = $(GridElement.class).first();
+
+ Assert.assertFalse(
+ "Loading indicator should not be visible before disabling waitForVaadin",
+ isLoadingIndicatorVisible());
+
+ testBench().disableWaitForVaadin();
+
+ // Scroll to a completely new location
+ gridElement.getCell(200, 1);
+
+ // Wait for loading indicator delay
+ Thread.sleep(500);
+
+ Assert.assertTrue(
+ "Loading indicator should be visible when fetching rows that are visible",
+ isLoadingIndicatorVisible());
+
+ waitUntilNot(ExpectedConditions.visibilityOfElementLocated(By
+ .className("v-loading-indicator")));
+
+ // Scroll so much that more data gets fetched, but not so much that
+ // missing rows are shown
+ gridElement.getCell(230, 1);
+
+ // Wait for potentially triggered loading indicator to become visible
+ Thread.sleep(500);
+
+ Assert.assertFalse(
+ "Loading indicator should not be visible when fetching rows that are not visible",
+ isLoadingIndicatorVisible());
+
+ // Finally verify that there was actually a request going on
+ Thread.sleep(2000);
+
+ String firstLogRow = getLogRow(0);
+ Assert.assertTrue(
+ "Last log message should be number 6: " + firstLogRow,
+ firstLogRow.startsWith("6. Requested items"));
+ }
+
+ private boolean isLoadingIndicatorVisible() {
+ WebElement loadingIndicator = findElement(By
+ .className("v-loading-indicator"));
+ if (loadingIndicator == null) {
+ return false;
+ } else {
+ return loadingIndicator.isDisplayed();
+ }
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/myBeanJsRenderer.js b/uitest/src/com/vaadin/tests/components/grid/myBeanJsRenderer.js
new file mode 100644
index 0000000000..5e7bde5ec7
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/myBeanJsRenderer.js
@@ -0,0 +1,16 @@
+window.com_vaadin_tests_components_grid_MyBeanJSRenderer = function() {
+ this.init = function(cell) {
+ cell.element.setAttribute("column", cell.columnIndex);
+ }
+
+ this.render = function(cell, data) {
+ cell.element.innerHTML = 'Bean(' + data.integer + ', ' + data.string + ')'
+ }
+
+ this.getConsumedEvents = function() { return ["click"] };
+
+ this.onBrowserEvent = function(cell, event) {
+ cell.element.innerHTML = "Clicked " + cell.rowIndex + " with key " + this.getRowKey(cell.rowIndex) +" at " + event.clientX;
+ return true;
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeer.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeer.java
new file mode 100644
index 0000000000..6cf7fb0ded
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeer.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.progressindicator;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.ProgressBar;
+import com.vaadin.ui.themes.Reindeer;
+
+@Theme(Reindeer.THEME_NAME)
+public class ProgressBarStaticReindeer extends AbstractTestUI {
+ @Override
+ protected void setup(VaadinRequest request) {
+ ProgressBar progressBar = new ProgressBar();
+ progressBar.addStyleName(Reindeer.PROGRESSBAR_STATIC);
+ addComponent(progressBar);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeerTest.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeerTest.java
new file mode 100644
index 0000000000..f1056a640d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticReindeerTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.progressindicator;
+
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class ProgressBarStaticReindeerTest extends MultiBrowserTest {
+ @Test
+ public void compareScreenshot() throws Exception {
+ openTestURL();
+ compareScreen("screen");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRuno.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRuno.java
new file mode 100644
index 0000000000..4e1ff7c886
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRuno.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.progressindicator;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.ProgressBar;
+import com.vaadin.ui.themes.Runo;
+
+@Theme(Runo.THEME_NAME)
+public class ProgressBarStaticRuno extends AbstractTestUI {
+ @Override
+ protected void setup(VaadinRequest request) {
+ ProgressBar progressBar = new ProgressBar();
+ progressBar.addStyleName(Runo.PROGRESSBAR_STATIC);
+ addComponent(progressBar);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRunoTest.java b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRunoTest.java
new file mode 100644
index 0000000000..751e048694
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/progressindicator/ProgressBarStaticRunoTest.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.progressindicator;
+
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class ProgressBarStaticRunoTest extends MultiBrowserTest {
+ @Test
+ public void compareScreenshot() throws Exception {
+ openTestURL();
+ compareScreen("screen");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/serialization/NoLayout.java b/uitest/src/com/vaadin/tests/serialization/NoLayout.java
new file mode 100644
index 0000000000..8ce8c437a4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/serialization/NoLayout.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.serialization;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.server.LayoutDetector;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.JavaScript;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class NoLayout extends AbstractTestUI {
+ private final LayoutDetector layoutDetector = new LayoutDetector();
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ addComponent(layoutDetector);
+
+ CheckBox uiPolling = new CheckBox("UI polling enabled");
+ uiPolling.addValueChangeListener(new ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ if (event.getProperty().getValue() == Boolean.TRUE) {
+ setPollInterval(100);
+ } else {
+ setPollInterval(-1);
+ }
+ }
+ });
+ addComponent(uiPolling);
+
+ addComponent(new Button("Change regular state",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ event.getButton().setCaption(
+ String.valueOf(System.currentTimeMillis()));
+ }
+ }));
+ addComponent(new Button("Change @NoLayout state",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ event.getButton().setDescription(
+ String.valueOf(System.currentTimeMillis()));
+ }
+ }));
+ addComponent(new Button("Do regular RPC", new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ JavaScript.eval("");
+ }
+ }));
+
+ addComponent(new Button("Do @NoLayout RPC", new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ layoutDetector.doNoLayoutRpc();
+ }
+ }));
+
+ addComponent(new Button("Update LegacyComponent",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ // Assumes UI is a LegacyComponent
+ markAsDirty();
+ }
+ }));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Checks which actions trigger a layout phase";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(12936);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/serialization/NoLayoutTest.java b/uitest/src/com/vaadin/tests/serialization/NoLayoutTest.java
new file mode 100644
index 0000000000..bb312e3f3f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/serialization/NoLayoutTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.serialization;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.CheckBoxElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class NoLayoutTest extends MultiBrowserTest {
+ @Test
+ public void testNoLayout() {
+ openTestURL();
+ assertCounts(1, 0);
+
+ $(CheckBoxElement.class).caption("UI polling enabled").first()
+ .findElement(By.tagName("input")).click();
+
+ // Toggling check box requires layout
+ assertCounts(2, 0);
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ // Count should not change even with polling enabled
+ assertCounts(2, 0);
+
+ // Disable polling
+ $(CheckBoxElement.class).caption("UI polling enabled").first()
+ .findElement(By.tagName("input")).click();
+ // Toggling checkbox layotus again
+ assertCounts(3, 0);
+
+ $(ButtonElement.class).caption("Change regular state").first().click();
+ // Updating normal state layouts
+ assertCounts(4, 0);
+
+ $(ButtonElement.class).caption("Change @NoLayout state").first();
+ // Updating @NoLayout state does not layout
+ assertCounts(4, 0);
+
+ $(ButtonElement.class).caption("Do regular RPC").first().click();
+ // Doing normal RPC layouts
+ assertCounts(5, 0);
+
+ $(ButtonElement.class).caption("Do @NoLayout RPC").first().click();
+ // Doing @NoLayout RPC does not layout, but updates the RPC count
+ assertCounts(5, 1);
+
+ $(ButtonElement.class).caption("Update LegacyComponent").first()
+ .click();
+ // Painting LegacyComponent layouts
+ assertCounts(6, 1);
+ }
+
+ private void assertCounts(int layoutCount, int rpcCount) {
+ Assert.assertEquals("Unexpected layout count", layoutCount,
+ getCount("layoutCount"));
+ Assert.assertEquals("Unexpected RPC count", rpcCount,
+ getCount("rpcCount"));
+ }
+
+ private int getCount(String id) {
+ return Integer.parseInt(getDriver().findElement(By.id(id)).getText());
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java
index bb8b34d462..2ac10c161d 100644
--- a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java
+++ b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java
@@ -44,10 +44,14 @@ import com.vaadin.tests.widgetset.client.SerializerTestState;
import com.vaadin.tests.widgetset.client.SimpleTestBean;
import com.vaadin.tests.widgetset.server.SerializerTestExtension;
+import elemental.json.Json;
+import elemental.json.JsonString;
+import elemental.json.JsonValue;
+
@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
public class SerializerTest extends AbstractTestUI {
- private Log log = new Log(40);
+ private Log log = new Log(45);
@Override
protected void setup(VaadinRequest request) {
@@ -258,6 +262,12 @@ public class SerializerTest extends AbstractTestUI {
rpc.sendDate(new Date(1));
rpc.sendDate(new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13));
+
+ state.jsonNull = Json.createNull();
+ state.jsonString = Json.create("a string");
+ state.jsonBoolean = Json.create(false);
+ rpc.sendJson(Json.create(true), Json.createNull(), Json.create("JSON"));
+
state.date1 = new Date(1);
state.date2 = new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13);
@@ -458,6 +468,13 @@ public class SerializerTest extends AbstractTestUI {
}
@Override
+ public void sendJson(JsonValue value1, JsonValue value2,
+ JsonString string) {
+ log.log("sendJson: " + value1.toJson() + ", " + value2.toJson()
+ + ", " + string.toJson());
+ }
+
+ @Override
public void log(String string) {
log.log(string);
@@ -468,7 +485,7 @@ public class SerializerTest extends AbstractTestUI {
@Override
protected String getTestDescription() {
- return "Test for lots of different cases of encoding and decoding variuos data types";
+ return "Test for lots of different cases of encoding and decoding various data types";
}
@Override
diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java
index 1624a89a01..23af74c78b 100644
--- a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java
+++ b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java
@@ -27,6 +27,9 @@ public class SerializerTestTest extends MultiBrowserTest {
openTestURL();
int logRow = 0;
+ Assert.assertEquals(
+ "sendJson: {\"b\":false,\"s\":\"JSON\"}, null, \"value\"",
+ getLogRow(logRow++));
Assert.assertEquals("sendDate: May 31, 2013 8:12:13 AM UTC",
getLogRow(logRow++));
Assert.assertEquals("sendDate: January 1, 1970 12:00:00 AM UTC",
@@ -77,6 +80,9 @@ public class SerializerTestTest extends MultiBrowserTest {
"sendBoolean: false, false, [false, false, true, false, true, true]",
getLogRow(logRow++));
Assert.assertEquals("sendBeanSubclass: 43", getLogRow(logRow++));
+ Assert.assertEquals("state.jsonBoolean: false", getLogRow(logRow++));
+ Assert.assertEquals("state.jsonString: a string", getLogRow(logRow++));
+ Assert.assertEquals("state.jsonNull: NULL", getLogRow(logRow++));
Assert.assertEquals(
"state.doubleArray: [1.7976931348623157e+308, 5e-324]",
getLogRow(logRow++));
diff --git a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml
index 2c25c54e04..8a02d91d2c 100644
--- a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml
+++ b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml
@@ -4,6 +4,8 @@
<!-- Inherit the DefaultWidgetSet -->
<inherits name="com.vaadin.DefaultWidgetSet" />
+ <inherits name="com.google.gwt.user.theme.standard.Standard" />
+
<replace-with class="com.vaadin.tests.widgetset.client.CustomUIConnector">
<when-type-is class="com.vaadin.client.ui.ui.UIConnector" />
</replace-with>
@@ -17,5 +19,9 @@
class="com.vaadin.tests.widgetset.client.MockApplicationConnection">
<when-type-is class="com.vaadin.client.ApplicationConnection" />
</replace-with>
+
+ <generate-with class="com.vaadin.tests.widgetset.rebind.TestWidgetRegistryGenerator">
+ <when-type-is class="com.vaadin.tests.widgetset.client.TestWidgetConnector.TestWidgetRegistry" />
+ </generate-with>
</module>
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/BasicExtensionTestConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/BasicExtensionTestConnector.java
index 6bd2abec60..86c918536f 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/BasicExtensionTestConnector.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/BasicExtensionTestConnector.java
@@ -19,7 +19,6 @@ package com.vaadin.tests.widgetset.client;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.vaadin.client.ServerConnector;
-import com.vaadin.client.Util;
import com.vaadin.client.extensions.AbstractExtensionConnector;
import com.vaadin.shared.ui.Connect;
import com.vaadin.tests.extensions.BasicExtension;
@@ -35,8 +34,8 @@ public class BasicExtensionTestConnector extends AbstractExtensionConnector {
}
private void appendMessage(String action) {
- String message = Util.getSimpleName(this) + action
- + Util.getSimpleName(target);
+ String message = getClass().getSimpleName() + action
+ + target.getClass().getSimpleName();
DivElement element = Document.get().createDivElement();
element.setInnerText(message);
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/CustomUIConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/CustomUIConnector.java
index b43da8e27e..7a93f5e360 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/CustomUIConnector.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/CustomUIConnector.java
@@ -18,7 +18,6 @@ package com.vaadin.tests.widgetset.client;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.SpanElement;
-import com.vaadin.client.Util;
import com.vaadin.client.ui.ui.UIConnector;
import com.vaadin.shared.ui.Connect;
import com.vaadin.ui.UI;
@@ -33,7 +32,7 @@ public class CustomUIConnector extends UIConnector {
public void test() {
SpanElement span = Document.get().createSpanElement();
span.setInnerText("This is the "
- + Util.getSimpleName(CustomUIConnector.this));
+ + CustomUIConnector.this.getClass().getSimpleName());
Document.get().getBody().insertFirst(span);
}
});
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/LayoutDetectorConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/LayoutDetectorConnector.java
new file mode 100644
index 0000000000..e999c83b75
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/LayoutDetectorConnector.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client;
+
+import com.google.gwt.user.client.ui.HTML;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.client.ui.PostLayoutListener;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.tests.widgetset.server.LayoutDetector;
+
+@Connect(LayoutDetector.class)
+public class LayoutDetectorConnector extends AbstractComponentConnector
+ implements PostLayoutListener {
+ private int layoutCount = 0;
+ private int rpcCount = 0;
+
+ @Override
+ protected void init() {
+ super.init();
+ updateText();
+
+ registerRpc(NoLayoutRpc.class, new NoLayoutRpc() {
+ @Override
+ public void doRpc() {
+ rpcCount++;
+ updateText();
+ }
+ });
+ }
+
+ @Override
+ public HTML getWidget() {
+ return (HTML) super.getWidget();
+ }
+
+ @Override
+ public void postLayout() {
+ layoutCount++;
+ updateText();
+ }
+
+ private void updateText() {
+ getWidget().setHTML(
+ "Layout count: <span id='layoutCount'>" + layoutCount
+ + "</span><br />RPC count: <span id='rpcCount'>"
+ + rpcCount + "</span>");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java b/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java
index 4ee5b71387..0da1c6c775 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java
@@ -18,13 +18,14 @@ package com.vaadin.tests.widgetset.client;
import java.util.Date;
import java.util.logging.Logger;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONValue;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ValueMap;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.tests.widgetset.server.csrf.ui.CsrfTokenDisabled;
+import elemental.json.JsonObject;
+import elemental.json.JsonValue;
+
/**
* Mock ApplicationConnection for several issues where we need to hack it.
*
@@ -71,9 +72,9 @@ public class MockApplicationConnection extends ApplicationConnection {
}
@Override
- protected void doUidlRequest(String uri, JSONObject payload) {
- JSONValue jsonValue = payload.get(ApplicationConstants.CSRF_TOKEN);
- lastCsrfTokenSent = jsonValue != null ? jsonValue.toString() : null;
+ protected void doUidlRequest(String uri, JsonObject payload) {
+ JsonValue jsonValue = payload.get(ApplicationConstants.CSRF_TOKEN);
+ lastCsrfTokenSent = jsonValue != null ? jsonValue.toJson() : null;
super.doUidlRequest(uri, payload);
}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/NoLayoutRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/NoLayoutRpc.java
new file mode 100644
index 0000000000..7c2693db1d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/NoLayoutRpc.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client;
+
+import com.vaadin.shared.annotations.NoLayout;
+import com.vaadin.shared.communication.ClientRpc;
+
+public interface NoLayoutRpc extends ClientRpc {
+
+ @NoLayout
+ public void doRpc();
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java
index 60a3fb1448..e71f9f1230 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/RoundTripTesterRpc.java
@@ -15,10 +15,12 @@
*/
package com.vaadin.tests.widgetset.client;
+import com.vaadin.shared.annotations.NoLayout;
import com.vaadin.shared.communication.ClientRpc;
import com.vaadin.shared.communication.ServerRpc;
public interface RoundTripTesterRpc extends ServerRpc, ClientRpc {
+ @NoLayout
public void ping(int nr, String payload);
public void done();
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
index 7758cdc2ac..07acd3d021 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
@@ -35,6 +35,13 @@ import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.tests.widgetset.server.SerializerTestExtension;
+import elemental.json.Json;
+import elemental.json.JsonBoolean;
+import elemental.json.JsonObject;
+import elemental.json.JsonString;
+import elemental.json.JsonType;
+import elemental.json.JsonValue;
+
@Connect(SerializerTestExtension.class)
public class SerializerTestConnector extends AbstractExtensionConnector {
@@ -259,6 +266,27 @@ public class SerializerTestConnector extends AbstractExtensionConnector {
}
@Override
+ public void sendJson(JsonValue value1, JsonValue value2,
+ JsonString string) {
+ if (value1.getType() != JsonType.BOOLEAN) {
+ throw new RuntimeException("Expected boolean, got "
+ + value1.toJson());
+ }
+
+ if (value2.getType() != JsonType.NULL) {
+ throw new RuntimeException("Expected null, got "
+ + value2.toJson());
+ }
+
+ JsonObject returnObject = Json.createObject();
+ returnObject.put("b", !((JsonBoolean) value1).asBoolean());
+ returnObject.put("s", string);
+
+ rpc.sendJson(returnObject, Json.createNull(),
+ Json.create("value"));
+ }
+
+ @Override
public void log(String message) {
// Do nothing, used only in the other direction
}
@@ -311,6 +339,11 @@ public class SerializerTestConnector extends AbstractExtensionConnector {
rpc.log("state.doubleObjectValue: " + getState().doubleObjectValue);
rpc.log("state.doubleArray: " + Arrays.toString(getState().doubleArray));
+ rpc.log("state.jsonNull: " + getState().jsonNull.getType().name());
+ rpc.log("state.jsonString: "
+ + ((JsonString) getState().jsonString).getString());
+ rpc.log("state.jsonBoolean: " + getState().jsonBoolean.getBoolean());
+
/*
* TODO public double doubleValue; public Double DoubleValue; public
* double[] doubleArray; ;
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java
index 6b4c4e7ac1..4baebc819e 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestRpc.java
@@ -26,6 +26,9 @@ import com.vaadin.shared.communication.ClientRpc;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.shared.ui.label.ContentMode;
+import elemental.json.JsonString;
+import elemental.json.JsonValue;
+
@SuppressWarnings("javadoc")
public interface SerializerTestRpc extends ServerRpc, ClientRpc {
public void sendBoolean(boolean value, Boolean boxedValue, boolean[] array);
@@ -82,5 +85,7 @@ public interface SerializerTestRpc extends ServerRpc, ClientRpc {
public void sendDate(Date date);
+ public void sendJson(JsonValue value1, JsonValue value2, JsonString string);
+
public void log(String string);
}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestState.java b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestState.java
index faf41fbf88..31ff58971f 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestState.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestState.java
@@ -24,6 +24,9 @@ import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.Connector;
import com.vaadin.shared.ui.label.ContentMode;
+import elemental.json.JsonBoolean;
+import elemental.json.JsonValue;
+
public class SerializerTestState extends AbstractComponentState {
public boolean booleanValue;
@@ -99,4 +102,8 @@ public class SerializerTestState extends AbstractComponentState {
public BeanWithAbstractSuperclass beanWithAbstractSuperclass;
+ public JsonValue jsonNull = null;
+ public JsonValue jsonString = null;
+ public JsonBoolean jsonBoolean = null;
+
}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/TestWidgetConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/TestWidgetConnector.java
new file mode 100644
index 0000000000..33a8956810
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/TestWidgetConnector.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.annotations.OnStateChange;
+import com.vaadin.client.metadata.Invoker;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.client.ui.SubPartAware;
+import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.tests.widgetset.server.TestWidgetComponent;
+
+@Connect(TestWidgetComponent.class)
+public class TestWidgetConnector extends AbstractComponentConnector {
+ public static class SubPartAwareSimplePanel extends SimplePanel implements
+ SubPartAware {
+ @Override
+ public Element getSubPartElement(String subPart) {
+ Widget target = getWidget();
+ if (target instanceof SubPartAware) {
+ return ((SubPartAware) target).getSubPartElement(subPart);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getSubPartName(Element subElement) {
+ Widget target = getWidget();
+ if (target instanceof SubPartAware) {
+ return ((SubPartAware) target).getSubPartName(subElement);
+
+ } else {
+ return null;
+ }
+ }
+
+ }
+
+ public static class TestWidgetState extends AbstractComponentState {
+ public String widgetClass;
+ }
+
+ private final TestWidgetRegistry registry = GWT
+ .create(TestWidgetRegistry.class);
+
+ public static abstract class TestWidgetRegistry {
+ private Map<String, Invoker> creators = new HashMap<String, Invoker>();
+
+ // Called by generated sub class
+ protected void register(String widgetClass, Invoker creator) {
+ creators.put(widgetClass, creator);
+ }
+
+ public Widget createWidget(String widgetClass) {
+ Invoker invoker = creators.get(widgetClass);
+ if (invoker == null) {
+ return new Label("Widget not found: " + widgetClass);
+ } else {
+ return (Widget) invoker.invoke(null);
+ }
+ }
+ }
+
+ @OnStateChange("widgetClass")
+ private void updateWidgetClass() {
+ getWidget().setWidget(registry.createWidget(getState().widgetClass));
+ }
+
+ @Override
+ public TestWidgetState getState() {
+ return (TestWidgetState) super.getState();
+ }
+
+ @Override
+ public SubPartAwareSimplePanel getWidget() {
+ return (SubPartAwareSimplePanel) super.getWidget();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java
new file mode 100644
index 0000000000..761f32bc9a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java
@@ -0,0 +1,702 @@
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.core.client.Duration;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.TableCellElement;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTML;
+import com.vaadin.client.widget.escalator.EscalatorUpdater;
+import com.vaadin.client.widget.escalator.FlyweightCell;
+import com.vaadin.client.widget.escalator.Row;
+import com.vaadin.client.widget.escalator.RowContainer;
+import com.vaadin.client.widgets.Escalator;
+
+public class EscalatorBasicClientFeaturesWidget extends
+ PureGWTTestApplication<Escalator> {
+
+ public static class LogWidget extends Composite {
+
+ private static final int MAX_LOG = 9;
+
+ private final HTML html = new HTML();
+ private final List<String> logs = new ArrayList<String>();
+ private Escalator escalator;
+
+ public LogWidget() {
+ initWidget(html);
+ getElement().setId("log");
+ }
+
+ public void setEscalator(Escalator escalator) {
+ this.escalator = escalator;
+ }
+
+ public void updateDebugLabel() {
+ int headers = escalator.getHeader().getRowCount();
+ int bodys = escalator.getBody().getRowCount();
+ int footers = escalator.getFooter().getRowCount();
+ int columns = escalator.getColumnConfiguration().getColumnCount();
+
+ while (logs.size() > MAX_LOG) {
+ logs.remove(0);
+ }
+
+ String logString = "<hr>";
+ for (String log : logs) {
+ logString += log + "<br>";
+ }
+
+ html.setHTML("Columns: " + columns + "<br>" + //
+ "Header rows: " + headers + "<br>" + //
+ "Body rows: " + bodys + "<br>" + //
+ "Footer rows: " + footers + "<br>" + //
+ logString);
+ }
+
+ public void log(String string) {
+ logs.add((Duration.currentTimeMillis() % 10000) + ": " + string);
+ }
+ }
+
+ public static class UpdaterLifetimeWidget extends
+ EscalatorBasicClientFeaturesWidget {
+
+ private final EscalatorUpdater debugUpdater = new EscalatorUpdater() {
+ @Override
+ public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) {
+ log("preAttach", cellsToAttach);
+ }
+
+ @Override
+ public void postAttach(Row row,
+ Iterable<FlyweightCell> attachedCells) {
+ log("postAttach", attachedCells);
+ }
+
+ @Override
+ public void update(Row row, Iterable<FlyweightCell> cellsToUpdate) {
+ log("update", cellsToUpdate);
+ }
+
+ @Override
+ public void preDetach(Row row, Iterable<FlyweightCell> cellsToDetach) {
+ log("preDetach", cellsToDetach);
+ }
+
+ @Override
+ public void postDetach(Row row,
+ Iterable<FlyweightCell> detachedCells) {
+ log("postDetach", detachedCells);
+ }
+
+ private void log(String methodName, Iterable<FlyweightCell> cells) {
+ if (!cells.iterator().hasNext()) {
+ return;
+ }
+
+ TableCellElement cellElement = cells.iterator().next()
+ .getElement();
+ boolean isAttached = cellElement.getParentElement() != null
+ && cellElement.getParentElement().getParentElement() != null;
+ logWidget.log(methodName + ": elementIsAttached == "
+ + isAttached);
+ }
+ };
+
+ public UpdaterLifetimeWidget() {
+ super();
+ escalator.getHeader().setEscalatorUpdater(debugUpdater);
+ escalator.getBody().setEscalatorUpdater(debugUpdater);
+ escalator.getFooter().setEscalatorUpdater(debugUpdater);
+ }
+ }
+
+ private static final String COLUMNS_AND_ROWS_MENU = "Columns and Rows";
+ private static final String GENERAL_MENU = "General";
+ private static final String FEATURES_MENU = "Features";
+
+ private static abstract class TestEscalatorUpdater implements
+ EscalatorUpdater {
+
+ @Override
+ public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) {
+ // noop
+ }
+
+ @Override
+ public void postAttach(Row row, Iterable<FlyweightCell> attachedCells) {
+ // noop
+ }
+
+ @Override
+ public void preDetach(Row row, Iterable<FlyweightCell> cellsToDetach) {
+ // noop
+ }
+
+ @Override
+ public void postDetach(Row row, Iterable<FlyweightCell> detachedCells) {
+ // noop
+ }
+ }
+
+ private class Data {
+ private int columnCounter = 0;
+ private int rowCounter = 0;
+ private final List<Integer> columns = new ArrayList<Integer>();
+ private final List<Integer> rows = new ArrayList<Integer>();
+
+ @SuppressWarnings("boxing")
+ public void insertRows(final int offset, final int amount) {
+ final List<Integer> newRows = new ArrayList<Integer>();
+ for (int i = 0; i < amount; i++) {
+ newRows.add(rowCounter++);
+ }
+ rows.addAll(offset, newRows);
+ }
+
+ @SuppressWarnings("boxing")
+ public void insertColumns(final int offset, final int amount) {
+ final List<Integer> newColumns = new ArrayList<Integer>();
+ for (int i = 0; i < amount; i++) {
+ newColumns.add(columnCounter++);
+ }
+ columns.addAll(offset, newColumns);
+ }
+
+ public EscalatorUpdater createHeaderUpdater() {
+ return new TestEscalatorUpdater() {
+ @Override
+ public void update(final Row row,
+ final Iterable<FlyweightCell> cellsToUpdate) {
+ for (final FlyweightCell cell : cellsToUpdate) {
+ final Integer columnName = columns
+ .get(cell.getColumn());
+ cell.getElement().setInnerText("Header " + columnName);
+
+ if (colspan == Colspan.NORMAL) {
+ if (cell.getColumn() % 2 == 0) {
+ cell.setColSpan(2);
+ }
+ } else if (colspan == Colspan.CRAZY) {
+ if (cell.getColumn() % 3 == 0) {
+ cell.setColSpan(2);
+ }
+ }
+ }
+ }
+ };
+ }
+
+ public EscalatorUpdater createFooterUpdater() {
+ return new TestEscalatorUpdater() {
+ @Override
+ public void update(final Row row,
+ final Iterable<FlyweightCell> cellsToUpdate) {
+ for (final FlyweightCell cell : cellsToUpdate) {
+ final Integer columnName = columns
+ .get(cell.getColumn());
+ cell.getElement().setInnerText("Footer " + columnName);
+
+ if (colspan == Colspan.NORMAL) {
+ if (cell.getColumn() % 2 == 0) {
+ cell.setColSpan(2);
+ }
+ } else if (colspan == Colspan.CRAZY) {
+ if (cell.getColumn() % 3 == 1) {
+ cell.setColSpan(2);
+ }
+ }
+ }
+ }
+ };
+ }
+
+ public EscalatorUpdater createBodyUpdater() {
+ return new TestEscalatorUpdater() {
+
+ public void renderCell(final FlyweightCell cell) {
+ final Integer columnName = columns.get(cell.getColumn());
+ final Integer rowName = rows.get(cell.getRow());
+ String cellInfo = columnName + "," + rowName;
+
+ if (cell.getColumn() > 0) {
+ cell.getElement().setInnerText("Cell: " + cellInfo);
+ } else {
+ cell.getElement().setInnerText(
+ "Row " + cell.getRow() + ": " + cellInfo);
+ }
+
+ if (colspan == Colspan.NORMAL) {
+ if (cell.getColumn() % 2 == 0) {
+ cell.setColSpan(2);
+ }
+ } else if (colspan == Colspan.CRAZY) {
+ if (cell.getColumn() % 3 == cell.getRow() % 3) {
+ cell.setColSpan(2);
+ }
+ }
+ }
+
+ @Override
+ public void update(final Row row,
+ final Iterable<FlyweightCell> cellsToUpdate) {
+ for (final FlyweightCell cell : cellsToUpdate) {
+ renderCell(cell);
+ }
+ }
+ };
+ }
+
+ public void removeRows(final int offset, final int amount) {
+ for (int i = 0; i < amount; i++) {
+ rows.remove(offset);
+ }
+ }
+
+ public void removeColumns(final int offset, final int amount) {
+ for (int i = 0; i < amount; i++) {
+ columns.remove(offset);
+ }
+ }
+ }
+
+ protected final Escalator escalator;
+ private final Data data = new Data();
+
+ private enum Colspan {
+ NONE, NORMAL, CRAZY;
+ }
+
+ private Colspan colspan = Colspan.NONE;
+ protected final LogWidget logWidget = new LogWidget();
+
+ public EscalatorBasicClientFeaturesWidget() {
+ super(new EscalatorProxy());
+ escalator = getTestedWidget();
+ logWidget.setEscalator(escalator);
+
+ ((EscalatorProxy) escalator).setLogWidget(logWidget);
+ addNorth(logWidget, 200);
+
+ final RowContainer header = escalator.getHeader();
+ header.setEscalatorUpdater(data.createHeaderUpdater());
+
+ final RowContainer footer = escalator.getFooter();
+ footer.setEscalatorUpdater(data.createFooterUpdater());
+
+ escalator.getBody().setEscalatorUpdater(data.createBodyUpdater());
+
+ setWidth("500px");
+ setHeight("500px");
+
+ escalator.getElement().getStyle().setZIndex(0);
+ addNorth(escalator, 500);
+
+ createGeneralMenu();
+ createColumnMenu();
+ createHeaderRowsMenu();
+ createBodyRowsMenu();
+ createFooterRowsMenu();
+ createColumnsAndRowsMenu();
+ createFrozenMenu();
+ createColspanMenu();
+ }
+
+ private void createFrozenMenu() {
+ String[] menupath = { FEATURES_MENU, "Frozen columns" };
+ addMenuCommand("Freeze 1 column", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getColumnConfiguration().setFrozenColumnCount(1);
+ }
+ }, menupath);
+ addMenuCommand("Freeze 0 columns", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getColumnConfiguration().setFrozenColumnCount(0);
+ }
+ }, menupath);
+ }
+
+ private void createColspanMenu() {
+ String[] menupath = { FEATURES_MENU, "Column spanning" };
+ addMenuCommand("Apply normal colspan", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ colspan = Colspan.NORMAL;
+ refreshEscalator();
+ }
+ }, menupath);
+ addMenuCommand("Apply crazy colspan", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ colspan = Colspan.CRAZY;
+ refreshEscalator();
+ }
+ }, menupath);
+ addMenuCommand("Apply no colspan", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ colspan = Colspan.NONE;
+ refreshEscalator();
+ }
+ }, menupath);
+ }
+
+ private void createColumnsAndRowsMenu() {
+ String[] menupath = { COLUMNS_AND_ROWS_MENU };
+ addMenuCommand("Add one of each row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ insertRows(escalator.getHeader(), 0, 1);
+ insertRows(escalator.getBody(), 0, 1);
+ insertRows(escalator.getFooter(), 0, 1);
+ }
+ }, menupath);
+ addMenuCommand("Remove one of each row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ removeRows(escalator.getHeader(), 0, 1);
+ removeRows(escalator.getBody(), 0, 1);
+ removeRows(escalator.getFooter(), 0, 1);
+ }
+ }, menupath);
+ }
+
+ private void createGeneralMenu() {
+ String[] menupath = { GENERAL_MENU };
+
+ addMenuCommand("Detach Escalator", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.removeFromParent();
+ }
+ }, menupath);
+
+ addMenuCommand("Attach Escalator", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ if (!escalator.isAttached()) {
+ addNorth(escalator, 500);
+ }
+ }
+ }, menupath);
+
+ addMenuCommand("Clear (columns, then rows)", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ resetColRow();
+ }
+ }, menupath);
+ addMenuCommand("Clear (rows, then columns)", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ resetRowCol();
+ }
+ }, menupath);
+ addMenuCommand("Populate Escalator (columns, then rows)",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ resetColRow();
+ insertColumns(0, 10);
+ insertRows(escalator.getHeader(), 0, 1);
+ insertRows(escalator.getBody(), 0, 100);
+ insertRows(escalator.getFooter(), 0, 1);
+ }
+ }, menupath);
+ addMenuCommand("Populate Escalator (rows, then columns)",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ resetColRow();
+ insertRows(escalator.getHeader(), 0, 1);
+ insertRows(escalator.getBody(), 0, 100);
+ insertRows(escalator.getFooter(), 0, 1);
+ insertColumns(0, 10);
+ }
+ }, menupath);
+
+ createSizeMenu();
+ }
+
+ private void createSizeMenu() {
+ String[] menupath = new String[] { "General", "Size" };
+
+ addSizeMenuItem(null, "height", menupath);
+ addSizeMenuItem("200px", "height", menupath);
+ addSizeMenuItem("400px", "height", menupath);
+ addSizeMenuItem(null, "width", menupath);
+ addSizeMenuItem("200px", "width", menupath);
+ addSizeMenuItem("400px", "width", menupath);
+ }
+
+ private void addSizeMenuItem(final String size, final String direction,
+ String[] menupath) {
+ final String title = (size != null ? size : "undefined");
+ addMenuCommand(title + " " + direction, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ if (direction.equals("height")) {
+ escalator.setHeight(size);
+ } else {
+ escalator.setWidth(size);
+ }
+ }
+ }, menupath);
+ }
+
+ private void createColumnMenu() {
+ String[] menupath = { COLUMNS_AND_ROWS_MENU, "Columns" };
+ addMenuCommand("Add one column to beginning", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ insertColumns(0, 1);
+ }
+ }, menupath);
+ addMenuCommand("Add one column to end", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ insertColumns(escalator.getColumnConfiguration()
+ .getColumnCount(), 1);
+ }
+ }, menupath);
+ addMenuCommand("Add ten columns", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ insertColumns(0, 10);
+ }
+ }, menupath);
+ addMenuCommand("Remove one column from beginning",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ removeColumns(0, 1);
+ }
+ }, menupath);
+ addMenuCommand("Remove one column from end", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ removeColumns(escalator.getColumnConfiguration()
+ .getColumnCount() - 1, 1);
+ }
+ }, menupath);
+
+ addMenuCommand("Refresh first column", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getColumnConfiguration().refreshColumns(0, 1);
+ }
+ }, menupath);
+
+ addMenuCommand("Resize first column to max width",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getColumnConfiguration()
+ .setColumnWidth(0, -1);
+ }
+ }, menupath);
+
+ addMenuCommand("Resize first column to 100 px", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getColumnConfiguration().setColumnWidth(0, 100);
+ }
+ }, menupath);
+ }
+
+ private void createHeaderRowsMenu() {
+ String[] menupath = { COLUMNS_AND_ROWS_MENU, "Header Rows" };
+ createRowsMenu(escalator.getHeader(), menupath);
+ }
+
+ private void createFooterRowsMenu() {
+ String[] menupath = { COLUMNS_AND_ROWS_MENU, "Footer Rows" };
+ createRowsMenu(escalator.getFooter(), menupath);
+ }
+
+ private void createBodyRowsMenu() {
+ String[] menupath = { COLUMNS_AND_ROWS_MENU, "Body Rows" };
+ createRowsMenu(escalator.getBody(), menupath);
+
+ addMenuCommand("Add 5 rows to top", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ insertRows(escalator.getBody(), 0, 5);
+ }
+ }, menupath);
+ addMenuCommand("Add 50 rows to top", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ insertRows(escalator.getBody(), 0, 50);
+ }
+ }, menupath);
+ addMenuCommand("Remove 5 rows from bottom", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ removeRows(escalator.getBody(), escalator.getBody()
+ .getRowCount() - 5, 5);
+ }
+ }, menupath);
+ addMenuCommand("Remove 50 rows from bottom", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ removeRows(escalator.getBody(), escalator.getBody()
+ .getRowCount() - 50, 50);
+ }
+ }, menupath);
+ addMenuCommand("Remove 50 rows from almost bottom",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ removeRows(escalator.getBody(), escalator.getBody()
+ .getRowCount() - 60, 50);
+ }
+ }, menupath);
+ addMenuCommand("Remove all, insert 30 and scroll 40px",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ removeRows(escalator.getBody(), 0, escalator.getBody()
+ .getRowCount());
+ insertRows(escalator.getBody(), 0, 30);
+ escalator.setScrollTop(40);
+ }
+ }, menupath);
+ }
+
+ private void createRowsMenu(final RowContainer container, String[] menupath) {
+ addMenuCommand("Add one row to beginning", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ int offset = 0;
+ int number = 1;
+ insertRows(container, offset, number);
+ }
+ }, menupath);
+ addMenuCommand("Add one row to end", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ int offset = container.getRowCount();
+ int number = 1;
+ insertRows(container, offset, number);
+ }
+ }, menupath);
+ addMenuCommand("Remove one row from beginning", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ int offset = 0;
+ int number = 1;
+ removeRows(container, offset, number);
+ }
+ }, menupath);
+ addMenuCommand("Remove one row from end", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ int offset = container.getRowCount() - 1;
+ int number = 1;
+ removeRows(container, offset, number);
+ }
+ }, menupath);
+ addMenuCommand("Remove all rows", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ if (container.getRowCount() > 0) {
+ removeRows(container, 0, container.getRowCount());
+ }
+ }
+ }, menupath);
+ }
+
+ private void insertRows(final RowContainer container, int offset, int number) {
+ if (container == escalator.getBody()) {
+ data.insertRows(offset, number);
+ escalator.getBody().insertRows(offset, number);
+ } else {
+ container.insertRows(offset, number);
+ }
+ }
+
+ private void removeRows(final RowContainer container, int offset, int number) {
+ if (container == escalator.getBody()) {
+ data.removeRows(offset, number);
+ escalator.getBody().removeRows(offset, number);
+ } else {
+ container.removeRows(offset, number);
+ }
+ }
+
+ private void insertColumns(final int offset, final int number) {
+ data.insertColumns(offset, number);
+ escalator.getColumnConfiguration().insertColumns(offset, number);
+ }
+
+ private void removeColumns(final int offset, final int number) {
+ data.removeColumns(offset, number);
+ escalator.getColumnConfiguration().removeColumns(offset, number);
+ }
+
+ private void resetColRow() {
+ if (escalator.getColumnConfiguration().getColumnCount() > 0) {
+ removeColumns(0, escalator.getColumnConfiguration()
+ .getColumnCount());
+ }
+ if (escalator.getFooter().getRowCount() > 0) {
+ removeRows(escalator.getFooter(), 0, escalator.getFooter()
+ .getRowCount());
+ }
+
+ if (escalator.getBody().getRowCount() > 0) {
+ removeRows(escalator.getBody(), 0, escalator.getBody()
+ .getRowCount());
+ }
+
+ if (escalator.getHeader().getRowCount() > 0) {
+ removeRows(escalator.getHeader(), 0, escalator.getHeader()
+ .getRowCount());
+ }
+ }
+
+ private void resetRowCol() {
+ if (escalator.getFooter().getRowCount() > 0) {
+ removeRows(escalator.getFooter(), 0, escalator.getFooter()
+ .getRowCount());
+ }
+
+ if (escalator.getBody().getRowCount() > 0) {
+ removeRows(escalator.getBody(), 0, escalator.getBody()
+ .getRowCount());
+ }
+
+ if (escalator.getHeader().getRowCount() > 0) {
+ removeRows(escalator.getHeader(), 0, escalator.getHeader()
+ .getRowCount());
+ }
+
+ if (escalator.getColumnConfiguration().getColumnCount() > 0) {
+ removeColumns(0, escalator.getColumnConfiguration()
+ .getColumnCount());
+ }
+ }
+
+ private void refreshEscalator() {
+ if (escalator.getHeader().getRowCount() > 0) {
+ escalator.getHeader().refreshRows(0,
+ escalator.getHeader().getRowCount());
+ }
+
+ if (escalator.getBody().getRowCount() > 0) {
+ escalator.getBody().refreshRows(0,
+ escalator.getBody().getRowCount());
+ }
+
+ if (escalator.getFooter().getRowCount() > 0) {
+ escalator.getFooter().refreshRows(0,
+ escalator.getFooter().getRowCount());
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java
new file mode 100644
index 0000000000..53bf96c587
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.TableRowElement;
+import com.vaadin.client.widget.escalator.Cell;
+import com.vaadin.client.widget.escalator.ColumnConfiguration;
+import com.vaadin.client.widget.escalator.EscalatorUpdater;
+import com.vaadin.client.widget.escalator.RowContainer;
+import com.vaadin.client.widgets.Escalator;
+import com.vaadin.tests.widgetset.client.grid.EscalatorBasicClientFeaturesWidget.LogWidget;
+
+public class EscalatorProxy extends Escalator {
+ private class ColumnConfigurationProxy implements ColumnConfiguration {
+ private ColumnConfiguration columnConfiguration;
+
+ public ColumnConfigurationProxy(ColumnConfiguration columnConfiguration) {
+ this.columnConfiguration = columnConfiguration;
+ }
+
+ @Override
+ public void removeColumns(int index, int numberOfColumns)
+ throws IndexOutOfBoundsException, IllegalArgumentException {
+ columnConfiguration.removeColumns(index, numberOfColumns);
+ logWidget.log("removeColumns " + index + ", " + numberOfColumns);
+ logWidget.updateDebugLabel();
+ }
+
+ @Override
+ public void insertColumns(int index, int numberOfColumns)
+ throws IndexOutOfBoundsException, IllegalArgumentException {
+ columnConfiguration.insertColumns(index, numberOfColumns);
+ logWidget.log("insertColumns " + index + ", " + numberOfColumns);
+ logWidget.updateDebugLabel();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return columnConfiguration.getColumnCount();
+ }
+
+ @Override
+ public void setFrozenColumnCount(int count)
+ throws IllegalArgumentException {
+ columnConfiguration.setFrozenColumnCount(count);
+ }
+
+ @Override
+ public int getFrozenColumnCount() {
+ return columnConfiguration.getFrozenColumnCount();
+ }
+
+ @Override
+ public void setColumnWidth(int index, double px)
+ throws IllegalArgumentException {
+ columnConfiguration.setColumnWidth(index, px);
+ }
+
+ @Override
+ public double getColumnWidth(int index) throws IllegalArgumentException {
+ return columnConfiguration.getColumnWidth(index);
+ }
+
+ @Override
+ public double getColumnWidthActual(int index)
+ throws IllegalArgumentException {
+ return columnConfiguration.getColumnWidthActual(index);
+ }
+
+ @Override
+ public void refreshColumns(int index, int numberOfColumns)
+ throws IndexOutOfBoundsException, IllegalArgumentException {
+ columnConfiguration.refreshColumns(index, numberOfColumns);
+ }
+ }
+
+ private class RowContainerProxy implements RowContainer {
+ private final RowContainer rowContainer;
+
+ public RowContainerProxy(RowContainer rowContainer) {
+ this.rowContainer = rowContainer;
+ }
+
+ @Override
+ public EscalatorUpdater getEscalatorUpdater() {
+ return rowContainer.getEscalatorUpdater();
+ }
+
+ @Override
+ public void setEscalatorUpdater(EscalatorUpdater escalatorUpdater)
+ throws IllegalArgumentException {
+ rowContainer.setEscalatorUpdater(escalatorUpdater);
+ }
+
+ @Override
+ public void removeRows(int index, int numberOfRows)
+ throws IndexOutOfBoundsException, IllegalArgumentException {
+ rowContainer.removeRows(index, numberOfRows);
+ logWidget.log(rowContainer.getClass().getSimpleName()
+ + " removeRows " + index + ", " + numberOfRows);
+ logWidget.updateDebugLabel();
+ }
+
+ @Override
+ public void insertRows(int index, int numberOfRows)
+ throws IndexOutOfBoundsException, IllegalArgumentException {
+ rowContainer.insertRows(index, numberOfRows);
+ logWidget.log(rowContainer.getClass().getSimpleName()
+ + " insertRows " + index + ", " + numberOfRows);
+ logWidget.updateDebugLabel();
+ }
+
+ @Override
+ public void refreshRows(int index, int numberOfRows)
+ throws IndexOutOfBoundsException, IllegalArgumentException {
+ rowContainer.refreshRows(index, numberOfRows);
+ logWidget.log(rowContainer.getClass().getSimpleName()
+ + " refreshRows " + index + ", " + numberOfRows);
+ }
+
+ @Override
+ public int getRowCount() {
+ return rowContainer.getRowCount();
+ }
+
+ @Override
+ public void setDefaultRowHeight(double px) throws IllegalArgumentException {
+ rowContainer.setDefaultRowHeight(px);
+ }
+
+ @Override
+ public double getDefaultRowHeight() {
+ return rowContainer.getDefaultRowHeight();
+ }
+
+ @Override
+ public Cell getCell(Element element) {
+ return rowContainer.getCell(element);
+ }
+
+ @Override
+ public TableRowElement getRowElement(int index)
+ throws IndexOutOfBoundsException, IllegalStateException {
+ return rowContainer.getRowElement(index);
+ }
+
+ @Override
+ public Element getElement() {
+ return rowContainer.getElement();
+ }
+
+ }
+
+ private RowContainer headerProxy = null;
+ private RowContainer bodyProxy = null;
+ private RowContainer footerProxy = null;
+ private ColumnConfiguration columnProxy = null;
+ private LogWidget logWidget;
+
+ @Override
+ public RowContainer getHeader() {
+ if (headerProxy == null) {
+ headerProxy = new RowContainerProxy(super.getHeader());
+ }
+ return headerProxy;
+ }
+
+ @Override
+ public RowContainer getFooter() {
+ if (footerProxy == null) {
+ footerProxy = new RowContainerProxy(super.getFooter());
+ }
+ return footerProxy;
+ }
+
+ @Override
+ public RowContainer getBody() {
+ if (bodyProxy == null) {
+ bodyProxy = new RowContainerProxy(super.getBody());
+ }
+ return bodyProxy;
+ }
+
+ @Override
+ public ColumnConfiguration getColumnConfiguration() {
+ if (columnProxy == null) {
+ columnProxy = new ColumnConfigurationProxy(
+ super.getColumnConfiguration());
+ }
+ return columnProxy;
+ }
+
+ public void setLogWidget(LogWidget logWidget) {
+ this.logWidget = logWidget;
+ logWidget.updateDebugLabel();
+ }
+
+ @Override
+ public void setScrollTop(double scrollTop) {
+ logWidget.log("setScrollTop " + scrollTop);
+ logWidget.updateDebugLabel();
+ super.setScrollTop(scrollTop);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
new file mode 100644
index 0000000000..25a04b88f9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
@@ -0,0 +1,1173 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.logging.Logger;
+
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.TextBox;
+import com.vaadin.client.data.DataSource;
+import com.vaadin.client.data.DataSource.RowHandle;
+import com.vaadin.client.renderers.DateRenderer;
+import com.vaadin.client.renderers.HtmlRenderer;
+import com.vaadin.client.renderers.NumberRenderer;
+import com.vaadin.client.renderers.Renderer;
+import com.vaadin.client.renderers.TextRenderer;
+import com.vaadin.client.ui.VLabel;
+import com.vaadin.client.widget.grid.CellReference;
+import com.vaadin.client.widget.grid.CellStyleGenerator;
+import com.vaadin.client.widget.grid.EditorHandler;
+import com.vaadin.client.widget.grid.RendererCellReference;
+import com.vaadin.client.widget.grid.RowReference;
+import com.vaadin.client.widget.grid.RowStyleGenerator;
+import com.vaadin.client.widget.grid.datasources.ListDataSource;
+import com.vaadin.client.widget.grid.datasources.ListSorter;
+import com.vaadin.client.widget.grid.events.BodyKeyDownHandler;
+import com.vaadin.client.widget.grid.events.BodyKeyPressHandler;
+import com.vaadin.client.widget.grid.events.BodyKeyUpHandler;
+import com.vaadin.client.widget.grid.events.FooterKeyDownHandler;
+import com.vaadin.client.widget.grid.events.FooterKeyPressHandler;
+import com.vaadin.client.widget.grid.events.FooterKeyUpHandler;
+import com.vaadin.client.widget.grid.events.GridKeyDownEvent;
+import com.vaadin.client.widget.grid.events.GridKeyPressEvent;
+import com.vaadin.client.widget.grid.events.GridKeyUpEvent;
+import com.vaadin.client.widget.grid.events.HeaderKeyDownHandler;
+import com.vaadin.client.widget.grid.events.HeaderKeyPressHandler;
+import com.vaadin.client.widget.grid.events.HeaderKeyUpHandler;
+import com.vaadin.client.widget.grid.events.ScrollEvent;
+import com.vaadin.client.widget.grid.events.ScrollHandler;
+import com.vaadin.client.widget.grid.selection.SelectionModel.None;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.FooterRow;
+import com.vaadin.client.widgets.Grid.HeaderRow;
+import com.vaadin.client.widgets.Grid.SelectionMode;
+import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget.Data;
+
+/**
+ * Grid basic client features test application.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridBasicClientFeaturesWidget extends
+ PureGWTTestApplication<Grid<List<Data>>> {
+ public static final String ROW_STYLE_GENERATOR_NONE = "None";
+ public static final String ROW_STYLE_GENERATOR_ROW_INDEX = "Row numbers";
+ public static final String ROW_STYLE_GENERATOR_EVERY_THIRD = "Every third";
+
+ public static final String CELL_STYLE_GENERATOR_NONE = "None";
+ public static final String CELL_STYLE_GENERATOR_SIMPLE = "Simple";
+ public static final String CELL_STYLE_GENERATOR_COL_INDEX = "Column index";
+
+ public static enum Renderers {
+ TEXT_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER;
+ }
+
+ private class TestEditorHandler implements EditorHandler<List<Data>> {
+
+ private Map<Grid.Column<?, ?>, TextBox> widgets = new HashMap<Grid.Column<?, ?>, TextBox>();
+
+ private Label log = new Label();
+
+ {
+ log.addStyleName("grid-editor-log");
+ addSouth(log, 20);
+ }
+
+ @Override
+ public void bind(EditorRequest<List<Data>> request) {
+ List<Data> rowData = ds.getRow(request.getRowIndex());
+
+ boolean hasSelectionColumn = !(grid.getSelectionModel() instanceof None);
+ for (int i = 0; i < rowData.size(); i++) {
+ int columnIndex = hasSelectionColumn ? i + 1 : i;
+ getWidget(columnIndex).setText(rowData.get(i).value.toString());
+ }
+ request.success();
+ }
+
+ @Override
+ public void cancel(EditorRequest<List<Data>> request) {
+ log.setText("Row " + request.getRowIndex() + " edit cancelled");
+ }
+
+ @Override
+ public void save(EditorRequest<List<Data>> request) {
+ try {
+ log.setText("Row " + request.getRowIndex() + " edit committed");
+ List<Data> rowData = ds.getRow(request.getRowIndex());
+
+ int i = 0;
+ for (; i < COLUMNS - MANUALLY_FORMATTED_COLUMNS; i++) {
+ rowData.get(i).value = getWidget(i).getText();
+ }
+
+ rowData.get(i).value = Integer
+ .valueOf(getWidget(i++).getText());
+ rowData.get(i).value = new Date(getWidget(i++).getText());
+ rowData.get(i).value = getWidget(i++).getText();
+ rowData.get(i).value = Integer
+ .valueOf(getWidget(i++).getText());
+ rowData.get(i).value = Integer
+ .valueOf(getWidget(i++).getText());
+
+ // notify data source of changes
+ ds.asList().set(request.getRowIndex(), rowData);
+ request.success();
+ } catch (Exception e) {
+ Logger.getLogger(getClass().getName()).warning(e.toString());
+ request.fail();
+ }
+ }
+
+ @Override
+ public TextBox getWidget(Grid.Column<?, List<Data>> column) {
+ if (grid.getColumns().indexOf(column) == 0
+ && !(grid.getSelectionModel() instanceof None)) {
+ return null;
+ }
+
+ TextBox w = widgets.get(column);
+ if (w == null) {
+ w = new TextBox();
+ w.getElement().getStyle().setMargin(0, Unit.PX);
+ widgets.put(column, w);
+ }
+ return w;
+ }
+
+ private TextBox getWidget(int i) {
+ return getWidget(grid.getColumn(i));
+ }
+ }
+
+ private static final int MANUALLY_FORMATTED_COLUMNS = 5;
+ public static final int COLUMNS = 12;
+ public static final int ROWS = 1000;
+
+ private final Grid<List<Data>> grid;
+ private List<List<Data>> data;
+ private final ListDataSource<List<Data>> ds;
+ private final ListSorter<List<Data>> sorter;
+
+ /**
+ * Our basic data object
+ */
+ public final static class Data {
+ Object value;
+ }
+
+ /**
+ * @since
+ * @return
+ */
+ private List<List<Data>> createData(int rowCount) {
+ List<List<Data>> dataList = new ArrayList<List<Data>>();
+ Random rand = new Random();
+ rand.setSeed(13334);
+ long timestamp = 0;
+ for (int row = 0; row < rowCount; row++) {
+
+ List<Data> datarow = createDataRow(COLUMNS);
+ dataList.add(datarow);
+ Data d;
+
+ int col = 0;
+ for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) {
+ d = datarow.get(col);
+ d.value = "(" + row + ", " + col + ")";
+ }
+
+ d = datarow.get(col++);
+ d.value = Integer.valueOf(row);
+
+ d = datarow.get(col++);
+ d.value = new Date(timestamp);
+ timestamp += 91250000; // a bit over a day, just to get
+ // variation
+
+ d = datarow.get(col++);
+ d.value = "<b>" + row + "</b>";
+
+ d = datarow.get(col++);
+ d.value = Integer.valueOf(rand.nextInt());
+
+ d = datarow.get(col++);
+ d.value = Integer.valueOf(rand.nextInt(5));
+ }
+
+ return dataList;
+ }
+
+ /**
+ * Convenience method for creating a list of Data objects to be used as a
+ * Row in the data source
+ *
+ * @param cols
+ * number of columns (items) to include in the row
+ * @return
+ */
+ private List<Data> createDataRow(int cols) {
+ List<Data> list = new ArrayList<Data>(cols);
+ for (int i = 0; i < cols; ++i) {
+ list.add(new Data());
+ }
+ return list;
+ }
+
+ @SuppressWarnings("unchecked")
+ public GridBasicClientFeaturesWidget() {
+ super(new Grid<List<Data>>());
+
+ // Initialize data source
+ data = createData(ROWS);
+
+ ds = new ListDataSource<List<Data>>(data);
+ grid = getTestedWidget();
+ grid.getElement().setId("testComponent");
+ grid.setDataSource(ds);
+ grid.addSelectAllHandler(ds.getSelectAllHandler());
+ grid.setSelectionMode(SelectionMode.NONE);
+ grid.setEditorHandler(new TestEditorHandler());
+
+ sorter = new ListSorter<List<Data>>(grid);
+
+ // Create a bunch of grid columns
+
+ // Data source layout:
+ // text (String) * (COLUMNS - MANUALLY_FORMATTED_COLUMNS + 1) |
+ // rownumber (Integer) | some date (Date) | row number as HTML (String)
+ // | random value (Integer)
+
+ int col = 0;
+
+ // Text times COLUMNS - MANUALLY_FORMATTED_COLUMNS
+ for (col = 0; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) {
+
+ final int c = col;
+
+ Grid.Column<String, List<Data>> column = new Grid.Column<String, List<Data>>(
+ createRenderer(Renderers.TEXT_RENDERER)) {
+ @Override
+ public String getValue(List<Data> row) {
+ return (String) row.get(c).value;
+ }
+ };
+
+ column.setWidth(50 + c * 25);
+ column.setHeaderCaption("Header (0," + c + ")");
+
+ grid.addColumn(column);
+ }
+
+ // Integer row number
+ {
+ final int c = col++;
+ Grid.Column<Integer, List<Data>> column = new Grid.Column<Integer, List<Data>>(
+ createRenderer(Renderers.NUMBER_RENDERER)) {
+ @Override
+ public Integer getValue(List<Data> row) {
+ return (Integer) row.get(c).value;
+ }
+ };
+ grid.addColumn(column);
+ column.setHeaderCaption("Header (0," + c + ")");
+ }
+
+ // Some date
+ {
+ final int c = col++;
+ Grid.Column<Date, List<Data>> column = new Grid.Column<Date, List<Data>>(
+ createRenderer(Renderers.DATE_RENDERER)) {
+ @Override
+ public Date getValue(List<Data> row) {
+ return (Date) row.get(c).value;
+ }
+ };
+ grid.addColumn(column);
+ column.setHeaderCaption("Header (0," + c + ")");
+ }
+
+ // Row number as a HTML string
+ {
+ final int c = col++;
+ Grid.Column<String, List<Data>> column = new Grid.Column<String, List<Data>>(
+ createRenderer(Renderers.HTML_RENDERER)) {
+ @Override
+ public String getValue(List<Data> row) {
+ return (String) row.get(c).value;
+ }
+ };
+ grid.addColumn(column);
+ column.setHeaderCaption("Header (0," + c + ")");
+ }
+
+ // Random integer value
+ {
+ final int c = col++;
+ Grid.Column<Integer, List<Data>> column = new Grid.Column<Integer, List<Data>>(
+ createRenderer(Renderers.NUMBER_RENDERER)) {
+ @Override
+ public Integer getValue(List<Data> row) {
+ return (Integer) row.get(c).value;
+ }
+ };
+ grid.addColumn(column);
+ column.setHeaderCaption("Header (0," + c + ")");
+ }
+
+ // Random integer value between 0 and 5
+ {
+ final int c = col++;
+ Grid.Column<Integer, List<Data>> column = new Grid.Column<Integer, List<Data>>(
+ createRenderer(Renderers.NUMBER_RENDERER)) {
+ @Override
+ public Integer getValue(List<Data> row) {
+ return (Integer) row.get(c).value;
+ }
+ };
+ grid.addColumn(column);
+ column.setHeaderCaption("Header (0," + c + ")");
+ }
+
+ HeaderRow row = grid.getDefaultHeaderRow();
+ for (int i = 0; i < col; ++i) {
+ String caption = "Header (0," + i + ")";
+ Grid.Column<?, ?> column = grid.getColumn(i);
+ // Lets use some different cell types
+ if (i % 3 == 0) {
+ // No-op
+ } else if (i % 2 == 0) {
+ row.getCell(column).setHtml("<b>" + caption + "</b>");
+ } else {
+ row.getCell(column).setWidget(new HTML(caption));
+ }
+ }
+ ++headerCounter;
+
+ //
+ // Populate the menu
+ //
+
+ createStateMenu();
+ createColumnsMenu();
+ createHeaderMenu();
+ createFooterMenu();
+ createEditorMenu();
+ createInternalsMenu();
+ createDataSourceMenu();
+
+ grid.getElement().getStyle().setZIndex(0);
+
+ //
+ // Composite wrapping for grid.
+ //
+ boolean isComposite = Window.Location.getParameter("composite") != null;
+ if (isComposite) {
+ addNorth(new Composite() {
+ {
+ initWidget(grid);
+ }
+ }, 400);
+ } else {
+ addNorth(grid, 400);
+ }
+
+ createKeyHandlers();
+ }
+
+ private void createInternalsMenu() {
+ String[] listenersPath = { "Component", "Internals", "Listeners" };
+ final Label label = new Label();
+ addSouth(label, 20);
+
+ addMenuCommand("Add scroll listener", new ScheduledCommand() {
+ private HandlerRegistration scrollHandler = null;
+
+ @Override
+ public void execute() {
+ if (scrollHandler != null) {
+ return;
+ }
+ scrollHandler = grid.addScrollHandler(new ScrollHandler() {
+ @Override
+ public void onScroll(ScrollEvent event) {
+ @SuppressWarnings("hiding")
+ final Grid<?> grid = (Grid<?>) event.getSource();
+ label.setText("scrollTop: " + grid.getScrollTop()
+ + ", scrollLeft: " + grid.getScrollLeft());
+ }
+ });
+ }
+ }, listenersPath);
+ }
+
+ private void createStateMenu() {
+ String[] selectionModePath = { "Component", "State", "Selection mode" };
+ String[] primaryStyleNamePath = { "Component", "State",
+ "Primary Stylename" };
+ String[] rowStyleGeneratorNamePath = { "Component", "State",
+ "Row style generator" };
+ String[] cellStyleGeneratorNamePath = { "Component", "State",
+ "Cell style generator" };
+
+ addMenuCommand("multi", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setSelectionMode(SelectionMode.MULTI);
+ }
+ }, selectionModePath);
+
+ addMenuCommand("single", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setSelectionMode(SelectionMode.SINGLE);
+ }
+ }, selectionModePath);
+
+ addMenuCommand("none", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setSelectionMode(SelectionMode.NONE);
+ }
+ }, selectionModePath);
+
+ addMenuCommand("v-grid", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setStylePrimaryName("v-grid");
+
+ }
+ }, primaryStyleNamePath);
+
+ addMenuCommand("v-escalator", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setStylePrimaryName("v-escalator");
+
+ }
+ }, primaryStyleNamePath);
+
+ addMenuCommand("v-custom-style", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setStylePrimaryName("v-custom-style");
+
+ }
+ }, primaryStyleNamePath);
+
+ addMenuCommand("Edit and refresh Row 0", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ DataSource<List<Data>> ds = grid.getDataSource();
+ RowHandle<List<Data>> rowHandle = ds.getHandle(ds.getRow(0));
+ rowHandle.getRow().get(0).value = "Foo";
+ rowHandle.updateRow();
+ }
+ }, "Component", "State");
+
+ addMenuCommand("Delayed edit of Row 0", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ DataSource<List<Data>> ds = grid.getDataSource();
+ final RowHandle<List<Data>> rowHandle = ds.getHandle(ds
+ .getRow(0));
+
+ new Timer() {
+ @Override
+ public void run() {
+ rowHandle.getRow().get(0).value = "Bar";
+ rowHandle.updateRow();
+ }
+
+ }.schedule(5000);
+ }
+ }, "Component", "State");
+
+ addMenuCommand(ROW_STYLE_GENERATOR_NONE, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setRowStyleGenerator(null);
+ }
+ }, rowStyleGeneratorNamePath);
+
+ addMenuCommand(ROW_STYLE_GENERATOR_EVERY_THIRD, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setRowStyleGenerator(new RowStyleGenerator<List<Data>>() {
+
+ @Override
+ public String getStyle(RowReference<List<Data>> rowReference) {
+ if (rowReference.getRowIndex() % 3 == 0) {
+ return "third";
+ } else {
+ // First manual col is integer
+ Integer value = (Integer) rowReference.getRow()
+ .get(COLUMNS - MANUALLY_FORMATTED_COLUMNS).value;
+ return value.toString();
+ }
+ }
+ });
+
+ }
+ }, rowStyleGeneratorNamePath);
+
+ addMenuCommand(ROW_STYLE_GENERATOR_ROW_INDEX, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setRowStyleGenerator(new RowStyleGenerator<List<Data>>() {
+
+ @Override
+ public String getStyle(RowReference<List<Data>> rowReference) {
+ return Integer.toString(rowReference.getRowIndex());
+ }
+ });
+
+ }
+ }, rowStyleGeneratorNamePath);
+
+ addMenuCommand(CELL_STYLE_GENERATOR_NONE, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setCellStyleGenerator(null);
+ }
+ }, cellStyleGeneratorNamePath);
+
+ addMenuCommand(CELL_STYLE_GENERATOR_SIMPLE, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setCellStyleGenerator(new CellStyleGenerator<List<Data>>() {
+
+ @Override
+ public String getStyle(
+ CellReference<List<Data>> cellReference) {
+ Grid.Column<?, List<Data>> column = cellReference
+ .getColumn();
+ if (column == grid.getColumn(2)) {
+ return "two";
+ } else if (column == grid.getColumn(COLUMNS
+ - MANUALLY_FORMATTED_COLUMNS)) {
+ // First manual col is integer
+ Integer value = (Integer) column
+ .getValue(cellReference.getRow());
+ return value.toString();
+
+ } else {
+ return null;
+ }
+ }
+ });
+ }
+ }, cellStyleGeneratorNamePath);
+ addMenuCommand(CELL_STYLE_GENERATOR_COL_INDEX, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setCellStyleGenerator(new CellStyleGenerator<List<Data>>() {
+
+ @Override
+ public String getStyle(
+ CellReference<List<Data>> cellReference) {
+ return cellReference.getRowIndex()
+ + "_"
+ + grid.getColumns().indexOf(
+ cellReference.getColumn());
+ }
+ });
+ }
+ }, cellStyleGeneratorNamePath);
+
+ for (int i = -1; i <= COLUMNS; i++) {
+ final int index = i;
+ // Including dummy "columns" prefix because TB fails to select item
+ // if it's too narrow
+ addMenuCommand(Integer.toString(index) + " columns",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setFrozenColumnCount(index);
+ }
+ }, "Component", "State", "Frozen column count");
+ }
+
+ addMenuCommand("Enabled", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ grid.setEnabled(!grid.isEnabled());
+ }
+ }, "Component", "State");
+ }
+
+ private void createColumnsMenu() {
+
+ for (int i = 0; i < COLUMNS; i++) {
+ final int index = i;
+ final Grid.Column<?, List<Data>> column = grid.getColumn(index);
+ addMenuCommand("Sortable", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ column.setSortable(!column.isSortable());
+ }
+ }, "Component", "Columns", "Column " + i);
+
+ addMenuCommand("auto", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ column.setWidth(-1);
+ }
+ }, "Component", "Columns", "Column " + i, "Width");
+ addMenuCommand("50px", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ column.setWidth(50);
+ }
+ }, "Component", "Columns", "Column " + i, "Width");
+ addMenuCommand("200px", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ column.setWidth(200);
+ }
+ }, "Component", "Columns", "Column " + i, "Width");
+
+ // Header types
+ addMenuCommand("Text Header", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ column.setHeaderCaption("Text Header");
+ }
+ }, "Component", "Columns", "Column " + i, "Header Type");
+ addMenuCommand("HTML Header", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.getHeaderRow(0).getCell(column)
+ .setHtml("<b>HTML Header</b>");
+ }
+ }, "Component", "Columns", "Column " + i, "Header Type");
+ addMenuCommand("Widget Header", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ final Button button = new Button("Button Header");
+ button.addClickHandler(new ClickHandler() {
+
+ @Override
+ public void onClick(ClickEvent event) {
+ button.setText("Clicked");
+ }
+ });
+ grid.getHeaderRow(0).getCell(column).setWidget(button);
+ }
+ }, "Component", "Columns", "Column " + i, "Header Type");
+
+ // Footer types
+ addMenuCommand("Text Footer", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.getFooterRow(0).getCell(column).setText("Text Footer");
+ }
+ }, "Component", "Columns", "Column " + i, "Footer Type");
+ addMenuCommand("HTML Footer", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.getFooterRow(0).getCell(column)
+ .setHtml("<b>HTML Footer</b>");
+ }
+ }, "Component", "Columns", "Column " + i, "Footer Type");
+ addMenuCommand("Widget Footer", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ final Button button = new Button("Button Footer");
+ button.addClickHandler(new ClickHandler() {
+
+ @Override
+ public void onClick(ClickEvent event) {
+ button.setText("Clicked");
+ }
+ });
+ grid.getFooterRow(0).getCell(column).setWidget(button);
+ }
+ }, "Component", "Columns", "Column " + i, "Footer Type");
+
+ // Renderer throwing exceptions
+ addMenuCommand("Broken renderer", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ final Renderer<Object> originalRenderer = (Renderer<Object>) column
+ .getRenderer();
+
+ column.setRenderer(new Renderer<Object>() {
+ @Override
+ public void render(RendererCellReference cell,
+ Object data) {
+ if (cell.getRowIndex() == cell.getColumnIndex()) {
+ throw new RuntimeException("I'm broken");
+ }
+ originalRenderer.render(cell, data);
+ }
+ });
+ }
+ }, "Component", "Columns", "Column " + i);
+ }
+ }
+
+ private int headerCounter = 0;
+ private int footerCounter = 0;
+
+ private void setHeaderTexts(HeaderRow row) {
+ for (int i = 0; i < COLUMNS; ++i) {
+ String caption = "Header (" + headerCounter + "," + i + ")";
+
+ // Lets use some different cell types
+ if (i % 3 == 0) {
+ row.getCell(grid.getColumn(i)).setText(caption);
+ } else if (i % 2 == 0) {
+ row.getCell(grid.getColumn(i))
+ .setHtml("<b>" + caption + "</b>");
+ } else {
+ row.getCell(grid.getColumn(i)).setWidget(new HTML(caption));
+ }
+ }
+ headerCounter++;
+ }
+
+ private void setFooterTexts(FooterRow row) {
+ for (int i = 0; i < COLUMNS; ++i) {
+ String caption = "Footer (" + footerCounter + "," + i + ")";
+
+ // Lets use some different cell types
+ if (i % 3 == 0) {
+ row.getCell(grid.getColumn(i)).setText(caption);
+ } else if (i % 2 == 0) {
+ row.getCell(grid.getColumn(i))
+ .setHtml("<b>" + caption + "</b>");
+ } else {
+ row.getCell(grid.getColumn(i)).setWidget(new HTML(caption));
+ }
+ }
+ footerCounter++;
+ }
+
+ private void createHeaderMenu() {
+ final String[] menuPath = { "Component", "Header" };
+
+ addMenuCommand("Visible", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setHeaderVisible(!grid.isHeaderVisible());
+ }
+ }, menuPath);
+
+ addMenuCommand("Top", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setDefaultHeaderRow(grid.getHeaderRow(0));
+ }
+ }, "Component", "Header", "Default row");
+ addMenuCommand("Bottom", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setDefaultHeaderRow(grid.getHeaderRow(grid
+ .getHeaderRowCount() - 1));
+ }
+ }, "Component", "Header", "Default row");
+ addMenuCommand("Unset", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setDefaultHeaderRow(null);
+ }
+ }, "Component", "Header", "Default row");
+
+ addMenuCommand("Prepend row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ configureHeaderRow(grid.prependHeaderRow());
+ }
+ }, menuPath);
+ addMenuCommand("Append row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ configureHeaderRow(grid.appendHeaderRow());
+ }
+ }, menuPath);
+ addMenuCommand("Remove top row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.removeHeaderRow(0);
+ }
+ }, menuPath);
+ addMenuCommand("Remove bottom row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.removeHeaderRow(grid.getHeaderRowCount() - 1);
+ }
+ }, menuPath);
+
+ }
+
+ private void configureHeaderRow(final HeaderRow row) {
+ setHeaderTexts(row);
+ String rowTitle = "Row " + grid.getHeaderRowCount();
+ final String[] menuPath = { "Component", "Header", rowTitle };
+
+ addMenuCommand("Join column cells 0, 1", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ row.join(row.getCell(grid.getColumn(0)),
+ row.getCell(grid.getColumn(1))).setText(
+ "Join column cells 0, 1");
+
+ }
+ }, menuPath);
+
+ addMenuCommand("Join columns 1, 2", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ row.join(grid.getColumn(1), grid.getColumn(2)).setText(
+ "Join columns 1, 2");
+ ;
+
+ }
+ }, menuPath);
+
+ addMenuCommand("Join columns 3, 4, 5", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ row.join(grid.getColumn(3), grid.getColumn(4),
+ grid.getColumn(5)).setText("Join columns 3, 4, 5");
+
+ }
+ }, menuPath);
+
+ addMenuCommand("Join all columns", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ row.join(
+ grid.getColumns().toArray(
+ new Grid.Column[grid.getColumnCount()]))
+ .setText("Join all columns");
+ ;
+
+ }
+ }, menuPath);
+ }
+
+ private void createFooterMenu() {
+ final String[] menuPath = { "Component", "Footer" };
+
+ addMenuCommand("Visible", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setFooterVisible(!grid.isFooterVisible());
+ }
+ }, menuPath);
+
+ addMenuCommand("Prepend row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ configureFooterRow(grid.prependFooterRow());
+ }
+ }, menuPath);
+ addMenuCommand("Append row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ configureFooterRow(grid.appendFooterRow());
+ }
+ }, menuPath);
+ addMenuCommand("Remove top row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.removeFooterRow(0);
+ }
+ }, menuPath);
+ addMenuCommand("Remove bottom row", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ assert grid.getFooterRowCount() > 0;
+ grid.removeFooterRow(grid.getFooterRowCount() - 1);
+ }
+ }, menuPath);
+ }
+
+ private void createEditorMenu() {
+ addMenuCommand("Enabled", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setEditorEnabled(!grid.isEditorEnabled());
+ }
+ }, "Component", "Editor");
+
+ addMenuCommand("Edit row 5", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.editRow(5);
+ }
+ }, "Component", "Editor");
+
+ addMenuCommand("Edit row 100", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.editRow(100);
+ }
+ }, "Component", "Editor");
+
+ addMenuCommand("Save", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.saveEditor();
+ }
+ }, "Component", "Editor");
+
+ addMenuCommand("Cancel edit", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.cancelEditor();
+ }
+ }, "Component", "Editor");
+
+ }
+
+ private void configureFooterRow(final FooterRow row) {
+ setFooterTexts(row);
+ String rowTitle = "Row " + grid.getFooterRowCount();
+ final String[] menuPath = { "Component", "Footer", rowTitle };
+
+ addMenuCommand("Join column cells 0, 1", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ row.join(row.getCell(grid.getColumn(0)),
+ row.getCell(grid.getColumn(1))).setText(
+ "Join column cells 0, 1");
+
+ }
+ }, menuPath);
+
+ addMenuCommand("Join columns 1, 2", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ row.join(grid.getColumn(1), grid.getColumn(2)).setText(
+ "Join columns 1, 2");
+ ;
+
+ }
+ }, menuPath);
+
+ addMenuCommand("Join all columns", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ row.join(
+ grid.getColumns().toArray(
+ new Grid.Column[grid.getColumnCount()]))
+ .setText("Join all columns");
+ ;
+
+ }
+ }, menuPath);
+ }
+
+ private void createDataSourceMenu() {
+ final String[] menuPath = { "Component", "DataSource" };
+
+ addMenuCommand("Reset with 100 rows of Data", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ ds.asList().clear();
+ data = createData(100);
+ ds.asList().addAll(data);
+ }
+ }, menuPath);
+
+ addMenuCommand("Reset with " + ROWS + " rows of Data",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ ds.asList().clear();
+ data = createData(ROWS);
+ ds.asList().addAll(data);
+ }
+ }, menuPath);
+ }
+
+ /**
+ * Creates a renderer for a {@link Renderers}
+ */
+ @SuppressWarnings("rawtypes")
+ private final Renderer createRenderer(Renderers renderer) {
+ switch (renderer) {
+ case TEXT_RENDERER:
+ return new TextRenderer();
+
+ case HTML_RENDERER:
+ return new HtmlRenderer() {
+
+ @Override
+ public void render(RendererCellReference cell, String htmlString) {
+ super.render(cell, "<b>" + htmlString + "</b>");
+ }
+ };
+
+ case NUMBER_RENDERER:
+ return new NumberRenderer();
+
+ case DATE_RENDERER:
+ return new DateRenderer();
+
+ default:
+ return new TextRenderer();
+ }
+ }
+
+ /**
+ * Creates a collection of handlers for all the grid key events
+ */
+ private void createKeyHandlers() {
+ final List<VLabel> labels = new ArrayList<VLabel>();
+ for (int i = 0; i < 9; ++i) {
+ VLabel tmp = new VLabel();
+ addNorth(tmp, 20);
+ labels.add(tmp);
+ }
+
+ // Key Down Events
+ grid.addBodyKeyDownHandler(new BodyKeyDownHandler() {
+ private final VLabel label = labels.get(0);
+
+ @Override
+ public void onKeyDown(GridKeyDownEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ grid.addHeaderKeyDownHandler(new HeaderKeyDownHandler() {
+ private final VLabel label = labels.get(1);
+
+ @Override
+ public void onKeyDown(GridKeyDownEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ grid.addFooterKeyDownHandler(new FooterKeyDownHandler() {
+ private final VLabel label = labels.get(2);
+
+ @Override
+ public void onKeyDown(GridKeyDownEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ // Key Up Events
+ grid.addBodyKeyUpHandler(new BodyKeyUpHandler() {
+ private final VLabel label = labels.get(3);
+
+ @Override
+ public void onKeyUp(GridKeyUpEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ grid.addHeaderKeyUpHandler(new HeaderKeyUpHandler() {
+ private final VLabel label = labels.get(4);
+
+ @Override
+ public void onKeyUp(GridKeyUpEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ grid.addFooterKeyUpHandler(new FooterKeyUpHandler() {
+ private final VLabel label = labels.get(5);
+
+ @Override
+ public void onKeyUp(GridKeyUpEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ // Key Press Events
+ grid.addBodyKeyPressHandler(new BodyKeyPressHandler() {
+ private final VLabel label = labels.get(6);
+
+ @Override
+ public void onKeyPress(GridKeyPressEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ grid.addHeaderKeyPressHandler(new HeaderKeyPressHandler() {
+ private final VLabel label = labels.get(7);
+
+ @Override
+ public void onKeyPress(GridKeyPressEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ grid.addFooterKeyPressHandler(new FooterKeyPressHandler() {
+ private final VLabel label = labels.get(8);
+
+ @Override
+ public void onKeyPress(GridKeyPressEvent event) {
+ CellReference<?> focused = event.getFocusedCell();
+ updateLabel(label, event.toDebugString(),
+ focused.getRowIndex(), focused.getColumnIndex());
+ }
+ });
+
+ }
+
+ private void updateLabel(VLabel label, String output, int object, int column) {
+ String coords = "(" + object + ", " + column + ")";
+ label.setText(coords + " " + output);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java
new file mode 100644
index 0000000000..f35f9820e0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window.Location;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.HasWidgets;
+import com.vaadin.client.data.DataChangeHandler;
+import com.vaadin.client.data.DataSource;
+import com.vaadin.client.renderers.ComplexRenderer;
+import com.vaadin.client.renderers.DateRenderer;
+import com.vaadin.client.renderers.HtmlRenderer;
+import com.vaadin.client.renderers.NumberRenderer;
+import com.vaadin.client.renderers.Renderer;
+import com.vaadin.client.renderers.TextRenderer;
+import com.vaadin.client.renderers.WidgetRenderer;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.client.widget.grid.CellReference;
+import com.vaadin.client.widget.grid.RendererCellReference;
+import com.vaadin.client.widget.grid.datasources.ListDataSource;
+import com.vaadin.client.widget.grid.datasources.ListSorter;
+import com.vaadin.client.widget.grid.sort.Sort;
+import com.vaadin.client.widget.grid.sort.SortEvent;
+import com.vaadin.client.widget.grid.sort.SortHandler;
+import com.vaadin.client.widget.grid.sort.SortOrder;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.tests.widgetset.server.grid.GridClientColumnRenderers;
+
+@Connect(GridClientColumnRenderers.GridController.class)
+public class GridClientColumnRendererConnector extends
+ AbstractComponentConnector {
+
+ public static enum Renderers {
+ TEXT_RENDERER, WIDGET_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER, CPLX_RENDERER;
+ }
+
+ /**
+ * Datasource for simulating network latency
+ */
+ private class DelayedDataSource implements DataSource<String> {
+
+ private DataSource<String> ds;
+ private int firstRowIndex = -1;
+ private int numberOfRows;
+ private DataChangeHandler dataChangeHandler;
+ private int latency;
+
+ public DelayedDataSource(DataSource<String> ds, int latency) {
+ this.ds = ds;
+ this.latency = latency;
+ }
+
+ @Override
+ public void ensureAvailability(final int firstRowIndex,
+ final int numberOfRows) {
+ new Timer() {
+
+ @Override
+ public void run() {
+ DelayedDataSource.this.firstRowIndex = firstRowIndex;
+ DelayedDataSource.this.numberOfRows = numberOfRows;
+ dataChangeHandler.dataUpdated(firstRowIndex, numberOfRows);
+ dataChangeHandler
+ .dataAvailable(firstRowIndex, numberOfRows);
+ }
+ }.schedule(latency);
+ }
+
+ @Override
+ public String getRow(int rowIndex) {
+ if (rowIndex >= firstRowIndex
+ && rowIndex <= firstRowIndex + numberOfRows) {
+ return ds.getRow(rowIndex);
+ }
+ return null;
+ }
+
+ @Override
+ public int size() {
+ return ds.size();
+ }
+
+ @Override
+ public void setDataChangeHandler(DataChangeHandler dataChangeHandler) {
+ this.dataChangeHandler = dataChangeHandler;
+ }
+
+ @Override
+ public RowHandle<String> getHandle(String row) {
+ // TODO Auto-generated method stub (henrik paul: 17.6.)
+ return null;
+ }
+
+ @Override
+ public int indexOf(String row) {
+ return ds.indexOf(row);
+ }
+ }
+
+ @Override
+ protected void init() {
+ Grid<String> grid = getWidget();
+ grid.setSelectionMode(Grid.SelectionMode.NONE);
+
+ // Generated some column data
+ List<String> columnData = new ArrayList<String>();
+ for (int i = 0; i < 100; i++) {
+ columnData.add(String.valueOf(i));
+ }
+
+ // Provide data as data source
+ if (Location.getParameter("latency") != null) {
+ grid.setDataSource(new DelayedDataSource(
+ new ListDataSource<String>(columnData), Integer
+ .parseInt(Location.getParameter("latency"))));
+ } else {
+ grid.setDataSource(new ListDataSource<String>(columnData));
+ }
+
+ // Add a column to display the data in
+ Grid.Column<String, String> c = createColumnWithRenderer(Renderers.TEXT_RENDERER);
+ grid.addColumn(c);
+ grid.getDefaultHeaderRow().getCell(c).setText("Column 1");
+
+ // Add another column with a custom complex renderer
+ c = createColumnWithRenderer(Renderers.CPLX_RENDERER);
+ grid.addColumn(c);
+ grid.getDefaultHeaderRow().getCell(c).setText("Column 2");
+
+ // Add method for testing sort event firing
+ grid.addSortHandler(new SortHandler<String>() {
+ @Override
+ public void sort(SortEvent<String> event) {
+ Element console = Document.get().getElementById(
+ "testDebugConsole");
+ String text = "Client-side sort event received<br>"
+ + "Columns: " + event.getOrder().size() + ", order: ";
+ for (SortOrder order : event.getOrder()) {
+ String columnHeader = getWidget().getDefaultHeaderRow()
+ .getCell(order.getColumn()).getText();
+ text += columnHeader + ": "
+ + order.getDirection().toString();
+ }
+ console.setInnerHTML(text);
+ }
+ });
+
+ // Handle RPC calls
+ registerRpc(GridClientColumnRendererRpc.class,
+ new GridClientColumnRendererRpc() {
+
+ @Override
+ public void addColumn(Renderers renderer) {
+
+ Grid.Column<?, String> column;
+ if (renderer == Renderers.NUMBER_RENDERER) {
+ column = createNumberColumnWithRenderer(renderer);
+ } else if (renderer == Renderers.DATE_RENDERER) {
+ column = createDateColumnWithRenderer(renderer);
+ } else {
+ column = createColumnWithRenderer(renderer);
+ }
+ getWidget().addColumn(column);
+
+ getWidget()
+ .getDefaultHeaderRow()
+ .getCell(column)
+ .setText(
+ "Column "
+ + String.valueOf(getWidget()
+ .getColumnCount() + 1));
+ }
+
+ @Override
+ public void detachAttach() {
+
+ // Detach
+ HasWidgets parent = (HasWidgets) getWidget()
+ .getParent();
+ parent.remove(getWidget());
+
+ // Re-attach
+ parent.add(getWidget());
+ }
+
+ @Override
+ public void triggerClientSorting() {
+ getWidget().sort(Sort.by(getWidget().getColumn(0)));
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void triggerClientSortingTest() {
+ Grid<String> grid = getWidget();
+ ListSorter<String> sorter = new ListSorter<String>(grid);
+
+ // Make sorter sort the numbers in natural order
+ sorter.setComparator(
+ (Grid.Column<String, String>) grid.getColumn(0),
+ new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return Integer.parseInt(o1)
+ - Integer.parseInt(o2);
+ }
+ });
+
+ // Sort along column 0 in ascending order
+ grid.sort(grid.getColumn(0));
+
+ // Remove the sorter once we're done
+ sorter.removeFromGrid();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void shuffle() {
+ Grid<String> grid = getWidget();
+ ListSorter<String> shuffler = new ListSorter<String>(
+ grid);
+
+ // Make shuffler return random order
+ shuffler.setComparator(
+ (Grid.Column<String, String>) grid.getColumn(0),
+ new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return com.google.gwt.user.client.Random
+ .nextInt(3) - 1;
+ }
+ });
+
+ // "Sort" (actually shuffle) along column 0
+ grid.sort(grid.getColumn(0));
+
+ // Remove the shuffler when we're done so that it
+ // doesn't interfere with further operations
+ shuffler.removeFromGrid();
+ }
+ });
+ }
+
+ /**
+ * Creates a a renderer for a {@link Renderers}
+ */
+ private Renderer createRenderer(Renderers renderer) {
+ switch (renderer) {
+ case TEXT_RENDERER:
+ return new TextRenderer();
+
+ case WIDGET_RENDERER:
+ return new WidgetRenderer<String, Button>() {
+
+ @Override
+ public Button createWidget() {
+ final Button button = new Button("");
+ button.addClickHandler(new ClickHandler() {
+
+ @Override
+ public void onClick(ClickEvent event) {
+ button.setText("Clicked");
+ }
+ });
+ return button;
+ }
+
+ @Override
+ public void render(RendererCellReference cell, String data,
+ Button button) {
+ button.setHTML(data);
+ }
+ };
+
+ case HTML_RENDERER:
+ return new HtmlRenderer() {
+
+ @Override
+ public void render(RendererCellReference cell, String htmlString) {
+ super.render(cell, "<b>" + htmlString + "</b>");
+ }
+ };
+
+ case NUMBER_RENDERER:
+ return new NumberRenderer();
+
+ case DATE_RENDERER:
+ return new DateRenderer();
+
+ case CPLX_RENDERER:
+ return new ComplexRenderer<String>() {
+
+ @Override
+ public void init(RendererCellReference cell) {
+ }
+
+ @Override
+ public void render(RendererCellReference cell, String data) {
+ cell.getElement().setInnerHTML("<span>" + data + "</span>");
+ cell.getElement().getStyle().clearBackgroundColor();
+ }
+
+ @Override
+ public void setContentVisible(RendererCellReference cell,
+ boolean hasData) {
+
+ // Visualize content visible property
+ cell.getElement().getStyle()
+ .setBackgroundColor(hasData ? "green" : "red");
+
+ super.setContentVisible(cell, hasData);
+ }
+
+ @Override
+ public boolean onActivate(CellReference<?> cell) {
+ cell.getElement().setInnerHTML("<span>Activated!</span>");
+ return true;
+ }
+ };
+
+ default:
+ return new TextRenderer();
+ }
+ }
+
+ private Grid.Column<String, String> createColumnWithRenderer(
+ Renderers renderer) {
+ return new Grid.Column<String, String>(createRenderer(renderer)) {
+
+ @Override
+ public String getValue(String row) {
+ return row;
+ }
+ };
+ }
+
+ private Grid.Column<Number, String> createNumberColumnWithRenderer(
+ Renderers renderer) {
+ return new Grid.Column<Number, String>(createRenderer(renderer)) {
+
+ @Override
+ public Number getValue(String row) {
+ return Long.parseLong(row);
+ }
+ };
+ }
+
+ private Grid.Column<Date, String> createDateColumnWithRenderer(
+ Renderers renderer) {
+ return new Grid.Column<Date, String>(createRenderer(renderer)) {
+
+ @Override
+ public Date getValue(String row) {
+ return new Date();
+ }
+ };
+ }
+
+ @Override
+ public Grid<String> getWidget() {
+ return (Grid<String>) super.getWidget();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererRpc.java
new file mode 100644
index 0000000000..90eee9e1c6
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererRpc.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import com.vaadin.shared.communication.ClientRpc;
+import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererConnector.Renderers;
+
+public interface GridClientColumnRendererRpc extends ClientRpc {
+
+ /**
+ * Adds a new column with a specific renderer to the grid
+ *
+ */
+ void addColumn(Renderers renderer);
+
+ /**
+ * Detaches and attaches the client side Grid
+ */
+ void detachAttach();
+
+ /**
+ * Used for client-side sorting API test
+ */
+ void triggerClientSorting();
+
+ /**
+ * @since
+ */
+ void triggerClientSortingTest();
+
+ /**
+ * @since
+ */
+ void shuffle();
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientDataSourcesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientDataSourcesWidget.java
new file mode 100644
index 0000000000..e352b10064
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientDataSourcesWidget.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.vaadin.client.data.AbstractRemoteDataSource;
+import com.vaadin.client.renderers.TextRenderer;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.SelectionMode;
+
+public class GridClientDataSourcesWidget extends
+ PureGWTTestApplication<Grid<String[]>> {
+
+ private interface RestCallback {
+ void onResponse(RestishDataSource.Backend.Result result);
+ }
+
+ /**
+ * This is an emulated datasource that has a back-end that changes size
+ * constantly. The back-end is unable to actively push data to Grid.
+ * Instead, with each row request, in addition to its row payload it tells
+ * how many rows it contains in total.
+ *
+ * A plausible response from this REST-like api would be:
+ *
+ * <pre>
+ * <code>
+ * GET /foos/4..8
+ *
+ * {
+ * "resultsize": 4,
+ * "data": [
+ * [4, "foo IV"],
+ * [5, "foo V"],
+ * [6, "foo VI"]
+ * [7, "foo VII"]
+ * ],
+ * "totalrows": 100
+ * }
+ * </code>
+ * </pre>
+ *
+ * In this case, the size of Grid needs to be updated to be able to show 100
+ * rows in total (no more, no less).
+ *
+ * This class
+ * <ol>
+ * <li>gets initialized
+ * <li>asks for its size
+ * <li>updates Grid once the reply is received
+ * <li>as the Grid fetches more data, the total row count is dynamically
+ * updated.
+ * </ol>
+ */
+ private class RestishDataSource extends AbstractRemoteDataSource<String[]> {
+ /**
+ * Pretend like this class doesn't exist. It just simulates a backend
+ * somewhere.
+ * <p>
+ * It's scoped inside the RDS class only because it's tied to that.
+ * */
+ private class Backend {
+ public class Result {
+ public int size;
+ public List<String[]> rows;
+ }
+
+ private int size = 200;
+ private int modCount = 0;
+
+ public void query(int firstRowIndex, int numberOfRows,
+ final RestCallback callback) {
+ final Result result = new Result();
+ result.size = size;
+ result.rows = fetchRows(firstRowIndex, numberOfRows);
+
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ callback.onResponse(result);
+ }
+ });
+
+ }
+
+ private List<String[]> fetchRows(int firstRowIndex, int numberOfRows) {
+ List<String[]> rows = new ArrayList<String[]>();
+ for (int i = 0; i < numberOfRows; i++) {
+ String id = String.valueOf(firstRowIndex + i);
+ rows.add(new String[] { id, "cell " + id + " #" + modCount });
+ }
+ return rows;
+ }
+
+ public void pushRowChanges(int rows) {
+ size += rows;
+ pushRowChanges();
+ }
+
+ public void pushRowChanges() {
+ modCount++;
+
+ // push "something happened" to datasource "over the wire":
+ resetDataAndSize(size);
+ }
+
+ public void addRows(int rowcount) {
+ modCount++;
+ size += rowcount;
+ }
+ }
+
+ final Backend backend;
+
+ public RestishDataSource() {
+ backend = new Backend();
+ }
+
+ @Override
+ protected void requestRows(int firstRowIndex, int numberOfRows,
+ final RequestRowsCallback<String[]> callback) {
+
+ backend.query(firstRowIndex, numberOfRows, new RestCallback() {
+ @Override
+ public void onResponse(Backend.Result result) {
+ callback.onResponse(result.rows, result.size);
+ }
+ });
+ }
+
+ @Override
+ public Object getRowKey(String[] row) {
+ return row[0];
+ }
+ }
+
+ private final Grid<String[]> grid;
+
+ private RestishDataSource restishDataSource;
+
+ private final ScheduledCommand setRestishCommand = new ScheduledCommand() {
+ @Override
+ public void execute() {
+ for (Grid.Column<?, String[]> column : grid.getColumns()) {
+ grid.removeColumn(column);
+ }
+
+ restishDataSource = new RestishDataSource();
+ grid.setDataSource(restishDataSource);
+ grid.addColumn(new Grid.Column<String, String[]>("column",
+ new TextRenderer()) {
+
+ @Override
+ public String getValue(String[] row) {
+ return row[1];
+ }
+ });
+ }
+ };
+
+ public GridClientDataSourcesWidget() {
+ super(new Grid<String[]>());
+ grid = getTestedWidget();
+
+ grid.getElement().getStyle().setZIndex(0);
+ grid.setHeight("400px");
+ grid.setSelectionMode(SelectionMode.NONE);
+ addNorth(grid, 400);
+
+ addMenuCommand("Use", setRestishCommand, "DataSources", "RESTish");
+ addMenuCommand("Next request +10", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ restishDataSource.backend.addRows(10);
+ }
+ }, "DataSources", "RESTish");
+ addMenuCommand("Next request -10", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ restishDataSource.backend.addRows(-10);
+ }
+ }, "DataSources", "RESTish");
+ addMenuCommand("Push data change", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ restishDataSource.backend.pushRowChanges();
+ }
+ }, "DataSources", "RESTish");
+ addMenuCommand("Push data change +10", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ restishDataSource.backend.pushRowChanges(10);
+ }
+ }, "DataSources", "RESTish");
+ addMenuCommand("Push data change -10", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ restishDataSource.backend.pushRowChanges(-10);
+ }
+ }, "DataSources", "RESTish");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridColumnAutoWidthClientWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridColumnAutoWidthClientWidget.java
new file mode 100644
index 0000000000..caaed12e70
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridColumnAutoWidthClientWidget.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import com.vaadin.client.renderers.HtmlRenderer;
+import com.vaadin.client.widget.grid.datasources.ListDataSource;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.SelectionMode;
+
+public class GridColumnAutoWidthClientWidget extends
+ PureGWTTestApplication<Grid<List<String>>> {
+
+ private Grid<List<String>> grid;
+
+ private class Col extends Grid.Column<String, List<String>> {
+ public Col(String header) {
+ super(header, new HtmlRenderer());
+ setExpandRatio(0);
+ }
+
+ @Override
+ public String getValue(List<String> row) {
+ int index = grid.getColumns().indexOf(this);
+ return "<span>" + String.valueOf(row.get(index)) + "</span>";
+ }
+ }
+
+ public GridColumnAutoWidthClientWidget() {
+ super(new Grid<List<String>>());
+ grid = getTestedWidget();
+ grid.setSelectionMode(SelectionMode.NONE);
+ grid.setWidth("700px");
+
+ List<List<String>> list = new ArrayList<List<String>>();
+ list.add(Arrays.asList("equal length", "a very long cell content",
+ "short", "fixed width narrow", "fixed width wide"));
+ grid.setDataSource(new ListDataSource<List<String>>(list));
+
+ addColumn("equal length");
+ addColumn("short");
+ addColumn("a very long header content");
+ addColumn("fixed width narrow").setWidth(50);
+ addColumn("fixed width wide").setWidth(200);
+
+ addNorth(grid, 400);
+ }
+
+ private Col addColumn(String header) {
+ Col column = grid.addColumn(new Col(header));
+ grid.getHeaderRow(0).getCell(column)
+ .setHtml("<span>" + header + "</span>");
+ return column;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridDefaultTextRendererWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridDefaultTextRendererWidget.java
new file mode 100644
index 0000000000..4f1ea48be5
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridDefaultTextRendererWidget.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import com.vaadin.client.widget.grid.datasources.ListDataSource;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.Column;
+import com.vaadin.client.widgets.Grid.SelectionMode;
+import com.vaadin.shared.ui.grid.HeightMode;
+
+public class GridDefaultTextRendererWidget extends
+ PureGWTTestApplication<Grid<String>> {
+ /*
+ * This can't be null, because grid thinks that a row object of null means
+ * "data is still being fetched".
+ */
+ private static final String NULL_STRING = "";
+
+ private Grid<String> grid;
+
+ public GridDefaultTextRendererWidget() {
+ super(new Grid<String>());
+ grid = getTestedWidget();
+
+ grid.setDataSource(new ListDataSource<String>(NULL_STRING, "string"));
+ grid.addColumn(new Column<String, String>() {
+ @Override
+ public String getValue(String row) {
+ if (!NULL_STRING.equals(row)) {
+ return row;
+ } else {
+ return null;
+ }
+ }
+ });
+
+ grid.addColumn(new Column<String, String>() {
+
+ @Override
+ public String getValue(String row) {
+ return "foo";
+ }
+
+ });
+
+ grid.setHeightByRows(2);
+ grid.setHeightMode(HeightMode.ROW);
+ grid.setSelectionMode(SelectionMode.NONE);
+ addNorth(grid, 500);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridHeightByRowOnInitWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridHeightByRowOnInitWidget.java
new file mode 100644
index 0000000000..8202c2ccc0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridHeightByRowOnInitWidget.java
@@ -0,0 +1,32 @@
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.Arrays;
+
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.vaadin.client.widget.grid.datasources.ListDataSource;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.Column;
+import com.vaadin.shared.ui.grid.HeightMode;
+
+public class GridHeightByRowOnInitWidget extends Composite {
+ private final SimplePanel panel = new SimplePanel();
+ private final Grid<String> grid = new Grid<String>();
+
+ public GridHeightByRowOnInitWidget() {
+ initWidget(panel);
+
+ panel.setWidget(grid);
+ grid.setDataSource(new ListDataSource<String>(Arrays.asList("A", "B",
+ "C", "D", "E")));
+ grid.addColumn(new Column<String, String>("letter") {
+ @Override
+ public String getValue(String row) {
+ return row;
+ }
+ });
+
+ grid.setHeightMode(HeightMode.ROW);
+ grid.setHeightByRows(5.0d);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java
new file mode 100644
index 0000000000..e89057a148
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import com.vaadin.client.connectors.AbstractRendererConnector;
+import com.vaadin.client.renderers.Renderer;
+import com.vaadin.client.widget.grid.RendererCellReference;
+import com.vaadin.shared.ui.Connect;
+
+@Connect(com.vaadin.tests.components.grid.IntArrayRenderer.class)
+public class IntArrayRendererConnector extends AbstractRendererConnector<int[]> {
+
+ public static class IntArrayRenderer implements Renderer<int[]> {
+ private static final String JOINER = " :: ";
+
+ @Override
+ public void render(RendererCellReference cell, int[] data) {
+ String text = "";
+ for (int i : data) {
+ text += i + JOINER;
+ }
+ if (!text.isEmpty()) {
+ text = text.substring(0, text.length() - JOINER.length());
+ }
+ cell.getElement().setInnerText(text);
+ }
+ }
+
+ @Override
+ public IntArrayRenderer getRenderer() {
+ return (IntArrayRenderer) super.getRenderer();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java
new file mode 100644
index 0000000000..e9c126f232
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.DockLayoutPanel;
+import com.google.gwt.user.client.ui.LayoutPanel;
+import com.google.gwt.user.client.ui.MenuBar;
+import com.google.gwt.user.client.ui.Panel;
+import com.vaadin.client.ui.SubPartAware;
+
+/**
+ * Pure GWT Test Application base for testing features of a single widget;
+ * provides a menu system and convenience method for adding items to it.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public abstract class PureGWTTestApplication<T> extends DockLayoutPanel
+ implements SubPartAware {
+
+ /**
+ * Class describing a menu item with an associated action
+ */
+ public static class Command {
+ private final String title;
+ private final ScheduledCommand command;
+
+ /**
+ * Creates a Command object, which is used as an action entry in the
+ * Menu
+ *
+ * @param t
+ * a title string
+ * @param cmd
+ * a scheduled command that is executed when this item is
+ * selected
+ */
+ public Command(String t, ScheduledCommand cmd) {
+ title = t;
+ command = cmd;
+ }
+
+ /**
+ * Returns the title of this command item
+ *
+ * @return a title string
+ */
+ public final String getTitle() {
+ return title;
+ }
+
+ /**
+ * Returns the actual scheduled command of this command item
+ *
+ * @return a scheduled command
+ */
+ public final ScheduledCommand getCommand() {
+ return command;
+ }
+ }
+
+ /**
+ * A menu object, providing a complete system for building a hierarchical
+ * menu bar system.
+ */
+ public static class Menu {
+
+ private final String title;
+ private final MenuBar menubar;
+ private final List<Menu> children;
+ private final List<Command> items;
+
+ /**
+ * Create base-level menu, without a title. This is the root menu bar,
+ * which can be attached to a client application window. All other Menus
+ * should be added as child menus to this Menu, in order to maintain a
+ * nice hierarchy.
+ */
+ private Menu() {
+ title = "";
+ menubar = new MenuBar();
+ children = new ArrayList<Menu>();
+ items = new ArrayList<Command>();
+ }
+
+ /**
+ * Create a sub-menu, with a title.
+ *
+ * @param title
+ */
+ public Menu(String title) {
+ this.title = title;
+ menubar = new MenuBar(true);
+ children = new ArrayList<Menu>();
+ items = new ArrayList<Command>();
+ }
+
+ /**
+ * Return the GWT {@link MenuBar} object that provides the widget for
+ * this Menu
+ *
+ * @return a menubar object
+ */
+ public MenuBar getMenuBar() {
+ return menubar;
+ }
+
+ /**
+ * Returns the title of this menu entry
+ *
+ * @return a title string
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Adds a child menu entry to this menu. The title for this entry is
+ * taken from the Menu object argument.
+ *
+ * @param m
+ * another Menu object
+ */
+ public void addChildMenu(Menu m) {
+ menubar.addItem(m.title, m.menubar);
+ children.add(m);
+ }
+
+ /**
+ * Tests for the existence of a child menu by title at this level of the
+ * menu hierarchy
+ *
+ * @param title
+ * a title string
+ * @return true, if this menu has a direct child menu with the specified
+ * title, otherwise false
+ */
+ public boolean hasChildMenu(String title) {
+ return getChildMenu(title) != null;
+ }
+
+ /**
+ * Gets a reference to a child menu with a certain title, that is a
+ * direct child of this menu level.
+ *
+ * @param title
+ * a title string
+ * @return a Menu object with the specified title string, or null, if
+ * this menu doesn't have a direct child with the specified
+ * title.
+ */
+ public Menu getChildMenu(String title) {
+ for (Menu m : children) {
+ if (m.title.equals(title)) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a command item to the menu. When the entry is clicked, the
+ * command is executed.
+ *
+ * @param cmd
+ * a command object.
+ */
+ public void addCommand(Command cmd) {
+ menubar.addItem(cmd.title, cmd.command);
+ items.add(cmd);
+ }
+
+ /**
+ * Tests for the existence of a {@link Command} that is the direct child
+ * of this level of menu.
+ *
+ * @param title
+ * the command's title
+ * @return true, if this menu level includes a command item with the
+ * specified title. Otherwise false.
+ */
+ public boolean hasCommand(String title) {
+ return getCommand(title) != null;
+ }
+
+ /**
+ * Gets a reference to a {@link Command} item that is the direct child
+ * of this level of menu.
+ *
+ * @param title
+ * the command's title
+ * @return a command, if found in this menu level, otherwise null.
+ */
+ public Command getCommand(String title) {
+ for (Command c : items) {
+ if (c.title.equals(title)) {
+ return c;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Base level menu object, provides visible menu bar
+ */
+ private final Menu menu;
+ private final T testedWidget;
+
+ /**
+ * This constructor creates the basic menu bar and adds it to the top of the
+ * parent {@link DockLayoutPanel}
+ */
+ protected PureGWTTestApplication(T widget) {
+ super(Unit.PX);
+ Panel menuPanel = new LayoutPanel();
+ menu = new Menu();
+ menuPanel.add(menu.getMenuBar());
+ addNorth(menuPanel, 25);
+ testedWidget = widget;
+ }
+
+ /**
+ * Connect an item to the menu structure
+ *
+ * @param cmd
+ * a scheduled command; see google's docs
+ * @param menupath
+ * path to the item
+ */
+ public void addMenuCommand(String title, ScheduledCommand cmd,
+ String... menupath) {
+ Menu m = createMenuPath(menupath);
+
+ m.addCommand(new Command(title, cmd));
+ }
+
+ /**
+ * Create a menu path, if one doesn't already exist, and return the last
+ * menu in the series.
+ *
+ * @param path
+ * a varargs list or array of strings describing a menu path,
+ * e.g. "File", "Recent", "User Files", which would result in the
+ * File menu having a submenu called "Recent" which would have a
+ * submenu called "User Files".
+ * @return the last Menu object specified by the path
+ */
+ private Menu createMenuPath(String... path) {
+ Menu m = menu;
+
+ for (String p : path) {
+ Menu sub = m.getChildMenu(p);
+
+ if (sub == null) {
+ sub = new Menu(p);
+ m.addChildMenu(sub);
+ }
+ m = sub;
+ }
+
+ return m;
+ }
+
+ @Override
+ public Element getSubPartElement(String subPart) {
+ if (testedWidget instanceof SubPartAware) {
+ return ((SubPartAware) testedWidget).getSubPartElement(subPart);
+ }
+ return null;
+ }
+
+ @Override
+ public String getSubPartName(Element subElement) {
+ if (testedWidget instanceof SubPartAware) {
+ return ((SubPartAware) testedWidget).getSubPartName(subElement);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the tested widget.
+ *
+ * @return tested widget
+ */
+ public T getTestedWidget() {
+ return testedWidget;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java
new file mode 100644
index 0000000000..63faf1d651
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client.grid;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import com.google.gwt.dom.client.BrowserEvents;
+import com.google.gwt.dom.client.DivElement;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.user.client.DOM;
+import com.vaadin.client.connectors.AbstractRendererConnector;
+import com.vaadin.client.renderers.ComplexRenderer;
+import com.vaadin.client.renderers.Renderer;
+import com.vaadin.client.widget.grid.CellReference;
+import com.vaadin.client.widget.grid.RendererCellReference;
+import com.vaadin.shared.communication.ServerRpc;
+import com.vaadin.shared.ui.Connect;
+
+import elemental.json.JsonObject;
+
+@Connect(com.vaadin.tests.components.grid.RowAwareRenderer.class)
+public class RowAwareRendererConnector extends AbstractRendererConnector<Void> {
+ public interface RowAwareRendererRpc extends ServerRpc {
+ void clicky(String key);
+ }
+
+ public class RowAwareRenderer extends ComplexRenderer<Void> {
+
+ @Override
+ public Collection<String> getConsumedEvents() {
+ return Arrays.asList(BrowserEvents.CLICK);
+ }
+
+ @Override
+ public void init(RendererCellReference cell) {
+ DivElement div = DivElement.as(DOM.createDiv());
+ div.setAttribute("style",
+ "border: 1px solid red; background: pink;");
+ div.setInnerText("Click me!");
+ cell.getElement().appendChild(div);
+ }
+
+ @Override
+ public void render(RendererCellReference cell, Void data) {
+ // NOOP
+ }
+
+ @Override
+ public boolean onBrowserEvent(CellReference<?> cell, NativeEvent event) {
+ String key = getRowKey((JsonObject) cell.getRow());
+ getRpcProxy(RowAwareRendererRpc.class).clicky(key);
+ cell.getElement().setInnerText(
+ "row: " + cell.getRowIndex() + ", key: " + key);
+ return true;
+ }
+ }
+
+ @Override
+ protected Renderer<Void> createRenderer() {
+ // cannot use the default createRenderer as RowAwareRenderer needs a
+ // reference to its connector - it has no "real" no-argument constructor
+ return new RowAwareRenderer();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java b/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java
new file mode 100644
index 0000000000..1bdbba2c36
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.rebind;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gwt.core.ext.Generator;
+import com.google.gwt.core.ext.GeneratorContext;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
+import com.google.gwt.user.rebind.SourceWriter;
+import com.vaadin.client.metadata.Invoker;
+import com.vaadin.tests.widgetset.client.TestWidgetConnector;
+import com.vaadin.tests.widgetset.client.TestWidgetConnector.TestWidgetRegistry;
+
+public class TestWidgetRegistryGenerator extends Generator {
+
+ @Override
+ public String generate(TreeLogger logger, GeneratorContext context,
+ String typeName) throws UnableToCompleteException {
+
+ try {
+ TypeOracle typeOracle = context.getTypeOracle();
+
+ // get classType and save instance variables
+ JClassType classType = typeOracle.getType(typeName);
+ String packageName = classType.getPackage().getName();
+ String className = classType.getSimpleSourceName() + "Impl";
+
+ // Generate class source code
+ generateClass(packageName, className, logger, context);
+ return packageName + "." + className;
+ } catch (Exception e) {
+ logger.log(TreeLogger.ERROR,
+ "Accept criterion factory creation failed", e);
+ throw new UnableToCompleteException();
+ }
+ // return the fully qualifed name of the class generated
+ }
+
+ private void generateClass(String packageName, String className,
+ TreeLogger logger, GeneratorContext context) {
+ PrintWriter printWriter = context.tryCreate(logger, packageName,
+ className);
+ // print writer if null, source code has ALREADY been generated
+ if (printWriter == null) {
+ return;
+ }
+
+ // init composer, set class properties, create source writer
+ ClassSourceFileComposerFactory composer = null;
+ composer = new ClassSourceFileComposerFactory(packageName, className);
+
+ composer.setSuperclass(TestWidgetRegistry.class.getCanonicalName());
+
+ List<JClassType> testWidgets = findTestWidgets(logger,
+ context.getTypeOracle());
+
+ SourceWriter w = composer.createSourceWriter(context, printWriter);
+
+ w.println("public %s() {", className);
+ w.indent();
+
+ w.println("super();");
+ w.println();
+
+ for (JClassType testWidgetType : testWidgets) {
+ w.println("register(\"%s\", new %s() {",
+ escape(testWidgetType.getQualifiedSourceName()),
+ Invoker.class.getCanonicalName());
+ w.indent();
+
+ w.println("public Object invoke(Object target, Object... params) {");
+ w.indent();
+
+ w.println("return new %s();",
+ testWidgetType.getQualifiedSourceName());
+
+ w.outdent();
+ w.println("}");
+
+ w.outdent();
+ w.println("});");
+ w.println();
+ }
+
+ // Close constructor
+ w.outdent();
+ w.println("}");
+
+ // Close class body
+ w.outdent();
+ w.println("}");
+
+ // commit generated class
+ context.commit(logger, printWriter);
+ }
+
+ private List<JClassType> findTestWidgets(TreeLogger logger,
+ TypeOracle typeOracle) {
+ List<JClassType> testWidgetTypes = new ArrayList<JClassType>();
+
+ JClassType[] widgetTypes = typeOracle.findType(Widget.class.getName())
+ .getSubtypes();
+ for (JClassType widgetType : widgetTypes) {
+ if (isTestWidget(widgetType)) {
+ testWidgetTypes.add(widgetType);
+ }
+ }
+
+ return testWidgetTypes;
+ }
+
+ private boolean isTestWidget(JClassType widgetType) {
+ if (widgetType.isAbstract()) {
+ return false;
+ } else if (!widgetType.getPackage().getName()
+ .startsWith(TestWidgetConnector.class.getPackage().getName())) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/LayoutDetector.java b/uitest/src/com/vaadin/tests/widgetset/server/LayoutDetector.java
new file mode 100644
index 0000000000..4b1aea67ea
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/LayoutDetector.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.server;
+
+import com.vaadin.tests.widgetset.client.NoLayoutRpc;
+import com.vaadin.ui.AbstractComponent;
+
+public class LayoutDetector extends AbstractComponent {
+
+ public void doNoLayoutRpc() {
+ getRpcProxy(NoLayoutRpc.class).doRpc();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/TestWidgetComponent.java b/uitest/src/com/vaadin/tests/widgetset/server/TestWidgetComponent.java
new file mode 100644
index 0000000000..1750e99727
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/TestWidgetComponent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.server;
+
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.TestWidgetConnector;
+import com.vaadin.tests.widgetset.client.TestWidgetConnector.TestWidgetState;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.UI;
+
+/**
+ * Testing component that shows any widget class inside the
+ * com.vaadin.tests.widgetset.client package.
+ */
+public class TestWidgetComponent extends AbstractComponent {
+ private static final String targetPackage = TestWidgetConnector.class
+ .getPackage().getName();
+
+ public TestWidgetComponent(Class<? extends Widget> widgetClass) {
+ String className = widgetClass.getCanonicalName();
+ if (!className.startsWith(targetPackage)) {
+ throw new IllegalArgumentException(
+ "Widget class must be inside the " + targetPackage
+ + " package");
+ }
+
+ getState().widgetClass = className;
+ setSizeFull();
+ }
+
+ @Override
+ public void attach() {
+ super.attach();
+
+ Class<? extends UI> uiClass = getUI().getClass();
+
+ Widgetset widgetset = uiClass.getAnnotation(Widgetset.class);
+ if (widgetset == null
+ || !widgetset.value().equals(TestingWidgetSet.NAME)) {
+ throw new IllegalStateException("You must add @"
+ + Widgetset.class.getSimpleName() + "("
+ + TestingWidgetSet.class.getSimpleName() + ".NAME) to "
+ + uiClass.getSimpleName());
+ }
+ }
+
+ @Override
+ protected TestWidgetState getState() {
+ return (TestWidgetState) super.getState();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/grid/GridClientColumnRenderers.java b/uitest/src/com/vaadin/tests/widgetset/server/grid/GridClientColumnRenderers.java
new file mode 100644
index 0000000000..ce260f108d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/grid/GridClientColumnRenderers.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.server.grid;
+
+import java.util.Arrays;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererConnector.Renderers;
+import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererRpc;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.NativeSelect;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class GridClientColumnRenderers extends UI {
+
+ /**
+ * Controls the grid on the client side
+ */
+ public static class GridController extends AbstractComponent {
+
+ private GridClientColumnRendererRpc rpc() {
+ return getRpcProxy(GridClientColumnRendererRpc.class);
+ }
+
+ /**
+ * Adds a new column with a renderer to the grid.
+ */
+ public void addColumn(Renderers renderer) {
+ rpc().addColumn(renderer);
+ }
+
+ /**
+ * Tests detaching and attaching grid
+ */
+ public void detachAttach() {
+ rpc().detachAttach();
+ }
+
+ /**
+ * @since
+ */
+ public void triggerClientSorting() {
+ rpc().triggerClientSorting();
+ }
+
+ /**
+ * @since
+ */
+ public void triggerClientSortingTest() {
+ rpc().triggerClientSortingTest();
+ }
+
+ /**
+ * @since
+ */
+ public void shuffle() {
+ rpc().shuffle();
+ }
+ }
+
+ @Override
+ protected void init(VaadinRequest request) {
+ final GridController controller = new GridController();
+ final CssLayout controls = new CssLayout();
+ final VerticalLayout content = new VerticalLayout();
+
+ content.addComponent(controller);
+ content.addComponent(controls);
+ setContent(content);
+
+ final NativeSelect select = new NativeSelect(
+ "Add Column with Renderer", Arrays.asList(Renderers.values()));
+ select.setItemCaptionMode(ItemCaptionMode.EXPLICIT);
+ for (Renderers renderer : Renderers.values()) {
+ select.setItemCaption(renderer, renderer.toString());
+ }
+ select.setValue(Renderers.TEXT_RENDERER);
+ select.setNullSelectionAllowed(false);
+ controls.addComponent(select);
+
+ NativeButton addColumnBtn = new NativeButton("Add");
+ addColumnBtn.addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ Renderers renderer = (Renderers) select.getValue();
+ controller.addColumn(renderer);
+ }
+ });
+ controls.addComponent(addColumnBtn);
+
+ NativeButton detachAttachBtn = new NativeButton("DetachAttach");
+ detachAttachBtn.addClickListener(new ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ controller.detachAttach();
+ }
+ });
+ controls.addComponent(detachAttachBtn);
+
+ NativeButton shuffleButton = new NativeButton("Shuffle");
+ shuffleButton.addClickListener(new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ controller.shuffle();
+ }
+ });
+ controls.addComponent(shuffleButton);
+
+ NativeButton sortButton = new NativeButton("Trigger sorting event");
+ sortButton.addClickListener(new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ controller.triggerClientSorting();
+ }
+ });
+ controls.addComponent(sortButton);
+
+ NativeButton testSortingButton = new NativeButton("Test sorting");
+ testSortingButton.addClickListener(new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ controller.triggerClientSortingTest();
+ }
+ });
+ controls.addComponent(testSortingButton);
+
+ Label console = new Label();
+ console.setContentMode(ContentMode.HTML);
+ console.setId("testDebugConsole");
+ content.addComponent(console);
+ }
+}