summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <tsuoanttila@users.noreply.github.com>2017-09-27 11:40:17 +0300
committerHenri Sara <henri.sara@gmail.com>2017-09-27 11:40:17 +0300
commit367c7751a6ff9234fd47bc5a48e6ef9a4117a7a2 (patch)
tree5b3849bafb37b49c3dcc8616e064f60bd081dff0 /server
parent69776b1d08d40bcdd89b9cc5b050e8db793ec06b (diff)
downloadvaadin-framework-367c7751a6ff9234fd47bc5a48e6ef9a4117a7a2.tar.gz
vaadin-framework-367c7751a6ff9234fd47bc5a48e6ef9a4117a7a2.zip
Add option to use PushState instead of URI fragments in Navigator (#10042)
* Navigator now by default uses pushState and normal URLs * added documentation for pushState and updated Navigator documentation * improving docs etc, adding one TODO to be solved before merging * pushState/replaceState no work better with changing titles * Making uri fragment navigator work when not using specially mapped UI * Revert to older default, add annotation for selecting * Fix tests, add null checks * Reorder if-clause, fix tests * Revert unnecessary test change * Use correct variable in UI, fix test clean up * Updates to JavaDocs, fix some methods and tests * Add comments, fix test ui, TODO for fallbacks * Navigation documentation, JavaDocs, removed TODOs * Documentation fixes * Improve JavaDocs * Fix link name in documentation * Improve throws declaration in getLocation * Change documentation about the PushState based navigation * Add since tags * Add since tags for UI
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/navigator/Navigator.java117
-rw-r--r--server/src/main/java/com/vaadin/navigator/PushStateNavigation.java47
-rw-r--r--server/src/main/java/com/vaadin/server/Page.java6
-rw-r--r--server/src/main/java/com/vaadin/ui/UI.java81
-rw-r--r--server/src/test/java/com/vaadin/server/ConnectorResourceHandlerTest.java7
-rw-r--r--server/src/test/java/com/vaadin/server/VaadinSessionTest.java29
-rw-r--r--server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java107
-rw-r--r--server/src/test/java/com/vaadin/ui/UIInitRefreshTest.java14
-rw-r--r--server/src/test/java/com/vaadin/ui/UIThemeEscapingTest.java21
9 files changed, 409 insertions, 20 deletions
diff --git a/server/src/main/java/com/vaadin/navigator/Navigator.java b/server/src/main/java/com/vaadin/navigator/Navigator.java
index 6b18cd4000..d65bad9db7 100644
--- a/server/src/main/java/com/vaadin/navigator/Navigator.java
+++ b/server/src/main/java/com/vaadin/navigator/Navigator.java
@@ -16,6 +16,7 @@
package com.vaadin.navigator;
import java.io.Serializable;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -27,6 +28,7 @@ import java.util.Objects;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.Page;
+import com.vaadin.server.Page.PopStateEvent;
import com.vaadin.shared.Registration;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Component;
@@ -82,6 +84,95 @@ public class Navigator implements Serializable {
}
/**
+ * A {@link NavigationStateManager} using path info, HTML5 push state and
+ * {@link PopStateEvent}s to track views and enable listening to view
+ * changes. This manager can be enabled with UI annotation
+ * {@link PushStateNavigation}.
+ * <p>
+ * The part of path after UI's "root path" (UI's path without view
+ * identifier) is used as {@link View}s identifier. The rest of the path
+ * after the view name can be used by the developer for extra parameters for
+ * the View.
+ * <p>
+ * This class is mostly for internal use by Navigator, and is only public
+ * and static to enable testing.
+ *
+ * @since 8.2
+ */
+ public static class PushStateManager implements NavigationStateManager {
+ private Registration popStateListenerRegistration;
+ private UI ui;
+
+ /**
+ * Creates a new PushStateManager.
+ *
+ * @param ui
+ * the UI where the Navigator is attached to
+ */
+ public PushStateManager(UI ui) {
+ this.ui = ui;
+ }
+
+ @Override
+ public void setNavigator(Navigator navigator) {
+ if (popStateListenerRegistration != null) {
+ popStateListenerRegistration.remove();
+ popStateListenerRegistration = null;
+ }
+ if (navigator != null) {
+ popStateListenerRegistration = ui.getPage()
+ .addPopStateListener(e -> {
+ navigator.navigateTo(getState());
+ });
+ }
+ }
+
+ @Override
+ public String getState() {
+ // Get the current URL
+ URI location = ui.getPage().getLocation();
+ String path = location.getPath();
+ if (ui.getUiPathInfo() != null
+ && path.contains(ui.getUiPathInfo())) {
+ // Split the path from after the UI PathInfo
+ path = path.substring(path.indexOf(ui.getUiPathInfo())
+ + ui.getUiPathInfo().length());
+ } else if (path.startsWith(ui.getUiRootPath())) {
+ // Use the whole path after UI RootPath
+ String uiRootPath = ui.getUiRootPath();
+ path = path.substring(uiRootPath.length());
+ } else {
+ throw new IllegalStateException(getClass().getSimpleName()
+ + " is unable to determine the view path from the URL.");
+ }
+
+ if (path.startsWith("/")) {
+ // Strip leading '/'
+ path = path.substring(1);
+ }
+ return path;
+ }
+
+ @Override
+ public void setState(String state) {
+ StringBuilder sb = new StringBuilder(ui.getUiRootPath());
+ if (!ui.getUiRootPath().endsWith("/")) {
+ // make sure there is a '/' between the root path and the
+ // navigation state.
+ sb.append("/");
+ }
+ sb.append(state);
+ URI location = ui.getPage().getLocation();
+ if (location != null) {
+ ui.getPage().pushState(location.resolve(sb.toString()));
+ } else {
+ throw new IllegalStateException(
+ "The Page of the UI does not have a location.");
+ }
+ }
+ }
+
+ /**
* A {@link NavigationStateManager} using hashbang fragments in the Page
* location URI to track views and enable listening to view changes.
* <p>
@@ -92,6 +183,10 @@ public class Navigator implements Serializable {
* <p>
* This class is mostly for internal use by Navigator, and is only public
* and static to enable testing.
+ * <p>
+ * <strong>Note:</strong> Since 8.2 you can use {@link PushStateManager},
+ * which is based on HTML5 History API. To use it, add
+ * {@link PushStateNavigation} annotation to the UI.
*/
public static class UriFragmentManager implements NavigationStateManager {
private final Page page;
@@ -426,7 +521,7 @@ public class Navigator implements Serializable {
* The ViewDisplay used to display the views.
*/
public Navigator(UI ui, ViewDisplay display) {
- this(ui, new UriFragmentManager(ui.getPage()), display);
+ this(ui, null, display);
}
/**
@@ -494,7 +589,7 @@ public class Navigator implements Serializable {
this.ui = ui;
this.ui.setNavigator(this);
if (stateManager == null) {
- stateManager = new UriFragmentManager(ui.getPage());
+ stateManager = createNavigationStateManager(ui);
}
if (stateManager != null && this.stateManager != null
&& stateManager != this.stateManager) {
@@ -506,6 +601,24 @@ public class Navigator implements Serializable {
}
/**
+ * Creates a navigation state manager for given UI. This method should take
+ * into account any navigation related annotations.
+ *
+ * @param ui
+ * the ui
+ * @return the navigation state manager
+ *
+ * @since 8.2
+ */
+ protected NavigationStateManager createNavigationStateManager(UI ui) {
+ if (ui.getClass().getAnnotation(PushStateNavigation.class) != null) {
+ return new PushStateManager(ui);
+ }
+ // Fall back to old default
+ return new UriFragmentManager(ui.getPage());
+ }
+
+ /**
* Navigates to a view and initialize the view with given parameters.
* <p>
* The view string consists of a view name optionally followed by a slash
diff --git a/server/src/main/java/com/vaadin/navigator/PushStateNavigation.java b/server/src/main/java/com/vaadin/navigator/PushStateNavigation.java
new file mode 100644
index 0000000000..f1cab0391b
--- /dev/null
+++ b/server/src/main/java/com/vaadin/navigator/PushStateNavigation.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2016 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.navigator;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import com.vaadin.server.DeploymentConfiguration;
+import com.vaadin.server.Page.PopStateEvent;
+import com.vaadin.ui.UI;
+
+/**
+ * Annotation for {@link UI}s to enable the PushState navigation mode when
+ * initializing a {@link Navigator} for it. PushState navigation is an
+ * alternative way to handle URLs in the {@link Navigator}. It uses path info,
+ * HTML5 push state and {@link PopStateEvent}s to track views and enable
+ * listening to view changes.
+ * <p>
+ * <strong>Note:</strong> For PushState navigation to work, the
+ * {@link DeploymentConfiguration} parameter
+ * {@link DeploymentConfiguration#isSendUrlsAsParameters() SendUrlAsParameters}
+ * must not be set to {@code false}.
+ *
+ * @since 8.2
+ */
+@Retention(RUNTIME)
+@Target(TYPE)
+@Inherited
+public @interface PushStateNavigation {
+}
diff --git a/server/src/main/java/com/vaadin/server/Page.java b/server/src/main/java/com/vaadin/server/Page.java
index 4c880c2a6b..3e95de0c4b 100644
--- a/server/src/main/java/com/vaadin/server/Page.java
+++ b/server/src/main/java/com/vaadin/server/Page.java
@@ -1035,8 +1035,12 @@ public class Page implements Serializable {
* deployed in due to potential proxies, redirections and similar.
*
* @return The browser location URI.
+ * @throws IllegalStateException
+ * if the
+ * {@link DeploymentConfiguration#isSendUrlsAsParameters()} is
+ * set to {@code false}
*/
- public URI getLocation() {
+ public URI getLocation() throws IllegalStateException {
if (location == null && !uI.getSession().getConfiguration()
.isSendUrlsAsParameters()) {
throw new IllegalStateException("Location is not available as the "
diff --git a/server/src/main/java/com/vaadin/ui/UI.java b/server/src/main/java/com/vaadin/ui/UI.java
index ac4815f92d..5d27c1de74 100644
--- a/server/src/main/java/com/vaadin/ui/UI.java
+++ b/server/src/main/java/com/vaadin/ui/UI.java
@@ -44,6 +44,7 @@ import com.vaadin.event.UIEvents.PollEvent;
import com.vaadin.event.UIEvents.PollListener;
import com.vaadin.event.UIEvents.PollNotifier;
import com.vaadin.navigator.Navigator;
+import com.vaadin.navigator.PushStateNavigation;
import com.vaadin.server.ClientConnector;
import com.vaadin.server.ComponentSizeValidator;
import com.vaadin.server.ComponentSizeValidator.InvalidLayout;
@@ -196,7 +197,6 @@ public abstract class UI extends AbstractSingleComponentContainer
@Override
public void popstate(String uri) {
getPage().updateLocation(uri, true, true);
-
}
};
private DebugWindowServerRpc debugRpc = new DebugWindowServerRpc() {
@@ -261,8 +261,7 @@ public abstract class UI extends AbstractSingleComponentContainer
private WindowOrderRpc windowOrderRpc = new WindowOrderRpc() {
@Override
- public void windowOrderChanged(
- Map<Integer, Connector> windowOrders) {
+ public void windowOrderChanged(Map<Integer, Connector> windowOrders) {
Map<Integer, Window> orders = new LinkedHashMap<>();
for (Entry<Integer, Connector> entry : windowOrders.entrySet()) {
if (entry.getValue() instanceof Window) {
@@ -661,6 +660,10 @@ public abstract class UI extends AbstractSingleComponentContainer
private String embedId;
+ private String uiPathInfo;
+
+ private String uiRootPath;
+
private boolean mobileHtml5DndPolyfillLoaded;
/**
@@ -740,6 +743,36 @@ public abstract class UI extends AbstractSingleComponentContainer
getPage().init(request);
+ String uiPathInfo = (String) request
+ .getAttribute(ApplicationConstants.UI_ROOT_PATH);
+ if (uiPathInfo != null) {
+ setUiPathInfo(uiPathInfo);
+ }
+
+ if (getSession() != null && getSession().getConfiguration() != null
+ && getSession().getConfiguration().isSendUrlsAsParameters()
+ && getPage().getLocation() != null) {
+ // By default the root is the URL from client
+ String uiRootPath = getPage().getLocation().getPath();
+
+ if (uiPathInfo != null && uiRootPath.contains(uiPathInfo)) {
+ // String everything from the URL after uiPathInfo
+ // This will remove the navigation state from the URL
+ uiRootPath = uiRootPath.substring(0,
+ uiRootPath.indexOf(uiPathInfo) + uiPathInfo.length());
+ } else if (request.getPathInfo() != null) {
+ // uiRootPath does not match the uiPathInfo
+ // This can happen for example when embedding a Vaadin UI
+ String pathInfo = request.getPathInfo();
+ if (uiRootPath.endsWith(pathInfo)) {
+ uiRootPath = uiRootPath.substring(0,
+ uiRootPath.length() - pathInfo.length());
+ }
+ }
+ // Store the URL as the UI Root Path
+ setUiRootPath(uiRootPath);
+ }
+
// Call the init overridden by the application developer
init(request);
@@ -750,6 +783,48 @@ public abstract class UI extends AbstractSingleComponentContainer
}
}
+ private void setUiRootPath(String uiRootPath) {
+ this.uiRootPath = uiRootPath;
+ }
+
+ /**
+ * Gets the part of path (from browser's URL) that points to this UI.
+ * Basically the same as the value from {@link Page#getLocation()}, but
+ * without possible view identifiers or path parameters.
+ *
+ * @return the part of path (from browser's URL) that points to this UI,
+ * without possible view identifiers or path parameters
+ *
+ * @since 8.2
+ */
+ public String getUiRootPath() {
+ return uiRootPath;
+ }
+
+ private void setUiPathInfo(String uiPathInfo) {
+ this.uiPathInfo = uiPathInfo;
+ }
+
+ /**
+ * Gets the path info part of the request that is used to detect the UI.
+ * This is defined during UI init by certain {@link UIProvider UIProviders}
+ * that map different UIs to different URIs, like Vaadin Spring. This
+ * information is used by the {@link Navigator} when the {@link UI} is
+ * annotated with {@link PushStateNavigation}.
+ * <p>
+ * For example if the UI is accessed through
+ * {@code http://example.com/MyUI/mainview/parameter=1} the path info would
+ * be {@code /MyUI}.
+ *
+ * @return the path info part of the request; {@code null} if no request
+ * from client has been processed
+ *
+ * @since 8.2
+ */
+ public String getUiPathInfo() {
+ return uiPathInfo;
+ }
+
/**
* Initializes this UI. This method is intended to be overridden by
* subclasses to build the view and configure non-component functionality.
diff --git a/server/src/test/java/com/vaadin/server/ConnectorResourceHandlerTest.java b/server/src/test/java/com/vaadin/server/ConnectorResourceHandlerTest.java
index fd7dc4291d..57b8ed8ff4 100644
--- a/server/src/test/java/com/vaadin/server/ConnectorResourceHandlerTest.java
+++ b/server/src/test/java/com/vaadin/server/ConnectorResourceHandlerTest.java
@@ -39,10 +39,14 @@ public class ConnectorResourceHandlerTest {
request = control.createMock(VaadinRequest.class);
response = control.createMock(VaadinResponse.class);
+ DeploymentConfiguration dc = control
+ .createMock(DeploymentConfiguration.class);
VaadinService service = control.createMock(VaadinService.class);
EasyMock.expect(request.getPathInfo())
.andReturn("/APP/connector/0/1/2");
+ EasyMock.expect(request.getParameter("v-loc"))
+ .andReturn("http://localhost/");
control.replay();
@@ -53,13 +57,14 @@ public class ConnectorResourceHandlerTest {
protected void init(VaadinRequest request) {
}
};
- ui.doInit(request, 0, "");
session.lock();
try {
+ session.setConfiguration(dc);
session.setCommunicationManager(
new LegacyCommunicationManager(session));
ui.setSession(session);
+ ui.doInit(request, 0, "");
session.addUI(ui);
} finally {
session.unlock();
diff --git a/server/src/test/java/com/vaadin/server/VaadinSessionTest.java b/server/src/test/java/com/vaadin/server/VaadinSessionTest.java
index 5b5528e8e3..a3d0746149 100644
--- a/server/src/test/java/com/vaadin/server/VaadinSessionTest.java
+++ b/server/src/test/java/com/vaadin/server/VaadinSessionTest.java
@@ -32,6 +32,7 @@ import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -96,12 +97,22 @@ public class VaadinSessionTest implements Serializable {
}
};
+ IMocksControl control = EasyMock.createNiceControl();
+ DeploymentConfiguration dc = control
+ .createMock(DeploymentConfiguration.class);
+
session = new VaadinSession(mockService);
+
mockService.storeSession(session, mockWrappedSession);
ui = new MockPageUI();
- vaadinRequest = new VaadinServletRequest(
- EasyMock.createMock(HttpServletRequest.class), mockService) {
+ HttpServletRequest request = control
+ .createMock(HttpServletRequest.class);
+ EasyMock.expect(request.getParameter("v-loc"))
+ .andReturn("http://localhost/");
+ control.replay();
+
+ vaadinRequest = new VaadinServletRequest(request, mockService) {
@Override
public String getParameter(String name) {
if ("theme".equals(name) || "restartApplication".equals(name)
@@ -116,6 +127,14 @@ public class VaadinSessionTest implements Serializable {
}
@Override
+ public Object getAttribute(String name) {
+ if (name.equals("com.vaadin.server.UI_ROOT_PATH")) {
+ return "/";
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
public String getMethod() {
return "POST";
}
@@ -128,9 +147,10 @@ public class VaadinSessionTest implements Serializable {
};
+ session.setConfiguration(dc);
+ ui.setSession(session);
ui.doInit(vaadinRequest, session.getNextUIid(), null);
- ui.setSession(session);
session.addUI(ui);
}
@@ -240,9 +260,6 @@ public class VaadinSessionTest implements Serializable {
// VaadinSessionTest.this which isn't serializable
private static class MockPageUI extends UI {
Page page = new Page(this, getState(false).pageState) {
- @Override
- public void init(VaadinRequest request) {
- }
};
@Override
diff --git a/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java b/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java
index 636c226e66..019c13698d 100644
--- a/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java
@@ -36,6 +36,7 @@ import org.junit.Test;
import com.vaadin.navigator.NavigationStateManager;
import com.vaadin.navigator.Navigator;
+import com.vaadin.navigator.PushStateNavigation;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewBeforeLeaveEvent;
import com.vaadin.navigator.ViewChangeListener;
@@ -138,6 +139,31 @@ public class NavigatorTest {
}
}
+ public static class TestNavigatorWithFragments extends Navigator {
+ public TestNavigatorWithFragments() {
+ super(createMockUI(), new NullFragmentManager(), new TestDisplay());
+ }
+
+ public TestNavigatorWithFragments(UI ui) {
+ super(ui, new UriFragmentManager(ui.getPage()),
+ EasyMock.createMock(ViewDisplay.class));
+ }
+
+ public View getView(String viewAndParameters) {
+ try {
+ navigateTo(viewAndParameters);
+ } catch (IllegalArgumentException e) {
+ // ignore
+ }
+ return ((TestDisplay) getDisplay()).getCurrentView();
+ }
+
+ @Override
+ protected NavigationStateManager getStateManager() {
+ return super.getStateManager();
+ }
+ }
+
public static class ViewChangeTestListener implements ViewChangeListener {
private final LinkedList<ViewChangeEvent> referenceEvents = new LinkedList<>();
private final LinkedList<Boolean> referenceIsCheck = new LinkedList<>();
@@ -244,6 +270,14 @@ public class NavigatorTest {
private final Page page;
}
+ @PushStateNavigation
+ private static class TestPushStateUI extends TestUI {
+
+ TestPushStateUI(Page page) {
+ super(page);
+ }
+ }
+
private static class TestPage extends Page {
public TestPage() {
@@ -251,6 +285,31 @@ public class NavigatorTest {
}
@Override
+ public Registration addPopStateListener(PopStateListener listener) {
+ addPopstateCalled = true;
+ return () -> removePopstateCalled = true;
+ }
+
+ boolean addPopstateCalled() {
+ return addPopstateCalled;
+ }
+
+ boolean removePopstateCalled() {
+ return removePopstateCalled;
+ }
+
+ private boolean addPopstateCalled;
+
+ private boolean removePopstateCalled;
+ }
+
+ private static class TestPageWithUriFragments extends Page {
+
+ public TestPageWithUriFragments() {
+ super(null, null);
+ }
+
+ @Override
public Registration addUriFragmentChangedListener(
UriFragmentChangedListener listener) {
addUriFragmentCalled = true;
@@ -304,12 +363,13 @@ public class NavigatorTest {
return new Navigator(createMockUI(), manager, display);
}
- @Test(expected = NullPointerException.class)
+ @Test
public void testDestroy_unsetNavigatorInUIAndUriFragmentManager() {
- TestPage page = new TestPage();
+ TestPageWithUriFragments page = new TestPageWithUriFragments();
UI ui = new TestUI(page);
- TestNavigator navigator = new TestNavigator(ui);
+ TestNavigatorWithFragments navigator = new TestNavigatorWithFragments(
+ ui);
Assert.assertTrue("Add URI fragment Page method has not been called",
page.addUriFragmentCalled());
Assert.assertFalse("Unexpected remove URI fragment Page method call",
@@ -323,11 +383,44 @@ public class NavigatorTest {
Assert.assertNull("Navigator is not null in UI after destroy",
ui.getNavigator());
- page.setUriFragment("foobar", true);
+ try {
+ page.setUriFragment("foobar", true); // This should throw
+ Assert.fail(
+ "Expected null pointer exception after call uriFragmentChanged "
+ + "for destroyed navigator");
+ } catch (NullPointerException e) {
+ // All ok.
+ }
+ }
+
+ @Test
+ public void testDestroy_unsetNavigatorInUIAndPopstateManager() {
+ TestPage page = new TestPage();
+ UI ui = new TestPushStateUI(page);
+
+ TestNavigator navigator = new TestNavigator(ui);
+ Assert.assertTrue("Add URI fragment Page method has not been called",
+ page.addPopstateCalled());
+ Assert.assertFalse("Unexpected remove URI fragment Page method call",
+ page.removePopstateCalled());
+ Assert.assertNotNull("Navigator is null in UI", ui.getNavigator());
+
+ navigator.destroy();
+ Assert.assertTrue(
+ "Remove URI fragment Page method has not been called after destroy",
+ page.removePopstateCalled());
+ Assert.assertNull("Navigator is not null in UI after destroy",
+ ui.getNavigator());
+
+ try {
+ page.updateLocation("http://server/path/info", true, true);
- Assert.fail(
- "Expected null pointer exception after call uriFragmentChanged "
- + "for destroyed navigator");
+ Assert.fail(
+ "Expected null pointer exception after call uriFragmentChanged "
+ + "for destroyed navigator");
+ } catch (NullPointerException e) {
+ // All ok.
+ }
}
@Test
diff --git a/server/src/test/java/com/vaadin/ui/UIInitRefreshTest.java b/server/src/test/java/com/vaadin/ui/UIInitRefreshTest.java
index c4a44d85a6..65bbc59a5b 100644
--- a/server/src/test/java/com/vaadin/ui/UIInitRefreshTest.java
+++ b/server/src/test/java/com/vaadin/ui/UIInitRefreshTest.java
@@ -15,17 +15,21 @@
*/
package com.vaadin.ui;
+import java.util.Locale;
+
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import com.vaadin.server.DeploymentConfiguration;
import com.vaadin.server.Page.BrowserWindowResizeEvent;
import com.vaadin.server.Page.BrowserWindowResizeListener;
import com.vaadin.server.Page.UriFragmentChangedEvent;
import com.vaadin.server.Page.UriFragmentChangedListener;
import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinSession;
public class UIInitRefreshTest {
@@ -87,6 +91,7 @@ public class UIInitRefreshTest {
IMocksControl control = EasyMock.createNiceControl();
VaadinRequest initRequest = control.createMock(VaadinRequest.class);
+
EasyMock.expect(initRequest.getParameter("v-loc"))
.andReturn("http://example.com/#foo");
EasyMock.expect(initRequest.getParameter("v-cw")).andReturn("100");
@@ -98,9 +103,18 @@ public class UIInitRefreshTest {
EasyMock.expect(reinitRequest.getParameter("v-cw")).andReturn("200");
EasyMock.expect(reinitRequest.getParameter("v-ch")).andReturn("200");
+ VaadinSession session = control.createMock(VaadinSession.class);
+ DeploymentConfiguration dc = control
+ .createMock(DeploymentConfiguration.class);
+
+ EasyMock.expect(session.hasLock()).andStubReturn(true);
+ EasyMock.expect(session.getConfiguration()).andStubReturn(dc);
+ EasyMock.expect(session.getLocale()).andStubReturn(Locale.getDefault());
+
control.replay();
UI ui = new TestUI();
+ ui.setSession(session);
ui.doInit(initRequest, 0, "");
Assert.assertTrue(initCalled);
diff --git a/server/src/test/java/com/vaadin/ui/UIThemeEscapingTest.java b/server/src/test/java/com/vaadin/ui/UIThemeEscapingTest.java
index 7c19694eec..656dd96b30 100644
--- a/server/src/test/java/com/vaadin/ui/UIThemeEscapingTest.java
+++ b/server/src/test/java/com/vaadin/ui/UIThemeEscapingTest.java
@@ -21,10 +21,16 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import java.util.Locale;
+
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;
+import com.vaadin.server.DeploymentConfiguration;
import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinSession;
public class UIThemeEscapingTest {
@@ -33,13 +39,28 @@ public class UIThemeEscapingTest {
private void initUiWithTheme(String theme) {
VaadinRequest request = getRequestWithTheme(theme);
+ IMocksControl control = EasyMock.createNiceControl();
+ VaadinSession session = control.createMock(VaadinSession.class);
+ DeploymentConfiguration dc = control
+ .createMock(DeploymentConfiguration.class);
+
+ EasyMock.expect(session.hasLock()).andStubReturn(true);
+ EasyMock.expect(session.getConfiguration()).andStubReturn(dc);
+ EasyMock.expect(session.getLocale()).andStubReturn(Locale.getDefault());
+
+ control.replay();
+
+ ui.setSession(session);
+ ui.getPage().init(request);
ui.doInit(request, 1234, "foobar");
}
private VaadinRequest getRequestWithTheme(String theme) {
VaadinRequest request = mock(VaadinRequest.class);
+ // when(request.getParameter())
when(request.getParameter("theme")).thenReturn(theme);
+ when(request.getParameter("v-loc")).thenReturn("http://localhost/");
return request;
}