reflex/integration/test_navigation.py
Masen Furer 279e9bfa28
[REF-1993] link: respect is_external prop and other attributes on A tag (#2651)
* link: respect `is_external` prop and other attributes on A tag

Instead of passing all props to NextLink by default, only pass props that
NextLink understands, placing the remaining props on the Radix link

Add a test case to avoid regression of `is_external` behavior.

* Link is a MemoizationLeaf

Because Link is often rendered with NextLink as_child, and NextLink breaks if
the href is stateful outside of a Link, ensure that any stateful child of Link
gets memoized together.
2024-02-19 15:43:27 -08:00

90 lines
2.4 KiB
Python

"""Integration tests for links and related components."""
from typing import Generator
from urllib.parse import urlsplit
import pytest
from selenium.webdriver.common.by import By
from reflex.testing import AppHarness
from .utils import poll_for_navigation
def NavigationApp():
"""Reflex app with links for navigation."""
import reflex as rx
class State(rx.State):
is_external: bool = True
app = rx.App()
@app.add_page
def index():
return rx.fragment(
rx.link("Internal", href="/internal", id="internal"),
rx.link(
"External",
href="/internal",
is_external=State.is_external,
id="external",
),
rx.link(
"External Target", href="/internal", target="_blank", id="external2"
),
)
@rx.page(route="/internal")
def internal():
return rx.text("Internal")
@pytest.fixture()
def navigation_app(tmp_path) -> Generator[AppHarness, None, None]:
"""Start NavigationApp app at tmp_path via AppHarness.
Args:
tmp_path: pytest tmp_path fixture
Yields:
running AppHarness instance
"""
with AppHarness.create(
root=tmp_path,
app_source=NavigationApp, # type: ignore
) as harness:
yield harness
@pytest.mark.asyncio
async def test_navigation_app(navigation_app: AppHarness):
"""Type text after moving cursor. Update text on backend.
Args:
navigation_app: harness for NavigationApp app
"""
assert navigation_app.app_instance is not None, "app is not running"
driver = navigation_app.frontend()
internal_link = driver.find_element(By.ID, "internal")
with poll_for_navigation(driver):
internal_link.click()
assert urlsplit(driver.current_url).path == f"/internal/"
with poll_for_navigation(driver):
driver.back()
external_link = driver.find_element(By.ID, "external")
external2_link = driver.find_element(By.ID, "external2")
external_link.click()
# Expect a new tab to open
assert AppHarness._poll_for(lambda: len(driver.window_handles) == 2)
# Switch back to the main tab
driver.switch_to.window(driver.window_handles[0])
external2_link.click()
# Expect another new tab to open
assert AppHarness._poll_for(lambda: len(driver.window_handles) == 3)