diff options
Diffstat (limited to 'uitest')
31 files changed, 1353 insertions, 79 deletions
diff --git a/uitest/eclipse-run-selected-test.properties b/uitest/eclipse-run-selected-test.properties index cbd1ab1cef..70010fd1da 100644 --- a/uitest/eclipse-run-selected-test.properties +++ b/uitest/eclipse-run-selected-test.properties @@ -1,4 +1,11 @@ ; +; This is an example property file showing how to control how TestBench is used +; in the Vaadin Framework project. You should not modify this file since it's +; under version control. Instead, create a copy of it inside the /work/ folder +; in the project and make your customizations to that file. +; + +; ; For both TestBench 2 and 3 ; @@ -8,6 +15,14 @@ com.vaadin.testbench.screenshot.directory=<enter the full path to the screenshot ; +; For only TestBench 3 +; + +; Simulates @RunLocally with the given value on all test classes without a @RunLocally annotation. +; com.vaadin.testbench.runLocally=firefox + + +; ; For only TestBench 2 ; diff --git a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java index a89ec4e587..1f72495596 100644 --- a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java +++ b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java @@ -17,12 +17,17 @@ package com.vaadin.launcher; import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; @@ -30,7 +35,11 @@ import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import com.vaadin.launcher.CustomDeploymentConfiguration.Conf; +import com.vaadin.server.DefaultDeploymentConfiguration; +import com.vaadin.server.DeploymentConfiguration; import com.vaadin.server.LegacyApplication; import com.vaadin.server.LegacyVaadinServlet; import com.vaadin.server.ServiceException; @@ -43,6 +52,7 @@ import com.vaadin.server.VaadinServletRequest; import com.vaadin.server.VaadinSession; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.UI; +import com.vaadin.util.CurrentInstance; @SuppressWarnings("serial") public class ApplicationRunnerServlet extends LegacyVaadinServlet { @@ -287,4 +297,129 @@ public class ApplicationRunnerServlet extends LegacyVaadinServlet { return Logger.getLogger(ApplicationRunnerServlet.class.getName()); } + @Override + protected DeploymentConfiguration createDeploymentConfiguration( + Properties initParameters) { + // Get the original configuration from the super class + final DeploymentConfiguration originalConfiguration = super + .createDeploymentConfiguration(initParameters); + + // And then create a proxy instance that delegates to the original + // configuration or a customized version + return (DeploymentConfiguration) Proxy.newProxyInstance( + DeploymentConfiguration.class.getClassLoader(), + new Class[] { DeploymentConfiguration.class }, + new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, + Object[] args) throws Throwable { + if (method.getDeclaringClass() == DeploymentConfiguration.class) { + // Find the configuration instance to delegate to + DeploymentConfiguration configuration = findDeploymentConfiguration(originalConfiguration); + + return method.invoke(configuration, args); + } else { + return method.invoke(proxy, args); + } + } + }); + } + + private DeploymentConfiguration findDeploymentConfiguration( + DeploymentConfiguration originalConfiguration) throws Exception { + // First level of cache + DeploymentConfiguration configuration = CurrentInstance + .get(DeploymentConfiguration.class); + + if (configuration == null) { + // Not in cache, try to find a VaadinSession to get it from + VaadinSession session = VaadinSession.getCurrent(); + + if (session == null) { + /* + * There's no current session, request or response when serving + * static resources, but there's still the current request + * maintained by AppliationRunnerServlet, and there's most + * likely also a HttpSession containing a VaadinSession for that + * request. + */ + + HttpServletRequest currentRequest = request.get(); + if (currentRequest != null) { + HttpSession httpSession = currentRequest.getSession(false); + if (httpSession != null) { + Map<Class<?>, CurrentInstance> oldCurrent = CurrentInstance + .setCurrent((VaadinSession) null); + try { + session = getService().findVaadinSession( + new VaadinServletRequest(currentRequest, + getService())); + } finally { + /* + * Clear some state set by findVaadinSession to + * avoid accidentally depending on it when coding on + * e.g. static request handling. + */ + CurrentInstance.restoreInstances(oldCurrent); + currentRequest.removeAttribute(VaadinSession.class + .getName()); + } + } + } + } + + if (session != null) { + String name = ApplicationRunnerServlet.class.getName() + + ".deploymentConfiguration"; + try { + session.lock(); + configuration = (DeploymentConfiguration) session + .getAttribute(name); + + if (configuration == null) { + Class<?> classToRun; + try { + classToRun = getClassToRun(); + } catch (ClassNotFoundException e) { + /* + * This happens e.g. if the UI class defined in the + * URL is not found or if this servlet just serves + * static resources while there's some other servlet + * that serves the UI (e.g. when using /run-push/). + */ + return originalConfiguration; + } + + CustomDeploymentConfiguration customDeploymentConfiguration = classToRun + .getAnnotation(CustomDeploymentConfiguration.class); + if (customDeploymentConfiguration != null) { + Properties initParameters = new Properties( + originalConfiguration.getInitParameters()); + + for (Conf entry : customDeploymentConfiguration + .value()) { + initParameters.put(entry.name(), entry.value()); + } + + configuration = new DefaultDeploymentConfiguration( + getClass(), initParameters); + } else { + configuration = originalConfiguration; + } + + session.setAttribute(name, configuration); + } + } finally { + session.unlock(); + } + + CurrentInstance.set(DeploymentConfiguration.class, + configuration); + + } else { + configuration = originalConfiguration; + } + } + return configuration; + } } diff --git a/uitest/src/com/vaadin/launcher/CustomDeploymentConfiguration.java b/uitest/src/com/vaadin/launcher/CustomDeploymentConfiguration.java new file mode 100644 index 0000000000..da903c13e0 --- /dev/null +++ b/uitest/src/com/vaadin/launcher/CustomDeploymentConfiguration.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.launcher; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(value = ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface CustomDeploymentConfiguration { + + @Target(value = ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + public @interface Conf { + public String name(); + + public String value(); + } + + public CustomDeploymentConfiguration.Conf[] value(); +} diff --git a/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConf.java b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConf.java new file mode 100644 index 0000000000..8ae7715a77 --- /dev/null +++ b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConf.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.applicationservlet; + +import com.vaadin.launcher.ApplicationRunnerServlet; +import com.vaadin.launcher.CustomDeploymentConfiguration; +import com.vaadin.launcher.CustomDeploymentConfiguration.Conf; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Label; + +@CustomDeploymentConfiguration({ + @Conf(name = "customParam", value = "customValue"), + @Conf(name = "resourceCacheTime", value = "3599") }) +public class CustomDeploymentConf extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + DeploymentConfiguration deploymentConfiguration = getSession() + .getService().getDeploymentConfiguration(); + addComponent(new Label("Resource cache time: " + + deploymentConfiguration.getResourceCacheTime())); + addComponent(new Label("Custom config param: " + + deploymentConfiguration.getApplicationOrSystemProperty( + "customParam", null))); + } + + @Override + protected String getTestDescription() { + return "Demonstrates the @" + + CustomDeploymentConfiguration.class.getSimpleName() + + " feature that allows customizing the effective deployment configuration for test UIs run through " + + ApplicationRunnerServlet.class.getSimpleName() + "."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(14215); + } + +} diff --git a/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConfTest.java b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConfTest.java new file mode 100644 index 0000000000..e74eea6c55 --- /dev/null +++ b/uitest/src/com/vaadin/tests/applicationservlet/CustomDeploymentConfTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.applicationservlet; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.VerticalLayoutElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class CustomDeploymentConfTest extends MultiBrowserTest { + @Test + public void testCustomDeploymentConf() { + openTestURL(); + + LabelElement cacheTimeLabel = $$(VerticalLayoutElement.class) + .$$(VerticalLayoutElement.class).$$(LabelElement.class).first(); + + LabelElement customParamLabel = $$(VerticalLayoutElement.class) + .$$(VerticalLayoutElement.class).$$(LabelElement.class).get(1); + + Assert.assertEquals("Resource cache time: 3599", + cacheTimeLabel.getText()); + Assert.assertEquals("Custom config param: customValue", + customParamLabel.getText()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/button/ButtonTooltips.html b/uitest/src/com/vaadin/tests/components/button/ButtonTooltips.html deleted file mode 100644 index 13fdf52c76..0000000000 --- a/uitest/src/com/vaadin/tests/components/button/ButtonTooltips.html +++ /dev/null @@ -1,37 +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.168: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.components.button.ButtonTooltips?restartApplication</td> - <td></td> -</tr> -<tr> - <td>showTooltip</td> - <td>vaadin=runcomvaadintestscomponentsbuttonButtonTooltips::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> - <td>0,0</td> -</tr> -<tr> - <td>showTooltip</td> - <td>vaadin=runcomvaadintestscomponentsbuttonButtonTooltips::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> - <td>0,0</td> -</tr> -<tr> - <td>screenCapture</td> - <td></td> - <td></td> -</tr> - -</tbody></table> -</body> -</html> diff --git a/uitest/src/com/vaadin/tests/components/table/MemoryLeakTable.java b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTable.java new file mode 100644 index 0000000000..1b76be3b72 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTable.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Table; + +/** + * Test UI Class for testing memory leak in table (#14159). + * + * @since + * @author Vaadin Ltd + */ +public class MemoryLeakTable extends AbstractTestUI { + Button btnAdd = new Button("Add rows"); + Button btnRemove = new Button("Remove rows"); + Button btnTenTimes = new Button("Do ten times"); + Table tbl = new Table(); + static final int COLS = 15; + static final int ROWS = 2000; + + private void addRows() { + IndexedContainer idx = new IndexedContainer(); + for (int i = 0; i < COLS; i++) { + idx.addContainerProperty("name " + i, String.class, "value"); + } + for (int i = 0; i < ROWS; i++) { + idx.addItem("item" + i); + } + tbl.setContainerDataSource(idx); + addComponent(tbl); + } + + private void removeRows() { + tbl.removeAllItems(); + removeComponent(tbl); + } + + @Override + protected void setup(VaadinRequest request) { + btnAdd.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + addRows(); + } + }); + btnRemove.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + removeRows(); + } + }); + addComponent(btnAdd); + addComponent(btnRemove); + } + + @Override + protected String getTestDescription() { + return "Generates table for memory leaking test"; + } + + @Override + protected Integer getTicketNumber() { + return 14159; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/MemoryLeakTableTest.java b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTableTest.java new file mode 100644 index 0000000000..b4b8d93fbe --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/MemoryLeakTableTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import java.io.IOException; +import java.util.Random; + +import org.junit.Ignore; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.AbstractTB3Test.RunLocally; +import com.vaadin.tests.tb3.MultiBrowserTest; +import com.vaadin.tests.tb3.MultiBrowserTest.Browser; + +/** + * Test case creating and deleting table component in a loop, testing memory + * lead in Table component. This test should not be used in auto testing. + * + * To test memory consuption. Run test in debug mode. Take memory snapshot in + * Profiler in browser before and after the loop. Compare memory consuption. + * + * @since + * @author Vaadin Ltd + */ +@RunLocally(Browser.CHROME) +public class MemoryLeakTableTest extends MultiBrowserTest { + + /** + * + */ + private static final int ITERATIONS = 200; + + // To run locally in chrome download ChromeDriver for TB3 + // Set path to the chrome driver. In + // ./work/eclipse-run-selected-test.properties add line + // chrome.driver.path=path_to_driver + + // Test is marked as ignore to exclude it from auto testing + @Test + @Ignore + public void memoryTest() throws IOException { + // Set breakoint and look memory consuption in Profiler + // Mozilla Firefox doesn't provide memory usage profiler, use chrome. + + openTestURL(); + + ButtonElement btnAdd = $(ButtonElement.class).get(0); + + for (int i = 0; i < ITERATIONS; i++) { + btnAdd.click(); + ButtonElement btnDel = $(ButtonElement.class).get(1); + TableElement tbl = $(TableElement.class).get(0); + Random rand = new Random(); + int scrollValue = rand.nextInt(1500); + scrollTable(tbl, scrollValue); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + btnDel.click(); + } + // Set breakoint and look memory consuption in Profiler + btnAdd = $(ButtonElement.class).get(0); + } + + // Scrolls table element + // Method scroll in TalbeElement class has a bug + // + private void scrollTable(TableElement tbl, int value) { + WebElement actualElement = tbl.findElement(By + .className("v-table-body-wrapper")); + JavascriptExecutor js = tbl.getCommandExecutor(); + js.executeScript("arguments[0].scrollTop = " + value, actualElement); + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableTooManyColumns.java b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumns.java new file mode 100644 index 0000000000..2d27636420 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumns.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.ColumnGenerator; + +public class TableTooManyColumns extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Table table = new Table(); + + table.setColumnCollapsingAllowed(true); + + for (int i = 0; i < 91; i++) { + table.addGeneratedColumn("COLUMN " + i, new ColumnGenerator() { + + @Override + public Object generateCell(Table source, Object itemId, + Object columnId) { + return columnId; + } + }); + } + + addComponent(table); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Table column drop down becomes too large to fit the screen."; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 14156; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableTooManyColumnsTest.java b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumnsTest.java new file mode 100644 index 0000000000..2244365e00 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableTooManyColumnsTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import java.io.IOException; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.commands.TestBenchElementCommands; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TableTooManyColumnsTest extends MultiBrowserTest { + + @Test + public void testDropdownTable() throws IOException { + openTestURL(); + + WebElement element = findElement(By + .className("v-table-column-selector")); + + element.click(); + + WebElement menu = findElement(By.className("gwt-MenuBar-vertical")); + + TestBenchElementCommands scrollable = testBenchElement(menu); + scrollable.scroll(3000); + + compareScreen(getScreenshotBaseName()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpace.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpace.java new file mode 100644 index 0000000000..0105498f27 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpace.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.tabsheet; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Panel; +import com.vaadin.ui.TabSheet; + +/** + * Test to see if tabsheet navigation buttons render correctly in Chameleon + * + * @author Vaadin Ltd + */ +@Theme("chameleon") +public class TabsheetNotEnoughHorizontalSpace extends AbstractTestUI { + + private TabSheet tabsheet = new TabSheet(); + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#setup(com.vaadin.server. + * VaadinRequest) + */ + @Override + protected void setup(VaadinRequest request) { + generateTabs(); + tabsheet.setSizeFull(); + addComponent(tabsheet); + + } + + private void generateTabs() { + tabsheet.removeAllComponents(); + for (int i = 0; i < 100; ++i) { + tabsheet.addTab(new Panel(), "Tab" + i); + } + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Scroll-buttons should render correctly on all browsers"; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 12154; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpaceTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpaceTest.java new file mode 100644 index 0000000000..990f545697 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/TabsheetNotEnoughHorizontalSpaceTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.tabsheet; + +import java.io.IOException; + +import org.junit.Test; + +import com.vaadin.testbench.By; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests that tabsheet's scroll button are rendered correctly in Chameleon + * theme. + * + * Ticket #12154 + * + * @since + * @author Vaadin Ltd + */ +public class TabsheetNotEnoughHorizontalSpaceTest extends MultiBrowserTest { + + @Test + public void testThatTabScrollButtonsAreRenderedCorrectly() + throws IOException { + openTestURL(); + + driver.findElement(By.className("v-tabsheet-scrollerPrev-disabled")); + driver.findElement(By.className("v-tabsheet-scrollerNext")); + + compareScreen(getScreenshotBaseName()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java b/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java index 1887427a72..ae966a5b07 100644 --- a/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java +++ b/uitest/src/com/vaadin/tests/components/upload/TestFileUploadTest.java @@ -109,7 +109,7 @@ public class TestFileUploadTest extends MultiBrowserTest { } private void setLocalFileDetector(WebElement element) throws Exception { - if (getClass().isAnnotationPresent(RunLocally.class)) { + if (getRunLocallyBrowser() != null) { return; } diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java index 1c18fb1912..333964e9bf 100644 --- a/uitest/src/com/vaadin/tests/serialization/SerializerTest.java +++ b/uitest/src/com/vaadin/tests/serialization/SerializerTest.java @@ -93,13 +93,13 @@ public class SerializerTest extends AbstractTestUI { rpc.sendInt(Integer.MAX_VALUE, Integer.valueOf(0), new int[] { 5, 7 }); state.intValue = Integer.MAX_VALUE; - state.intObjectValue = Integer.valueOf(0); + state.intObjectValue = Integer.valueOf(42); state.intArray = new int[] { 5, 7 }; rpc.sendLong(577431841358l, Long.valueOf(0), new long[] { -57841235865l, 57 }); - state.longValue = 577431841358l; - state.longObjectValue = Long.valueOf(0); + state.longValue = 577431841359l; + state.longObjectValue = Long.valueOf(577431841360l); state.longArray = new long[] { -57841235865l, 57 }; rpc.sendFloat(3.14159f, Float.valueOf(Math.nextUp(1)), new float[] { @@ -111,7 +111,7 @@ public class SerializerTest extends AbstractTestUI { rpc.sendDouble(Math.PI, Double.valueOf(-Math.E), new double[] { Double.MAX_VALUE, Double.MIN_VALUE }); state.doubleValue = Math.PI; - state.doubleValue = Double.valueOf(-Math.E); + state.doubleObjectValue = Double.valueOf(-Math.E); state.doubleArray = new double[] { Double.MAX_VALUE, Double.MIN_VALUE }; rpc.sendString("This is a tesing string ‡"); diff --git a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java index 5ca1e9ce6a..47bb212347 100644 --- a/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java +++ b/uitest/src/com/vaadin/tests/serialization/SerializerTestTest.java @@ -77,5 +77,36 @@ public class SerializerTestTest extends MultiBrowserTest { "sendBoolean: false, false, [false, false, true, false, true, true]", getLogRow(logRow++)); Assert.assertEquals("sendBeanSubclass: 43", getLogRow(logRow++)); + Assert.assertEquals( + "state.doubleArray: [1.7976931348623157e+308, 5e-324]", + getLogRow(logRow++)); + Assert.assertEquals("state.doubleObjectValue: -2.718281828459045", + getLogRow(logRow++)); + Assert.assertEquals("state.doubleValue: 3.141592653589793", + getLogRow(logRow++)); + Assert.assertEquals("state.floatArray: [57, 0, -12]", + getLogRow(logRow++)); + Assert.assertEquals("state.floatObjectValue: 1.0000001", + getLogRow(logRow++)); + Assert.assertEquals("state.floatValue: 3.14159", getLogRow(logRow++)); + Assert.assertEquals("state.longArray: [-57841235865, 57]", + getLogRow(logRow++)); + Assert.assertEquals("state.longObjectValue: 577431841360", + getLogRow(logRow++)); + Assert.assertEquals("state.longValue: 577431841359", + getLogRow(logRow++)); + Assert.assertEquals("state.intArray: [5, 7]", getLogRow(logRow++)); + Assert.assertEquals("state.intObjectValue: 42", getLogRow(logRow++)); + Assert.assertEquals("state.intValue: 2147483647", getLogRow(logRow++)); + Assert.assertEquals("state.charArray: aBcD", getLogRow(logRow++)); + Assert.assertEquals("state.charObjectValue: å", getLogRow(logRow++)); + Assert.assertEquals("state.charValue: ∫", getLogRow(logRow++)); + Assert.assertEquals("state.byteArray: [3, 1, 2]", getLogRow(logRow++)); + Assert.assertEquals("state.byteObjectValue: -12", getLogRow(logRow++)); + Assert.assertEquals("state.byteValue: 5", getLogRow(logRow++)); + Assert.assertEquals( + "state.booleanArray: [true, true, false, true, false, false]", + getLogRow(logRow++)); + } } diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java index fa704d7b0b..8dd10216d2 100644 --- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java +++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java @@ -120,9 +120,13 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { protected void setupDriver() throws Exception { DesiredCapabilities capabilities; - RunLocally runLocally = getClass().getAnnotation(RunLocally.class); - if (runLocally != null) { - capabilities = runLocally.value().getDesiredCapabilities(); + Browser runLocallyBrowser = getRunLocallyBrowser(); + if (runLocallyBrowser != null) { + if (System.getenv().containsKey("TEAMCITY_VERSION")) { + throw new RuntimeException( + "@RunLocally is not supported for tests run on the build server"); + } + capabilities = runLocallyBrowser.getDesiredCapabilities(); setupLocalDriver(capabilities); } else { capabilities = getDesiredCapabilities(); @@ -152,6 +156,15 @@ public abstract class AbstractTB3Test extends TestBenchTestCase { } + protected Browser getRunLocallyBrowser() { + RunLocally runLocally = getClass().getAnnotation(RunLocally.class); + if (runLocally != null) { + return runLocally.value(); + } else { + return null; + } + } + protected WebElement getTooltipElement() { return getDriver().findElement(com.vaadin.testbench.By.className("v-tooltip-text")); } diff --git a/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java index 305caf1cb5..15ca97f701 100644 --- a/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java +++ b/uitest/src/com/vaadin/tests/tb3/PrivateTB3Configuration.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.util.Arrays; import java.util.Enumeration; import java.util.Properties; @@ -34,6 +35,7 @@ import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.safari.SafariDriver; import com.vaadin.testbench.TestBench; +import com.vaadin.tests.tb3.MultiBrowserTest.Browser; /** * Provides values for parameters which depend on where the test is run. @@ -43,14 +45,16 @@ import com.vaadin.testbench.TestBench; * @author Vaadin Ltd */ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test { + private static final String RUN_LOCALLY_PROPERTY = "com.vaadin.testbench.runLocally"; private static final String HOSTNAME_PROPERTY = "com.vaadin.testbench.deployment.hostname"; private static final String PORT_PROPERTY = "com.vaadin.testbench.deployment.port"; private static final Properties properties = new Properties(); + private static final File propertiesFile = new File("work", + "eclipse-run-selected-test.properties"); static { - File file = new File("work", "eclipse-run-selected-test.properties"); - if (file.exists()) { + if (propertiesFile.exists()) { try { - properties.load(new FileInputStream(file)); + properties.load(new FileInputStream(propertiesFile)); } catch (IOException e) { throw new RuntimeException(e); } @@ -66,6 +70,16 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test { return property; } + private static String getSource(String propertyName) { + if (properties.containsKey(propertyName)) { + return propertiesFile.getAbsolutePath(); + } else if (System.getProperty(propertyName) != null) { + return "System.getProperty()"; + } else { + return null; + } + } + @Override protected String getScreenshotDirectory() { String screenshotDirectory = getProperty("com.vaadin.testbench.screenshot.directory"); @@ -83,7 +97,7 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test { @Override protected String getDeploymentHostname() { - if (getClass().getAnnotation(RunLocally.class) != null) { + if (getRunLocallyBrowser() != null) { return "localhost"; } return getConfiguredDeploymentHostname(); @@ -180,8 +194,21 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test { driver = new FirefoxDriver(); } } else if (BrowserUtil.isChrome(desiredCapabilities)) { - System.setProperty("webdriver.chrome.driver", - getProperty("chrome.driver.path")); + String propertyName = "chrome.driver.path"; + String chromeDriverPath = getProperty(propertyName); + if (chromeDriverPath == null) { + throw new RuntimeException( + "You need to install ChromeDriver to use @" + + RunLocally.class.getSimpleName() + + " with Chrome." + + "\nFirst install it from https://code.google.com/p/selenium/wiki/ChromeDriver." + + "\nThen update " + + propertiesFile.getAbsolutePath() + + " to define a property named " + + propertyName + + " containing the path of your local ChromeDriver installation."); + } + System.setProperty("webdriver.chrome.driver", chromeDriverPath); driver = new ChromeDriver(); } else if (BrowserUtil.isSafari(desiredCapabilities)) { driver = new SafariDriver(); @@ -196,4 +223,28 @@ public abstract class PrivateTB3Configuration extends ScreenshotTB3Test { setDriver(TestBench.createDriver(driver)); setDesiredCapabilities(desiredCapabilities); } + + @Override + protected Browser getRunLocallyBrowser() { + Browser runLocallyBrowser = super.getRunLocallyBrowser(); + if (runLocallyBrowser != null) { + // Always use annotation value if present + return runLocallyBrowser; + } + + String runLocallyValue = getProperty(RUN_LOCALLY_PROPERTY); + if (runLocallyValue == null || runLocallyValue.trim().isEmpty()) { + return null; + } + + String browserName = runLocallyValue.trim().toUpperCase(); + try { + return Browser.valueOf(browserName); + } catch (IllegalArgumentException e) { + throw new RuntimeException("Invalid " + RUN_LOCALLY_PROPERTY + + " property from " + getSource(RUN_LOCALLY_PROPERTY) + + ": " + runLocallyValue + ". Expected one of " + + Arrays.toString(Browser.values())); + } + } } diff --git a/uitest/src/com/vaadin/tests/tb3/TB3Runner.java b/uitest/src/com/vaadin/tests/tb3/TB3Runner.java index 4d29e479e2..5b5a6dcf39 100644 --- a/uitest/src/com/vaadin/tests/tb3/TB3Runner.java +++ b/uitest/src/com/vaadin/tests/tb3/TB3Runner.java @@ -37,7 +37,7 @@ import org.openqa.selenium.remote.DesiredCapabilities; import com.vaadin.tests.annotations.TestCategory; import com.vaadin.tests.tb3.AbstractTB3Test.BrowserUtil; -import com.vaadin.tests.tb3.AbstractTB3Test.RunLocally; +import com.vaadin.tests.tb3.MultiBrowserTest.Browser; /** * This runner is loosely based on FactoryTestRunner by Ted Young @@ -185,17 +185,17 @@ public class TB3Runner extends BlockJUnit4ClassRunner { /* * Returns a list of desired browser capabilities according to browsers * defined in the test class, filtered by possible filter parameters. Use - * {@code @RunLocally} annotation to override all capabilities. + * {@code @RunLocally} annotation or com.vaadin.testbench.runLocally + * property to override all capabilities. */ private Collection<DesiredCapabilities> getDesiredCapabilities( AbstractTB3Test testClassInstance) { Collection<DesiredCapabilities> desiredCapabilites = getFilteredCapabilities(testClassInstance); - if (isRunLocally(testClassInstance)) { + Browser runLocallyBrowser = testClassInstance.getRunLocallyBrowser(); + if (runLocallyBrowser != null) { desiredCapabilites = new ArrayList<DesiredCapabilities>(); - desiredCapabilites.add(testClassInstance.getClass() - .getAnnotation(RunLocally.class).value() - .getDesiredCapabilities()); + desiredCapabilites.add(runLocallyBrowser.getDesiredCapabilities()); } return desiredCapabilites; @@ -237,10 +237,6 @@ public class TB3Runner extends BlockJUnit4ClassRunner { return filteredCapabilities; } - private boolean isRunLocally(AbstractTB3Test testClassInstance) { - return testClassInstance.getClass().getAnnotation(RunLocally.class) != null; - } - private AbstractTB3Test getTestClassInstance() throws InstantiationException, IllegalAccessException, InvocationTargetException { diff --git a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java index d212a13058..c341aa689b 100644 --- a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java +++ b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltips.java @@ -1,14 +1,18 @@ package com.vaadin.tests.tooltip; -import com.vaadin.tests.components.TestBase; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.VerticalLayout; -public class ButtonTooltips extends TestBase { +public class ButtonTooltips extends AbstractTestUI { + + public static final String shortDescription = "Another"; + public static final String longDescription = "long descidescidescpription"; @Override - protected String getDescription() { + protected String getTestDescription() { return "Button tooltip's size gets messed up if moving from one tooltip to another before a timer expires."; } @@ -18,12 +22,12 @@ public class ButtonTooltips extends TestBase { } @Override - protected void setup() { + protected void setup(VaadinRequest request) { VerticalLayout vl = new VerticalLayout(); Button button = new Button("One"); - button.setDescription("long descidescidescpription"); + button.setDescription(longDescription); Button button2 = new Button("Two"); - button2.setDescription("Another"); + button2.setDescription(shortDescription); vl.addComponent(button); vl.addComponent(button2); vl.setComponentAlignment(button, Alignment.TOP_RIGHT); diff --git a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java index d64dd900a7..08436b1332 100644 --- a/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java +++ b/uitest/src/com/vaadin/tests/tooltip/ButtonTooltipsTest.java @@ -1,12 +1,12 @@ /* * Copyright 2000-2014 Vaadin Ltd. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -26,7 +26,7 @@ import com.vaadin.tests.tb3.TooltipTest; /** * Tests that tooltip sizes do not change when moving between adjacent elements - * + * * @author Vaadin Ltd */ public class ButtonTooltipsTest extends TooltipTest { @@ -38,12 +38,12 @@ public class ButtonTooltipsTest extends TooltipTest { WebElement buttonOne = $(ButtonElement.class).caption("One").first(); WebElement buttonTwo = $(ButtonElement.class).caption("Two").first(); - checkTooltip(buttonOne, "long descidescidescpription"); + checkTooltip(buttonOne, ButtonTooltips.longDescription); int originalWidth = getTooltipElement().getSize().getWidth(); int originalHeight = getTooltipElement().getSize().getHeight(); clearTooltip(); - checkTooltip(buttonTwo, "Another"); + checkTooltip(buttonTwo, ButtonTooltips.shortDescription); moveMouseTo(buttonOne, 5, 5); sleep(100); assertThat(getTooltipElement().getSize().getWidth(), is(originalWidth)); diff --git a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml index ac93efd7d4..d23903f9db 100644 --- a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml +++ b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml @@ -15,4 +15,9 @@ <when-type-is class="com.vaadin.client.communication.PushConnection" /> </replace-with> + <replace-with + class="com.vaadin.tests.widgetset.client.MockApplicationConnection"> + <when-type-is class="com.vaadin.client.ApplicationConnection" /> + </replace-with> + </module> diff --git a/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java b/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java new file mode 100644 index 0000000000..4ee5b71387 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/MockApplicationConnection.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.client; + +import java.util.Date; +import java.util.logging.Logger; + +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONValue; +import com.vaadin.client.ApplicationConnection; +import com.vaadin.client.ValueMap; +import com.vaadin.shared.ApplicationConstants; +import com.vaadin.tests.widgetset.server.csrf.ui.CsrfTokenDisabled; + +/** + * Mock ApplicationConnection for several issues where we need to hack it. + * + * @since + * @author Vaadin Ltd + */ +public class MockApplicationConnection extends ApplicationConnection { + + private static final Logger LOGGER = Logger + .getLogger(MockApplicationConnection.class.getName()); + + // The last token received from the server. + private String lastCsrfTokenReceiver; + + // The last token sent to the server. + private String lastCsrfTokenSent; + + /** + * Provide the last token received from the server. <br/> + * We added this to test the change done on CSRF token. + * + * @see CsrfTokenDisabled + */ + public String getLastCsrfTokenReceiver() { + return lastCsrfTokenReceiver; + } + + /** + * Provide the last token sent to the server. <br/> + * We added this to test the change done on CSRF token. + * + * @see CsrfTokenDisabled + */ + public String getLastCsrfTokenSent() { + return lastCsrfTokenSent; + } + + @Override + protected void handleUIDLMessage(Date start, String jsonText, ValueMap json) { + lastCsrfTokenReceiver = json + .getString(ApplicationConstants.UIDL_SECURITY_TOKEN_ID); + + super.handleUIDLMessage(start, jsonText, json); + } + + @Override + protected void doUidlRequest(String uri, JSONObject payload) { + JSONValue jsonValue = payload.get(ApplicationConstants.CSRF_TOKEN); + lastCsrfTokenSent = jsonValue != null ? jsonValue.toString() : null; + + super.doUidlRequest(uri, payload); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java index 0ef4b664ac..7758cdc2ac 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/SerializerTestConnector.java @@ -284,11 +284,12 @@ public class SerializerTestConnector extends AbstractExtensionConnector { public void onStateChanged(StateChangeEvent stateChangeEvent) { rpc.log("state.booleanValue: " + getState().booleanValue); rpc.log("state.booleanObjectValue: " + getState().booleanObjectValue); - rpc.log("state.booleanArray: " + getState().booleanArray); + rpc.log("state.booleanArray: " + + Arrays.toString(getState().booleanArray)); rpc.log("state.byteValue: " + getState().byteValue); rpc.log("state.byteObjectValue: " + getState().byteObjectValue); - rpc.log("state.byteArray: " + getState().byteArray); + rpc.log("state.byteArray: " + Arrays.toString(getState().byteArray)); rpc.log("state.charValue: " + getState().charValue); rpc.log("state.charObjectValue: " + getState().charObjectValue); @@ -296,19 +297,19 @@ public class SerializerTestConnector extends AbstractExtensionConnector { rpc.log("state.intValue: " + getState().intValue); rpc.log("state.intObjectValue: " + getState().intObjectValue); - rpc.log("state.intArray: " + getState().intArray); + rpc.log("state.intArray: " + Arrays.toString(getState().intArray)); rpc.log("state.longValue: " + getState().longValue); rpc.log("state.longObjectValue: " + getState().longObjectValue); - rpc.log("state.longArray: " + getState().longArray); + rpc.log("state.longArray: " + Arrays.toString(getState().longArray)); rpc.log("state.floatValue: " + getState().floatValue); rpc.log("state.floatObjectValue: " + getState().floatObjectValue); - rpc.log("state.floatArray: " + getState().floatArray); + rpc.log("state.floatArray: " + Arrays.toString(getState().floatArray)); rpc.log("state.doubleValue: " + getState().doubleValue); rpc.log("state.doubleObjectValue: " + getState().doubleObjectValue); - rpc.log("state.doubleArray: " + getState().doubleArray); + rpc.log("state.doubleArray: " + Arrays.toString(getState().doubleArray)); /* * TODO public double doubleValue; public Double DoubleValue; public diff --git a/uitest/src/com/vaadin/tests/widgetset/client/csrf/CsrfButtonConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/csrf/CsrfButtonConnector.java new file mode 100644 index 0000000000..cf24ed6921 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/csrf/CsrfButtonConnector.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.client.csrf; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.client.ui.VButton; +import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.widgetset.client.MockApplicationConnection; +import com.vaadin.tests.widgetset.server.csrf.CsrfButton; + +/** + * Dummy connector to test our CSRF bug. See #14111. + * + * @author Vaadin Ltd + */ +@SuppressWarnings("serial") +@Connect(CsrfButton.class) +public class CsrfButtonConnector extends AbstractComponentConnector { + + static Logger logger = Logger + .getLogger(CsrfButtonConnector.class.getName()); + static { + logger.setLevel(Level.ALL); + } + + @Override + public VButton getWidget() { + return (VButton) super.getWidget(); + } + + @Override + protected VButton createWidget() { + return GWT.create(VButton.class); + } + + public final static String ID = "CsrfButton"; + + @Override + public void init() { + super.init(); + + getWidget().getElement().setId(ID); + getWidget().setText(csrfTokenInfo()); + getWidget().addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + getWidget().setText(csrfTokenInfo()); + } + }); + } + + private String csrfTokenInfo() { + return getMockConnection().getCsrfToken() + ", " + + getMockConnection().getLastCsrfTokenReceiver() + ", " + + getMockConnection().getLastCsrfTokenSent(); + } + + private MockApplicationConnection getMockConnection() { + return (MockApplicationConnection) getConnection(); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/CsrfButton.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/CsrfButton.java new file mode 100644 index 0000000000..567127927d --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/CsrfButton.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.csrf; + +import com.vaadin.ui.AbstractComponent; + +/** + * Dummy client connector to link with the client functionality if the + * CsrfToken. + * + * @since + * @author Vaadin Ltd + */ +@SuppressWarnings("serial") +public class CsrfButton extends AbstractComponent { + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUI.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUI.java new file mode 100644 index 0000000000..f8f1754385 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUI.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.csrf.ui; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.tests.widgetset.server.csrf.CsrfButton; +import com.vaadin.ui.Button; +import com.vaadin.ui.Label; + +/** + * Abstract UI to test the CSRF token issue as reported in (#14111) + * + * @since + * @author Vaadin Ltd + */ +@SuppressWarnings("serial") +@Widgetset(TestingWidgetSet.NAME) +public abstract class AbstractCsrfTokenUI extends AbstractTestUI { + + public static final String PRESS_ID = "PressMe"; + + @Override + protected void setup(VaadinRequest request) { + + addComponent(new Label("The button's text is the client token:")); + addComponent(new CsrfButton()); + addComponent(new Label("This one is from the server")); + addComponent(new Label(getSession().getCsrfToken())); + Button pressMe = new Button("Click me to send a request"); + pressMe.setId(PRESS_ID); + addComponent(pressMe); + } + + @Override + protected String getTestDescription() { + return "Remove csrfToken from the request if security protection is disabled."; + } + + @Override + protected Integer getTicketNumber() { + return 14111; + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUITest.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUITest.java new file mode 100644 index 0000000000..614eaa063e --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/AbstractCsrfTokenUITest.java @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.csrf.ui; + +import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.tests.tb3.MultiBrowserTest; +import com.vaadin.tests.widgetset.client.csrf.CsrfButtonConnector; + +public abstract class AbstractCsrfTokenUITest extends MultiBrowserTest { + + static final Logger LOGGER = Logger.getLogger(AbstractCsrfTokenUITest.class + .getName()); + + @Test + public void testTokens() { + openTestURL(); + + final By debugButton = By.id(CsrfButtonConnector.ID); + + final String debugMessage1 = getDriver().findElement(debugButton) + .getText(); + + getDriver().findElement(By.id(CsrfTokenDisabled.PRESS_ID)).click(); + + waitUntil(new ExpectedCondition<Boolean>() { + + @Override + public Boolean apply(WebDriver input) { + getDriver().findElement(debugButton).click(); + String debugMessage2 = input.findElement(debugButton).getText(); + + LOGGER.log(Level.INFO, "1: " + debugMessage1); + LOGGER.log(Level.INFO, "2: " + debugMessage2); + + if (!debugMessage1.equals(debugMessage2)) { + + compareMessage(split(debugMessage1), split(debugMessage2)); + + LOGGER.log(Level.INFO, "DONE"); + + return true; + + } else { + return false; + } + } + }); + } + + private TokenGroup split(String debugMessage) { + StringTokenizer tokenizer = new StringTokenizer(debugMessage, ", \""); + + return new TokenGroup(tokenizer.nextToken(), tokenizer.nextToken(), + tokenizer.nextToken()); + } + + /* + * Just implement this. + */ + protected abstract boolean compareMessage(TokenGroup tokenGroup1, + TokenGroup tokenGroup2); + + boolean isNullOrUndefined(String value) { + return isNull(value) || isUndefined(value); + } + + boolean isUndefined(String value) { + return value.equals("undefined"); + } + + boolean isNull(String value) { + return value.equals("null"); + } + + /* + * Wrapps all tokens from the client app. + */ + static class TokenGroup { + + public final String clientToken; + + public final String tokenReceivedFromServer; + + public final String tokenSentToServer; + + public TokenGroup(String clientToken, String tokenReceivedFromServer, + String tokenSentToServer) { + this.clientToken = clientToken; + this.tokenReceivedFromServer = tokenReceivedFromServer; + this.tokenSentToServer = tokenSentToServer; + } + + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabled.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabled.java new file mode 100644 index 0000000000..6283285b40 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabled.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.csrf.ui; + +import com.vaadin.launcher.CustomDeploymentConfiguration; +import com.vaadin.launcher.CustomDeploymentConfiguration.Conf; + +/** + * When the disable-xsrf-protection is true csrfToken is not present anymore + * with the requests.<br/> + * This is useful mostly when the client is not Vaadin and so it will not push + * the parameter anyway. So now the server knows how to deal the issue if the + * csrfToken is not present. + * + * @since + * @author Vaadin Ltd + */ +@SuppressWarnings("serial") +@CustomDeploymentConfiguration({ @Conf(name = "disable-xsrf-protection", value = "true") }) +public class CsrfTokenDisabled extends AbstractCsrfTokenUI { + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabledTest.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabledTest.java new file mode 100644 index 0000000000..504425fead --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenDisabledTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.csrf.ui; + +import com.vaadin.shared.ApplicationConstants; + +/** + * Test the CSRF Token issue. + * + * @since + * @author Vaadin Ltd + */ +public class CsrfTokenDisabledTest extends AbstractCsrfTokenUITest { + + @Override + protected boolean compareMessage(TokenGroup tokenGroup1, + TokenGroup tokenGroup2) { + + return tokenGroup1.clientToken + .equals(ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE) + && isUndefined(tokenGroup1.tokenReceivedFromServer) + && isUndefined(tokenGroup1.tokenSentToServer) + && tokenGroup2.clientToken + .equals(ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE) + && isUndefined(tokenGroup2.tokenReceivedFromServer) + // This is it actually, no token sent to the server. + && isNull(tokenGroup2.tokenSentToServer); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabled.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabled.java new file mode 100644 index 0000000000..cd02c6da77 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabled.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.csrf.ui; + +import com.vaadin.launcher.CustomDeploymentConfiguration; +import com.vaadin.launcher.CustomDeploymentConfiguration.Conf; + +@SuppressWarnings("serial") +@CustomDeploymentConfiguration({ @Conf(name = "disable-xsrf-protection", value = "false") }) +public class CsrfTokenEnabled extends AbstractCsrfTokenUI { + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabledTest.java b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabledTest.java new file mode 100644 index 0000000000..1d51f1c372 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/csrf/ui/CsrfTokenEnabledTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.csrf.ui; + +/** + * Test the CSRF Token issue. + * + * @since + * @author Vaadin Ltd + */ +public class CsrfTokenEnabledTest extends AbstractCsrfTokenUITest { + + @Override + protected boolean compareMessage(TokenGroup tokenGroup1, + TokenGroup tokenGroup2) { + + return tokenGroup1.clientToken.equals(tokenGroup2.clientToken) + // Valid token received and set on the client + && tokenGroup1.clientToken + .equals(tokenGroup1.tokenReceivedFromServer) + // No token sent yet to the server. + && isUndefined(tokenGroup1.tokenSentToServer) + // Token is sent to the server. + && tokenGroup2.clientToken + .equals(tokenGroup2.tokenSentToServer) + // And no more token received from the server. + && isUndefined(tokenGroup2.tokenReceivedFromServer); + } + +} |