diff --git a/flow-client/src/main/frontend/Flow.ts b/flow-client/src/main/frontend/Flow.ts
index d08fa5f544e..30ae84eb881 100644
--- a/flow-client/src/main/frontend/Flow.ts
+++ b/flow-client/src/main/frontend/Flow.ts
@@ -217,7 +217,8 @@ export class Flow {
this.container.localName,
this.container.id,
this.getFlowRoute(ctx),
- this.appShellTitle
+ this.appShellTitle,
+ history.state
);
});
} else {
diff --git a/flow-server/src/main/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUI.java b/flow-server/src/main/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUI.java
index 121f09b34db..d5daf6a3463 100644
--- a/flow-server/src/main/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUI.java
+++ b/flow-server/src/main/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUI.java
@@ -26,6 +26,7 @@
import com.vaadin.flow.component.HasElement;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.UI;
+import com.vaadin.flow.component.page.History;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.internal.nodefeature.NodeProperties;
import com.vaadin.flow.router.ErrorNavigationEvent;
@@ -43,10 +44,12 @@
import com.vaadin.flow.router.internal.PathUtil;
import com.vaadin.flow.server.communication.JavaScriptBootstrapHandler;
+import elemental.json.JsonValue;
+
/**
* Custom UI for {@link JavaScriptBootstrapHandler}. This class is intended for
* internal use in client side bootstrapping.
- *
+ *
*
* For internal use only. May be renamed or removed in a future release.
*/
@@ -105,13 +108,25 @@ public String getForwardToClientUrl() {
* client side element id
* @param flowRoute
* flow route that should be attached to the client element
+ * @param appShellTitle
+ * client side title of the application shell
+ * @param historyState
+ * client side history state value
*/
@ClientCallable
public void connectClient(String clientElementTag, String clientElementId,
- String flowRoute, String appShellTitle) {
+ String flowRoute, String appShellTitle, JsonValue historyState) {
if (appShellTitle != null && !appShellTitle.isEmpty()) {
getInternals().setAppShellTitle(appShellTitle);
}
+
+ final String trimmedRoute = PathUtil.trimPath(flowRoute);
+ if (!trimmedRoute.equals(flowRoute)) {
+ // See InternalRedirectHandler invoked via Router.
+ getPage().getHistory().replaceState(null, trimmedRoute);
+ }
+ final Location location = new Location(trimmedRoute);
+
if (wrapperElement == null) {
// Create flow reference for the client outlet element
wrapperElement = new Element(clientElementTag);
@@ -120,23 +135,25 @@ public void connectClient(String clientElementTag, String clientElementId,
getElement().getStateProvider().appendVirtualChild(
getElement().getNode(), wrapperElement,
NodeProperties.INJECT_BY_ID, clientElementId);
- }
- final String trimmedRoute = PathUtil.trimPath(flowRoute);
- if (!trimmedRoute.equals(flowRoute)) {
- // See InternalRedirectHandler invoked via Router.
- getPage().getHistory().replaceState(null, trimmedRoute);
- }
+ getPage().getHistory().setHistoryStateChangeHandler(
+ event -> renderViewForRoute(event.getLocation(),
+ NavigationTrigger.CLIENT_SIDE));
- // Render the flow view that the user wants to navigate to.
- renderViewForRoute(new Location(trimmedRoute),
- NavigationTrigger.CLIENT_SIDE);
+ // Render the flow view that the user wants to navigate to.
+ renderViewForRoute(location, NavigationTrigger.CLIENT_SIDE);
+ } else {
+ History.HistoryStateChangeHandler handler = getPage().getHistory()
+ .getHistoryStateChangeHandler();
+ handler.onHistoryStateChange(new History.HistoryStateChangeEvent(
+ getPage().getHistory(), historyState, location,
+ NavigationTrigger.CLIENT_SIDE));
+ }
// true if the target is client-view and the push mode is disable
if (getForwardToClientUrl() != null) {
navigateToClient(getForwardToClientUrl());
acknowledgeClient();
-
} else if (isPostponed()) {
cancelClient();
} else {
@@ -181,41 +198,41 @@ public void navigate(String pathname, QueryParameters queryParameters) {
if (Boolean.TRUE.equals(getSession().getAttribute(SERVER_ROUTING))) {
// server-side routing
renderViewForRoute(location, NavigationTrigger.UI_NAVIGATE);
- } else {
- // client-side routing
+ return;
+ }
- // There is an in-progress navigation or there are no changes,
- // prevent looping
- if (navigationInProgress || getInternals().hasLastHandledLocation()
- && sameLocation(getInternals().getLastHandledLocation(),
- location)) {
- return;
- }
+ // client-side routing
+
+ // There is an in-progress navigation or there are no changes,
+ // prevent looping
+ if (navigationInProgress
+ || getInternals().hasLastHandledLocation() && sameLocation(
+ getInternals().getLastHandledLocation(), location)) {
+ return;
+ }
- navigationInProgress = true;
- try {
- Optional navigationState = getInternals()
- .getRouter().resolveNavigationTarget(location);
-
- if (navigationState.isPresent()) {
- // Navigation can be done in server side without extra
- // round-trip
- handleNavigation(location, navigationState.get(),
- NavigationTrigger.UI_NAVIGATE);
- if (getForwardToClientUrl() != null) {
- // Server is forwarding to a client route from a
- // BeforeEnter.
- navigateToClient(getForwardToClientUrl());
- }
- } else {
- // Server cannot resolve navigation, let client-side to
- // handle it.
- navigateToClient(location.getPathWithQueryParameters());
+ navigationInProgress = true;
+ try {
+ Optional navigationState = getInternals()
+ .getRouter().resolveNavigationTarget(location);
+
+ if (navigationState.isPresent()) {
+ // Navigation can be done in server side without extra
+ // round-trip
+ handleNavigation(location, navigationState.get(),
+ NavigationTrigger.UI_NAVIGATE);
+ if (getForwardToClientUrl() != null) {
+ // Server is forwarding to a client route from a
+ // BeforeEnter.
+ navigateToClient(getForwardToClientUrl());
}
- } finally {
- navigationInProgress = false;
+ } else {
+ // Server cannot resolve navigation, let client-side to
+ // handle it.
+ navigateToClient(location.getPathWithQueryParameters());
}
-
+ } finally {
+ navigationInProgress = false;
}
}
diff --git a/flow-server/src/main/java/com/vaadin/flow/component/page/History.java b/flow-server/src/main/java/com/vaadin/flow/component/page/History.java
index 687ed079a74..f384c24bd68 100644
--- a/flow-server/src/main/java/com/vaadin/flow/component/page/History.java
+++ b/flow-server/src/main/java/com/vaadin/flow/component/page/History.java
@@ -182,11 +182,13 @@ public void pushState(JsonValue state, String location) {
* to only change the JSON state
*/
public void pushState(JsonValue state, Location location) {
+ final String pathWithQueryParameters = Optional.ofNullable(location)
+ .map(Location::getPathWithQueryParameters).orElse(null);
// Second parameter is title which is currently ignored according to
// https://developer.mozilla.org/en-US/docs/Web/API/History_API
ui.getPage().executeJs(
"setTimeout(() => window.history.pushState($0, '', $1))", state,
- location.getPathWithQueryParameters());
+ pathWithQueryParameters);
}
/**
@@ -219,11 +221,13 @@ public void replaceState(JsonValue state, String location) {
* to only change the JSON state
*/
public void replaceState(JsonValue state, Location location) {
+ final String pathWithQueryParameters = Optional.ofNullable(location)
+ .map(Location::getPathWithQueryParameters).orElse(null);
// Second parameter is title which is currently ignored according to
// https://developer.mozilla.org/en-US/docs/Web/API/History_API
ui.getPage().executeJs(
"setTimeout(() => window.history.replaceState($0, '', $1))",
- state, location.getPathWithQueryParameters());
+ state, pathWithQueryParameters);
}
/**
diff --git a/flow-server/src/test/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUITest.java b/flow-server/src/test/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUITest.java
index a877101bc39..be99aa3d248 100644
--- a/flow-server/src/test/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUITest.java
+++ b/flow-server/src/test/java/com/vaadin/flow/component/internal/JavaScriptBootstrapUITest.java
@@ -207,13 +207,13 @@ public void cleanup() {
@Test
public void should_allow_navigation() {
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H2,
ui.wrapperElement.getChild(0).getChild(0).getTag());
// Dirty view is allowed after clean view
- ui.connectClient("foo", "bar", "/dirty", "");
+ ui.connectClient("foo", "bar", "/dirty", "", null);
assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H1,
ui.wrapperElement.getChild(0).getChild(0).getTag());
@@ -221,7 +221,7 @@ public void should_allow_navigation() {
@Test
public void should_navigate_when_endingSlash() {
- ui.connectClient("foo", "bar", "/clean/", "");
+ ui.connectClient("foo", "bar", "/clean/", "", null);
assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H2,
ui.wrapperElement.getChild(0).getChild(0).getTag());
@@ -229,7 +229,7 @@ public void should_navigate_when_endingSlash() {
@Test
public void getChildren_should_notReturnAnEmptyList() {
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
assertEquals(1, ui.getChildren().count());
}
@@ -237,7 +237,7 @@ public void getChildren_should_notReturnAnEmptyList() {
public void addRemoveComponent_clientSideRouting_addsToBody() {
final Element uiElement = ui.getElement();
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
// router outlet is a virtual child that is not reflected on element
// level
assertEquals(1, ui.getChildren().count());
@@ -293,7 +293,7 @@ public void addRemoveComponent_serverSideRouting_addsDirectlyToUI() {
public void addComponent_clientSideRouterAndNavigation_componentsRemain() {
final Element uiElement = ui.getElement();
// trigger route via client
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
final RouterLink routerLink = new RouterLink();
ui.add(routerLink);
@@ -331,25 +331,25 @@ public void addComponent_serverSideRouterAndNavigation_componentsRemain() {
@Test
public void should_prevent_navigation_on_dirty() {
- ui.connectClient("foo", "bar", "/dirty", "");
+ ui.connectClient("foo", "bar", "/dirty", "", null);
assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H1,
ui.wrapperElement.getChild(0).getChild(0).getTag());
// clean view cannot be rendered after dirty
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
assertEquals(Tag.H1,
ui.wrapperElement.getChild(0).getChild(0).getTag());
// an error route cannot be rendered after dirty
- ui.connectClient("foo", "bar", "/errr", "");
+ ui.connectClient("foo", "bar", "/errr", "", null);
assertEquals(Tag.H1,
ui.wrapperElement.getChild(0).getChild(0).getTag());
}
@Test
public void should_remove_content_on_leaveNavigation() {
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H2,
ui.wrapperElement.getChild(0).getChild(0).getTag());
@@ -361,7 +361,7 @@ public void should_remove_content_on_leaveNavigation() {
@Test
public void should_keep_content_on_leaveNavigation_postpone() {
- ui.connectClient("foo", "bar", "/dirty", "");
+ ui.connectClient("foo", "bar", "/dirty", "", null);
assertEquals(Tag.SPAN, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H1,
ui.wrapperElement.getChild(0).getChild(0).getTag());
@@ -375,7 +375,7 @@ public void should_keep_content_on_leaveNavigation_postpone() {
@Test
public void should_handle_forward_to_client_side_view_on_beforeEnter() {
ui.connectClient("foo", "bar", "/forwardToClientSideViewOnBeforeEnter",
- "");
+ "", null);
assertEquals("client-view", ui.getForwardToClientUrl());
}
@@ -383,14 +383,15 @@ public void should_handle_forward_to_client_side_view_on_beforeEnter() {
@Test
public void should_not_handle_forward_to_client_side_view_on_beforeLeave() {
ui.connectClient("foo", "bar", "/forwardToClientSideViewOnBeforeLeave",
- "");
+ "", null);
assertNull(ui.getForwardToClientUrl());
}
@Test
public void should_not_handle_forward_to_client_side_view_on_reroute() {
- ui.connectClient("foo", "bar", "/forwardToClientSideViewOnReroute", "");
+ ui.connectClient("foo", "bar", "/forwardToClientSideViewOnReroute", "",
+ null);
assertNull(ui.getForwardToClientUrl());
}
@@ -398,7 +399,7 @@ public void should_not_handle_forward_to_client_side_view_on_reroute() {
@Test
public void should_handle_forward_to_server_side_view_on_beforeEnter_and_update_url() {
ui.connectClient("foo", "bar", "/forwardToServerSideViewOnBeforeEnter",
- "");
+ "", null);
assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H2,
@@ -417,7 +418,7 @@ public void should_handle_forward_to_server_side_view_on_beforeEnter_and_update_
@Test
public void should_show_error_page() {
- ui.connectClient("foo", "bar", "/err", "");
+ ui.connectClient("foo", "bar", "/err", "", null);
assertEquals(Tag.DIV, ui.wrapperElement.getChild(0).getTag());
assertTrue(ui.wrapperElement.toString().contains("Available routes:"));
}
@@ -433,7 +434,7 @@ public void should_initializeUI_when_wrapperElement_null() {
@Test
public void should_navigate_when_server_routing() {
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H2,
ui.wrapperElement.getChild(0).getChild(0).getTag());
@@ -538,7 +539,7 @@ public void should_not_notify_clientRoute_when_navigatingToTheSame() {
@Test
public void server_should_not_doClientRoute_when_navigatingToServer() {
- ui.connectClient("foo", "bar", "/clean", "");
+ ui.connectClient("foo", "bar", "/clean", "", null);
assertEquals(Tag.HEADER, ui.wrapperElement.getChild(0).getTag());
assertEquals(Tag.H2,
ui.wrapperElement.getChild(0).getChild(0).getTag());
@@ -581,22 +582,23 @@ public void should_removeTitle_when_noAppShellTitle() {
@Test
public void should_restoreIndexHtmlTitle() {
- ui.connectClient("foo", "bar", "empty", "app-shell-title");
+ ui.connectClient("foo", "bar", "empty", "app-shell-title", null);
assertEquals("", ui.getInternals().getTitle());
- ui.connectClient("foo", "bar", "dirty", "app-shell-title");
+ ui.connectClient("foo", "bar", "dirty", "app-shell-title", null);
assertEquals("app-shell-title", ui.getInternals().getTitle());
}
@Test
public void should_not_share_dynamic_app_title_for_different_UIs() {
String dynamicTitle = UUID.randomUUID().toString();
- ui.connectClient("foo", "bar", "clean", dynamicTitle);
+ ui.connectClient("foo", "bar", "clean", dynamicTitle, null);
assertEquals(dynamicTitle, ui.getInternals().getTitle());
String anotherDynamicTitle = UUID.randomUUID().toString();
JavaScriptBootstrapUI anotherUI = new JavaScriptBootstrapUI();
anotherUI.getInternals().setSession(mocks.getSession());
- anotherUI.connectClient("foo", "bar", "clean", anotherDynamicTitle);
+ anotherUI.connectClient("foo", "bar", "clean", anotherDynamicTitle,
+ null);
assertEquals(anotherDynamicTitle, anotherUI.getInternals().getTitle());
ui.navigate("dirty");
diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/IndexHtmlRequestHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/IndexHtmlRequestHandlerTest.java
index a4d3b950fc0..7328cf60199 100644
--- a/flow-server/src/test/java/com/vaadin/flow/server/communication/IndexHtmlRequestHandlerTest.java
+++ b/flow-server/src/test/java/com/vaadin/flow/server/communication/IndexHtmlRequestHandlerTest.java
@@ -535,7 +535,7 @@ public void should_use_client_routing_when_there_is_a_router_call()
Boolean.FALSE);
((JavaScriptBootstrapUI) UI.getCurrent()).connectClient("foo", "bar",
- "/foo", "");
+ "/foo", "", null);
Mockito.verify(session, Mockito.times(1)).setAttribute(SERVER_ROUTING,
Boolean.FALSE);
diff --git a/flow-server/src/test/java/com/vaadin/flow/server/communication/JavaScriptBootstrapHandlerTest.java b/flow-server/src/test/java/com/vaadin/flow/server/communication/JavaScriptBootstrapHandlerTest.java
index 5dc4aed5366..a594dcc2834 100644
--- a/flow-server/src/test/java/com/vaadin/flow/server/communication/JavaScriptBootstrapHandlerTest.java
+++ b/flow-server/src/test/java/com/vaadin/flow/server/communication/JavaScriptBootstrapHandlerTest.java
@@ -143,7 +143,7 @@ public void should_attachViewTo_UiContainer() throws Exception {
jsInitHandler.handleRequest(session, request, response);
JavaScriptBootstrapUI ui = (JavaScriptBootstrapUI) UI.getCurrent();
- ui.connectClient("a-tag", "an-id", "a-route", "");
+ ui.connectClient("a-tag", "an-id", "a-route", "", null);
TestNodeVisitor visitor = new TestNodeVisitor(true);
BasicElementStateProvider.get().visit(ui.getElement().getNode(),
diff --git a/flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/RouterLinkView.java b/flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/RouterLinkView.java
index df87a864e6b..c3d093e546f 100644
--- a/flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/RouterLinkView.java
+++ b/flow-tests/test-root-context/src/main/java/com/vaadin/flow/uitest/ui/RouterLinkView.java
@@ -2,12 +2,13 @@
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Anchor;
-import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.dom.ElementFactory;
+import com.vaadin.flow.router.Location;
import com.vaadin.flow.router.Route;
+import elemental.json.Json;
import elemental.json.JsonObject;
@Route("com.vaadin.flow.uitest.ui.RouterLinkView")
diff --git a/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/HistoryIT.java b/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/HistoryIT.java
index 3877a013eab..4e1ff4f3a57 100644
--- a/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/HistoryIT.java
+++ b/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/HistoryIT.java
@@ -22,7 +22,6 @@
import java.util.stream.Collectors;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
@@ -33,7 +32,6 @@
public class HistoryIT extends ChromeBrowserTest {
@Test
- @Ignore("Ignored because of fusion issue: https://github.com/vaadin/flow/issues/8213")
public void testHistory() throws URISyntaxException {
open();
diff --git a/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/PopStateHandlerIT.java b/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/PopStateHandlerIT.java
index bcf6e79ee41..35c766d78a5 100644
--- a/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/PopStateHandlerIT.java
+++ b/flow-tests/test-root-context/src/test/java/com/vaadin/flow/uitest/ui/PopStateHandlerIT.java
@@ -5,6 +5,8 @@
import org.junit.Test;
import org.openqa.selenium.By;
+import com.vaadin.flow.component.ClientCallable;
+import com.vaadin.flow.router.internal.PathUtil;
import com.vaadin.flow.testutil.ChromeBrowserTest;
public class PopStateHandlerIT extends ChromeBrowserTest {
@@ -35,7 +37,6 @@ public void testDifferentPath_ServerSideEvent() {
}
@Test
- @Ignore("Ignored because of fusion issue: https://github.com/vaadin/flow/issues/10485")
public void testDifferentPath_doubleBack_ServerSideEvent() {
open();
@@ -78,7 +79,7 @@ public void testSamePathHashChanges_noServerSideEvent() {
}
@Test
- @Ignore("Ignored because of fusion issue: https://github.com/vaadin/flow/issues/10485")
+ @Ignore("Ignored because of the issue https://github.com/vaadin/flow/issues/10825")
public void testSamePathHashChanges_tripleeBack_noServerSideEvent() {
open();
@@ -134,7 +135,6 @@ public void testEmptyHash_noHashServerToServer() {
}
@Test
- @Ignore("Ignored because of fusion issue: https://github.com/vaadin/flow/issues/10485")
public void testEmptyHash_quadrupleBack_noHashServerToServer() {
open();
@@ -149,7 +149,8 @@ public void testEmptyHash_quadrupleBack_noHashServerToServer() {
goBack();
verifyPopStateEvent(FORUM);
- verifyInsideServletLocation(EMPTY_HASH);
+ // NOTE: see https://github.com/vaadin/flow/issues/10865
+ verifyInsideServletLocation(isClientRouter() ? FORUM : EMPTY_HASH);
goBack();
@@ -159,7 +160,8 @@ public void testEmptyHash_quadrupleBack_noHashServerToServer() {
goBack();
verifyPopStateEvent(FORUM);
- verifyInsideServletLocation(EMPTY_HASH);
+ // NOTE: see https://github.com/vaadin/flow/issues/10865
+ verifyInsideServletLocation(isClientRouter() ? FORUM : EMPTY_HASH);
goBack();
@@ -175,10 +177,16 @@ private void pushState(String id) {
findElement(By.id(id)).click();
}
+ private String trimPathForClientRouter(String path) {
+ // NOTE: see https://github.com/vaadin/flow/issues/10865
+ return isClientRouter() ? PathUtil.trimPath(path) : path;
+ }
+
private void verifyInsideServletLocation(String pathAfterServletMapping) {
Assert.assertEquals("Invalid URL",
- getRootURL() + "/view/" + pathAfterServletMapping,
- getDriver().getCurrentUrl());
+ trimPathForClientRouter(
+ getRootURL() + "/view/" + pathAfterServletMapping),
+ trimPathForClientRouter(getDriver().getCurrentUrl()));
}
private void verifyNoServerVisit() {
@@ -186,7 +194,9 @@ private void verifyNoServerVisit() {
}
private void verifyPopStateEvent(String location) {
- Assert.assertEquals("Invalid server side event location", location,
- findElement(By.id("location")).getText());
+ Assert.assertEquals("Invalid server side event location",
+ trimPathForClientRouter(
+ findElement(By.id("location")).getText()),
+ trimPathForClientRouter(location));
}
}