Skip to content

Commit 05b66d3

Browse files
authored
ENG-9553: prepend frontend_path to RouterData.url and RouterData.page.raw_path (#6535)
* ENG-9553: prepend `frontend_path` to RouterData.url and RouterData.page.raw_path If a frontend path is configured for the app, the framework must prepend it to the reported path, which only includes the internal route path. * assert that the router url ends in the expected path This is in addition to the {base} assertion which really is only a validation that the AppHarness itself is giving us the correct link.
1 parent 2aa49c5 commit 05b66d3

2 files changed

Lines changed: 83 additions & 2 deletions

File tree

reflex/istate/data.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from urllib.parse import _NetlocResultMixinStr, parse_qsl, urlsplit
88

99
from reflex_base import constants
10+
from reflex_base.config import get_config
1011
from reflex_base.utils import console, format
1112
from reflex_base.utils.serializers import serializer
1213
from reflex_base.vars.base import (
@@ -360,7 +361,12 @@ def from_router_data(cls, router_data: dict) -> "PageData":
360361
"""
361362
host = router_data.get(constants.RouteVar.HEADERS, {}).get("origin", "")
362363
path = router_data.get(constants.RouteVar.PATH, "")
363-
raw_path = router_data.get(constants.RouteVar.ORIGIN, "")
364+
# raw_path is the browser-visible URL path, so it includes the configured
365+
# frontend_path prefix. path remains the matched route pattern, which is
366+
# defined without the prefix.
367+
raw_path = get_config().prepend_frontend_path(
368+
router_data.get(constants.RouteVar.ORIGIN, "")
369+
)
364370
return cls(
365371
host=host,
366372
path=path,
@@ -447,7 +453,9 @@ def from_router_data(cls, router_data: dict) -> "RouterData":
447453
_page=PageData.from_router_data(router_data),
448454
url=ReflexURL(
449455
router_data.get(constants.RouteVar.HEADERS, {}).get("origin", "")
450-
+ router_data.get(constants.RouteVar.ORIGIN, "")
456+
+ get_config().prepend_frontend_path(
457+
router_data.get(constants.RouteVar.ORIGIN, "")
458+
)
451459
),
452460
route_id=router_data.get(constants.RouteVar.PATH, ""),
453461
)

tests/integration/tests_playwright/test_frontend_path.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from __future__ import annotations
1111

12+
import re
1213
from collections.abc import Generator
1314

1415
import httpx
@@ -107,6 +108,25 @@ def _chunk(chunk_type: bytes, data: bytes) -> bytes:
107108

108109
# ---- Pages ----
109110

111+
def _router_info():
112+
return rx.fragment(
113+
rx.input(
114+
value=FPState.router.url,
115+
read_only=True,
116+
id="router-url",
117+
),
118+
rx.input(
119+
value=FPState.router.url.path,
120+
read_only=True,
121+
id="router-url-path",
122+
),
123+
rx.input(
124+
value=FPState.router.page.raw_path, # pyright: ignore[reportDeprecated]
125+
read_only=True,
126+
id="router-page-raw-path",
127+
),
128+
)
129+
110130
@rx.page("/", on_load=FPState.on_load_index)
111131
def index():
112132
return rx.box(
@@ -117,6 +137,7 @@ def index():
117137
read_only=True,
118138
id="token",
119139
),
140+
_router_info(),
120141
# Links to app-relative paths.
121142
rx.link("go to static", href="/static-page", id="link-static"),
122143
rx.link("go to dynamic 7", href="/dynamic/7", id="link-dynamic"),
@@ -169,6 +190,7 @@ def static_page():
169190
read_only=True,
170191
id="token",
171192
),
193+
_router_info(),
172194
rx.link("go home", href="/", id="link-home"),
173195
rx.link("go to dynamic 7", href="/dynamic/7", id="link-dynamic"),
174196
rx.box(
@@ -186,6 +208,7 @@ def dynamic_page():
186208
read_only=True,
187209
id="token",
188210
),
211+
_router_info(),
189212
rx.link("go home", href="/", id="link-home"),
190213
rx.link("go to static", href="/static-page", id="link-static"),
191214
rx.box(
@@ -458,6 +481,56 @@ def test_navigate_back_and_forth(frontend_path_app: AppHarness, page: Page):
458481
expect(log).to_contain_text("dynamic-7")
459482

460483

484+
def test_router_includes_frontend_path(
485+
frontend_path_app: AppHarness, page: Page, frontend_path: str
486+
):
487+
"""State.router.url and State.router.page expose paths prefixed with frontend_path."""
488+
base = _navigate(frontend_path_app, page)
489+
490+
prefix = "/" + frontend_path.strip("/") if frontend_path else ""
491+
492+
# Index page: in-app path is "/".
493+
expected_path = f"{prefix}/"
494+
expect(page.locator("#router-url-path")).to_have_value(expected_path)
495+
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
496+
expect(page.locator("#router-url")).to_have_value(
497+
re.compile(rf".+{re.escape(expected_path)}$")
498+
)
499+
expect(page.locator("#router-url")).to_have_value(f"{base}/")
500+
501+
# Client-side navigation to static page.
502+
page.click("#link-static")
503+
expect(page.locator("#page-id")).to_have_text("static page")
504+
expected_path = f"{prefix}/static-page"
505+
expect(page.locator("#router-url-path")).to_have_value(expected_path)
506+
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
507+
expect(page.locator("#router-url")).to_have_value(
508+
re.compile(rf".+{re.escape(expected_path)}$")
509+
)
510+
expect(page.locator("#router-url")).to_have_value(f"{base}/static-page")
511+
512+
# Client-side navigation to dynamic page.
513+
page.click("#link-dynamic")
514+
expect(page.locator("#page-id")).to_contain_text("dynamic page")
515+
expected_path = f"{prefix}/dynamic/7"
516+
expect(page.locator("#router-url-path")).to_have_value(expected_path)
517+
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
518+
expect(page.locator("#router-url")).to_have_value(
519+
re.compile(rf".+{re.escape(expected_path)}$")
520+
)
521+
expect(page.locator("#router-url")).to_have_value(f"{base}/dynamic/7")
522+
523+
# Direct (full-page-load) navigation to dynamic page with different id.
524+
_navigate(frontend_path_app, page, "/dynamic/42")
525+
expected_path = f"{prefix}/dynamic/42"
526+
expect(page.locator("#router-url-path")).to_have_value(expected_path)
527+
expect(page.locator("#router-page-raw-path")).to_have_value(expected_path)
528+
expect(page.locator("#router-url")).to_have_value(
529+
re.compile(rf".+{re.escape(expected_path)}$")
530+
)
531+
expect(page.locator("#router-url")).to_have_value(f"{base}/dynamic/42")
532+
533+
461534
def test_frontend_url_format(frontend_path_app: AppHarness, frontend_path: str):
462535
"""Verify that the frontend_url correctly incorporates the frontend_path."""
463536
url = frontend_path_app.frontend_url

0 commit comments

Comments
 (0)