test_navigation.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """Integration tests for links and related components."""
  2. from collections.abc import Generator
  3. from urllib.parse import urlsplit
  4. import pytest
  5. from selenium.webdriver.common.by import By
  6. from reflex.testing import AppHarness
  7. from .utils import SessionStorage, poll_for_navigation
  8. def NavigationApp():
  9. """Reflex app with links for navigation."""
  10. import reflex as rx
  11. class State(rx.State):
  12. is_external: bool = True
  13. app = rx.App()
  14. @app.add_page
  15. def index():
  16. return rx.fragment(
  17. rx.link("Internal", href="/internal", id="internal"),
  18. rx.link(
  19. "External",
  20. href="/internal",
  21. is_external=State.is_external,
  22. id="external",
  23. ),
  24. rx.link(
  25. "External Target", href="/internal", target="_blank", id="external2"
  26. ),
  27. )
  28. @rx.page(route="/internal")
  29. def internal():
  30. return rx.text("Internal")
  31. @pytest.fixture()
  32. def navigation_app(tmp_path) -> Generator[AppHarness, None, None]:
  33. """Start NavigationApp app at tmp_path via AppHarness.
  34. Args:
  35. tmp_path: pytest tmp_path fixture
  36. Yields:
  37. running AppHarness instance
  38. """
  39. with AppHarness.create(
  40. root=tmp_path,
  41. app_source=NavigationApp,
  42. ) as harness:
  43. yield harness
  44. @pytest.mark.asyncio
  45. async def test_navigation_app(navigation_app: AppHarness):
  46. """Type text after moving cursor. Update text on backend.
  47. Args:
  48. navigation_app: harness for NavigationApp app
  49. """
  50. assert navigation_app.app_instance is not None, "app is not running"
  51. driver = navigation_app.frontend()
  52. ss = SessionStorage(driver)
  53. assert AppHarness._poll_for(lambda: ss.get("token") is not None), "token not found"
  54. internal_link = driver.find_element(By.ID, "internal")
  55. with poll_for_navigation(driver):
  56. internal_link.click()
  57. assert urlsplit(driver.current_url).path == "/internal/"
  58. with poll_for_navigation(driver):
  59. driver.back()
  60. external_link = driver.find_element(By.ID, "external")
  61. external2_link = driver.find_element(By.ID, "external2")
  62. external_link.click()
  63. # Expect a new tab to open
  64. assert AppHarness._poll_for(lambda: len(driver.window_handles) == 2)
  65. # Switch back to the main tab
  66. driver.switch_to.window(driver.window_handles[0])
  67. external2_link.click()
  68. # Expect another new tab to open
  69. assert AppHarness._poll_for(lambda: len(driver.window_handles) == 3)