diff options
author | Artur Signell <artur@vaadin.com> | 2013-09-26 09:28:50 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2013-09-26 09:28:50 +0300 |
commit | c18b20050d6b04a2c69b3fdfc75ca901b78edc0a (patch) | |
tree | 1d91200782aa20a4fcf331bb0f773070c7cd080a | |
parent | 7c5bdce3b4c76e7f19bc46bcaed135d67a94f06a (diff) | |
parent | bd0ae0581f265be57374b236cfe1b71043ab69aa (diff) | |
download | vaadin-framework-c18b20050d6b04a2c69b3fdfc75ca901b78edc0a.tar.gz vaadin-framework-c18b20050d6b04a2c69b3fdfc75ca901b78edc0a.zip |
Merge changes from origin/7.1
7f7dc31 Base files for TB3 tests (#12572)
6b17abe Make it possible to override web driver in tests (#12572)
a682e3b Refactored build scripts to support TB2, TB3 + integration tests (#12572)
e556642 Converted servlet integration tests to TB3 (#12573)
21af0c3 Updated TB3 tests to use Firefox 24 (#12604)
a7583c6 TB3 test for browsers (#12572)
37b8543 Do not add empty package javadoc for new classes
0248b8f Fixes browser detection for IE11 (#12638)
1df28c3 Run TB3 tests also on IE11 (#12631)
a2daf65 Converted TB2 push tests to TB3 (#12580)
d3261d7 Fixes issue with Table not scrolling completely to the end #12651
bd0ae05 Limit the number of tests run concurrently (#12572)
Change-Id: Idb4389aac388b728490a4ffd57d30aee20ea9fe8
53 files changed, 3137 insertions, 831 deletions
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs index 31240a63bd..4f3b6f7ed3 100644 --- a/.settings/org.eclipse.jdt.ui.prefs +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -3,7 +3,7 @@ editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_Vaadin Java Conventions 20110923 formatter_settings_version=12 org.eclipse.jdt.ui.javadoc=true -org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * \n * @since \n * @author Vaadin Ltd\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * @since\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">/*\n * Copyright 2000-2013 Vaadin Ltd.\n * \n * Licensed under the Apache License, Version 2.0 (the "License"); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n * \n * http\://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n\n${filecomment}\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates> +org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\n * @return the ${bare_field_name}\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\n * @param ${param} the ${bare_field_name} to set\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\n * ${tags}\n */</template><template autoinsert\="false" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/**\n * \n */</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\n * \n * @since \n * @author Vaadin Ltd\n * ${tags}\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\n * \n */</template><template autoinsert\="false" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\n * @since\n * ${tags}\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\n * ${tags}\n * ${see_to_target}\n */</template><template autoinsert\="false" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">/*\n * Copyright 2000-2013 Vaadin Ltd.\n * \n * Licensed under the Apache License, Version 2.0 (the "License"); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n * \n * http\://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates> sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false sp_cleanup.add_missing_annotations=true @@ -43,19 +43,16 @@ <target name="test" depends="buildorder"> <subant buildpathref="build-path" target="test" /> </target> + <target name="test-all" depends="buildorder"> <property name="war.file" location="result/artifacts/${vaadin.version}/vaadin-uitest/vaadin-uitest-${vaadin.version}.war" /> + <parallel> - <sequential> - <!-- Sleep before running integration tests so testbench - tests have time to compile and start --> - <sleep minutes="4" /> - <ant antfile="uitest/integration_tests.xml" target="integration-test-all" inheritall="false" inheritrefs="false"> - <property name="demo.war" value="${war.file}" /> - </ant> - </sequential> + <!-- JUnit tests, can be run without a server --> <subant buildpathref="build-path" target="test" /> - <ant antfile="uitest/test.xml" target="test-package"> + + <!-- Server deployment + TestBench tests --> + <ant antfile="uitest/build.xml" target="test-testbench"> <property name="war.file" location="${war.file}" /> </ant> </parallel> diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 3733ee204a..492730259a 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -176,6 +176,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private int firstRowInViewPort = 0; private int pageLength = 15; private int lastRequestedFirstvisible = 0; // to detect "serverside scroll" + private int firstvisibleOnLastPage = -1; // To detect if the first visible + // is on the last page /** For internal use only. May be removed or replaced in the future. */ public boolean showRowHeaders = false; @@ -1111,8 +1113,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private ScheduledCommand lazyScroller = new ScheduledCommand() { @Override public void execute() { - int offsetTop = measureRowHeightOffset(firstvisible); - scrollBodyPanel.setScrollPosition(offsetTop); + if (firstvisibleOnLastPage > -1) { + scrollBodyPanel + .setScrollPosition(measureRowHeightOffset(firstvisibleOnLastPage)); + } else { + scrollBodyPanel + .setScrollPosition(measureRowHeightOffset(firstvisible)); + } + firstRowInViewPort = firstvisible; } }; @@ -1120,6 +1128,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, public void updateFirstVisibleAndScrollIfNeeded(UIDL uidl) { firstvisible = uidl.hasVariable("firstvisible") ? uidl .getIntVariable("firstvisible") : 0; + firstvisibleOnLastPage = uidl.hasVariable("firstvisibleonlastpage") ? uidl + .getIntVariable("firstvisibleonlastpage") : -1; if (firstvisible != lastRequestedFirstvisible && scrollBody != null) { // received 'surprising' firstvisible from server: scroll there firstRowInViewPort = firstvisible; @@ -2150,18 +2160,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, isNewBody = false; - if (firstvisible > 0) { - // Deferred due to some Firefox oddities - Scheduler.get().scheduleDeferred(new Command() { - - @Override - public void execute() { - scrollBodyPanel - .setScrollPosition(measureRowHeightOffset(firstvisible)); - firstRowInViewPort = firstvisible; - } - }); - } + Scheduler.get().scheduleFinally(lazyScroller); if (enabled) { // Do we need cache rows diff --git a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java index 7d5911f5a0..5b428574e2 100644 --- a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java +++ b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java @@ -27,6 +27,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { private static final String IE9_BETA_WINDOWS_7 = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"; private static final String IE10_WINDOWS_8 = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"; + private static final String IE11_WINDOWS_7 = "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; rv:11.0) like Gecko"; // "Version/" was added in 10.00 private static final String OPERA964_WINDOWS = "Opera/9.64(Windows NT 5.1; U; en) Presto/2.1.1"; @@ -314,6 +315,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { public void testIE8() { VBrowserDetails bd = new VBrowserDetails(IE8_WINDOWS); + assertTrident(bd); assertEngineVersion(bd, 4); assertIE(bd); assertBrowserMajorVersion(bd, 8); @@ -325,6 +327,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { VBrowserDetails bd = new VBrowserDetails(IE8_IN_IE7_MODE_WINDOWS); bd.setIEMode(7); + assertTrident(bd); assertEngineVersion(bd, 4); assertIE(bd); assertBrowserMajorVersion(bd, 7); @@ -335,6 +338,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { public void testIE9() { VBrowserDetails bd = new VBrowserDetails(IE9_BETA_WINDOWS_7); + assertTrident(bd); assertEngineVersion(bd, 5); assertIE(bd); assertBrowserMajorVersion(bd, 9); @@ -346,6 +350,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { VBrowserDetails bd = new VBrowserDetails(IE9_IN_IE7_MODE_WINDOWS_7); // bd.setIE8InCompatibilityMode(); + assertTrident(bd); assertEngineVersion(bd, 5); assertIE(bd); assertBrowserMajorVersion(bd, 7); @@ -362,6 +367,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { * Trident/4.0 in example user agent string based on beta even though it * should be Trident/5.0 in real (non-beta) user agent strings */ + assertTrident(bd); assertEngineVersion(bd, 4); assertIE(bd); assertBrowserMajorVersion(bd, 8); @@ -372,6 +378,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { public void testIE10() { VBrowserDetails bd = new VBrowserDetails(IE10_WINDOWS_8); + assertTrident(bd); assertEngineVersion(bd, 6); assertIE(bd); assertBrowserMajorVersion(bd, 10); @@ -379,6 +386,16 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertWindows(bd); } + public void testIE11() { + VBrowserDetails bd = new VBrowserDetails(IE11_WINDOWS_7); + assertTrident(bd); + assertEngineVersion(bd, 7); + assertIE(bd); + assertBrowserMajorVersion(bd, 11); + assertBrowserMinorVersion(bd, 0); + assertWindows(bd); + } + /* * Helper methods below */ @@ -406,6 +423,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertTrue(browserDetails.isGecko()); assertFalse(browserDetails.isWebKit()); assertFalse(browserDetails.isPresto()); + assertFalse(browserDetails.isTrident()); } private void assertPresto(VBrowserDetails browserDetails) { @@ -413,6 +431,15 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertFalse(browserDetails.isGecko()); assertFalse(browserDetails.isWebKit()); assertTrue(browserDetails.isPresto()); + assertFalse(browserDetails.isTrident()); + } + + private void assertTrident(VBrowserDetails browserDetails) { + // Engine + assertFalse(browserDetails.isGecko()); + assertFalse(browserDetails.isWebKit()); + assertFalse(browserDetails.isPresto()); + assertTrue(browserDetails.isTrident()); } private void assertWebKit(VBrowserDetails browserDetails) { @@ -420,6 +447,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertFalse(browserDetails.isGecko()); assertTrue(browserDetails.isWebKit()); assertFalse(browserDetails.isPresto()); + assertFalse(browserDetails.isTrident()); } private void assertFirefox(VBrowserDetails browserDetails) { diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index bd2b7828de..32ed738697 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -427,6 +427,12 @@ public class Table extends AbstractSelect implements Action.Container, private int currentPageFirstItemIndex = 0; /** + * Index of the "first" item on the last page if a user has used + * setCurrentPageFirstItemIndex to scroll down. -1 if not set. + */ + private int currentPageFirstItemIndexOnLastPage = -1; + + /** * Holds value of property selectable. */ private boolean selectable = false; @@ -1477,12 +1483,14 @@ public class Table extends AbstractSelect implements Action.Container, } /* - * FIXME #7607 Take somehow into account the case where we want to - * scroll to the bottom so that the last row is completely visible even - * if (table height) / (row height) is not an integer. Reverted the - * original fix because of #8662 regression. + * If the new index is on the last page we set the index to be the first + * item on that last page and make a note of the real index for the + * client side to be able to move the scroll position to the correct + * position. */ + int indexOnLastPage = -1; if (newIndex > maxIndex) { + indexOnLastPage = newIndex; newIndex = maxIndex; } @@ -1494,6 +1502,20 @@ public class Table extends AbstractSelect implements Action.Container, currentPageFirstItemId = null; } currentPageFirstItemIndex = newIndex; + + if (needsPageBufferReset) { + /* + * The flag currentPageFirstItemIndexOnLastPage denotes a user + * set scrolling position on the last page via + * setCurrentPageFirstItemIndex() and shouldn't be changed by + * the table component internally changing the firstvisible item + * on lazy row fetching. Doing so would make the scrolling + * position not be updated correctly when the lazy rows are + * finally rendered. + */ + currentPageFirstItemIndexOnLastPage = indexOnLastPage; + } + } else { // For containers not supporting indexes, we must iterate the @@ -3447,6 +3469,8 @@ public class Table extends AbstractSelect implements Action.Container, if (getCurrentPageFirstItemIndex() != 0 || getPageLength() > 0) { target.addVariable(this, "firstvisible", getCurrentPageFirstItemIndex()); + target.addVariable(this, "firstvisibleonlastpage", + currentPageFirstItemIndexOnLastPage); } } diff --git a/shared/src/com/vaadin/shared/VBrowserDetails.java b/shared/src/com/vaadin/shared/VBrowserDetails.java index f31f5f3c04..a745a212b0 100644 --- a/shared/src/com/vaadin/shared/VBrowserDetails.java +++ b/shared/src/com/vaadin/shared/VBrowserDetails.java @@ -31,6 +31,7 @@ public class VBrowserDetails implements Serializable { private boolean isGecko = false; private boolean isWebKit = false; private boolean isPresto = false; + private boolean isTrident = false; private boolean isChromeFrameCapable = false; private boolean isChromeFrame = false; @@ -65,9 +66,11 @@ public class VBrowserDetails implements Serializable { // browser engine name isGecko = userAgent.indexOf("gecko") != -1 - && userAgent.indexOf("webkit") == -1; + && userAgent.indexOf("webkit") == -1 + && userAgent.indexOf("trident/") == -1; isWebKit = userAgent.indexOf("applewebkit") != -1; isPresto = userAgent.indexOf(" presto/") != -1; + isTrident = userAgent.indexOf("trident/") != -1; // browser name isChrome = userAgent.indexOf(" chrome/") != -1; @@ -75,6 +78,9 @@ public class VBrowserDetails implements Serializable { isOpera = userAgent.indexOf("opera") != -1; isIE = userAgent.indexOf("msie") != -1 && !isOpera && (userAgent.indexOf("webtv") == -1); + // IE 11 no longer contains MSIE in the user agent + isIE = isIE || isTrident; + isFirefox = userAgent.indexOf(" firefox/") != -1; // chromeframe @@ -113,11 +119,21 @@ public class VBrowserDetails implements Serializable { // Browser version try { if (isIE) { - String ieVersionString = userAgent.substring(userAgent - .indexOf("msie ") + 5); - ieVersionString = safeSubstring(ieVersionString, 0, - ieVersionString.indexOf(";")); - parseVersionString(ieVersionString); + if (userAgent.indexOf("msie") == -1) { + // IE 11+ + int rvPos = userAgent.indexOf("rv:"); + if (rvPos >= 0) { + String tmp = userAgent.substring(rvPos + 3); + tmp = tmp.replaceFirst("(\\.[0-9]+).+", "$1"); + parseVersionString(tmp); + } + } else { + String ieVersionString = userAgent.substring(userAgent + .indexOf("msie ") + 5); + ieVersionString = safeSubstring(ieVersionString, 0, + ieVersionString.indexOf(";")); + parseVersionString(ieVersionString); + } } else if (isFirefox) { int i = userAgent.indexOf(" firefox/") + 9; parseVersionString(safeSubstring(userAgent, i, i + 5)); @@ -288,6 +304,16 @@ public class VBrowserDetails implements Serializable { } /** + * Tests if the browser is using the Trident engine + * + * @since 7.1.7 + * @return true if it is Trident, false otherwise + */ + public boolean isTrident() { + return isTrident; + } + + /** * Tests if the browser is Safari. * * @return true if it is Safari, false otherwise diff --git a/uitest/build.xml b/uitest/build.xml index bd0f49ae1e..76b75e9203 100644 --- a/uitest/build.xml +++ b/uitest/build.xml @@ -9,6 +9,7 @@ <!-- global properties --> <property name="module.name" value="vaadin-uitest" /> + <property name="uitest.dir" location="${vaadin.basedir}/uitest" /> <property name="result.dir" value="result" /> <property name="result.war" location="${result.dir}/lib/${module.name}-${vaadin.version}.war" /> @@ -107,6 +108,11 @@ <path refid="classpath.runtime.dependencies" /> </copy> + <delete> + <!-- 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" /> @@ -148,4 +154,53 @@ <echo>WHAT? No JUnit tests for ${module.name}!</echo> </target> + <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" /> + </daemons> + <sequential> + <!-- Server tests --> + + <!-- 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"> + <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" /> + + <!-- Run all different kinds of TestBench tests in parallel --> + <parallel> + + <!-- Legacy TestBench 2 tests --> + <sequential> + <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" /> + <echo message="TestBench 3 tests complete" /> + </sequential> + </parallel> + </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" /> + <mkdir dir="${com.vaadin.testbench.screenshot.directory}/errors" /> + <delete> + <fileset dir="${com.vaadin.testbench.screenshot.directory}/errors"> + <include name="*" /> + </fileset> + </delete> + </target> + </project> diff --git a/uitest/eclipse-run-selected-test.properties b/uitest/eclipse-run-selected-test.properties index f6cb2551e9..cbd1ab1cef 100644 --- a/uitest/eclipse-run-selected-test.properties +++ b/uitest/eclipse-run-selected-test.properties @@ -1,14 +1,23 @@ -; Location where vaadin-testbench jar can be found -com.vaadin.testbench.lib.dir=<enter location of testbench here> - -; Deployment url to use for testing. Context path must be / -com.vaadin.testbench.deployment.url=http://<enter your ip here>:8888/ +; +; For both TestBench 2 and 3 +; ; Location of the screenshot directory. ; This is the directory that contains the "references" directory com.vaadin.testbench.screenshot.directory=<enter the full path to the screenshots directory, parent of "references" directory> -; Run the whole test even if + +; +; For only TestBench 2 +; + +; Location where TestBench 2 jar can be found +com.vaadin.testbench.lib.dir=<enter location of testbench here> + +; Deployment url to use for testing. Context path must be / +com.vaadin.testbench.deployment.url=http://<enter your ip here>:8888/ + +; Run the whole test even if a screenshot comparison fails com.vaadin.testbench.screenshot.softfail=true ; Screen capture at the end if the test fails @@ -23,7 +32,8 @@ com.vaadin.testbench.screenshot.cursor=true ; Uncomment to limit to certain browsers or override in launch configuration ; browsers=winxp-opera10 -; Claim that the server has started succesfully. Needed for the tests to run +; Claim that the server has started succesfully. Needed for TB2 tests to be executed server.start.succeeded=1 -test-output-dir=../build/test-output
\ No newline at end of file +; Directory where temporary Java classes are created +test-output-dir=../build/test-output diff --git a/uitest/integration_tests.xml b/uitest/integration_tests.xml index 78e053991e..f1b2070bc8 100644 --- a/uitest/integration_tests.xml +++ b/uitest/integration_tests.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> -<project xmlns:antcontrib="antlib:net.sf.antcontrib" name="Vaadin Integration Tests" basedir="." default="integration-test-all"> +<project xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:ivy="antlib:org.apache.ivy.ant" name="Vaadin Integration Tests" basedir="." default="integration-test-all"> <!-- Import common targets --> <import file="../common.xml" /> @@ -32,33 +32,22 @@ <property name="user" value="${test.integration.user}" /> <property name="passphrase" value="" /> + <ivy:resolve file="ivy.xml" conf="build, build-provided" /> + <ivy:cachepath pathid="classpath.tb3.lib" conf="build, build-provided" /> + <path id="classpath.tb3"> + <path refid="classpath.tb3.lib" /> + <path location="result/classes" /> + </path> + <!-- Upload war to deploy to ssh host --> <target name="integration-test-upload-demo"> <scp file="${demo.war}" todir="${user}@${test.integration.server}:integration-tests/servers/demo.war" keyfile="${sshkey.file}" passphrase="${passphrase}" /> </target> <!-- Run basic integration test test --> - <target name="integration-test-servlet"> - <fileset dir="integration-testscripts" id="html-test-files" includes="integration-test-${server-name}-servlet.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - <subant target="run-tests" failonerror="false" antfile="test.xml"> - <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> - <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> - <property name="com.vaadin.testbench.deployment.url" value="${deployment.url}" /> - <property name="server.start.succeeded" value="1" /> - <property name="browsers" value="${test_browsers}" /> - <property name="testfiles" value="${testfiles}" /> - <property name="test-output-dir" value="${integration_test.dir}/result/integration-test-output/${server-name}" /> - <property name="retries" value="0" /> - - <fileset dir="." includes="test.xml" /> - </subant> - </target> - - <target name="integration-test-push-servlet"> - <fileset dir="integration-testscripts" id="html-test-files" includes="integration-test-${server-name}-push-servlet.html" /> - <pathconvert pathsep=" " property="testfiles" refid="html-test-files" /> - <subant target="run-tests" failonerror="false" antfile="test.xml"> + <target name="legacy-integration-test"> + <fail unless="testfiles" message="You need to specify the files to run using the 'testfiles' property" /> + <subant target="run-tb2-tests" failonerror="false" antfile="test.xml"> <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> <property name="com.vaadin.testbench.deployment.url" value="${deployment.url}" /> @@ -73,7 +62,7 @@ </target> <target name="integration-test-theme"> - <subant target="run-tests" failonerror="false" antfile="test.xml"> + <subant target="run-tb2-tests" failonerror="false" antfile="test.xml"> <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> <property name="com.vaadin.testbench.deployment.url" value="${deployment.url}" /> @@ -90,7 +79,7 @@ <fileset dir="integration-testscripts" id="html-test-files" includes="GoogleAppEngine/integration-test-GAE.html" /> <pathconvert pathsep=" " property="test-GAE" refid="html-test-files" /> - <subant target="run-tests" failonerror="false" antfile="test.xml"> + <subant target="run-tb2-tests" failonerror="false" antfile="test.xml"> <property name="com.vaadin.testbench.lib.dir" value="${com.vaadin.testbench.lib.dir}" /> <property name="com.vaadin.testbench.tester.host" value="${com.vaadin.testbench.tester.host}" /> <property name="com.vaadin.testbench.deployment.url" value="http://vaadin-integration-test.appspot.com/" /> @@ -107,6 +96,27 @@ <sshexec host="${test.integration.server}" username="${user}" keyfile="${sshkey.file}" command="ant -f ${ant.hub} deploy-to-GAE" /> </target> + <target name="run-tb3-servlet-test"> + <antcall target="run-tb3-test" inheritall="true"> + <param name="junit.test.suite" value="com.vaadin.tests.tb3.ServletIntegrationTests" /> + </antcall> + </target> + <target name="run-tb3-test"> + <fail unless="server-name" message="Server name must be defined in server-name" /> + <fail unless="deployment.url" message="Deplyoment url must be defined in deployment.url" /> + <fail unless="com.vaadin.testbench.screenshot.directory" message="Screenshot directory must be defined in com.vaadin.testbench.screenshot.directory" /> + + <junit printsummary="withOutAndErr" fork="yes"> + <formatter usefile="false" type="plain" /> + <classpath refid="classpath.tb3" /> + + <jvmarg value="-Dcom.vaadin.testbench.screenshot.directory=${com.vaadin.testbench.screenshot.directory}" /> + <jvmarg value="-Ddeployment.url=${deployment.url}" /> + <jvmarg value="-Dserver-name=${server-name}" /> + <jvmarg value="-Djava.awt.headless=true" /> + <test name="${junit.test.suite}" /> + </junit> + </target> <target name="integration-test-tomcat7"> <antcall target="run-generic-integration-test"> @@ -333,7 +343,7 @@ <!-- Upload demo, clean error screenshots and test deployment on all servers --> - <target name="integration-test-all"> + <target name="integration-test-all" unless="tests.integration.skip"> <property name="passphrase" value="${passphrase}" /> <fail unless="sshkey.file" message="You must define an ssh.keyfile parameter" /> <fail unless="com.vaadin.testbench.screenshot.directory" message="You must define a com.vaadin.testbench.screenshot.directory parameter" /> @@ -341,7 +351,8 @@ <antcontrib:trycatch property="tried"> <try> <!-- Still running GAE test from the old server which - requires its own lock --> + requires its own lock --> + <echo message="Getting lock" /> <antcall target="integration-test-get-lock" /> <echo message="Got lock" /> @@ -387,7 +398,6 @@ <antcall target="integration-test-tomcat6" /> <antcall target="integration-test-tomcat7" /> <antcall target="integration-test-websphere8" /> - </parallel> </target> @@ -446,31 +456,24 @@ </condition> </fail> - <copy file="integration-testscripts/common/integration_test.tpl" tofile="integration-testscripts/integration-test-${target-server}-servlet.html" overwrite="true" /> - <antcall target="integration-test-servlet"> - <param name="server-name" value="${target-server}" /> - <param name="deployment.url" value="http://${target-host}:${target-port}" /> - </antcall> - - <!-- Run theme tests in all browsers if there's a property - with the test files --> <antcontrib:if> - <isset property="testfiles-theme" /> + <isset property="testfiles" /> <antcontrib:then> - <antcall target="integration-test-theme"> + <echo>Starting legacy (TB2) test for ${target-server}</echo> + <antcall target="legacy-integration-test"> <param name="server-name" value="${target-server}" /> <param name="deployment.url" value="http://${target-host}:${target-port}" /> </antcall> </antcontrib:then> + <antcontrib:else> + <echo>Starting TB3 test for ${target-server}</echo> + <antcall target="run-tb3-servlet-test"> + <param name="server-name" value="${target-server}" /> + <param name="deployment.url" value="http://${target-host}:${target-port}" /> + </antcall> + </antcontrib:else> </antcontrib:if> - <!-- Run integration tests with push --> - <copy file="integration-testscripts/common/integration_push_test.tpl" tofile="integration-testscripts/integration-test-${target-server}-push-servlet.html" overwrite="true" /> - <antcall target="integration-test-push-servlet"> - <param name="server-name" value="${target-server}" /> - <param name="deployment.url" value="http://${target-host}:${target-port}" /> - </antcall> - <!-- Run theme tests in all browsers if there's a property with the test files --> <antcontrib:if> diff --git a/uitest/src/com/vaadin/tests/VerifyBrowserVersion.java b/uitest/src/com/vaadin/tests/VerifyBrowserVersion.java index 022a343196..59663a78d6 100644 --- a/uitest/src/com/vaadin/tests/VerifyBrowserVersion.java +++ b/uitest/src/com/vaadin/tests/VerifyBrowserVersion.java @@ -1,17 +1,65 @@ package com.vaadin.tests; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.remote.DesiredCapabilities; + import com.vaadin.server.WebBrowser; import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.tb3.MultiBrowserTest; import com.vaadin.ui.Label; public class VerifyBrowserVersion extends TestBase { + public static class BrowserVersionTest extends MultiBrowserTest { + + private Map<DesiredCapabilities, String> expectedUserAgent = new HashMap<DesiredCapabilities, String>(); + + { + expectedUserAgent + .put(BrowserUtil.firefox(24), + "Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0"); + expectedUserAgent + .put(BrowserUtil.ie(8), + "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"); + expectedUserAgent + .put(BrowserUtil.ie(9), + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"); + expectedUserAgent + .put(BrowserUtil.ie(10), + "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"); + expectedUserAgent + .put(BrowserUtil.chrome(29), + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36"); + expectedUserAgent + .put(BrowserUtil.opera(12), + "Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.15"); + + } + + @Test + public void verifyUserAgent() { + Assert.assertEquals( + expectedUserAgent.get(getDesiredCapabilities()), + vaadinElementById("userAgent").getText()); + Assert.assertEquals("Touch device? No", + vaadinElementById("touchDevice").getText()); + } + } + @Override protected void setup() { WebBrowser browser = getBrowser(); - addComponent(new Label(browser.getBrowserApplication())); - addComponent(new Label("Touch device? " - + (browser.isTouchDevice() ? "YES" : "No"))); + Label userAgent = new Label(browser.getBrowserApplication()); + userAgent.setId("userAgent"); + addComponent(userAgent); + Label touchDevice = new Label("Touch device? " + + (browser.isTouchDevice() ? "YES" : "No")); + touchDevice.setId("touchDevice"); + addComponent(touchDevice); } @Override diff --git a/uitest/src/com/vaadin/tests/components/label/LabelModes.html b/uitest/src/com/vaadin/tests/components/label/LabelModes.html deleted file mode 100644 index 356688b456..0000000000 --- a/uitest/src/com/vaadin/tests/components/label/LabelModes.html +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.label.LabelModes?restartApplication</td> - <td></td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td>labelmodes</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/label/LabelModes.java b/uitest/src/com/vaadin/tests/components/label/LabelModes.java index e5bc539f36..1959447a4b 100644 --- a/uitest/src/com/vaadin/tests/components/label/LabelModes.java +++ b/uitest/src/com/vaadin/tests/components/label/LabelModes.java @@ -2,10 +2,19 @@ package com.vaadin.tests.components.label; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.tests.components.ComponentTestCase; +import com.vaadin.tests.tb3.SimpleMultiBrowserTest; import com.vaadin.ui.Label; public class LabelModes extends ComponentTestCase<Label> { + public static class LabelModesTest extends SimpleMultiBrowserTest { + @Override + public void test() throws Exception { + compareScreen("labelmodes"); + } + + } + @Override protected Class<Label> getTestClass() { return Label.class; diff --git a/uitest/src/com/vaadin/tests/push/PushFromInit.html b/uitest/src/com/vaadin/tests/components/table/ShowLastItem.html index d009eb3baf..c9c93198fa 100644 --- a/uitest/src/com/vaadin/tests/push/PushFromInit.html +++ b/uitest/src/com/vaadin/tests/components/table/ShowLastItem.html @@ -3,7 +3,6 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head profile="http://selenium-ide.openqa.org/profiles/test-case"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> <title>New Test</title> </head> <body> @@ -12,19 +11,24 @@ <tr><td rowspan="1" colspan="3">New Test</td></tr> </thead><tbody> <tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.push.PushFromInit?debug&restartApplication</td> - <td></td> + <td>open</td> + <td>/run/com.vaadin.tests.components.table.ShowLastItem?restartApplication</td> + <td></td> </tr> <tr> - <td>waitForText</td> - <td>vaadin=runpushcomvaadintestspushPushFromInit::PID_SLog_row_1</td> - <td>1. Logged in init</td> + <td>click</td> + <td>vaadin=runcomvaadintestscomponentstableShowLastItem::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> </tr> <tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushPushFromInit::PID_SLog_row_0</td> - <td>2. Logged from background thread started in init</td> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>row-20-fully-visible</td> </tr> </tbody></table> diff --git a/uitest/src/com/vaadin/tests/components/table/ShowLastItem.java b/uitest/src/com/vaadin/tests/components/table/ShowLastItem.java new file mode 100644 index 0000000000..6d6f744918 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/ShowLastItem.java @@ -0,0 +1,66 @@ +package com.vaadin.tests.components.table; + +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.Table; + +public class ShowLastItem extends AbstractTestUI { + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + final Table table = new Table(); + table.setHeight("210px"); + + table.addContainerProperty("Col", String.class, ""); + + for (int i = 0; i < 20; i++) { + table.addItem(i).getItemProperty("Col") + .setValue("row " + String.valueOf(i)); + } + + Button addItemBtn = new Button("Add item", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + Object itemId = "row " + table.getItemIds().size(); + + table.addItem(itemId).getItemProperty("Col") + .setValue(String.valueOf(itemId)); + + table.setCurrentPageFirstItemIndex(table.getItemIds().size() - 1); + } + }); + + addComponent(table); + addComponent(addItemBtn); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Show last item in Table by using setCurrentPageFirstItemId"; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 12407; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/ui/UiAccess.java b/uitest/src/com/vaadin/tests/components/ui/UIAccess.java index 09f2fd8816..057dcaa917 100644 --- a/uitest/src/com/vaadin/tests/components/ui/UiAccess.java +++ b/uitest/src/com/vaadin/tests/components/ui/UIAccess.java @@ -21,17 +21,48 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; + import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinSession; import com.vaadin.shared.communication.PushMode; import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.tests.tb3.MultiBrowserTest; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.UI; import com.vaadin.util.CurrentInstance; -public class UiAccess extends AbstractTestUIWithLog { +public class UIAccess extends AbstractTestUIWithLog { + + public static class UIAccessTest extends MultiBrowserTest { + @Override + protected boolean isPushEnabled() { + return true; + } + + @Test + public void testThreadLocals() { + getCurrentInstanceWhenPushingButton().click(); + waitUntil(ExpectedConditions.textToBePresentInElement( + vaadinLocatorById("Log_row_0"), "1.")); + Assert.assertEquals( + "0. Current UI matches in beforeResponse? true", + vaadinElementById("Log_row_1").getText()); + Assert.assertEquals( + "1. Current session matches in beforeResponse? true", + vaadinElementById("Log_row_0").getText()); + + } + + private WebElement getCurrentInstanceWhenPushingButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[7]/VButton[0]"); + } + } private volatile boolean checkCurrentInstancesBeforeResponse = false; diff --git a/uitest/src/com/vaadin/tests/components/ui/UiAccessPush.html b/uitest/src/com/vaadin/tests/components/ui/UiAccessPush.html deleted file mode 100644 index bc29534ee4..0000000000 --- a/uitest/src/com/vaadin/tests/components/ui/UiAccessPush.html +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.components.ui.UiAccess?restartApplication&transport=websocket</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runcomvaadintestscomponentsuiUiAccess::/VVerticalLayout[0]/Slot[2]/VVerticalLayout[0]/Slot[7]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>waitForNotText</td> - <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_0</td> - <td>exact:1. Current session matches in beforeResponse? true</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestscomponentsuiUiAccess::PID_SLog_row_1</td> - <td>exact:0. Current UI matches in beforeResponse? true</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/integration/AbstractIntegrationTestTB3.java b/uitest/src/com/vaadin/tests/integration/AbstractIntegrationTestTB3.java new file mode 100644 index 0000000000..e170450619 --- /dev/null +++ b/uitest/src/com/vaadin/tests/integration/AbstractIntegrationTestTB3.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2013 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.integration; + +import java.util.Collection; +import java.util.Collections; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized.Parameters; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.tb3.PrivateTB3Configuration; + +/** + * Base class for integration tests. Integration tests use the + * {@literal deployment.url} parameter to determine the base deployment url + * (http://hostname:123) + * + * @author Vaadin Ltd + */ +@RunWith(IntegrationTestRunner.class) +public abstract class AbstractIntegrationTestTB3 extends + PrivateTB3Configuration { + @Override + protected String getBaseURL() { + String deploymentUrl = System.getProperty("deployment.url"); + if (deploymentUrl == null || deploymentUrl.equals("")) { + throw new RuntimeException( + "Deployment url must be given as deployment.url"); + } + + return deploymentUrl; + } + + @Parameters + public static Collection<DesiredCapabilities> getBrowsersForTest() { + return Collections.singleton(BrowserUtil.firefox(17)); + } + +} diff --git a/uitest/src/com/vaadin/tests/integration/IntegrationTestRunner.java b/uitest/src/com/vaadin/tests/integration/IntegrationTestRunner.java new file mode 100644 index 0000000000..29ee4e6023 --- /dev/null +++ b/uitest/src/com/vaadin/tests/integration/IntegrationTestRunner.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2013 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.integration; + +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; + +import com.vaadin.tests.tb3.TB3Runner; + +/** + * JUnit runner for integration tests. Replaces the actual method name with the + * server-name property when generating the test name. + * + * @author Vaadin Ltd + */ +public class IntegrationTestRunner extends TB3Runner { + + private Class<?> testClass; + + public IntegrationTestRunner(Class<?> klass) throws InitializationError { + super(klass); + testClass = klass; + } + + /* + * (non-Javadoc) + * + * @see + * org.junit.runners.BlockJUnit4ClassRunner#testName(org.junit.runners.model + * .FrameworkMethod) + */ + @Override + protected String testName(FrameworkMethod method) { + if (AbstractIntegrationTestTB3.class.isAssignableFrom(testClass)) { + return System.getProperty("server-name"); + } else { + return super.testName(method); + } + } +} diff --git a/uitest/src/com/vaadin/tests/integration/IntegrationTestStreaming.java b/uitest/src/com/vaadin/tests/integration/IntegrationTestStreaming.java new file mode 100644 index 0000000000..20ddac9dd1 --- /dev/null +++ b/uitest/src/com/vaadin/tests/integration/IntegrationTestStreaming.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2013 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.integration; + +import com.vaadin.annotations.Push; +import com.vaadin.shared.ui.ui.Transport; + +/** + * Server test which uses streaming + * + * @since 7.1 + * @author Vaadin Ltd + */ +@Push(transport = Transport.STREAMING) +public class IntegrationTestStreaming extends IntegrationTestUI { + + public static class IntegrationTestStreamingTB3 extends + ServletIntegrationTestTB3 { + // Uses the test method declared in the super class + } + +} diff --git a/uitest/src/com/vaadin/tests/integration/IntegrationTestUI.java b/uitest/src/com/vaadin/tests/integration/IntegrationTestUI.java index 0e6cb19b30..3d0a338bba 100755 --- a/uitest/src/com/vaadin/tests/integration/IntegrationTestUI.java +++ b/uitest/src/com/vaadin/tests/integration/IntegrationTestUI.java @@ -12,6 +12,11 @@ import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; public class IntegrationTestUI extends UI { + + public class IntegrationTestXhrTB3 extends ServletIntegrationTestTB3 { + // Uses the test method declared in the super class + } + @Override protected void init(VaadinRequest request) { VerticalLayout layout = new VerticalLayout(); diff --git a/uitest/src/com/vaadin/tests/integration/IntegrationTestWebsocket.java b/uitest/src/com/vaadin/tests/integration/IntegrationTestWebsocket.java new file mode 100644 index 0000000000..eaa23de3cf --- /dev/null +++ b/uitest/src/com/vaadin/tests/integration/IntegrationTestWebsocket.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2013 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.integration; + +import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.ui.Transport; + +/** + * Server test which uses websockets + * + * @since 7.1 + * @author Vaadin Ltd + */ +@Push(transport = Transport.WEBSOCKET) +public class IntegrationTestWebsocket extends IntegrationTestUI { + + public class IntegrationTestWebsocketTB3 extends ServletIntegrationTestTB3 { + // Uses the test method declared in the super class + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.tests.integration.IntegrationTestUI#init(com.vaadin.server + * .VaadinRequest) + */ + @Override + protected void init(VaadinRequest request) { + super.init(request); + // Ensure no fallback is used + getPushConfiguration().setFallbackTransport(Transport.WEBSOCKET); + } + +} diff --git a/uitest/src/com/vaadin/tests/integration/ServletIntegrationTestTB3.java b/uitest/src/com/vaadin/tests/integration/ServletIntegrationTestTB3.java new file mode 100644 index 0000000000..ae83083d85 --- /dev/null +++ b/uitest/src/com/vaadin/tests/integration/ServletIntegrationTestTB3.java @@ -0,0 +1,62 @@ +/* + * Copyright 2000-2013 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.integration; + +import java.io.IOException; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +/** + * Base class for servlet integration tests. Automatically prepends "/demo" to + * the deployment path + * + * @author Vaadin Ltd + */ +public abstract class ServletIntegrationTestTB3 extends + AbstractIntegrationTestTB3 { + + @Test + public void runTest() throws IOException, AssertionError { + compareScreen("initial"); + + WebElement cell = vaadinElement(getTableCell(getTable(), 0, 1)); + testBenchElement(cell).click(51, 13); + + compareScreen("finland"); + } + + private String getTableCell(String tableLocator, int row, int col) { + return tableLocator + + "/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[" + + row + "]/domChild[" + col + "]/domChild[0]"; + } + + protected String getTable() { + return "/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]"; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.tb3.AbstractTB3Test#getDeploymentPath() + */ + @Override + protected String getDeploymentPath() { + return "/demo" + super.getDeploymentPath(); + } + +} diff --git a/uitest/src/com/vaadin/tests/push/BarInUIDL.html b/uitest/src/com/vaadin/tests/push/BarInUIDL.html deleted file mode 100644 index 66f03158b6..0000000000 --- a/uitest/src/com/vaadin/tests/push/BarInUIDL.html +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.push.BarInUIDL?restartApplication</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBarInUIDL::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBarInUIDL::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]</td> - <td>Thank you for clicking | bar</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBarInUIDL::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBarInUIDL::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VLabel[0]</td> - <td>Thank you for clicking | bar</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/BarInUIDL.java b/uitest/src/com/vaadin/tests/push/BarInUIDL.java index 7e414cc89d..ef2568bebe 100644 --- a/uitest/src/com/vaadin/tests/push/BarInUIDL.java +++ b/uitest/src/com/vaadin/tests/push/BarInUIDL.java @@ -16,14 +16,44 @@ package com.vaadin.tests.push; +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.annotations.Push; import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.ui.Transport; import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.tb3.MultiBrowserTest; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Label; +@Push(transport = Transport.STREAMING) public class BarInUIDL extends AbstractTestUI { + public static class BarInUIDLTest extends MultiBrowserTest { + @Test + public void sendBarInUIDL() { + getButton().click(); + Assert.assertEquals( + "Thank you for clicking | bar", + vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]") + .getText()); + getButton().click(); + Assert.assertEquals( + "Thank you for clicking | bar", + vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VLabel[0]") + .getText()); + } + + private WebElement getButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]"); + } + } + /* * (non-Javadoc) * diff --git a/uitest/src/com/vaadin/tests/push/BasicPush.html b/uitest/src/com/vaadin/tests/push/BasicPush.html deleted file mode 100644 index 173ec90674..0000000000 --- a/uitest/src/com/vaadin/tests/push/BasicPush.html +++ /dev/null @@ -1,88 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.push.BasicPush?restartApplication&debug</td> - <td></td> -</tr> -<!--Test client initiated push --> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]</td> - <td>0</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]</td> - <td>1</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]</td> - <td>4</td> -</tr> -<!--Test server initiated push--> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VLabel[0]</td> - <td>0</td> -</tr> -<tr> - <td>pause</td> - <td>3000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VLabel[0]</td> - <td>1</td> -</tr> -<tr> - <td>pause</td> - <td>3000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VLabel[0]</td> - <td>2</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/BasicPush.java b/uitest/src/com/vaadin/tests/push/BasicPush.java index b80d287a1d..1f184863f7 100644 --- a/uitest/src/com/vaadin/tests/push/BasicPush.java +++ b/uitest/src/com/vaadin/tests/push/BasicPush.java @@ -1,40 +1,115 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.vaadin.tests.push; -import java.util.Date; import java.util.Timer; import java.util.TimerTask; -import com.vaadin.annotations.Widgetset; +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.annotations.Push; import com.vaadin.data.util.ObjectProperty; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.tests.components.AbstractTestUI; -import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.tests.tb3.MultiBrowserTest; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Label; -@Widgetset(TestingWidgetSet.NAME) +@Push public class BasicPush extends AbstractTestUI { + public static abstract class BasicPushTest extends MultiBrowserTest { + + @Test + public void testPush() { + // Test client initiated push + Assert.assertEquals(0, getClientCounter()); + getIncrementButton().click(); + Assert.assertEquals( + "Client counter not incremented by button click", 1, + getClientCounter()); + getIncrementButton().click(); + getIncrementButton().click(); + getIncrementButton().click(); + Assert.assertEquals( + "Four clicks should have incremented counter to 4", 4, + getClientCounter()); + + // Test server initiated push + getServerCounterStartButton().click(); + try { + Assert.assertEquals(0, getServerCounter()); + sleep(3000); + int serverCounter = getServerCounter(); + if (serverCounter < 1) { + // No push has happened + Assert.fail("No push has occured within 3s"); + } + sleep(3000); + if (getServerCounter() <= serverCounter) { + // No push has happened + Assert.fail("Only one push took place within 6s"); + + } + } finally { + // Avoid triggering push assertions + getServerCounterStopButton().click(); + } + } + + private int getServerCounter() { + return Integer.parseInt(getServerCounterElement().getText()); + } + + private int getClientCounter() { + return Integer.parseInt(getClientCounterElement().getText()); + } + + private WebElement getServerCounterElement() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VLabel[0]"); + } + + private WebElement getServerCounterStartButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VButton[0]/domChild[0]/domChild[0]"); + } + + private WebElement getServerCounterStopButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[6]/VButton[0]/domChild[0]/domChild[0]"); + } + + private WebElement getIncrementButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]"); + } + + private WebElement getClientCounterElement() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]"); + } + } + private ObjectProperty<Integer> counter = new ObjectProperty<Integer>(0); private ObjectProperty<Integer> counter2 = new ObjectProperty<Integer>(0); private final Timer timer = new Timer(true); - private final TimerTask task = new TimerTask() { - - @Override - public void run() { - access(new Runnable() { - @Override - public void run() { - counter2.setValue(counter2.getValue() + 1); - } - }); - } - }; + private TimerTask task; @Override protected void setup(VaadinRequest request) { @@ -65,11 +140,37 @@ public class BasicPush extends AbstractTestUI { lbl.setCaption("Server counter (updates each 3s by server thread) :"); addComponent(lbl); - addComponent(new Button("Reset", new Button.ClickListener() { + addComponent(new Button("Start timer", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { counter2.setValue(0); + if (task != null) { + task.cancel(); + } + task = new TimerTask() { + + @Override + public void run() { + access(new Runnable() { + @Override + public void run() { + counter2.setValue(counter2.getValue() + 1); + } + }); + } + }; + timer.scheduleAtFixedRate(task, 3000, 3000); + } + })); + + addComponent(new Button("Stop timer", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + if (task != null) { + task.cancel(); + task = null; + } } })); } @@ -94,7 +195,6 @@ public class BasicPush extends AbstractTestUI { @Override public void attach() { super.attach(); - timer.scheduleAtFixedRate(task, new Date(), 3000); } @Override diff --git a/uitest/src/com/vaadin/tests/push/BasicPushStreaming.java b/uitest/src/com/vaadin/tests/push/BasicPushStreaming.java index 37a8afd819..29534e1f5c 100644 --- a/uitest/src/com/vaadin/tests/push/BasicPushStreaming.java +++ b/uitest/src/com/vaadin/tests/push/BasicPushStreaming.java @@ -1,12 +1,42 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.vaadin.tests.push; +import org.junit.Test; + import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.ui.Transport; @Push(transport = Transport.STREAMING) public class BasicPushStreaming extends BasicPush { @Override - protected void setup(com.vaadin.server.VaadinRequest request) { - addComponent(new PushConfigurator(this)); + public void init(VaadinRequest request) { + super.init(request); + // Don't use fallback so we can easier detect if streaming fails + getPushConfiguration().setFallbackTransport(Transport.STREAMING); + } + + public static class BasicPushStreamingTest extends BasicPushTest { + @Override + @Test + public void testPush() { + super.testPush(); + } + } + } diff --git a/uitest/src/com/vaadin/tests/push/BasicPushWebsocket.java b/uitest/src/com/vaadin/tests/push/BasicPushWebsocket.java index 6fc27e8974..4765183fca 100644 --- a/uitest/src/com/vaadin/tests/push/BasicPushWebsocket.java +++ b/uitest/src/com/vaadin/tests/push/BasicPushWebsocket.java @@ -1,8 +1,44 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.vaadin.tests.push; +import java.util.Collection; + +import org.openqa.selenium.remote.DesiredCapabilities; + import com.vaadin.annotations.Push; +import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.ui.Transport; +import com.vaadin.tests.tb3.WebsocketTest; @Push(transport = Transport.WEBSOCKET) public class BasicPushWebsocket extends BasicPush { + + @Override + public void init(VaadinRequest request) { + super.init(request); + // Don't use fallback so we can easier detect if websocket fails + getPushConfiguration().setFallbackTransport(Transport.WEBSOCKET); + } + + public static class BasicPushWebsocketTest extends BasicPushTest { + @Override + public Collection<DesiredCapabilities> getBrowsersToTest() { + return WebsocketTest.getWebsocketBrowsers(); + } + } + } diff --git a/uitest/src/com/vaadin/tests/push/PushConfiguration.html b/uitest/src/com/vaadin/tests/push/PushConfiguration.html deleted file mode 100644 index c3786b1cc1..0000000000 --- a/uitest/src/com/vaadin/tests/push/PushConfiguration.html +++ /dev/null @@ -1,130 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<!--Websocket--> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.push.PushConfigurationTest?debug&restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertNotText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<tr> - <td>select</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]</td> - <td>label=WEBSOCKET</td> -</tr> -<tr> - <td>assertNotText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<tr> - <td>select</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> - <td>label=AUTOMATIC</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]</td> - <td>*fallbackTransport: streaming*transport: websocket*</td> -</tr> -<tr> - <td>assertNotText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<tr> - <td>waitForText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<!--Use debug console to verify we used the correct transport type--> -<tr> - <td>assertTextPresent</td> - <td>Push connection established using websocket</td> - <td></td> -</tr> -<tr> - <td>assertTextNotPresent</td> - <td>Push connection established using streaming</td> - <td>Push connection established using streaming</td> -</tr> -<tr> - <td>select</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> - <td>label=DISABLED</td> -</tr> -<!--Streaming--> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.push.PushConfigurationTest?debug&restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertNotText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<tr> - <td>select</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]</td> - <td>label=STREAMING</td> -</tr> -<tr> - <td>assertNotText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<tr> - <td>select</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> - <td>label=AUTOMATIC</td> -</tr> -<tr> - <td>assertNotText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]</td> - <td>*fallbackTransport: streaming*transport: streaming*</td> -</tr> -<tr> - <td>waitForText</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td> - <td>4</td> -</tr> -<!--Use debug console to verify we used the correct transport type--> -<tr> - <td>assertTextNotPresent</td> - <td>Push connection established using websocket</td> - <td></td> -</tr> -<tr> - <td>assertTextPresent</td> - <td>Push connection established using streaming</td> - <td></td> -</tr> -<tr> - <td>select</td> - <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td> - <td>label=DISABLED</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java index b57e9732cc..f4a537392d 100644 --- a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java +++ b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java @@ -1,19 +1,132 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.vaadin.tests.push; import java.util.Date; import java.util.Timer; import java.util.TimerTask; +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.Select; + import com.vaadin.data.util.ObjectProperty; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.tb3.WebsocketTest; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Label; public class PushConfigurationTest extends AbstractTestUI { + public static class PushConfigurationWebsocket extends WebsocketTest { + + @Override + protected boolean isDebug() { + return true; + } + + @Test + public void testWebsocketAndStreaming() { + // Websocket + Assert.assertEquals(1, getServerCounter()); + new Select(getTransportSelect()).selectByVisibleText("WEBSOCKET"); + new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC"); + Assert.assertTrue(vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]") + .getText() + .matches( + "^[\\s\\S]*fallbackTransport: streaming[\\s\\S]*transport: websocket[\\s\\S]*$")); + int counter = getServerCounter(); + + for (int second = 0;; second++) { + if (second >= 5) { + Assert.fail("timeout"); + } + if (getServerCounter() >= (counter + 2)) { + break; + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + + // Use debug console to verify we used the correct transport type + Assert.assertTrue(driver.getPageSource().contains( + "Push connection established using websocket")); + Assert.assertFalse(driver.getPageSource().contains( + "Push connection established using streaming")); + + new Select(getPushModeSelect()).selectByVisibleText("DISABLED"); + + // Streaming + driver.get(getTestUrl()); + Assert.assertEquals(1, getServerCounter()); + + new Select(getTransportSelect()).selectByVisibleText("STREAMING"); + new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC"); + Assert.assertTrue(vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]") + .getText() + .matches( + "^[\\s\\S]*fallbackTransport: streaming[\\s\\S]*transport: streaming[\\s\\S]*$")); + + counter = getServerCounter(); + for (int second = 0;; second++) { + if (second >= 5) { + Assert.fail("timeout"); + } + if (getServerCounter() >= (counter + 2)) { + break; + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + + // Use debug console to verify we used the correct transport type + Assert.assertFalse(driver.getPageSource().contains( + "Push connection established using websocket")); + Assert.assertTrue(driver.getPageSource().contains( + "Push connection established using streaming")); + + } + + private WebElement getPushModeSelect() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]"); + } + + private WebElement getTransportSelect() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]"); + } + + private int getServerCounter() { + return Integer.parseInt(getServerCounterElement().getText()); + } + + private WebElement getServerCounterElement() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]"); + } + } + private ObjectProperty<Integer> counter = new ObjectProperty<Integer>(0); private ObjectProperty<Integer> counter2 = new ObjectProperty<Integer>(0); diff --git a/uitest/src/com/vaadin/tests/push/PushFromInit.java b/uitest/src/com/vaadin/tests/push/PushFromInit.java index 4b442de499..000d5c0bce 100644 --- a/uitest/src/com/vaadin/tests/push/PushFromInit.java +++ b/uitest/src/com/vaadin/tests/push/PushFromInit.java @@ -1,11 +1,57 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.vaadin.tests.push; +import org.junit.Assert; +import org.junit.Test; + import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.tests.tb3.MultiBrowserTest; import com.vaadin.ui.Button; public class PushFromInit extends AbstractTestUIWithLog { + public static class PushFromInitTB3 extends MultiBrowserTest { + @Test + public void testPushFromInit() { + for (int second = 0;; second++) { + if (second >= 30) { + Assert.fail("timeout"); + } + try { + if ("1. Logged in init".equals(vaadinElementById( + "Log_row_1").getText())) { + break; + } + } catch (Exception e) { + } + try { + Thread.sleep(200); + } catch (InterruptedException e) { + } + } + + Assert.assertEquals( + "2. Logged from background thread started in init", + vaadinElementById("Log_row_0").getText()); + + } + } + @Override protected void setup(VaadinRequest request) { new Thread() { diff --git a/uitest/src/com/vaadin/tests/push/PushReattachedComponent.html b/uitest/src/com/vaadin/tests/push/PushReattachedComponent.html deleted file mode 100644 index e1f6a5f048..0000000000 --- a/uitest/src/com/vaadin/tests/push/PushReattachedComponent.html +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://192.168.2.162:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.components.panel.PanelChangeContents?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/Slot[1]/VPanel[0]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>stats</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/Slot[0]/VHorizontalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/Slot[1]/VPanel[0]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>companies</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/Slot[0]/VHorizontalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/Slot[1]/VPanel[0]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>stats</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/PushReattachedComponent.java b/uitest/src/com/vaadin/tests/push/PushReattachedComponent.java new file mode 100644 index 0000000000..35934273a4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushReattachedComponent.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * + */ +package com.vaadin.tests.push; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.tests.components.panel.PanelChangeContents; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class PushReattachedComponent extends MultiBrowserTest { + + @Override + protected boolean isPushEnabled() { + return true; + } + + @Override + protected Class<?> getUIClass() { + return PanelChangeContents.class; + } + + @Test + public void testReattachComponentUsingPush() { + Assert.assertEquals( + "stats", + vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VPanel[0]/VVerticalLayout[0]/Slot[0]/VLabel[0]") + .getText()); + vaadinElement( + "/VVerticalLayout[0]/Slot[0]/VHorizontalLayout[0]/Slot[1]/VButton[0]/domChild[0]/domChild[0]") + .click(); + Assert.assertEquals( + "companies", + vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VPanel[0]/VVerticalLayout[0]/Slot[0]/VLabel[0]") + .getText()); + vaadinElement( + "/VVerticalLayout[0]/Slot[0]/VHorizontalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]") + .click(); + Assert.assertEquals( + "stats", + vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VPanel[0]/VVerticalLayout[0]/Slot[0]/VLabel[0]") + .getText()); + + } +} diff --git a/uitest/src/com/vaadin/tests/push/PushTransportAnnotation.html b/uitest/src/com/vaadin/tests/push/PushTransportAnnotation.html deleted file mode 100644 index 854dd458bb..0000000000 --- a/uitest/src/com/vaadin/tests/push/PushTransportAnnotation.html +++ /dev/null @@ -1,46 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.push.BasicPushStreaming?debug&restartApplication</td> - <td></td> -</tr> -<tr> - <td>waitForTextPresent</td> - <td>Push connection established using streaming</td> - <td></td> -</tr> -<tr> - <td>assertTextNotPresent</td> - <td>Push connection established using websocket</td> - <td></td> -</tr> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.push.BasicPushWebsocket?debug&restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertTextNotPresent</td> - <td>Push connection established using streaming</td> - <td></td> -</tr> -<tr> - <td>waitForTextPresent</td> - <td>Push connection established using websocket</td> - <td></td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/StreamingPush.html b/uitest/src/com/vaadin/tests/push/StreamingPush.html deleted file mode 100644 index cf94a09c63..0000000000 --- a/uitest/src/com/vaadin/tests/push/StreamingPush.html +++ /dev/null @@ -1,88 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.push.BasicPush?restartApplication&debug&transport=streaming</td> - <td></td> -</tr> -<!--Test client initiated push --> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]</td> - <td>0</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]</td> - <td>1</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VLabel[0]</td> - <td>4</td> -</tr> -<!--Test server initiated push--> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VLabel[0]</td> - <td>0</td> -</tr> -<tr> - <td>pause</td> - <td>3000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VLabel[0]</td> - <td>1</td> -</tr> -<tr> - <td>pause</td> - <td>3000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushBasicPush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VLabel[0]</td> - <td>2</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/TogglePush.html b/uitest/src/com/vaadin/tests/push/TogglePush.html deleted file mode 100644 index b752d2120c..0000000000 --- a/uitest/src/com/vaadin/tests/push/TogglePush.html +++ /dev/null @@ -1,91 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.push.TogglePush?restartApplication</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pause</td> - <td>2000</td> - <td></td> -</tr> -<!--Push is enabled, so text gets updated--> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>Counter has been updated 1 times</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> - <td>61,6</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pause</td> - <td>2000</td> - <td></td> -</tr> -<!--Push is disabled, so text is not updated--> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>Counter has been updated 1 times</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<!--Direct update is visible, and includes previous update--> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>Counter has been updated 3 times</td> -</tr> -<tr> - <td>mouseClick</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> - <td>61,3</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pause</td> - <td>2000</td> - <td></td> -</tr> -<!--Push is enabled again, so text gets updated--> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>Counter has been updated 4 times</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/TogglePush.java b/uitest/src/com/vaadin/tests/push/TogglePush.java index c0bdc54ee0..f59ef83fe7 100644 --- a/uitest/src/com/vaadin/tests/push/TogglePush.java +++ b/uitest/src/com/vaadin/tests/push/TogglePush.java @@ -1,19 +1,173 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ package com.vaadin.tests.push; import java.util.Timer; import java.util.TimerTask; +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; + import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.server.VaadinRequest; import com.vaadin.shared.communication.PushMode; import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.tb3.MultiBrowserTest; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.CheckBox; import com.vaadin.ui.Label; public class TogglePush extends AbstractTestUI { + public static class TogglePushInInitTB3 extends MultiBrowserTest { + @Override + protected boolean isPushEnabled() { + return true; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.tb3.AbstractTB3Test#getTestUrl() + */ + @Override + protected String getTestUrl() { + return null; + } + + @Test + public void togglePushInInit() { + String baseUrl = getBaseURL(); + if (baseUrl.endsWith("/")) { + baseUrl = baseUrl.substring(0, baseUrl.length() - 1); + } + + String url = baseUrl + getDeploymentPath(); + + // Open with push disabled + driver.get(addParameter(url, "push=disabled")); + + Assert.assertFalse(getPushToggle().isSelected()); + + getDelayedCounterUpdateButton().click(); + sleep(2000); + Assert.assertEquals("Counter has been updated 0 times", + getCounterText()); + + // Open with push enabled + driver.get(addParameter(url, "push=enabled")); + Assert.assertTrue(getPushToggle().isSelected()); + + getDelayedCounterUpdateButton().click(); + sleep(2000); + Assert.assertEquals("Counter has been updated 1 times", + getCounterText()); + + } + + /** + * @since + * @param url + * @param string + * @return + */ + private String addParameter(String url, String queryParameter) { + if (url.contains("?")) { + return url + "&" + queryParameter; + } else { + return url + "?" + queryParameter; + } + } + + private String getCounterText() { + return vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]") + .getText(); + } + + private WebElement getPushToggle() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]"); + } + + private WebElement getDelayedCounterUpdateButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]"); + } + + } + + public static class TogglePushTB3 extends MultiBrowserTest { + + @Override + protected boolean isPushEnabled() { + return true; + } + + @Test + public void togglePush() { + getDelayedCounterUpdateButton().click(); + sleep(2000); + + // Push is enabled, so text gets updated + Assert.assertEquals("Counter has been updated 1 times", + getCounterText()); + + // Disable push + getPushToggle().click(); + getDelayedCounterUpdateButton().click(); + sleep(2000); + // Push is disabled, so text is not updated + Assert.assertEquals("Counter has been updated 1 times", + getCounterText()); + + getDirectCounterUpdateButton().click(); + // Direct update is visible, and includes previous update + Assert.assertEquals("Counter has been updated 3 times", + getCounterText()); + + // Re-enable push + getPushToggle().click(); + getDelayedCounterUpdateButton().click(); + sleep(2000); + + // Push is enabled again, so text gets updated + Assert.assertEquals("Counter has been updated 4 times", + getCounterText()); + } + + private WebElement getDirectCounterUpdateButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VButton[0]/domChild[0]/domChild[0]"); + } + + private WebElement getPushToggle() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]"); + } + + private String getCounterText() { + return vaadinElement( + "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]") + .getText(); + } + + private WebElement getDelayedCounterUpdateButton() { + return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]"); + } + } + private final Label counterLabel = new Label(); private int counter = 0; diff --git a/uitest/src/com/vaadin/tests/push/TogglePushInInit.html b/uitest/src/com/vaadin/tests/push/TogglePushInInit.html deleted file mode 100644 index c735f225e1..0000000000 --- a/uitest/src/com/vaadin/tests/push/TogglePushInInit.html +++ /dev/null @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://localhost:8071/" /> -<title>TogglePushInInit</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">TogglePushInInit</td></tr> -</thead><tbody> -<!--Open with push disabled--> -<tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.push.TogglePush?restartApplication&push=disabled</td> - <td></td> -</tr> -<tr> - <td>assertValue</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> - <td>off</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pause</td> - <td>2000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>Counter has been updated 0 times</td> -</tr> -<!--Open with push enabled--> -<tr> - <td>open</td> - <td>/run-push/com.vaadin.tests.push.TogglePush?restartApplication&push=enabled</td> - <td></td> -</tr> -<tr> - <td>assertValue</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VCheckBox[0]/domChild[0]</td> - <td>on</td> -</tr> -<tr> - <td>click</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VButton[0]/domChild[0]/domChild[0]</td> - <td></td> -</tr> -<tr> - <td>pause</td> - <td>2000</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runpushcomvaadintestspushTogglePush::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> - <td>Counter has been updated 1 times</td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/TrackMessageSizeUnitTests.html b/uitest/src/com/vaadin/tests/push/TrackMessageSizeUnitTests.html deleted file mode 100644 index 89dd7d4e78..0000000000 --- a/uitest/src/com/vaadin/tests/push/TrackMessageSizeUnitTests.html +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://192.168.2.162:8888/" /> -<title>New Test</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">New Test</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/run/com.vaadin.tests.push.TrackMessageSizeUnitTests?restartApplication</td> - <td></td> -</tr> -<tr> - <td>assertText</td> - <td>vaadin=runcomvaadintestspushTrackMessageSizeUnitTests::PID_SLog_row_0</td> - <td>1. All tests run</td> -</tr> -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/push/TrackMessageSizeUnitTests.java b/uitest/src/com/vaadin/tests/push/TrackMessageSizeUnitTests.java index 062698edf5..d7459f83ab 100644 --- a/uitest/src/com/vaadin/tests/push/TrackMessageSizeUnitTests.java +++ b/uitest/src/com/vaadin/tests/push/TrackMessageSizeUnitTests.java @@ -25,18 +25,29 @@ import javax.servlet.ServletContext; import org.apache.commons.io.IOUtils; import org.json.JSONArray; import org.json.JSONException; +import org.junit.Assert; +import org.junit.Test; import com.vaadin.annotations.JavaScript; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinServletService; import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.tests.tb3.MultiBrowserTest; import com.vaadin.ui.JavaScriptFunction; // Load vaadinPush.js so that jQueryVaadin is defined @JavaScript("vaadin://vaadinPush.js") public class TrackMessageSizeUnitTests extends AbstractTestUIWithLog { + public static class TrackMessageSizeUnitTestsTB3 extends MultiBrowserTest { + @Test + public void runTests() { + Assert.assertEquals("1. All tests run", + vaadinElementById("Log_row_0").getText()); + } + } + private String testMethod = "function testSequence(expected, data) {\n" + " var request = {trackMessageLength: true, messageDelimiter: '|'};\n" + " var response = {partialMessage: ''};\n" diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java new file mode 100644 index 0000000000..1897728366 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -0,0 +1,605 @@ +/* + * Copyright 2000-2013 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.tb3; + +import java.net.URL; +import java.util.Collection; +import java.util.Collections; + +import org.junit.After; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.Platform; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.BrowserType; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; + +import com.vaadin.server.LegacyApplication; +import com.vaadin.testbench.TestBench; +import com.vaadin.testbench.TestBenchTestCase; +import com.vaadin.ui.UI; + +/** + * Base class for TestBench 3+ tests. All TB3+ tests in the project should + * extend this class. + * + * Provides: + * <ul> + * <li>Helpers for browser selection</li> + * <li>Hub connection setup and teardown</li> + * <li>Automatic opening of a given test on the development server using + * {@link #getUIClass()} or by automatically finding an enclosing UI class</li> + * <li>Generic helpers for creating TB3+ tests</li> + * <li>Automatic URL generation based on needed features, e.g. + * {@link #isDebug()}, {@link #isPushEnabled()}</li> + * </ul> + * + * @author Vaadin Ltd + */ +@RunWith(value = TB3Runner.class) +public abstract class AbstractTB3Test extends TestBenchTestCase { + /** + * Height of the screenshots we want to capture + */ + private static final int SCREENSHOT_HEIGHT = 850; + + /** + * Width of the screenshots we want to capture + */ + private static final int SCREENSHOT_WIDTH = 1500; + + private DesiredCapabilities desiredCapabilities; + { + // Default browser to run on unless setDesiredCapabilities is called + desiredCapabilities = BrowserUtil.firefox(24); + } + + /** + * Connect to the hub using a remote web driver, set the canvas size and + * opens the initial URL as specified by {@link #getTestUrl()} + * + * @throws Exception + */ + @Before + public void setup() throws Exception { + setupDriver(); + + String testUrl = getTestUrl(); + if (testUrl != null) { + driver.get(testUrl); + } + } + + /** + * Creates and configure the web driver to be used for the test. By default + * creates a remote web driver which connects to {@link #getHubURL()} and + * selects a browser based on {@link #getDesiredCapabilities()}. + * + * This method MUST call {@link #setDriver(WebDriver)} with the newly + * generated driver. + * + * @throws Exception + * If something goes wrong + */ + protected void setupDriver() throws Exception { + DesiredCapabilities capabilities = getDesiredCapabilities(); + + WebDriver dr = TestBench.createDriver(new RemoteWebDriver(new URL( + getHubURL()), capabilities)); + setDriver(dr); + + int w = SCREENSHOT_WIDTH; + int h = SCREENSHOT_HEIGHT; + + if (BrowserUtil.isIE8(capabilities)) { + // IE8 gets size wrong, who would have guessed... + w += 4; + h += 4; + } + try { + testBench().resizeViewPortTo(w, h); + } catch (UnsupportedOperationException e) { + // Opera does not support this... + } + + } + + /** + * Returns the full URL to be opened when the test starts. + * + * @return the full URL to open or null to not open any URL automatically + */ + protected String getTestUrl() { + String baseUrl = getBaseURL(); + if (baseUrl.endsWith("/")) { + baseUrl = baseUrl.substring(0, baseUrl.length() - 1); + } + + return baseUrl + getDeploymentPath(); + } + + /** + * + * @return the location (URL) of the TB hub + */ + protected String getHubURL() { + return "http://" + getHubHostname() + ":4444/wd/hub"; + } + + /** + * Used for building the hub URL to use for the test + * + * @return the host name of the TestBench hub + */ + protected abstract String getHubHostname(); + + /** + * Used to determine what URL to initially open for the test + * + * @return the host name of development server + */ + protected abstract String getDeploymentHostname(); + + /** + * Produces a collection of browsers to run the test on. This method is + * executed by the test runner when determining how many test methods to + * invoke and with what parameters. For each returned value a test method is + * ran and before running that, + * {@link #setDesiredCapabilities(DesiredCapabilities)} is invoked with the + * value returned by this method. + * + * This method is not static to allow overriding it in sub classes. By + * default runs the test only on Firefox + * + * @return The browsers to run the test on + */ + public Collection<DesiredCapabilities> getBrowsersToTest() { + return Collections.singleton(BrowserUtil.firefox(17)); + + } + + /** + * Used to determine which capabilities should be used when setting up a + * {@link WebDriver} for this test. Typically set by a test runner or left + * at its default (Firefox 24). If you want to run a test on a single + * browser other than Firefox 24 you can override this method. + * + * @return the requested browser capabilities + */ + protected DesiredCapabilities getDesiredCapabilities() { + return desiredCapabilities; + } + + /** + * Sets the requested browser capabilities (typically browser name and + * version) + * + * @param desiredCapabilities + */ + public void setDesiredCapabilities(DesiredCapabilities desiredCapabilities) { + this.desiredCapabilities = desiredCapabilities; + } + + /** + * Shuts down the driver after the test has been completed + * + * @throws Exception + */ + @After + public void tearDown() throws Exception { + if (driver != null) { + driver.quit(); + } + driver = null; + } + + /** + * Finds an element based on the part of a TB2 style locator following the + * :: (e.g. vaadin=runLabelModes::PID_Scheckboxaction-Enabled/domChild[0] -> + * PID_Scheckboxaction-Enabled/domChild[0]). + * + * @param vaadinLocator + * The part following :: of the vaadin locator string + * @return + */ + protected WebElement vaadinElement(String vaadinLocator) { + return driver.findElement(vaadinLocator(vaadinLocator)); + } + + /** + * Find a Vaadin element based on its id given using Component.setId + * + * @param id + * The id to locate + * @return + */ + public WebElement vaadinElementById(String id) { + return driver.findElement(vaadinLocatorById(id)); + } + + /** + * Finds a {@link By} locator based on the part of a TB2 style locator + * following the :: (e.g. + * vaadin=runLabelModes::PID_Scheckboxaction-Enabled/domChild[0] -> + * PID_Scheckboxaction-Enabled/domChild[0]). + * + * @param vaadinLocator + * The part following :: of the vaadin locator string + * @return + */ + public org.openqa.selenium.By vaadinLocator(String vaadinLocator) { + String base = getApplicationId(getDeploymentPath()); + + base += "::"; + return com.vaadin.testbench.By.vaadin(base + vaadinLocator); + } + + /** + * Constructs a {@link By} locator for the id given using Component.setId + * + * @param id + * The id to locate + * @return a locator for the given id + */ + public By vaadinLocatorById(String id) { + return vaadinLocator("PID_S" + id); + } + + /** + * Waits a short while for the given condition to become true. Use e.g. as + * {@link #waitUntil(ExpectedConditions.textToBePresentInElement(by, text))} + * + * @param condition + * the condition to wait for to become true + */ + protected void waitUntil(ExpectedCondition<Boolean> condition) { + new WebDriverWait(driver, 10).until(condition); + } + + /** + * Waits a short while for the given condition to become false. Use e.g. as + * {@link #waitUntilNot(ExpectedConditions.textToBePresentInElement(by, + * text))} + * + * @param condition + * the condition to wait for to become false + */ + protected void waitUntilNot(ExpectedCondition<Boolean> condition) { + new WebDriverWait(driver, 10).until(ExpectedConditions.not(condition)); + } + + /** + * Returns the path that should be used for the test. The path contains the + * full path (appended to hostname+port) and must start with a slash. + * + * @return The path to open automatically when the test starts + */ + protected String getDeploymentPath() { + Class<?> uiClass = getUIClass(); + if (uiClass != null) { + return getDeploymentPath(uiClass); + } + throw new IllegalArgumentException("Unable to determine path for " + + getClass().getCanonicalName()); + + } + + /** + * Returns the UI class the current test is connected to. Uses the enclosing + * class if the test class is a static inner class to a UI class. + * + * Test which are not enclosed by a UI class must implement this method and + * return the UI class they want to test. + * + * Note that this method will update the test name to the enclosing class to + * be compatible with TB2 screenshot naming + * + * @return the UI class the current test is connected to + */ + protected Class<?> getUIClass() { + Class<?> enclosingClass = getClass().getEnclosingClass(); + if (enclosingClass != null) { + return enclosingClass; + } + return null; + } + + /** + * Determines whether to run the test in debug mode (with the debug console + * open) or not + * + * @return true to run with the debug window open, false by default + */ + protected boolean isDebug() { + return false; + } + + /** + * Determines whether to run the test with push enabled (using /run-push) or + * not. Note that push tests can and should typically be created using @Push + * on the UI instead of overriding this method + * + * @return true to use push in the test, false to use whatever UI specifies + */ + protected boolean isPushEnabled() { + return false; + } + + /** + * Returns the path for the given UI class when deployed on the test server. + * The path contains the full path (appended to hostname+port) and must + * start with a slash. + * + * This method takes into account {@link #isPushEnabled()} and + * {@link #isDebug()} when the path is generated. + * + * @param uiClass + * @return The path to the given UI class + */ + private String getDeploymentPath(Class<?> uiClass) { + String runPath = "/run"; + if (isPushEnabled()) { + runPath = "/run-push"; + } + + if (UI.class.isAssignableFrom(uiClass)) { + return runPath + "/" + uiClass.getCanonicalName() + + (isDebug() ? "?debug" : ""); + } else if (LegacyApplication.class.isAssignableFrom(uiClass)) { + return runPath + "/" + uiClass.getCanonicalName() + + "?restartApplication" + (isDebug() ? "&debug" : ""); + } else { + throw new IllegalArgumentException( + "Unable to determine path for enclosing class " + + uiClass.getCanonicalName()); + } + } + + /** + * Used to determine what URL to initially open for the test + * + * @return The base URL for the test. Does not include a trailing slash. + */ + protected String getBaseURL() { + return "http://" + getDeploymentHostname() + ":8888"; + } + + /** + * Generates the application id based on the URL in a way compatible with + * VaadinServletService. + * + * @param pathWithQueryParameters + * The path part of the URL, possibly still containing query + * parameters + * @return The application ID string used in Vaadin locators + */ + private String getApplicationId(String pathWithQueryParameters) { + // Remove any possible URL parameters + String pathWithoutQueryParameters = pathWithQueryParameters.replaceAll( + "\\?.*", ""); + if ("".equals(pathWithoutQueryParameters)) { + return "ROOT"; + } + + // Retain only a-z and numbers + return pathWithoutQueryParameters.replaceAll("[^a-zA-Z0-9]", ""); + } + + /** + * Helper method for sleeping X ms in a test. Catches and ignores + * InterruptedExceptions + * + * @param timeoutMillis + * Number of ms to wait + */ + protected void sleep(int timeoutMillis) { + try { + Thread.sleep(timeoutMillis); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + /** + * Provides helper method for selecting the browser to run on + * + * @author Vaadin Ltd + */ + public static class BrowserUtil { + /** + * Gets the capabilities for Safari of the given version + * + * @param version + * the major version + * @return an object describing the capabilities required for running a + * test on the given Safari version + */ + public static DesiredCapabilities safari(int version) { + DesiredCapabilities c = DesiredCapabilities.safari(); + c.setVersion("" + version); + return c; + } + + /** + * Gets the capabilities for Chrome of the given version + * + * @param version + * the major version + * @return an object describing the capabilities required for running a + * test on the given Chrome version + */ + public static DesiredCapabilities chrome(int version) { + DesiredCapabilities c = DesiredCapabilities.chrome(); + c.setVersion("" + version); + c.setPlatform(Platform.XP); + return c; + } + + /** + * Gets the capabilities for Opera of the given version + * + * @param version + * the major version + * @return an object describing the capabilities required for running a + * test on the given Opera version + */ + public static DesiredCapabilities opera(int version) { + DesiredCapabilities c = DesiredCapabilities.opera(); + c.setVersion("" + version); + c.setPlatform(Platform.XP); + return c; + } + + /** + * Gets the capabilities for Firefox of the given version + * + * @param version + * the major version + * @return an object describing the capabilities required for running a + * test on the given Firefox version + */ + public static DesiredCapabilities firefox(int version) { + DesiredCapabilities c = DesiredCapabilities.firefox(); + c.setVersion("" + version); + c.setPlatform(Platform.XP); + return c; + } + + /** + * Gets the capabilities for Internet Explorer of the given version + * + * @param version + * the major version + * @return an object describing the capabilities required for running a + * test on the given Internet Explorer version + */ + public static DesiredCapabilities ie(int version) { + DesiredCapabilities c = DesiredCapabilities.internetExplorer(); + c.setVersion("" + version); + return c; + } + + /** + * Checks if the given capabilities refer to Internet Explorer 8 + * + * @param capabilities + * @return true if the capabilities refer to IE8, false otherwise + */ + public static boolean isIE8(DesiredCapabilities capabilities) { + return BrowserType.IE.equals(capabilities.getBrowserName()) + && "8".equals(capabilities.getVersion()); + } + + /** + * Returns a human readable identifier of the given browser. Used for + * test naming and screenshots + * + * @param capabilities + * @return a human readable string describing the capabilities + */ + public static String getBrowserIdentifier( + DesiredCapabilities capabilities) { + String browserName = capabilities.getBrowserName(); + + if (BrowserType.IE.equals(browserName)) { + return "InternetExplorer"; + } else if (BrowserType.FIREFOX.equals(browserName)) { + return "Firefox"; + } else if (BrowserType.CHROME.equals(browserName)) { + return "Chrome"; + } else if (BrowserType.SAFARI.equals(browserName)) { + return "Safari"; + } else if (BrowserType.OPERA.equals(browserName)) { + return "Opera"; + } + + return browserName; + } + + /** + * Returns a human readable identifier of the platform described by the + * given capabilities. Used mainly for screenshots + * + * @param capabilities + * @return a human readable string describing the platform + */ + public static String getPlatform(DesiredCapabilities capabilities) { + if (capabilities.getPlatform() == Platform.WIN8 + || capabilities.getPlatform() == Platform.WINDOWS + || capabilities.getPlatform() == Platform.VISTA + || capabilities.getPlatform() == Platform.XP) { + return "Windows"; + } else if (capabilities.getPlatform() == Platform.MAC) { + return "Mac"; + } + return capabilities.getPlatform().toString(); + } + + /** + * Returns a string which uniquely (enough) identifies this browser. + * Used mainly in screenshot names. + * + * @param capabilities + * + * @return a unique string for each browser + */ + public static String getUniqueIdentifier( + DesiredCapabilities capabilities) { + return getUniqueIdentifier(getPlatform(capabilities), + getBrowserIdentifier(capabilities), + capabilities.getVersion()); + } + + /** + * Returns a string which uniquely (enough) identifies this browser. + * Used mainly in screenshot names. + * + * @param capabilities + * + * @return a unique string for each browser + */ + public static String getUniqueIdentifier( + DesiredCapabilities capabilities, String versionOverride) { + return getUniqueIdentifier(getPlatform(capabilities), + getBrowserIdentifier(capabilities), versionOverride); + } + + private static String getUniqueIdentifier(String platform, + String browser, String version) { + return platform + "_" + browser + "_" + version; + } + + } + + /** + * Called by the test runner whenever there is an exception in the test that + * will cause termination of the test + * + * @param t + * the throwable which caused the termination + */ + public void onUncaughtException(Throwable t) { + // Do nothing by default + + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/AllTB3Tests.java b/uitest/src/com/vaadin/tests/tb3/AllTB3Tests.java new file mode 100644 index 0000000000..bd9027bec2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/AllTB3Tests.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2013 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.tb3; + +import org.junit.runner.RunWith; +import org.junit.runners.model.InitializationError; + +import com.vaadin.tests.tb3.AllTB3Tests.AllTB3TestsSuite; + +/** + * Test consisting of all TB3 tests except integration tests (classes extending + * AbstractTB3Test, excludes package com.vaadin.test.integration). + * + * @author Vaadin Ltd + */ +@RunWith(AllTB3TestsSuite.class) +public class AllTB3Tests { + + public static class AllTB3TestsSuite extends TB3TestSuite { + + public AllTB3TestsSuite(Class<?> klass) throws InitializationError { + super(klass, AbstractTB3Test.class, "com.vaadin.tests", + new String[] { "com.vaadin.tests.integration" }); + } + + } + +} diff --git a/uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java b/uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java new file mode 100644 index 0000000000..3553954ec0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/MultiBrowserTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2013 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.tb3; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.openqa.selenium.remote.DesiredCapabilities; + +/** + * Base class for tests which should be run on all supported browsers. The test + * is automatically launched for multiple browsers in parallel by the test + * runner. + * + * Sub classes can, but typically should not, restrict the browsers used by + * implementing a + * + * <pre> + * @Parameters + * public static Collection<DesiredCapabilities> getBrowsersForTest() { + * } + * </pre> + * + * @author Vaadin Ltd + */ +public abstract class MultiBrowserTest extends PrivateTB3Configuration { + + static List<DesiredCapabilities> allBrowsers = new ArrayList<DesiredCapabilities>(); + static { + allBrowsers.add(BrowserUtil.ie(8)); + allBrowsers.add(BrowserUtil.ie(9)); + allBrowsers.add(BrowserUtil.ie(10)); + allBrowsers.add(BrowserUtil.ie(11)); + allBrowsers.add(BrowserUtil.firefox(24)); + // Uncomment once we have the capability to run on Safari 6 + // allBrowsers.add(safari(6)); + allBrowsers.add(BrowserUtil.chrome(29)); + allBrowsers.add(BrowserUtil.opera(12)); + + } + + /** + * @return all supported browsers which are actively tested + */ + public static List<DesiredCapabilities> getAllBrowsers() { + return allBrowsers; + } + + @Override + public Collection<DesiredCapabilities> getBrowsersToTest() { + return allBrowsers; + } + +} diff --git a/uitest/src/com/vaadin/tests/tb3/ParallelScheduler.java b/uitest/src/com/vaadin/tests/tb3/ParallelScheduler.java new file mode 100644 index 0000000000..912d7d010e --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/ParallelScheduler.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2013 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.tb3; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import org.junit.runners.model.RunnerScheduler; + +/** + * JUnit scheduler capable of running multiple tets in parallel. Each test is + * run in its own thread. Uses an {@link ExecutorService} to manage the threads. + * + * @author Vaadin Ltd + */ +public class ParallelScheduler implements RunnerScheduler { + private final List<Future<Object>> fResults = new ArrayList<Future<Object>>(); + private ExecutorService fService; + + /** + * Creates a parallel scheduler which will use the given executor service + * when submitting test jobs. + * + * @param service + * The service to use for tests + */ + public ParallelScheduler(ExecutorService service) { + fService = service; + } + + @Override + public void schedule(final Runnable childStatement) { + fResults.add(fService.submit(new Callable<Object>() { + @Override + public Object call() throws Exception { + childStatement.run(); + return null; + } + })); + } + + @Override + public void finished() { + for (Future<Object> each : fResults) { + try { + each.get(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java new file mode 100644 index 0000000000..3d7dead928 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java @@ -0,0 +1,123 @@ +/* + * Copyright 2000-2013 Vaadind 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.tb3; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Enumeration; +import java.util.Properties; + +/** + * Provides values for parameters which depend on where the test is run. + * Parameters should be configured in work/eclipse-run-selected-test.properties. + * A template is available in uitest/. + * + * @author Vaadin Ltd + */ +public abstract class PrivateTB3Configuration extends ScreenshotTB3Test { + private static final String HOSTNAME_PROPERTY = "com.vaadin.testbench.deployment.hostname"; + private final Properties properties = new Properties(); + + public PrivateTB3Configuration() { + File file = new File("work", "eclipse-run-selected-test.properties"); + if (file.exists()) { + try { + properties.load(new FileInputStream(file)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private String getProperty(String name) { + String property = properties.getProperty(name); + if (property == null) { + property = System.getProperty(name); + } + + return property; + } + + @Override + protected String getScreenshotDirectory() { + String screenshotDirectory = getProperty("com.vaadin.testbench.screenshot.directory"); + if (screenshotDirectory == null) { + throw new RuntimeException( + "No screenshot directory defined. Use -Dcom.vaadin.testbench.screenshot.directory=<path>"); + } + return screenshotDirectory; + } + + @Override + protected String getHubHostname() { + return "tb3-hub.intra.itmill.com"; + } + + @Override + protected String getDeploymentHostname() { + String hostName = getProperty(HOSTNAME_PROPERTY); + + if (hostName == null || "".equals(hostName)) { + hostName = findAutoHostname(); + } + + return hostName; + } + + /** + * Tries to automatically determine the IP address of the machine the test + * is running on. + * + * @return An IP address of one of the network interfaces in the machine. + * @throws RuntimeException + * if there was an error or no IP was found + */ + private String findAutoHostname() { + try { + Enumeration<NetworkInterface> interfaces = NetworkInterface + .getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface current = interfaces.nextElement(); + if (!current.isUp() || current.isLoopback() + || current.isVirtual()) { + continue; + } + Enumeration<InetAddress> addresses = current.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress current_addr = addresses.nextElement(); + if (current_addr.isLoopbackAddress()) { + continue; + } + String hostAddress = current_addr.getHostAddress(); + if (hostAddress.startsWith("192.168.")) { + return hostAddress; + } + } + } + } catch (SocketException e) { + throw new RuntimeException("Could not enumerate "); + } + + throw new RuntimeException( + "No compatible (192.168.*) ip address found."); + } + +} diff --git a/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java new file mode 100644 index 0000000000..645d9cd0cb --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/ScreenshotTB3Test.java @@ -0,0 +1,392 @@ +/* + * Copyright 2000-2013 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.tb3; + +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.imageio.ImageIO; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TakesScreenshot; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.Parameters; +import com.vaadin.testbench.commands.TestBenchCommands; + +/** + * Base class which provides functionality for tests which use the automatic + * screenshot comparison function. + * + * @author Vaadin Ltd + */ +public abstract class ScreenshotTB3Test extends AbstractTB3Test { + + private String screenshotBaseName; + + @Rule + public TestRule watcher = new TestWatcher() { + + @Override + protected void starting(org.junit.runner.Description description) { + Class<?> testClass = description.getTestClass(); + // Runner adds [BrowserName] which we do not want to use in the + // screenshot name + String testMethod = description.getMethodName(); + testMethod = testMethod.replaceAll("\\[.*\\]", ""); + + String className = testClass.getSimpleName(); + if (testClass.getEnclosingClass() != null) { + className = testClass.getEnclosingClass().getSimpleName(); + } + + screenshotBaseName = className + "-" + testMethod; + }; + }; + + /** + * Contains a list of screenshot identifiers for which + * {@link #compareScreen(String)} has failed during the test + */ + private List<String> screenshotFailures = new ArrayList<String>(); + + /** + * Defines TestBench screen comparison parameters before each test run + */ + @Before + public void setupScreenComparisonParameters() { + Parameters.setScreenshotErrorDirectory(getScreenshotErrorDirectory()); + Parameters + .setScreenshotReferenceDirectory(getScreenshotReferenceDirectory()); + } + + /** + * Grabs a screenshot and compares with the reference image with the given + * identifier. Supports alternative references and will succeed if the + * screenshot matches at least one of the references. + * + * In case of a failed comparison this method stores the grabbed screenshots + * in the error directory as defined by + * {@link #getScreenshotErrorDirectory()}. It will also generate a html file + * in the same directory, comparing the screenshot with the first found + * reference. + * + * @param identifier + * @throws IOException + */ + protected void compareScreen(String identifier) throws IOException { + if (identifier == null || identifier.isEmpty()) { + throw new IllegalArgumentException("Empty identifier not supported"); + } + + File mainReference = getScreenshotReferenceFile(identifier); + + List<File> alternativeFiles = findReferenceAlternatives(mainReference); + List<File> failedReferenceAlternatives = new ArrayList<File>(); + + for (File file : alternativeFiles) { + if (testBench(driver).compareScreen(file)) { + break; + } else { + failedReferenceAlternatives.add(file); + } + } + + File referenceToKeep = null; + if (failedReferenceAlternatives.size() != alternativeFiles.size()) { + // Matched one comparison but not all, remove all error images + + // HTML files + } else { + // All comparisons failed, keep the main error image + HTML + screenshotFailures.add(mainReference.getName()); + referenceToKeep = mainReference; + } + + // Remove all PNG/HTML files we no longer need (failed alternative + // references or all error files (PNG/HTML) if comparison succeeded) + for (File failedAlternative : failedReferenceAlternatives) { + File failurePng = getErrorFileFromReference(failedAlternative); + if (failedAlternative != referenceToKeep) { + // Delete png + HTML + String htmlFileName = failurePng.getName().replace(".png", + ".html"); + File failureHtml = new File(failurePng.getParentFile(), + htmlFileName); + + failurePng.delete(); + failureHtml.delete(); + } + } + } + + /** + * + * @param referenceFile + * The reference image file (in the directory defined by + * {@link #getScreenshotReferenceDirectory()}) + * @return the file name of the file generated in the directory defined by + * {@link #getScreenshotErrorDirectory()} if comparison with the + * given reference image fails. + */ + private File getErrorFileFromReference(File referenceFile) { + return new File(referenceFile.getAbsolutePath().replace( + getScreenshotReferenceDirectory(), + getScreenshotErrorDirectory())); + } + + /** + * Finds alternative references for the given files + * + * @param reference + * @return all references which should be considered when comparing with the + * given files, including the given reference + */ + private List<File> findReferenceAlternatives(File reference) { + List<File> files = new ArrayList<File>(); + files.add(reference); + + File screenshotDir = reference.getParentFile(); + String name = reference.getName(); + // Remove ".png" + String nameBase = name.substring(0, name.length() - 4); + for (int i = 1;; i++) { + File file = new File(screenshotDir, nameBase + "_" + i + ".png"); + if (file.exists()) { + files.add(file); + } else { + break; + } + } + + return files; + } + + /** + * @param testName + * @return the reference file name to use for the given browser, as + * described by {@literal capabilities}, and identifier + */ + private File getScreenshotReferenceFile(String identifier) { + DesiredCapabilities capabilities = getDesiredCapabilities(); + + String originalName = getScreenshotReferenceName(identifier); + File exactVersionFile = new File(originalName); + if (exactVersionFile.exists()) { + return exactVersionFile; + } + + String browserVersion = capabilities.getVersion(); + + if (browserVersion.matches("\\d+")) { + for (int version = Integer.parseInt(browserVersion); version > 0; version--) { + String fileName = getScreenshotReferenceName(identifier, + version); + File oldVersionFile = new File(fileName); + if (oldVersionFile.exists()) { + return oldVersionFile; + } + } + } + + return exactVersionFile; + } + + /** + * @return the base directory of 'reference' and 'errors' screenshots + */ + protected abstract String getScreenshotDirectory(); + + /** + * @return the directory where reference images are stored (the 'reference' + * folder inside the screenshot directory) + */ + private String getScreenshotReferenceDirectory() { + return getScreenshotDirectory() + "/reference"; + } + + /** + * @return the directory where comparison error images should be created + * (the 'errors' folder inside the screenshot directory) + */ + private String getScreenshotErrorDirectory() { + return getScreenshotDirectory() + "/errors"; + } + + /** + * Checks if any screenshot comparisons failures occurred during the test + * and combines all comparison errors into one exception + * + * @throws IOException + * If there were failures during the test + */ + @After + public void checkCompareFailures() throws IOException { + if (!screenshotFailures.isEmpty()) { + throw new IOException( + "The following screenshots did not match the reference: " + + screenshotFailures.toString()); + } + + } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.tests.tb3.AbstractTB3Test#onUncaughtException(java.lang.Throwable + * ) + */ + @Override + public void onUncaughtException(Throwable cause) { + super.onUncaughtException(cause); + // Grab a "failure" screenshot and store in the errors folder for later + // analysis + try { + TestBenchCommands testBench = testBench(); + if (testBench != null) { + testBench.disableWaitForVaadin(); + } + } catch (Throwable t) { + t.printStackTrace(); + } + try { + if (driver != null) { + BufferedImage screenshotImage = ImageIO + .read(new ByteArrayInputStream( + ((TakesScreenshot) driver) + .getScreenshotAs(OutputType.BYTES))); + ImageIO.write(screenshotImage, "png", new File( + getScreenshotFailureName())); + } + } catch (Throwable t) { + t.printStackTrace(); + } + + } + + /** + * @return the name of a "failure" image which is stored in the folder + * defined by {@link #getScreenshotErrorDirectory()} when the test + * fails + */ + private String getScreenshotFailureName() { + return getScreenshotErrorBaseName() + "-failure.png"; + } + + /** + * @return the base name used for screenshots. This is the first part of the + * screenshot file name, typically created as "testclass-testmethod" + */ + public String getScreenshotBaseName() { + return screenshotBaseName; + } + + /** + * Returns the name of the reference file based on the given parameters. + * + * @param testName + * @param capabilities + * @param identifier + * @return the full path of the reference + */ + private String getScreenshotReferenceName(String identifier) { + return getScreenshotReferenceName(identifier, null); + } + + /** + * Returns the name of the reference file based on the given parameters. The + * version given in {@literal capabilities} is used unless it is overridden + * by the {@literal versionOverride} parameter. + * + * @param testName + * @param capabilities + * @param identifier + * @return the full path of the reference + */ + private String getScreenshotReferenceName(String identifier, + Integer versionOverride) { + String uniqueBrowserIdentifier; + if (versionOverride == null) { + uniqueBrowserIdentifier = BrowserUtil + .getUniqueIdentifier(getDesiredCapabilities()); + } else { + uniqueBrowserIdentifier = BrowserUtil.getUniqueIdentifier( + getDesiredCapabilities(), "" + versionOverride); + } + + // WindowMaximizeRestoreTest_Windows_InternetExplorer_8_window-1-moved-maximized-restored.png + return getScreenshotReferenceDirectory() + "/" + + getScreenshotBaseName() + "_" + uniqueBrowserIdentifier + "_" + + identifier + ".png"; + } + + /** + * Returns the base name of the screenshot in the error directory. This is a + * name so that all files matching {@link #getScreenshotErrorBaseName()}* + * are owned by this test instance (taking into account + * {@link #getDesiredCapabilities()}) and can safely be removed before + * running this test. + */ + private String getScreenshotErrorBaseName() { + return getScreenshotReferenceName("dummy", null).replace( + getScreenshotReferenceDirectory(), + getScreenshotErrorDirectory()).replace("_dummy.png", ""); + } + + /** + * Removes any old screenshots related to this test from the errors + * directory before running the test + */ + @Before + public void cleanErrorDirectory() { + // Remove any screenshots for this test from the error directory + // before running it. Leave unrelated files as-is + File errorDirectory = new File(getScreenshotErrorDirectory()); + + // Create errors directory if it does not exist + if (!errorDirectory.exists()) { + errorDirectory.mkdirs(); + } + + final String errorBase = getScreenshotErrorBaseName() + .replace("\\", "/"); + File[] files = errorDirectory.listFiles(new FileFilter() { + + @Override + public boolean accept(File pathname) { + String thisFile = pathname.getAbsolutePath().replace("\\", "/"); + if (thisFile.startsWith(errorBase)) { + return true; + } + return false; + } + }); + for (File f : files) { + f.delete(); + } + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/ServletIntegrationTests.java b/uitest/src/com/vaadin/tests/tb3/ServletIntegrationTests.java new file mode 100644 index 0000000000..d2aa413749 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/ServletIntegrationTests.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2013 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.tb3; + +import org.junit.runner.RunWith; +import org.junit.runners.model.InitializationError; + +import com.vaadin.tests.integration.ServletIntegrationTestTB3; +import com.vaadin.tests.tb3.ServletIntegrationTests.ServletIntegrationTestSuite; + +@RunWith(ServletIntegrationTestSuite.class) +public class ServletIntegrationTests { + + public static class ServletIntegrationTestSuite extends TB3TestSuite { + public ServletIntegrationTestSuite(Class<?> klass) + throws InitializationError { + super(klass, ServletIntegrationTestTB3.class, + "com.vaadin.tests.integration", new String[] {}); + } + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/SimpleMultiBrowserTest.java b/uitest/src/com/vaadin/tests/tb3/SimpleMultiBrowserTest.java new file mode 100644 index 0000000000..a7ade3f9f7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/SimpleMultiBrowserTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2013 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.tb3; + +import org.junit.Test; + +/** + * A simple version of {@link MultiBrowserTest} which allows only one test + * method ({@link #test()}). Uses only the enclosing class name as test + * identifier (i.e. excludes "-test"). + * + * This class is only provided as a helper for converting existing TB2 tests + * without renaming all screenshots. All new TB3+ tests should extend + * {@link MultiBrowserTest} directly instead of this. + * + * @author Vaadin Ltd + */ +public abstract class SimpleMultiBrowserTest extends MultiBrowserTest { + + @Test + public abstract void test() throws Exception; + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.tb3.ScreenshotTB3Test#getScreenshotBaseName() + */ + @Override + public String getScreenshotBaseName() { + return super.getScreenshotBaseName().replaceFirst("-test$", ""); + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/TB3Runner.java b/uitest/src/com/vaadin/tests/tb3/TB3Runner.java new file mode 100644 index 0000000000..b612b17caa --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/TB3Runner.java @@ -0,0 +1,154 @@ +/* + * Copyright 2000-2013 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.tb3; + +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.junit.Test; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.junit.runners.Parameterized; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.Statement; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.tb3.AbstractTB3Test.BrowserUtil; + +/** + * This runner is loosely based on FactoryTestRunner by Ted Young + * (http://tedyoung.me/2011/01/23/junit-runtime-tests-custom-runners/). The + * generated test names give information about the parameters used (unlike + * {@link Parameterized}). + * + * @since 7.1 + */ +public class TB3Runner extends BlockJUnit4ClassRunner { + + /** + * This is the total limit of actual JUnit test instances run in parallel + */ + private static final int MAX_CONCURRENT_TESTS = 50; + + /** + * This is static so it is shared by all tests running concurrently on the + * same machine and thus can limit the number of threads in use. + */ + private static final ExecutorService service = Executors + .newFixedThreadPool(MAX_CONCURRENT_TESTS); + + public TB3Runner(Class<?> klass) throws InitializationError { + super(klass); + setScheduler(new ParallelScheduler(service)); + } + + @Override + protected List<FrameworkMethod> computeTestMethods() { + List<FrameworkMethod> tests = new LinkedList<FrameworkMethod>(); + + if (!AbstractTB3Test.class.isAssignableFrom(getTestClass() + .getJavaClass())) { + throw new RuntimeException(getClass().getName() + " only supports " + + AbstractTB3Test.class.getName()); + } + + try { + AbstractTB3Test testClassInstance = (AbstractTB3Test) getTestClass() + .getOnlyConstructor().newInstance(); + for (DesiredCapabilities capabilities : testClassInstance + .getBrowsersToTest()) { + + // Find any methods marked with @Test. + for (FrameworkMethod m : getTestClass().getAnnotatedMethods( + Test.class)) { + tests.add(new TB3Method(m.getMethod(), capabilities)); + } + } + } catch (Exception e) { + throw new RuntimeException("Error retrieving browsers to run on", e); + } + + return tests; + } + + /* + * (non-Javadoc) + * + * @see + * org.junit.runners.BlockJUnit4ClassRunner#withBefores(org.junit.runners + * .model.FrameworkMethod, java.lang.Object, + * org.junit.runners.model.Statement) + */ + @Override + protected Statement withBefores(final FrameworkMethod method, + final Object target, Statement statement) { + if (!(method instanceof TB3Method)) { + throw new RuntimeException("Unexpected method type " + + method.getClass().getName() + ", expected TB3Method"); + } + final TB3Method tb3method = (TB3Method) method; + + // setDesiredCapabilities before running the real @Befores (which use + // capabilities) + + final Statement realBefores = super.withBefores(method, target, + statement); + return new Statement() { + + @Override + public void evaluate() throws Throwable { + ((AbstractTB3Test) target) + .setDesiredCapabilities(tb3method.capabilities); + try { + realBefores.evaluate(); + } catch (Throwable t) { + // Give the test a chance to e.g. produce an error + // screenshot before failing the test by re-throwing the + // exception + ((AbstractTB3Test) target).onUncaughtException(t); + throw t; + } + } + }; + } + + private static class TB3Method extends FrameworkMethod { + private DesiredCapabilities capabilities; + + public TB3Method(Method method, DesiredCapabilities capabilities) { + super(method); + this.capabilities = capabilities; + } + + @Override + public Object invokeExplosively(final Object target, Object... params) + throws Throwable { + // Executes the test method with the supplied parameters + return super.invokeExplosively(target); + } + + @Override + public String getName() { + return String.format("%s[%s]", getMethod().getName(), + BrowserUtil.getUniqueIdentifier(capabilities)); + } + + } +} diff --git a/uitest/src/com/vaadin/tests/tb3/TB3TestSuite.java b/uitest/src/com/vaadin/tests/tb3/TB3TestSuite.java new file mode 100644 index 0000000000..e1c8edfd60 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/TB3TestSuite.java @@ -0,0 +1,238 @@ +/* + * Copyright 2000-2013 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.tb3; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.net.JarURLConnection; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.jar.JarEntry; + +import org.junit.runners.Suite; +import org.junit.runners.model.InitializationError; + +/** + * Test suite which consists of all the TB3 tests passed in the constructor. + * Runs the tests in parallel using a {@link ParallelScheduler} + * + * @author Vaadin Ltd + */ +public class TB3TestSuite extends Suite { + + /** + * This only restricts the number of test suites running concurrently. The + * number of tests to run concurrently are configured in {@link TB3Runner}. + */ + private static final int MAX_CONCURRENT_TEST_SUITES = 20; + + /** + * This is static so it is shared by all test suites running concurrently on + * the same machine and thus can limit the number of threads in use. + */ + private final ExecutorService service = Executors + .newFixedThreadPool(MAX_CONCURRENT_TEST_SUITES); + + public TB3TestSuite(Class<?> klass, + Class<? extends AbstractTB3Test> baseClass, String basePackage, + String[] ignorePackages) throws InitializationError { + super(klass, findTests(baseClass, basePackage, ignorePackages)); + setScheduler(new ParallelScheduler(service)); + } + + /** + * Traverses the directory on the classpath (inside or outside a Jar file) + * specified by 'basePackage'. Collects all classes inside the location + * which can be assigned to 'baseClass' except for classes inside packages + * listed in 'ignoredPackages'. + * + * @param baseClass + * @param basePackage + * @param ignorePackages + * @return + */ + private static Class<?>[] findTests( + Class<? extends AbstractTB3Test> baseClass, String basePackage, + String[] ignorePackages) { + try { + List<?> l = findClasses(baseClass, basePackage, ignorePackages); + return l.toArray(new Class[] {}); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + /** + * Traverses the directory on the classpath (inside or outside a Jar file) + * specified by 'basePackage'. Collects all classes inside the location + * which can be assigned to 'baseClass' except for classes inside packages + * listed in 'ignoredPackages'. + * + * @param baseClass + * @param basePackage + * @param ignoredPackages + * @return + * @throws IOException + */ + private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass, + String basePackage, String[] ignoredPackages) throws IOException { + List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>(); + String basePackageDirName = "/" + basePackage.replace('.', '/'); + URL location = baseClass.getResource(basePackageDirName); + if (location.getProtocol().equals("file")) { + try { + File f = new File(location.toURI()); + if (!f.exists()) { + throw new IOException("Directory " + f.toString() + + " does not exist"); + } + findPackages(f, basePackage, baseClass, classes, + ignoredPackages); + } catch (URISyntaxException e) { + throw new IOException(e.getMessage()); + } + } else if (location.getProtocol().equals("jar")) { + JarURLConnection juc = (JarURLConnection) location.openConnection(); + findClassesInJar(juc, basePackage, baseClass, classes); + } + + Collections.sort(classes, new Comparator<Class<? extends T>>() { + + @Override + public int compare(Class<? extends T> o1, Class<? extends T> o2) { + return o1.getName().compareTo(o2.getName()); + } + + }); + return classes; + } + + /** + * Traverses the given directory and collects all classes which are inside + * the given 'javaPackage' and can be assigned to the given 'baseClass'. The + * found classes are added to 'result'. + * + * @param parent + * The directory to traverse + * @param javaPackage + * The java package which 'parent' contains + * @param baseClass + * The class which the target classes extend + * @param result + * The collection to which found classes are added + * @param ignoredPackages + * A collection of packages (including sub packages) to ignore + */ + private static <T> void findPackages(File parent, String javaPackage, + Class<T> baseClass, Collection<Class<? extends T>> result, + String[] ignoredPackages) { + for (String ignoredPackage : ignoredPackages) { + if (javaPackage.equals(ignoredPackage)) { + return; + } + } + + for (File file : parent.listFiles()) { + if (file.isDirectory()) { + findPackages(file, javaPackage + "." + file.getName(), + baseClass, result, ignoredPackages); + } else if (file.getName().endsWith(".class")) { + String fullyQualifiedClassName = javaPackage + "." + + file.getName().replace(".class", ""); + addClassIfMatches(result, fullyQualifiedClassName, baseClass); + } + } + + } + + /** + * Traverses a Jar file using the given connection and collects all classes + * which are inside the given 'javaPackage' and can be assigned to the given + * 'baseClass'. The found classes are added to 'result'. + * + * @param javaPackage + * The java package containing the classes (classes may be in a + * sub package) + * @param baseClass + * The class which the target classes extend + * @param result + * The collection to which found classes are added + * @throws IOException + */ + private static <T> void findClassesInJar(JarURLConnection juc, + String javaPackage, Class<T> baseClass, + Collection<Class<? extends T>> result) throws IOException { + String javaPackageDir = javaPackage.replace('.', '/'); + Enumeration<JarEntry> ent = juc.getJarFile().entries(); + while (ent.hasMoreElements()) { + JarEntry e = ent.nextElement(); + if (e.getName().endsWith(".class") + && e.getName().startsWith(javaPackageDir)) { + String fullyQualifiedClassName = e.getName().replace('/', '.') + .replace(".class", ""); + addClassIfMatches(result, fullyQualifiedClassName, baseClass); + } + } + } + + /** + * Verifies that the class represented by 'fullyQualifiedClassName' can be + * loaded, assigned to 'baseClass' and is not an abstract or anonymous + * class. + * + * @param result + * The collection to add to + * @param fullyQualifiedClassName + * The candidate class + * @param baseClass + * The class 'fullyQualifiedClassName' should be assignable to + */ + @SuppressWarnings("unchecked") + private static <T> void addClassIfMatches( + Collection<Class<? extends T>> result, + String fullyQualifiedClassName, Class<T> baseClass) { + try { + // Try to load the class + + Class<?> c = Class.forName(fullyQualifiedClassName); + if (!baseClass.isAssignableFrom(c)) { + return; + } + if (!Modifier.isAbstract(c.getModifiers()) && !c.isAnonymousClass()) { + result.add((Class<? extends T>) c); + } + } catch (Exception e) { + // Could ignore that class cannot be loaded + e.printStackTrace(); + } catch (LinkageError e) { + // Ignore. Client side classes will at least throw LinkageErrors + } + + } + +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/tb3/WebsocketTest.java b/uitest/src/com/vaadin/tests/tb3/WebsocketTest.java new file mode 100644 index 0000000000..5c6ea329f5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/tb3/WebsocketTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2013 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.tb3; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.openqa.selenium.remote.DesiredCapabilities; + +/** + * A {@link MultiBrowserTest} which restricts the tests to the browsers which + * support websocket + * + * @author Vaadin Ltd + */ +public abstract class WebsocketTest extends PrivateTB3Configuration { + private static List<DesiredCapabilities> websocketBrowsers = new ArrayList<DesiredCapabilities>(); + static { + websocketBrowsers.addAll(MultiBrowserTest.getAllBrowsers()); + websocketBrowsers.remove(BrowserUtil.ie(8)); + websocketBrowsers.remove(BrowserUtil.ie(9)); + } + + /** + * @return All supported browsers which are actively tested and support + * websockets + */ + public static Collection<DesiredCapabilities> getWebsocketBrowsers() { + return Collections.unmodifiableCollection(websocketBrowsers); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.tb3.AbstractTB3Test#getBrowserToRunOn() + */ + @Override + public Collection<DesiredCapabilities> getBrowsersToTest() { + return getWebsocketBrowsers(); + } +} diff --git a/uitest/tb3test.xml b/uitest/tb3test.xml new file mode 100644 index 0000000000..92008ff9f3 --- /dev/null +++ b/uitest/tb3test.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<project name="tb3test" xmlns:antcontrib="antlib:net.sf.antcontrib" xmlns:ivy="antlib:org.apache.ivy.ant" basedir="."> + + <dirname property="tb3test.dir" file="${ant.file.tb3test}" /> + + <ivy:resolve file="${tb3test.dir}/ivy.xml" conf="build, build-provided" /> + <ivy:cachepath pathid="classpath.tb3.lib" conf="build, build-provided" /> + <path id="classpath.tb3"> + <path refid="classpath.tb3.lib" /> + <path location="${tb3test.dir}/result/classes" /> + </path> + + <target name="run-all-tb3-tests" description="Run all the TB3 tests (except server tests) in the project"> + <antcall target="run-tb3-suite"> + <param name="junit.test.suite" value="com.vaadin.tests.tb3.AllTB3Tests" /> + </antcall> + </target> + + <target name="run-tb3-suite"> + <fail unless="junit.test.suite" message="Define suite to run using junit.test.suite" /> + <fail unless="com.vaadin.testbench.screenshot.directory" message="Define screenshot directory using -Dcom.vaadin.testbench.screenshot.directory" /> + <junit printsummary="withOutAndErr" fork="yes"> + <formatter usefile="false" type="plain" /> + <classpath refid="classpath.tb3" /> + + <jvmarg value="-Dcom.vaadin.testbench.screenshot.directory=${com.vaadin.testbench.screenshot.directory}" /> + <jvmarg value="-Djava.awt.headless=true" /> + <test name="${junit.test.suite}" /> + </junit> + + </target> + +</project> diff --git a/uitest/test.xml b/uitest/test.xml index 3baccb4117..dd6964e59c 100644 --- a/uitest/test.xml +++ b/uitest/test.xml @@ -83,7 +83,7 @@ <fail unless="com.vaadin.testbench.deployment.url" message="The 'com.vaadin.testbench.deployment.url' property must be defined." /> </target> - <target name="run-tests" depends="compile-tests"> + <target name="run-tb2-tests" depends="check-parameters,compile-tests"> <fileset dir="${test-output-dir}" id="tests-fileset"> <include name="**/**.java" /> </fileset> @@ -161,12 +161,10 @@ <!-- ================================================================== --> <!-- The default target. --> - <target name="run-and-clean-up" depends="check-parameters,remove-error-screens,run-tests" /> + <target name="run-and-clean-up" depends="check-parameters,remove-error-screens,run-tb2-tests" /> - - <!-- Starts the server and runs all TestBench tests --> - <target name="test-package"> - <fail unless="war.file" message="No 'war.file' parameter given." /> + <!-- Runs all TestBench 2 tests --> + <target name="tb2-tests"> <property name="test-output-dir" location="${test.xml.dir}/result/testbench-junit-classes" /> <property name="retries" value="2" /> @@ -177,15 +175,6 @@ <property name="com.vaadin.testbench.screenshot.block.error" value="0.025" /> <property name="com.vaadin.testbench.debug" value="false" /> - <parallel> - <daemons> - <ant antfile="${test.xml.dir}/vaadin-server.xml" inheritall="true" inheritrefs="true" target="deploy-and-start" /> - </daemons> - <sequential> - <ant antfile="${test.xml.dir}/vaadin-server.xml" target="wait-for-startup" /> - <antcall inheritall="true" inheritrefs="true" target="run-and-clean-up" /> - <echo message="All TestBench tests have been run" /> - </sequential> - </parallel> + <antcall inheritall="true" inheritrefs="true" target="run-tb2-tests" /> </target> </project> |