diff --git a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx index df2fa59b7c8..6f075ee93b7 100644 --- a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx +++ b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx @@ -382,7 +382,11 @@ function Flow() { (event: CustomEvent<{ state: unknown; url: string; replace?: boolean; callback: boolean }>) => { // @ts-ignore window.Vaadin.Flow.navigation = true; - const path = '/' + event.detail.url; + // clean base uri away if for instance redirected to http://localhost/path/user?id=10 + // else the whole http... will be appended to the url see #19580 + const path = event.detail.url.startsWith(document.baseURI) + ? '/' + event.detail.url.slice(document.baseURI.length) + : '/' + event.detail.url; fromAnchor.current = false; queuedNavigate(path, event.detail.callback, { state: event.detail.state, replace: event.detail.replace }); }, diff --git a/flow-tests/test-react-router/src/main/java/com/vaadin/flow/AddQueryParamView.java b/flow-tests/test-react-router/src/main/java/com/vaadin/flow/AddQueryParamView.java new file mode 100644 index 00000000000..de35da3f5f4 --- /dev/null +++ b/flow-tests/test-react-router/src/main/java/com/vaadin/flow/AddQueryParamView.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2024 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.flow; + +import com.vaadin.flow.component.UI; +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.NativeButton; +import com.vaadin.flow.component.page.Page; +import com.vaadin.flow.router.BeforeEnterEvent; +import com.vaadin.flow.router.BeforeEnterObserver; +import com.vaadin.flow.router.Route; + +@Route("com.vaadin.flow.AddQueryParamView") +public class AddQueryParamView extends Div { + + public static final String PARAM_BUTTON_ID = "setParameter"; + public static final String QUERY_ID = "query"; + + public AddQueryParamView() { + NativeButton button = new NativeButton("Add URL Parameter", e -> { + updateUrlRequestParameter("test", "HELLO!"); + }); + button.setId(PARAM_BUTTON_ID); + add(button); + } + + public void updateUrlRequestParameter(String key, String value) { + Page page = UI.getCurrent().getPage(); + page.fetchCurrentURL(url -> { + String newLocation = url + "?" + key + "=" + value; + page.getHistory().replaceState(null, newLocation); + Div div = new Div(newLocation); + div.setId(QUERY_ID); + add(div); + }); + } +} diff --git a/flow-tests/test-react-router/src/test/java/com/vaadin/flow/AddQueryParamIT.java b/flow-tests/test-react-router/src/test/java/com/vaadin/flow/AddQueryParamIT.java new file mode 100644 index 00000000000..97957413dc7 --- /dev/null +++ b/flow-tests/test-react-router/src/test/java/com/vaadin/flow/AddQueryParamIT.java @@ -0,0 +1,30 @@ +package com.vaadin.flow; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.flow.component.html.testbench.DivElement; +import com.vaadin.flow.component.html.testbench.NativeButtonElement; +import com.vaadin.flow.component.html.testbench.SpanElement; +import com.vaadin.flow.testutil.ChromeBrowserTest; + +public class AddQueryParamIT extends ChromeBrowserTest { + + @Test + public void validateReactInUse() { + open(); + + waitForDevServer(); + + $(NativeButtonElement.class).id(AddQueryParamView.PARAM_BUTTON_ID) + .click(); + + waitForElementPresent(By.id(AddQueryParamView.QUERY_ID)); + + Assert.assertEquals( + $(DivElement.class).id(AddQueryParamView.QUERY_ID).getText(), + driver.getCurrentUrl()); + } + +}