1
0

test_dynamic_components.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. """Integration tests for var operations."""
  2. import time
  3. from collections.abc import Callable, Generator
  4. from typing import TypeVar
  5. import pytest
  6. from selenium.webdriver.common.by import By
  7. from reflex.testing import AppHarness
  8. # pyright: reportOptionalMemberAccess=false, reportGeneralTypeIssues=false, reportUnknownMemberType=false
  9. def DynamicComponents():
  10. """App with var operations."""
  11. import reflex as rx
  12. class DynamicComponentsState(rx.State):
  13. value: int = 10
  14. button: rx.Component = rx.button(
  15. "Click me",
  16. custom_attrs={
  17. "id": "button",
  18. },
  19. )
  20. @rx.event
  21. def got_clicked(self):
  22. self.button = rx.button(
  23. "Clicked",
  24. custom_attrs={
  25. "id": "button",
  26. },
  27. )
  28. @rx.var
  29. def client_token_component(self) -> rx.Component:
  30. return rx.vstack(
  31. rx.el.input(
  32. custom_attrs={
  33. "id": "token",
  34. },
  35. value=self.router.session.client_token,
  36. is_read_only=True,
  37. ),
  38. rx.button(
  39. "Update",
  40. custom_attrs={
  41. "id": "update",
  42. },
  43. on_click=DynamicComponentsState.got_clicked,
  44. ),
  45. )
  46. app = rx.App()
  47. def factorial(n: int) -> int:
  48. if n == 0:
  49. return 1
  50. return n * factorial(n - 1)
  51. @app.add_page
  52. def index():
  53. return rx.vstack(
  54. DynamicComponentsState.client_token_component,
  55. DynamicComponentsState.button,
  56. rx.text(
  57. DynamicComponentsState._evaluate(
  58. lambda state: factorial(state.value), of_type=int
  59. ),
  60. id="factorial",
  61. ),
  62. )
  63. @pytest.fixture(scope="module")
  64. def dynamic_components(tmp_path_factory) -> Generator[AppHarness, None, None]:
  65. """Start VarOperations app at tmp_path via AppHarness.
  66. Args:
  67. tmp_path_factory: pytest tmp_path_factory fixture
  68. Yields:
  69. running AppHarness instance
  70. """
  71. with AppHarness.create(
  72. root=tmp_path_factory.mktemp("dynamic_components"),
  73. app_source=DynamicComponents,
  74. ) as harness:
  75. assert harness.app_instance is not None, "app is not running"
  76. yield harness
  77. T = TypeVar("T")
  78. def poll_for_result(
  79. f: Callable[[], T], exception=Exception, max_attempts=5, seconds_between_attempts=1
  80. ) -> T:
  81. """Poll for a result from a function.
  82. Args:
  83. f: function to call
  84. exception: exception to catch
  85. max_attempts: maximum number of attempts
  86. seconds_between_attempts: seconds to wait between
  87. Returns:
  88. Result of the function
  89. Raises:
  90. AssertionError: if the function does not return a value
  91. """
  92. attempts = 0
  93. while attempts < max_attempts:
  94. try:
  95. return f()
  96. except exception:
  97. attempts += 1
  98. time.sleep(seconds_between_attempts)
  99. raise AssertionError("Function did not return a value")
  100. @pytest.fixture
  101. def driver(dynamic_components: AppHarness):
  102. """Get an instance of the browser open to the dynamic components app.
  103. Args:
  104. dynamic_components: AppHarness for the dynamic components
  105. Yields:
  106. WebDriver instance.
  107. """
  108. driver = dynamic_components.frontend()
  109. try:
  110. token_input = poll_for_result(lambda: driver.find_element(By.ID, "token"))
  111. assert token_input
  112. # wait for the backend connection to send the token
  113. token = dynamic_components.poll_for_value(token_input)
  114. assert token is not None
  115. yield driver
  116. finally:
  117. driver.quit()
  118. def test_dynamic_components(driver, dynamic_components: AppHarness):
  119. """Test that the var operations produce the right results.
  120. Args:
  121. driver: selenium WebDriver open to the app
  122. dynamic_components: AppHarness for the dynamic components
  123. """
  124. button = poll_for_result(lambda: driver.find_element(By.ID, "button"))
  125. assert button
  126. assert button.text == "Click me"
  127. update_button = driver.find_element(By.ID, "update")
  128. assert update_button
  129. update_button.click()
  130. assert (
  131. dynamic_components.poll_for_content(button, exp_not_equal="Click me")
  132. == "Clicked"
  133. )
  134. factorial = poll_for_result(lambda: driver.find_element(By.ID, "factorial"))
  135. assert factorial
  136. assert factorial.text == "3628800"