From 2198a748104c0d0dee97436f2e406239769da687 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Wed, 13 Aug 2025 22:14:26 +1000 Subject: [PATCH 01/14] Add integration tests for frontend_path configuration --- reflex/environment.py | 3 + .../tests_playwright/test_frontend_path.py | 101 ++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 tests/integration/tests_playwright/test_frontend_path.py diff --git a/reflex/environment.py b/reflex/environment.py index 5e5eb5ff873..80b1c98f024 100644 --- a/reflex/environment.py +++ b/reflex/environment.py @@ -640,6 +640,9 @@ class EnvironmentVariables: # Enable full logging of debug messages to reflex user directory. REFLEX_ENABLE_FULL_LOGGING: EnvVar[bool] = env_var(False) + # The path underwhich the frontend is served. + REFLEX_FRONTEND_PATH: EnvVar[str] = env_var("") + environment = EnvironmentVariables() diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py new file mode 100644 index 00000000000..45be0e7650a --- /dev/null +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -0,0 +1,101 @@ +from collections.abc import Generator + +import pytest +from playwright.sync_api import Page, expect + +from reflex.environment import environment +from reflex.testing import AppHarness, AppHarnessProd + + +def OnLoadRedirectApp(): + import reflex as rx + + @rx.page("/") + def index(): + return rx.container( + rx.input( + value=rx.State.router.session.client_token, + read_only=True, + id="token", + ), + rx.vstack( + rx.heading("This is the index page!"), + rx.button("Go to Subpage!", on_click=rx.redirect("/subpage")), + ), + ) + + @rx.page("/subpage") + def subpage(): + return rx.container( + rx.vstack( + rx.heading("This is the sub page!"), + rx.button("Go to index!", on_click=rx.redirect("/")), + rx.button("Bounce to index!", on_click=rx.redirect("/bouncer")), + ) + ) + + @rx.page("/bouncer", on_load=rx.redirect("/")) + def bouncer(): + return rx.container( + rx.vstack( + rx.heading("This is the bouncer page!"), + rx.text("You should not be here!"), + rx.button("Go to index!", on_click=rx.redirect("/")), + ), + ) + + app = rx.App() # noqa: F841 + + +@pytest.fixture +def onload_redirect_app(tmp_path_factory) -> Generator[AppHarness, None, None]: + with AppHarnessProd.create( + root=tmp_path_factory.mktemp("frontend_path_app"), + app_source=OnLoadRedirectApp, + ) as harness: + assert harness.app_instance is not None, "app is not running" + yield harness + + +@pytest.fixture +def onload_redirect_with_prefix_app( + tmp_path_factory, +) -> Generator[AppHarness, None, None]: + prefix = "/prefix" + environment.REFLEX_FRONTEND_PATH.set(prefix) + with AppHarness.create( + root=tmp_path_factory.mktemp("frontend_path_app"), + app_source=OnLoadRedirectApp, + ) as harness: + assert harness.app_instance is not None, "app is not running" + yield harness + environment.REFLEX_FRONTEND_PATH.set("") + + +@pytest.mark.parametrize( + ("app_fixture_name", "prefix"), + [ + ("onload_redirect_app", ""), + ("onload_redirect_with_prefix_app", "/prefix"), + ], +) +def test_onload_redirect(app_fixture_name: str, prefix: str, page: Page, request): + app_fixture = request.getfixturevalue(app_fixture_name) + assert app_fixture.frontend_url is not None + + base_url = app_fixture.frontend_url.rstrip("/") + base_url += prefix + page.goto(f"{base_url}/") + expect(page.get_by_text("This is the index page!")).to_be_visible() + + # Go to /subpage + page.get_by_text("Go to Subpage!").click() + expect(page.get_by_text("This is the sub page!")).to_be_visible() + + # Click "Bounce to index!" (should redirect to index via on_load) + page.get_by_text("Bounce to index!").click() + expect(page.get_by_text("This is the index page!")).to_be_visible() + + # Optionally, reload /prefix/bouncer/ and check redirect + page.goto(f"{base_url}/bouncer/") + expect(page.get_by_text("This is the index page!")).to_be_visible() From 2abec6989e3ae52bf1ec44cc79bbf85eb55c3a86 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Thu, 14 Aug 2025 13:16:03 +1000 Subject: [PATCH 02/14] Set an xfail mark noting the bug --- tests/integration/tests_playwright/test_frontend_path.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 45be0e7650a..ec4c91b0417 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -76,7 +76,11 @@ def onload_redirect_with_prefix_app( ("app_fixture_name", "prefix"), [ ("onload_redirect_app", ""), - ("onload_redirect_with_prefix_app", "/prefix"), + pytest.param( + "onload_redirect_with_prefix_app", + "/prefix", + marks=pytest.mark.xfail(reason="bug #5674"), + ), ], ) def test_onload_redirect(app_fixture_name: str, prefix: str, page: Page, request): From 812b168448b2833305ba6d1a2927c80bf3e87e89 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Thu, 14 Aug 2025 13:32:33 +1000 Subject: [PATCH 03/14] Update reflex/environment.py Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- reflex/environment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflex/environment.py b/reflex/environment.py index 80b1c98f024..839448be273 100644 --- a/reflex/environment.py +++ b/reflex/environment.py @@ -640,7 +640,7 @@ class EnvironmentVariables: # Enable full logging of debug messages to reflex user directory. REFLEX_ENABLE_FULL_LOGGING: EnvVar[bool] = env_var(False) - # The path underwhich the frontend is served. + # The path under which the frontend is served. REFLEX_FRONTEND_PATH: EnvVar[str] = env_var("") From 243726e13b90d1a3b91eaaacf6c16bff03309437 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Thu, 14 Aug 2025 13:33:15 +1000 Subject: [PATCH 04/14] Update tests/integration/tests_playwright/test_frontend_path.py Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- .../tests_playwright/test_frontend_path.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index ec4c91b0417..45f93d877d8 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -62,7 +62,16 @@ def onload_redirect_with_prefix_app( tmp_path_factory, ) -> Generator[AppHarness, None, None]: prefix = "/prefix" - environment.REFLEX_FRONTEND_PATH.set(prefix) + try: + environment.REFLEX_FRONTEND_PATH.set(prefix) + with AppHarness.create( + root=tmp_path_factory.mktemp("frontend_path_app"), + app_source=OnLoadRedirectApp, + ) as harness: + assert harness.app_instance is not None, "app is not running" + yield harness + finally: + environment.REFLEX_FRONTEND_PATH.set("") with AppHarness.create( root=tmp_path_factory.mktemp("frontend_path_app"), app_source=OnLoadRedirectApp, From 2a06383a902022da83f739c7d80e09a28c33077b Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Thu, 14 Aug 2025 16:39:33 +1000 Subject: [PATCH 05/14] Adjust environment variable commment to match config comment --- reflex/environment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reflex/environment.py b/reflex/environment.py index 839448be273..e889fd493ae 100644 --- a/reflex/environment.py +++ b/reflex/environment.py @@ -640,7 +640,7 @@ class EnvironmentVariables: # Enable full logging of debug messages to reflex user directory. REFLEX_ENABLE_FULL_LOGGING: EnvVar[bool] = env_var(False) - # The path under which the frontend is served. + # The path to run the frontend on. For example, "/app" will run the frontend on http://localhost:3000/app REFLEX_FRONTEND_PATH: EnvVar[str] = env_var("") From 64cf139bd02e6541485b09bc0bb5a59cafef942d Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Thu, 14 Aug 2025 16:40:21 +1000 Subject: [PATCH 06/14] Remove duplication introduced by online suggestion --- tests/integration/tests_playwright/test_frontend_path.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 45f93d877d8..747b51fef9c 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -69,16 +69,10 @@ def onload_redirect_with_prefix_app( app_source=OnLoadRedirectApp, ) as harness: assert harness.app_instance is not None, "app is not running" + environment.REFLEX_FRONTEND_PATH.set("") yield harness finally: environment.REFLEX_FRONTEND_PATH.set("") - with AppHarness.create( - root=tmp_path_factory.mktemp("frontend_path_app"), - app_source=OnLoadRedirectApp, - ) as harness: - assert harness.app_instance is not None, "app is not running" - yield harness - environment.REFLEX_FRONTEND_PATH.set("") @pytest.mark.parametrize( From cc23e8b5bfbcf7d634c8e478b4eae2138b2e5868 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Thu, 14 Aug 2025 16:41:20 +1000 Subject: [PATCH 07/14] Ensure link test fixture does not display a buiit with reflex badge --- reflex/environment.py | 3 +++ .../tests_playwright/test_link_hover.py | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/reflex/environment.py b/reflex/environment.py index e889fd493ae..cf354f22bfd 100644 --- a/reflex/environment.py +++ b/reflex/environment.py @@ -643,6 +643,9 @@ class EnvironmentVariables: # The path to run the frontend on. For example, "/app" will run the frontend on http://localhost:3000/app REFLEX_FRONTEND_PATH: EnvVar[str] = env_var("") + # Whether to display the sticky "Built with Reflex" badge on all pages. + REFLEX_SHOW_BUILT_WITH_REFLEX: EnvVar[bool | None] = env_var(None) + environment = EnvironmentVariables() diff --git a/tests/integration/tests_playwright/test_link_hover.py b/tests/integration/tests_playwright/test_link_hover.py index c4a473f410f..dcfc86478d4 100644 --- a/tests/integration/tests_playwright/test_link_hover.py +++ b/tests/integration/tests_playwright/test_link_hover.py @@ -3,6 +3,7 @@ import pytest from playwright.sync_api import Page, expect +from reflex.environment import environment from reflex.testing import AppHarness @@ -27,12 +28,17 @@ def index(): @pytest.fixture def link_app(tmp_path_factory) -> Generator[AppHarness, None, None]: - with AppHarness.create( - root=tmp_path_factory.mktemp("link_app"), - app_source=LinkApp, - ) as harness: - assert harness.app_instance is not None, "app is not running" - yield harness + try: + environment.REFLEX_SHOW_BUILT_WITH_REFLEX.set(False) + with AppHarness.create( + root=tmp_path_factory.mktemp("link_app"), + app_source=LinkApp, + ) as harness: + assert harness.app_instance is not None, "app is not running" + environment.REFLEX_SHOW_BUILT_WITH_REFLEX.set(None) + yield harness + finally: + environment.REFLEX_SHOW_BUILT_WITH_REFLEX.set(None) def test_link_hover(link_app: AppHarness, page: Page): From 4c0795380fcca32f6d0b28a93e063a9e3b326977 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Fri, 15 Aug 2025 10:07:06 +1000 Subject: [PATCH 08/14] Remove the xfail after merge from main --- tests/integration/tests_playwright/test_frontend_path.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 747b51fef9c..23bb5e10811 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -79,11 +79,7 @@ def onload_redirect_with_prefix_app( ("app_fixture_name", "prefix"), [ ("onload_redirect_app", ""), - pytest.param( - "onload_redirect_with_prefix_app", - "/prefix", - marks=pytest.mark.xfail(reason="bug #5674"), - ), + ("onload_redirect_with_prefix_app", "/prefix"), ], ) def test_onload_redirect(app_fixture_name: str, prefix: str, page: Page, request): From 989f86e827c739fb4fe6a52808c942c36446d5dc Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Fri, 15 Aug 2025 12:15:07 +1000 Subject: [PATCH 09/14] Add docstrings for functions and classes --- .../tests_playwright/test_frontend_path.py | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 23bb5e10811..30b5952783d 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -8,6 +8,10 @@ def OnLoadRedirectApp(): + """App to demonstrate an on_load redirection issue. + + See https://github.com/reflex-dev/reflex/issues/5674 for details. + """ import reflex as rx @rx.page("/") @@ -49,6 +53,16 @@ def bouncer(): @pytest.fixture def onload_redirect_app(tmp_path_factory) -> Generator[AppHarness, None, None]: + """Start the OnLoadRedirectApp without setting REFLEX_FRONTEND_PATH". + + This is a baseline used to show on_load redirects work without a frontend_path. + + Args: + tmp_path_factory: pytest tmp_path_factory fixture + + Yields: + running AppHarness instance + """ with AppHarnessProd.create( root=tmp_path_factory.mktemp("frontend_path_app"), app_source=OnLoadRedirectApp, @@ -61,6 +75,16 @@ def onload_redirect_app(tmp_path_factory) -> Generator[AppHarness, None, None]: def onload_redirect_with_prefix_app( tmp_path_factory, ) -> Generator[AppHarness, None, None]: + """Start the OnLoadRedirectApp with REFLEX_FRONTEND_PATH set to "/prefix". + + This simulates setting the REFLEX_FRONTEND_PATH to identify issues with redirection. + + Args: + tmp_path_factory: pytest tmp_path_factory fixture + + Yields: + running AppHarness instance + """ prefix = "/prefix" try: environment.REFLEX_FRONTEND_PATH.set(prefix) @@ -76,18 +100,28 @@ def onload_redirect_with_prefix_app( @pytest.mark.parametrize( - ("app_fixture_name", "prefix"), + ("app_fixture_name", "frontend_path"), [ ("onload_redirect_app", ""), ("onload_redirect_with_prefix_app", "/prefix"), ], ) -def test_onload_redirect(app_fixture_name: str, prefix: str, page: Page, request): +def test_onload_redirect( + app_fixture_name: str, frontend_path: str, page: Page, request +): + """Ensure that on_load redirects work correctly when a frontend_path is present. + + Args: + app_fixture_name: Name of the app fixture to use for the test. + frontend_path: The REFLEX_FRONTEND_PATH used by the app fixture. + page: Playwright Page object to interact with the app. + request: Pytest request object to access fixtures. + """ app_fixture = request.getfixturevalue(app_fixture_name) assert app_fixture.frontend_url is not None base_url = app_fixture.frontend_url.rstrip("/") - base_url += prefix + base_url += frontend_path page.goto(f"{base_url}/") expect(page.get_by_text("This is the index page!")).to_be_visible() From badab5bfde191256431a79707c6af34e769867a5 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Fri, 15 Aug 2025 12:15:50 +1000 Subject: [PATCH 10/14] Add a test to ensure 404's still work as expected --- tests/integration/tests_playwright/test_frontend_path.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 30b5952783d..3f52e0671d0 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -136,3 +136,8 @@ def test_onload_redirect( # Optionally, reload /prefix/bouncer/ and check redirect page.goto(f"{base_url}/bouncer/") expect(page.get_by_text("This is the index page!")).to_be_visible() + + # Check that 404's work and do not change the url + page.goto(f"{base_url}/not-a-page") + expect(page.get_by_text("404: Page not found")).to_be_visible() + expect(page).to_have_url(f"{base_url}/not-a-page") From ca32c738ed423b1806d9b4f856eeee3f1b6cd53b Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Fri, 15 Aug 2025 13:42:10 +1000 Subject: [PATCH 11/14] Switch to using get_by_role for buttons --- tests/integration/tests_playwright/test_frontend_path.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 3f52e0671d0..fa7e320e892 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -126,11 +126,11 @@ def test_onload_redirect( expect(page.get_by_text("This is the index page!")).to_be_visible() # Go to /subpage - page.get_by_text("Go to Subpage!").click() + page.get_by_role("button", name="Go to Subpage!").click() expect(page.get_by_text("This is the sub page!")).to_be_visible() # Click "Bounce to index!" (should redirect to index via on_load) - page.get_by_text("Bounce to index!").click() + page.get_by_role("button", name="Bounce to index!").click() expect(page.get_by_text("This is the index page!")).to_be_visible() # Optionally, reload /prefix/bouncer/ and check redirect From 02650f363ea6cf721c838c0833a0da740ac94de5 Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Fri, 15 Aug 2025 13:43:49 +1000 Subject: [PATCH 12/14] Check url at each step --- tests/integration/tests_playwright/test_frontend_path.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index fa7e320e892..88047a0d3b3 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -128,10 +128,12 @@ def test_onload_redirect( # Go to /subpage page.get_by_role("button", name="Go to Subpage!").click() expect(page.get_by_text("This is the sub page!")).to_be_visible() + expect(page).to_have_url(f"{base_url}/subpage") # Click "Bounce to index!" (should redirect to index via on_load) page.get_by_role("button", name="Bounce to index!").click() expect(page.get_by_text("This is the index page!")).to_be_visible() + expect(page).to_have_url(f"{base_url}/") # Optionally, reload /prefix/bouncer/ and check redirect page.goto(f"{base_url}/bouncer/") From bbe8847d3eec4754dc16f245d6909c588ea85c1a Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Fri, 3 Oct 2025 15:39:05 +1000 Subject: [PATCH 13/14] Switch to using isolated tmp dirs for test fixtures --- .../tests_playwright/test_frontend_path.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 88047a0d3b3..9b0cab1b929 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -52,19 +52,19 @@ def bouncer(): @pytest.fixture -def onload_redirect_app(tmp_path_factory) -> Generator[AppHarness, None, None]: +def onload_redirect_app(tmp_path) -> Generator[AppHarness, None, None]: """Start the OnLoadRedirectApp without setting REFLEX_FRONTEND_PATH". This is a baseline used to show on_load redirects work without a frontend_path. Args: - tmp_path_factory: pytest tmp_path_factory fixture + tmp_path: pytest tmp_path fixture Yields: running AppHarness instance """ with AppHarnessProd.create( - root=tmp_path_factory.mktemp("frontend_path_app"), + root=tmp_path / "onload_redirect_app", app_source=OnLoadRedirectApp, ) as harness: assert harness.app_instance is not None, "app is not running" @@ -72,15 +72,13 @@ def onload_redirect_app(tmp_path_factory) -> Generator[AppHarness, None, None]: @pytest.fixture -def onload_redirect_with_prefix_app( - tmp_path_factory, -) -> Generator[AppHarness, None, None]: +def onload_redirect_with_prefix_app(tmp_path) -> Generator[AppHarness, None, None]: """Start the OnLoadRedirectApp with REFLEX_FRONTEND_PATH set to "/prefix". This simulates setting the REFLEX_FRONTEND_PATH to identify issues with redirection. Args: - tmp_path_factory: pytest tmp_path_factory fixture + tmp_path: pytest tmp_path fixture Yields: running AppHarness instance @@ -89,7 +87,7 @@ def onload_redirect_with_prefix_app( try: environment.REFLEX_FRONTEND_PATH.set(prefix) with AppHarness.create( - root=tmp_path_factory.mktemp("frontend_path_app"), + root=tmp_path / "onload_redirect_with_prefix_app", app_source=OnLoadRedirectApp, ) as harness: assert harness.app_instance is not None, "app is not running" From 9aebd436e5e43640dc1231f8385b680106ac5afe Mon Sep 17 00:00:00 2001 From: Kahlil Hodgson Date: Tue, 7 Oct 2025 08:05:22 +1100 Subject: [PATCH 14/14] Extend tests to cover onmount case --- .../tests_playwright/test_frontend_path.py | 93 ++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/tests/integration/tests_playwright/test_frontend_path.py b/tests/integration/tests_playwright/test_frontend_path.py index 9b0cab1b929..f96f824d999 100644 --- a/tests/integration/tests_playwright/test_frontend_path.py +++ b/tests/integration/tests_playwright/test_frontend_path.py @@ -97,17 +97,106 @@ def onload_redirect_with_prefix_app(tmp_path) -> Generator[AppHarness, None, Non environment.REFLEX_FRONTEND_PATH.set("") +def OnMountRedirectApp(): + """App demonstrate on_mount redirection behaviour.""" + import reflex as rx + + @rx.page("/") + def index(): + return rx.container( + rx.input( + value=rx.State.router.session.client_token, + read_only=True, + id="token", + ), + rx.vstack( + rx.heading("This is the index page!"), + rx.button("Go to Subpage!", on_click=rx.redirect("/subpage")), + ), + ) + + @rx.page("/subpage") + def subpage(): + return rx.container( + rx.vstack( + rx.heading("This is the sub page!"), + rx.button("Go to index!", on_click=rx.redirect("/")), + rx.button("Bounce to index!", on_click=rx.redirect("/bouncer")), + ) + ) + + @rx.page("/bouncer") + def bouncer(): + return rx.container( + rx.vstack( + rx.heading("This is the bouncer page!"), + rx.text("You should not be here!"), + rx.spinner("Go to index!", on_mount=rx.redirect("/")), + ), + ) + + app = rx.App() # noqa: F841 + + +@pytest.fixture +def onmount_redirect_app(tmp_path) -> Generator[AppHarness, None, None]: + """Start the OnMountRedirectApp without setting REFLEX_FRONTEND_PATH". + + This is a baseline used to show on_mount redirects work without a frontend_path. + + Args: + tmp_path: pytest tmp_path fixture + + Yields: + running AppHarness instance + """ + with AppHarnessProd.create( + root=tmp_path / "onmount_redirect_app", + app_source=OnMountRedirectApp, + ) as harness: + assert harness.app_instance is not None, "app is not running" + yield harness + + +@pytest.fixture +def onmount_redirect_with_prefix_app(tmp_path) -> Generator[AppHarness, None, None]: + """Start the OnMountRedirectApp with REFLEX_FRONTEND_PATH set to "/prefix". + + This simulates setting the REFLEX_FRONTEND_PATH to identify issues with redirection. + + Args: + tmp_path: pytest tmp_path fixture + + Yields: + running AppHarness instance + """ + prefix = "/prefix" + try: + environment.REFLEX_FRONTEND_PATH.set(prefix) + with AppHarness.create( + root=tmp_path / "onmount_redirect_with_prefix_app", + app_source=OnMountRedirectApp, + ) as harness: + assert harness.app_instance is not None, "app is not running" + environment.REFLEX_FRONTEND_PATH.set("") + yield harness + finally: + environment.REFLEX_FRONTEND_PATH.set("") + + @pytest.mark.parametrize( ("app_fixture_name", "frontend_path"), [ ("onload_redirect_app", ""), ("onload_redirect_with_prefix_app", "/prefix"), + ("onmount_redirect_app", ""), + ("onmount_redirect_with_prefix_app", "/prefix"), ], ) -def test_onload_redirect( +def test_redirection_triggers( app_fixture_name: str, frontend_path: str, page: Page, request ): - """Ensure that on_load redirects work correctly when a frontend_path is present. + """Ensure that on_load and on_mount redirects work with/without a frontend_path. Args: app_fixture_name: Name of the app fixture to use for the test.