diff options
author | Teemu Suo-Anttila <tsuoanttila@users.noreply.github.com> | 2017-10-13 09:44:32 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-13 09:44:32 +0300 |
commit | 569072dccd09a018850abb3a7f9d39373c082d4f (patch) | |
tree | 03b19813308487fa1f83437edc0f75ee692511dc /test | |
parent | c147b5d85bca3ddf30d9adbcd268066165889f37 (diff) | |
download | vaadin-framework-569072dccd09a018850abb3a7f9d39373c082d4f.tar.gz vaadin-framework-569072dccd09a018850abb3a7f9d39373c082d4f.zip |
Add Navigator testing to Spring Boot test (#10174)
Diffstat (limited to 'test')
31 files changed, 1021 insertions, 46 deletions
diff --git a/test/pom.xml b/test/pom.xml index f9b5a2e473..6c01fd7530 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -109,6 +109,7 @@ <module>space in directory</module> <module>vaadinservletconfiguration-widget-set</module> <module>spring-boot</module> + <module>spring-boot-subcontext</module> <module>cdi</module> <!-- Servlet container tests --> diff --git a/test/spring-boot-subcontext/pom.xml b/test/spring-boot-subcontext/pom.xml new file mode 100644 index 0000000000..0a8bc052df --- /dev/null +++ b/test/spring-boot-subcontext/pom.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-test</artifactId> + <version>8.2-SNAPSHOT</version> + </parent> + <artifactId>vaadin-test-spring-boot-subcontext</artifactId> + <packaging>jar</packaging> + + <name>vaadin-test-spring-boot-subcontext</name> + <description>Demo project for Vaadin Spring Boot</description> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <java.version>1.8</java.version> + <spring.boot.version>1.4.2.RELEASE</spring.boot.version> + <jetty.skip>true</jetty.skip> + </properties> + + <dependencies> + <dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-spring-boot-starter</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>com.vaadin</groupId> + <artifactId>vaadin-bom</artifactId> + <version>${vaadin.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <type>pom</type> + <scope>import</scope> + <version>${spring.boot.version}</version> + </dependency> + </dependencies> + </dependencyManagement> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>${spring.boot.version}</version> + </plugin> + </plugins> + </build> + +</project> diff --git a/test/spring-boot-subcontext/src/main/java/com/example/CustomSpringNavigator.java b/test/spring-boot-subcontext/src/main/java/com/example/CustomSpringNavigator.java new file mode 100644 index 0000000000..fd11bb1473 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/CustomSpringNavigator.java @@ -0,0 +1,19 @@ +package com.example; + +import org.springframework.stereotype.Component; + +import com.vaadin.navigator.ViewDisplay; +import com.vaadin.spring.annotation.UIScope; +import com.vaadin.spring.navigator.SpringNavigator; +import com.vaadin.ui.UI; + +@UIScope +@Component +public class CustomSpringNavigator extends SpringNavigator { + + @Override + public void init(UI ui, ViewDisplay display) { + // FIXME: Should be in Spring plug-in + init(ui, null, display); + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/DemoApplication.java b/test/spring-boot-subcontext/src/main/java/com/example/DemoApplication.java new file mode 100644 index 0000000000..81af148442 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/DemoApplication.java @@ -0,0 +1,25 @@ +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; + +import com.vaadin.spring.server.SpringVaadinServlet; + +@SpringBootApplication +public class DemoApplication { + + public static final String CONTEXT = "/subcontext"; + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + + @Bean + ServletRegistrationBean servlet() { + return new ServletRegistrationBean(new SpringVaadinServlet(), false, + CONTEXT + "/*", "/VAADIN/*"); + } + +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/ThankYouService.java b/test/spring-boot-subcontext/src/main/java/com/example/ThankYouService.java new file mode 100644 index 0000000000..b387046659 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/ThankYouService.java @@ -0,0 +1,13 @@ +package com.example; + +import org.springframework.stereotype.Service; + +@Service +public class ThankYouService { + + public static final String THANK_YOU_TEXT = "Thank you for clicking."; + + public String getText() { + return THANK_YOU_TEXT; + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/ViewGreeter.java b/test/spring-boot-subcontext/src/main/java/com/example/ViewGreeter.java new file mode 100644 index 0000000000..54d60d2d9c --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/ViewGreeter.java @@ -0,0 +1,13 @@ +package com.example; + +import com.vaadin.spring.annotation.SpringComponent; + +@SpringComponent +public class ViewGreeter { + private int counter = 0; + + public String sayHello() { + return "Hello number " + counter++ + + " from bean with same scope as view " + toString(); + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/ui/AbstractSpringUI.java b/test/spring-boot-subcontext/src/main/java/com/example/ui/AbstractSpringUI.java new file mode 100644 index 0000000000..2549e7e8a8 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/ui/AbstractSpringUI.java @@ -0,0 +1,62 @@ +package com.example.ui; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.view.DefaultView; +import com.example.view.UIScopedView; +import com.example.view.ViewDisplayPanel; +import com.example.view.ViewScopedView; +import com.vaadin.server.VaadinRequest; +import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.ValoTheme; + +abstract class AbstractSpringUI extends UI { + + @Autowired + private ViewDisplayPanel springViewDisplay; + protected CssLayout navigationBar; + + @Override + protected void init(VaadinRequest request) { + final VerticalLayout root = new VerticalLayout(); + root.setSizeFull(); + root.setMargin(true); + root.setSpacing(true); + setContent(root); + + navigationBar = new CssLayout(); + navigationBar.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP); + navigationBar.addComponent( + createNavigationButton("Default View", DefaultView.VIEW_NAME)); + navigationBar.addComponent(createNavigationButton("UI Scoped View", + UIScopedView.VIEW_NAME)); + navigationBar.addComponent(createNavigationButton("View Scoped View", + ViewScopedView.VIEW_NAME)); + root.addComponent(navigationBar); + + root.addComponent(springViewDisplay); + root.setExpandRatio(springViewDisplay, 1.0f); + + } + + private Button createNavigationButton(String caption, + final String viewName) { + Button button = new Button(caption); + button.setId(viewName + "-button"); + button.addStyleName(ValoTheme.BUTTON_SMALL); + button.addClickListener( + event -> getUI().getNavigator().navigateTo(viewName)); + return button; + } + + @Override + public String getUiRootPath() { + // FIXME: Should be handled by Spring plug-in + return super.getUiRootPath() + "/" + + getClass().getAnnotation(SpringUI.class).path(); + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/ui/RootPathUI.java b/test/spring-boot-subcontext/src/main/java/com/example/ui/RootPathUI.java new file mode 100644 index 0000000000..1ed2725c42 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/ui/RootPathUI.java @@ -0,0 +1,18 @@ +package com.example.ui; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.ui.Label; + +@SpringUI +public class RootPathUI extends AbstractSpringUI { + + @Override + protected void init(VaadinRequest request) { + super.init(request); + + Label label = new Label("RootPathUI"); + label.setId("rootpath"); + navigationBar.addComponent(label); + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/ui/SubPathUI.java b/test/spring-boot-subcontext/src/main/java/com/example/ui/SubPathUI.java new file mode 100644 index 0000000000..605d771d52 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/ui/SubPathUI.java @@ -0,0 +1,22 @@ +package com.example.ui; + +import com.vaadin.navigator.PushStateNavigation; +import com.vaadin.server.VaadinRequest; +import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.ui.Label; + +@PushStateNavigation +@SpringUI(path = SubPathUI.SUBPATH) +public class SubPathUI extends AbstractSpringUI { + + public static final String SUBPATH = "subpath"; + + @Override + protected void init(VaadinRequest request) { + super.init(request); + + Label label = new Label("SubPathUI"); + label.setId(SUBPATH); + navigationBar.addComponent(label); + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/view/DefaultView.java b/test/spring-boot-subcontext/src/main/java/com/example/view/DefaultView.java new file mode 100644 index 0000000000..7fe9572e3e --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/view/DefaultView.java @@ -0,0 +1,33 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.ThankYouService; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.spring.annotation.SpringView; +import com.vaadin.ui.Button; +import com.vaadin.ui.Notification; +import com.vaadin.ui.VerticalLayout; + +@SpringView(name = DefaultView.VIEW_NAME) +public class DefaultView extends VerticalLayout implements View { + public static final String VIEW_NAME = ""; + + @Autowired + private ThankYouService service; + + @PostConstruct + void init() { + setId("default-view"); + Button button = new Button("Click Me!", + e -> Notification.show(service.getText())); + addComponent(button); + } + + @Override + public void enter(ViewChangeEvent event) { + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/view/UIScopedView.java b/test/spring-boot-subcontext/src/main/java/com/example/view/UIScopedView.java new file mode 100644 index 0000000000..e3a5aa57d0 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/view/UIScopedView.java @@ -0,0 +1,35 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.ViewGreeter; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.spring.annotation.SpringView; +import com.vaadin.spring.annotation.UIScope; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +@UIScope +@SpringView(name = UIScopedView.VIEW_NAME) +public class UIScopedView extends VerticalLayout implements View { + public static final String VIEW_NAME = "ui-scoped"; + + @Autowired + ViewGreeter service; + + @PostConstruct + void init() { + setId(VIEW_NAME); + setMargin(true); + setSpacing(true); + addComponents(new Label("This is a UI scoped view."), + new Label(service.sayHello())); + } + + @Override + public void enter(ViewChangeEvent event) { + } +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/view/ViewDisplayPanel.java b/test/spring-boot-subcontext/src/main/java/com/example/view/ViewDisplayPanel.java new file mode 100644 index 0000000000..ab4f5ffda8 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/view/ViewDisplayPanel.java @@ -0,0 +1,26 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewDisplay; +import com.vaadin.spring.annotation.SpringViewDisplay; +import com.vaadin.spring.annotation.UIScope; +import com.vaadin.ui.Component; +import com.vaadin.ui.Panel; + +@UIScope +@SpringViewDisplay +public class ViewDisplayPanel extends Panel implements ViewDisplay { + + @PostConstruct + void init() { + setSizeFull(); + } + + @Override + public void showView(View view) { + setContent((Component) view); + } + +} diff --git a/test/spring-boot-subcontext/src/main/java/com/example/view/ViewScopedView.java b/test/spring-boot-subcontext/src/main/java/com/example/view/ViewScopedView.java new file mode 100644 index 0000000000..33b0a553cc --- /dev/null +++ b/test/spring-boot-subcontext/src/main/java/com/example/view/ViewScopedView.java @@ -0,0 +1,34 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.ViewGreeter; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.spring.annotation.SpringView; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +@SpringView(name = ViewScopedView.VIEW_NAME) +public class ViewScopedView extends VerticalLayout implements View { + public static final String VIEW_NAME = "view-scoped"; + + @Autowired + ViewGreeter service; + + @PostConstruct + void init() { + setId(VIEW_NAME); + setMargin(true); + setSpacing(true); + addComponents(new Label("This is a view scoped view"), + new Label(service.sayHello())); + + } + + @Override + public void enter(ViewChangeEvent event) { + } +} diff --git a/test/spring-boot-subcontext/src/main/resources/application.properties b/test/spring-boot-subcontext/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/spring-boot-subcontext/src/main/resources/application.properties diff --git a/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootPushStateNavigatorIT.java b/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootPushStateNavigatorIT.java new file mode 100644 index 0000000000..41692789f7 --- /dev/null +++ b/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootPushStateNavigatorIT.java @@ -0,0 +1,25 @@ +package com.example; + +import org.junit.Ignore; +import org.junit.Test; + +public class VaadinSpringBootPushStateNavigatorIT + extends VaadinSpringBootURIFragmentNavigatorIT { + + @Ignore("PushState navigation is partially broken with Spring.") + @Override + @Test + public void testNotDefaultView() { + super.testNotDefaultView(); + } + + @Override + protected String getPath() { + return "subpath"; + } + + @Override + protected String getViewSeparator() { + return "/"; + } +} diff --git a/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootSmokeIT.java b/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootSmokeIT.java new file mode 100644 index 0000000000..f6f3db6243 --- /dev/null +++ b/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootSmokeIT.java @@ -0,0 +1,61 @@ +package com.example; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.phantomjs.PhantomJSDriver; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.example.ui.SubPathUI; +import com.vaadin.testbench.ScreenshotOnFailureRule; +import com.vaadin.testbench.TestBench; +import com.vaadin.testbench.TestBenchTestCase; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.testbench.elements.PanelElement; +import com.vaadin.testbench.parallel.Browser; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class VaadinSpringBootSmokeIT extends TestBenchTestCase { + + @Rule + public ScreenshotOnFailureRule screenshotRule = new ScreenshotOnFailureRule( + this, true); + + @LocalServerPort + Integer port; + + @Before + public void setUp() { + setDriver(TestBench.createDriver(new PhantomJSDriver( + Browser.PHANTOMJS.getDesiredCapabilities()))); + } + + @Test + public void testPageLoadsAndButtonWorks() { + getDriver().navigate() + .to("http://localhost:" + port + "/" + DemoApplication.CONTEXT); + runSmokeTest(); + } + + @Test + public void testSubPathPageLoadsAndButtonWorks() { + getDriver().navigate().to("http://localhost:" + port + "/" + + DemoApplication.CONTEXT + "/" + SubPathUI.SUBPATH); + runSmokeTest(); + } + + private void runSmokeTest() { + $(ButtonElement.class).in($(PanelElement.class)).first().click(); + + Assert.assertTrue($(NotificationElement.class).exists()); + Assert.assertEquals(ThankYouService.THANK_YOU_TEXT, + $(NotificationElement.class).first().getText()); + } +} diff --git a/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootURIFragmentNavigatorIT.java b/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootURIFragmentNavigatorIT.java new file mode 100644 index 0000000000..c7c4d0a1db --- /dev/null +++ b/test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootURIFragmentNavigatorIT.java @@ -0,0 +1,132 @@ +package com.example; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.phantomjs.PhantomJSDriver; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.example.view.DefaultView; +import com.example.view.UIScopedView; +import com.example.view.ViewScopedView; +import com.vaadin.testbench.ScreenshotOnFailureRule; +import com.vaadin.testbench.TestBench; +import com.vaadin.testbench.TestBenchTestCase; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.parallel.Browser; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class VaadinSpringBootURIFragmentNavigatorIT extends TestBenchTestCase { + + @Rule + public ScreenshotOnFailureRule screenshotRule = new ScreenshotOnFailureRule( + this, true); + + private String currentUIPath; + + @LocalServerPort + Integer port; + + @Before + public void setUp() { + setDriver(TestBench.createDriver(new PhantomJSDriver( + Browser.PHANTOMJS.getDesiredCapabilities()))); + } + + @Test + public void testUINavigation() { + currentUIPath = "http://localhost:" + port + DemoApplication.CONTEXT + + "/" + getPath(); + + runNavigationTestPattern(); + } + + @Test + public void testNotDefaultView() { + currentUIPath = "http://localhost:" + port + DemoApplication.CONTEXT + + "/" + getPath(); + getDriver().navigate().to( + currentUIPath + getViewSeparator() + ViewScopedView.VIEW_NAME); + + verifyViewScopeViewOpen(); + } + + private void runNavigationTestPattern() { + getDriver().navigate().to(currentUIPath); + + verifyDefaultViewOpen(""); + + openView(UIScopedView.VIEW_NAME); + verifyUIScopedViewOpen(); + + openView(ViewScopedView.VIEW_NAME); + verifyViewScopeViewOpen(); + + openView(DefaultView.VIEW_NAME); + verifyDefaultViewOpen(getViewSeparator()); + + getDriver().navigate().back(); + verifyViewScopeViewOpen(); + + getDriver().navigate().back(); + verifyUIScopedViewOpen(); + + getDriver().navigate().back(); + verifyDefaultViewOpen(""); + + getDriver().navigate().forward(); + verifyUIScopedViewOpen(); + + getDriver().navigate().forward(); + verifyViewScopeViewOpen(); + } + + private void verifyDefaultViewOpen(String viewIdentifier) { + verifyViewOpen("default-view"); + verifyURL(currentUIPath + viewIdentifier); + } + + private void verifyViewScopeViewOpen() { + verifyViewOpen(ViewScopedView.VIEW_NAME); + verifyURL( + currentUIPath + getViewSeparator() + ViewScopedView.VIEW_NAME); + } + + private void verifyUIScopedViewOpen() { + verifyViewOpen(UIScopedView.VIEW_NAME); + verifyURL(currentUIPath + getViewSeparator() + UIScopedView.VIEW_NAME); + } + + private void verifyViewOpen(String viewName) { + try { + findElement(By.id(viewName)); + } catch (NoSuchElementException e) { + Assert.fail( + "View <" + viewName + "> was not open, no element found"); + } + } + + private void verifyURL(String url) { + Assert.assertEquals("Invalid URL", url, getDriver().getCurrentUrl()); + } + + private void openView(String viewName) { + $(ButtonElement.class).id(viewName + "-button").click(); + } + + protected String getPath() { + return ""; + } + + protected String getViewSeparator() { + return "#!"; + } +} diff --git a/test/spring-boot/pom.xml b/test/spring-boot/pom.xml index 10aa184aed..40d50437b3 100644 --- a/test/spring-boot/pom.xml +++ b/test/spring-boot/pom.xml @@ -19,6 +19,7 @@ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring.boot.version>1.5.1.RELEASE</spring.boot.version> + <jetty.skip>true</jetty.skip> </properties> <dependencies> @@ -59,23 +60,6 @@ <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring.boot.version}</version> </plugin> - - <!-- Disable jetty-plugin --> - <plugin> - <groupId>org.eclipse.jetty</groupId> - <artifactId>jetty-maven-plugin</artifactId> - <version>${jetty.version}</version> - <executions> - <execution> - <id>start-jetty</id> - <phase /> - </execution> - <execution> - <id>stop-jetty</id> - <phase /> - </execution> - </executions> - </plugin> </plugins> </build> diff --git a/test/spring-boot/src/main/java/com/example/CustomSpringNavigator.java b/test/spring-boot/src/main/java/com/example/CustomSpringNavigator.java new file mode 100644 index 0000000000..fd11bb1473 --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/CustomSpringNavigator.java @@ -0,0 +1,19 @@ +package com.example; + +import org.springframework.stereotype.Component; + +import com.vaadin.navigator.ViewDisplay; +import com.vaadin.spring.annotation.UIScope; +import com.vaadin.spring.navigator.SpringNavigator; +import com.vaadin.ui.UI; + +@UIScope +@Component +public class CustomSpringNavigator extends SpringNavigator { + + @Override + public void init(UI ui, ViewDisplay display) { + // FIXME: Should be in Spring plug-in + init(ui, null, display); + } +} diff --git a/test/spring-boot/src/main/java/com/example/DemoApplication.java b/test/spring-boot/src/main/java/com/example/DemoApplication.java index 62e6a76a36..909a1ec36e 100644 --- a/test/spring-boot/src/main/java/com/example/DemoApplication.java +++ b/test/spring-boot/src/main/java/com/example/DemoApplication.java @@ -1,32 +1,13 @@ package com.example; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import com.vaadin.server.VaadinRequest; -import com.vaadin.spring.annotation.SpringUI; -import com.vaadin.ui.Button; -import com.vaadin.ui.Notification; -import com.vaadin.ui.UI; - @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } -} - -@SpringUI -class MyUI extends UI { - @Autowired - ThankYouService service; - - @Override - protected void init(VaadinRequest request) { - setContent(new Button("Click Me!", - e -> Notification.show(service.getText()))); - } } diff --git a/test/spring-boot/src/main/java/com/example/ViewGreeter.java b/test/spring-boot/src/main/java/com/example/ViewGreeter.java new file mode 100644 index 0000000000..54d60d2d9c --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/ViewGreeter.java @@ -0,0 +1,13 @@ +package com.example; + +import com.vaadin.spring.annotation.SpringComponent; + +@SpringComponent +public class ViewGreeter { + private int counter = 0; + + public String sayHello() { + return "Hello number " + counter++ + + " from bean with same scope as view " + toString(); + } +} diff --git a/test/spring-boot/src/main/java/com/example/ui/AbstractSpringUI.java b/test/spring-boot/src/main/java/com/example/ui/AbstractSpringUI.java new file mode 100644 index 0000000000..2549e7e8a8 --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/ui/AbstractSpringUI.java @@ -0,0 +1,62 @@ +package com.example.ui; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.view.DefaultView; +import com.example.view.UIScopedView; +import com.example.view.ViewDisplayPanel; +import com.example.view.ViewScopedView; +import com.vaadin.server.VaadinRequest; +import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.themes.ValoTheme; + +abstract class AbstractSpringUI extends UI { + + @Autowired + private ViewDisplayPanel springViewDisplay; + protected CssLayout navigationBar; + + @Override + protected void init(VaadinRequest request) { + final VerticalLayout root = new VerticalLayout(); + root.setSizeFull(); + root.setMargin(true); + root.setSpacing(true); + setContent(root); + + navigationBar = new CssLayout(); + navigationBar.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP); + navigationBar.addComponent( + createNavigationButton("Default View", DefaultView.VIEW_NAME)); + navigationBar.addComponent(createNavigationButton("UI Scoped View", + UIScopedView.VIEW_NAME)); + navigationBar.addComponent(createNavigationButton("View Scoped View", + ViewScopedView.VIEW_NAME)); + root.addComponent(navigationBar); + + root.addComponent(springViewDisplay); + root.setExpandRatio(springViewDisplay, 1.0f); + + } + + private Button createNavigationButton(String caption, + final String viewName) { + Button button = new Button(caption); + button.setId(viewName + "-button"); + button.addStyleName(ValoTheme.BUTTON_SMALL); + button.addClickListener( + event -> getUI().getNavigator().navigateTo(viewName)); + return button; + } + + @Override + public String getUiRootPath() { + // FIXME: Should be handled by Spring plug-in + return super.getUiRootPath() + "/" + + getClass().getAnnotation(SpringUI.class).path(); + } +} diff --git a/test/spring-boot/src/main/java/com/example/ui/RootPathUI.java b/test/spring-boot/src/main/java/com/example/ui/RootPathUI.java new file mode 100644 index 0000000000..1ed2725c42 --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/ui/RootPathUI.java @@ -0,0 +1,18 @@ +package com.example.ui; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.ui.Label; + +@SpringUI +public class RootPathUI extends AbstractSpringUI { + + @Override + protected void init(VaadinRequest request) { + super.init(request); + + Label label = new Label("RootPathUI"); + label.setId("rootpath"); + navigationBar.addComponent(label); + } +} diff --git a/test/spring-boot/src/main/java/com/example/ui/SubPathUI.java b/test/spring-boot/src/main/java/com/example/ui/SubPathUI.java new file mode 100644 index 0000000000..605d771d52 --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/ui/SubPathUI.java @@ -0,0 +1,22 @@ +package com.example.ui; + +import com.vaadin.navigator.PushStateNavigation; +import com.vaadin.server.VaadinRequest; +import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.ui.Label; + +@PushStateNavigation +@SpringUI(path = SubPathUI.SUBPATH) +public class SubPathUI extends AbstractSpringUI { + + public static final String SUBPATH = "subpath"; + + @Override + protected void init(VaadinRequest request) { + super.init(request); + + Label label = new Label("SubPathUI"); + label.setId(SUBPATH); + navigationBar.addComponent(label); + } +} diff --git a/test/spring-boot/src/main/java/com/example/view/DefaultView.java b/test/spring-boot/src/main/java/com/example/view/DefaultView.java new file mode 100644 index 0000000000..7fe9572e3e --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/view/DefaultView.java @@ -0,0 +1,33 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.ThankYouService; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.spring.annotation.SpringView; +import com.vaadin.ui.Button; +import com.vaadin.ui.Notification; +import com.vaadin.ui.VerticalLayout; + +@SpringView(name = DefaultView.VIEW_NAME) +public class DefaultView extends VerticalLayout implements View { + public static final String VIEW_NAME = ""; + + @Autowired + private ThankYouService service; + + @PostConstruct + void init() { + setId("default-view"); + Button button = new Button("Click Me!", + e -> Notification.show(service.getText())); + addComponent(button); + } + + @Override + public void enter(ViewChangeEvent event) { + } +} diff --git a/test/spring-boot/src/main/java/com/example/view/UIScopedView.java b/test/spring-boot/src/main/java/com/example/view/UIScopedView.java new file mode 100644 index 0000000000..e3a5aa57d0 --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/view/UIScopedView.java @@ -0,0 +1,35 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.ViewGreeter; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.spring.annotation.SpringView; +import com.vaadin.spring.annotation.UIScope; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +@UIScope +@SpringView(name = UIScopedView.VIEW_NAME) +public class UIScopedView extends VerticalLayout implements View { + public static final String VIEW_NAME = "ui-scoped"; + + @Autowired + ViewGreeter service; + + @PostConstruct + void init() { + setId(VIEW_NAME); + setMargin(true); + setSpacing(true); + addComponents(new Label("This is a UI scoped view."), + new Label(service.sayHello())); + } + + @Override + public void enter(ViewChangeEvent event) { + } +} diff --git a/test/spring-boot/src/main/java/com/example/view/ViewDisplayPanel.java b/test/spring-boot/src/main/java/com/example/view/ViewDisplayPanel.java new file mode 100644 index 0000000000..ab4f5ffda8 --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/view/ViewDisplayPanel.java @@ -0,0 +1,26 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewDisplay; +import com.vaadin.spring.annotation.SpringViewDisplay; +import com.vaadin.spring.annotation.UIScope; +import com.vaadin.ui.Component; +import com.vaadin.ui.Panel; + +@UIScope +@SpringViewDisplay +public class ViewDisplayPanel extends Panel implements ViewDisplay { + + @PostConstruct + void init() { + setSizeFull(); + } + + @Override + public void showView(View view) { + setContent((Component) view); + } + +} diff --git a/test/spring-boot/src/main/java/com/example/view/ViewScopedView.java b/test/spring-boot/src/main/java/com/example/view/ViewScopedView.java new file mode 100644 index 0000000000..33b0a553cc --- /dev/null +++ b/test/spring-boot/src/main/java/com/example/view/ViewScopedView.java @@ -0,0 +1,34 @@ +package com.example.view; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.example.ViewGreeter; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; +import com.vaadin.spring.annotation.SpringView; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; + +@SpringView(name = ViewScopedView.VIEW_NAME) +public class ViewScopedView extends VerticalLayout implements View { + public static final String VIEW_NAME = "view-scoped"; + + @Autowired + ViewGreeter service; + + @PostConstruct + void init() { + setId(VIEW_NAME); + setMargin(true); + setSpacing(true); + addComponents(new Label("This is a view scoped view"), + new Label(service.sayHello())); + + } + + @Override + public void enter(ViewChangeEvent event) { + } +} diff --git a/test/spring-boot/src/test/java/com/example/VaadinSpringBootPushStateNavigatorIT.java b/test/spring-boot/src/test/java/com/example/VaadinSpringBootPushStateNavigatorIT.java new file mode 100644 index 0000000000..41692789f7 --- /dev/null +++ b/test/spring-boot/src/test/java/com/example/VaadinSpringBootPushStateNavigatorIT.java @@ -0,0 +1,25 @@ +package com.example; + +import org.junit.Ignore; +import org.junit.Test; + +public class VaadinSpringBootPushStateNavigatorIT + extends VaadinSpringBootURIFragmentNavigatorIT { + + @Ignore("PushState navigation is partially broken with Spring.") + @Override + @Test + public void testNotDefaultView() { + super.testNotDefaultView(); + } + + @Override + protected String getPath() { + return "subpath"; + } + + @Override + protected String getViewSeparator() { + return "/"; + } +} diff --git a/test/spring-boot/src/test/java/com/example/VaadinSpringBootSmokeIT.java b/test/spring-boot/src/test/java/com/example/VaadinSpringBootSmokeIT.java index d0e3b4c4ae..cd23397fc1 100644 --- a/test/spring-boot/src/test/java/com/example/VaadinSpringBootSmokeIT.java +++ b/test/spring-boot/src/test/java/com/example/VaadinSpringBootSmokeIT.java @@ -1,8 +1,6 @@ package com.example; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -13,17 +11,15 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import com.example.ui.SubPathUI; import com.vaadin.testbench.ScreenshotOnFailureRule; import com.vaadin.testbench.TestBench; import com.vaadin.testbench.TestBenchTestCase; import com.vaadin.testbench.elements.ButtonElement; import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.testbench.elements.PanelElement; import com.vaadin.testbench.parallel.Browser; -/** - * @author Vaadin Ltd - * - */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class VaadinSpringBootSmokeIT extends TestBenchTestCase { @@ -44,9 +40,21 @@ public class VaadinSpringBootSmokeIT extends TestBenchTestCase { @Test public void testPageLoadsAndButtonWorks() { getDriver().navigate().to("http://localhost:" + port + ""); - $(ButtonElement.class).first().click(); - assertTrue($(NotificationElement.class).exists()); - assertEquals(ThankYouService.THANK_YOU_TEXT, + runSmokeTest(); + } + + @Test + public void testSubPathPageLoadsAndButtonWorks() { + getDriver().navigate() + .to("http://localhost:" + port + "/" + SubPathUI.SUBPATH); + runSmokeTest(); + } + + private void runSmokeTest() { + $(ButtonElement.class).in($(PanelElement.class)).first().click(); + + Assert.assertTrue($(NotificationElement.class).exists()); + Assert.assertEquals(ThankYouService.THANK_YOU_TEXT, $(NotificationElement.class).first().getText()); } } diff --git a/test/spring-boot/src/test/java/com/example/VaadinSpringBootURIFragmentNavigatorIT.java b/test/spring-boot/src/test/java/com/example/VaadinSpringBootURIFragmentNavigatorIT.java new file mode 100644 index 0000000000..decc893fbd --- /dev/null +++ b/test/spring-boot/src/test/java/com/example/VaadinSpringBootURIFragmentNavigatorIT.java @@ -0,0 +1,130 @@ +package com.example; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.phantomjs.PhantomJSDriver; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.example.view.DefaultView; +import com.example.view.UIScopedView; +import com.example.view.ViewScopedView; +import com.vaadin.testbench.ScreenshotOnFailureRule; +import com.vaadin.testbench.TestBench; +import com.vaadin.testbench.TestBenchTestCase; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.parallel.Browser; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class VaadinSpringBootURIFragmentNavigatorIT extends TestBenchTestCase { + + @Rule + public ScreenshotOnFailureRule screenshotRule = new ScreenshotOnFailureRule( + this, true); + + private String currentUIPath; + + @LocalServerPort + Integer port; + + @Before + public void setUp() { + setDriver(TestBench.createDriver(new PhantomJSDriver( + Browser.PHANTOMJS.getDesiredCapabilities()))); + } + + @Test + public void testUINavigation() { + currentUIPath = "http://localhost:" + port + "/" + getPath(); + + runNavigationTestPattern(); + } + + @Test + public void testNotDefaultView() { + currentUIPath = "http://localhost:" + port + "/" + getPath(); + getDriver().navigate().to( + currentUIPath + getViewSeparator() + ViewScopedView.VIEW_NAME); + + verifyViewScopeViewOpen(); + } + + private void runNavigationTestPattern() { + getDriver().navigate().to(currentUIPath); + + verifyDefaultViewOpen(""); + + openView(UIScopedView.VIEW_NAME); + verifyUIScopedViewOpen(); + + openView(ViewScopedView.VIEW_NAME); + verifyViewScopeViewOpen(); + + openView(DefaultView.VIEW_NAME); + verifyDefaultViewOpen(getViewSeparator()); + + getDriver().navigate().back(); + verifyViewScopeViewOpen(); + + getDriver().navigate().back(); + verifyUIScopedViewOpen(); + + getDriver().navigate().back(); + verifyDefaultViewOpen(""); + + getDriver().navigate().forward(); + verifyUIScopedViewOpen(); + + getDriver().navigate().forward(); + verifyViewScopeViewOpen(); + } + + private void verifyDefaultViewOpen(String viewIdentifier) { + verifyViewOpen("default-view"); + verifyURL(currentUIPath + viewIdentifier); + } + + private void verifyViewScopeViewOpen() { + verifyViewOpen(ViewScopedView.VIEW_NAME); + verifyURL( + currentUIPath + getViewSeparator() + ViewScopedView.VIEW_NAME); + } + + private void verifyUIScopedViewOpen() { + verifyViewOpen(UIScopedView.VIEW_NAME); + verifyURL(currentUIPath + getViewSeparator() + UIScopedView.VIEW_NAME); + } + + private void verifyViewOpen(String viewName) { + try { + findElement(By.id(viewName)); + } catch (NoSuchElementException e) { + Assert.fail( + "View <" + viewName + "> was not open, no element found"); + } + } + + private void verifyURL(String url) { + Assert.assertEquals("Invalid URL", url, getDriver().getCurrentUrl()); + } + + private void openView(String viewName) { + $(ButtonElement.class).id(viewName + "-button").click(); + } + + protected String getPath() { + return ""; + } + + protected String getViewSeparator() { + return "#!"; + } +} |