test_server_side_event.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. """Integration tests for special server side events."""
  2. import time
  3. from typing import Generator
  4. import pytest
  5. from selenium.webdriver.common.by import By
  6. from reflex.testing import AppHarness
  7. def ServerSideEvent():
  8. """App with inputs set via event handlers and set_value."""
  9. import reflex as rx
  10. class SSState(rx.State):
  11. def set_value_yield(self):
  12. yield rx.set_value("a", "")
  13. yield rx.set_value("b", "")
  14. yield rx.set_value("c", "")
  15. def set_value_yield_return(self):
  16. yield rx.set_value("a", "")
  17. yield rx.set_value("b", "")
  18. return rx.set_value("c", "")
  19. def set_value_return(self):
  20. return [
  21. rx.set_value("a", ""),
  22. rx.set_value("b", ""),
  23. rx.set_value("c", ""),
  24. ]
  25. def set_value_return_c(self):
  26. return rx.set_value("c", "")
  27. @rx.var
  28. def token(self) -> str:
  29. return self.get_token()
  30. app = rx.App(state=SSState)
  31. @app.add_page
  32. def index():
  33. return rx.fragment(
  34. rx.input(id="token", value=SSState.token, is_read_only=True),
  35. rx.input(default_value="a", id="a"),
  36. rx.input(default_value="b", id="b"),
  37. rx.input(default_value="c", id="c"),
  38. rx.button(
  39. "Clear Immediate",
  40. id="clear_immediate",
  41. on_click=[
  42. rx.set_value("a", ""),
  43. rx.set_value("b", ""),
  44. rx.set_value("c", ""),
  45. ],
  46. ),
  47. rx.button(
  48. "Clear Chained Yield",
  49. id="clear_chained_yield",
  50. on_click=SSState.set_value_yield,
  51. ),
  52. rx.button(
  53. "Clear Chained Yield+Return",
  54. id="clear_chained_yield_return",
  55. on_click=SSState.set_value_yield_return,
  56. ),
  57. rx.button(
  58. "Clear Chained Return",
  59. id="clear_chained_return",
  60. on_click=SSState.set_value_return,
  61. ),
  62. rx.button(
  63. "Clear C Return",
  64. id="clear_return_c",
  65. on_click=SSState.set_value_return_c,
  66. ),
  67. )
  68. app.compile()
  69. @pytest.fixture(scope="session")
  70. def server_side_event(tmp_path_factory) -> Generator[AppHarness, None, None]:
  71. """Start ServerSideEvent app at tmp_path via AppHarness.
  72. Args:
  73. tmp_path_factory: pytest tmp_path_factory fixture
  74. Yields:
  75. running AppHarness instance
  76. """
  77. with AppHarness.create(
  78. root=tmp_path_factory.mktemp("server_side_event"),
  79. app_source=ServerSideEvent, # type: ignore
  80. ) as harness:
  81. yield harness
  82. @pytest.fixture
  83. def driver(server_side_event: AppHarness):
  84. """Get an instance of the browser open to the server_side_event app.
  85. Args:
  86. server_side_event: harness for ServerSideEvent app
  87. Yields:
  88. WebDriver instance.
  89. """
  90. assert server_side_event.app_instance is not None, "app is not running"
  91. driver = server_side_event.frontend()
  92. try:
  93. token_input = driver.find_element(By.ID, "token")
  94. assert token_input
  95. # wait for the backend connection to send the token
  96. token = server_side_event.poll_for_value(token_input)
  97. assert token is not None
  98. yield driver
  99. finally:
  100. driver.quit()
  101. @pytest.mark.parametrize(
  102. "button_id",
  103. [
  104. "clear_immediate",
  105. "clear_chained_yield",
  106. "clear_chained_yield_return",
  107. "clear_chained_return",
  108. ],
  109. )
  110. def test_set_value(driver, button_id: str):
  111. """Call set_value as an event chain, via yielding, via yielding with return.
  112. Args:
  113. driver: selenium WebDriver open to the app
  114. button_id: id of the button to click (parametrized)
  115. """
  116. input_a = driver.find_element(By.ID, "a")
  117. input_b = driver.find_element(By.ID, "b")
  118. input_c = driver.find_element(By.ID, "c")
  119. btn = driver.find_element(By.ID, button_id)
  120. assert input_a
  121. assert input_b
  122. assert input_c
  123. assert btn
  124. assert input_a.get_attribute("value") == "a"
  125. assert input_b.get_attribute("value") == "b"
  126. assert input_c.get_attribute("value") == "c"
  127. btn.click()
  128. time.sleep(0.2)
  129. assert input_a.get_attribute("value") == ""
  130. assert input_b.get_attribute("value") == ""
  131. assert input_c.get_attribute("value") == ""
  132. def test_set_value_return_c(driver):
  133. """Call set_value returning single event.
  134. Args:
  135. driver: selenium WebDriver open to the app
  136. """
  137. input_a = driver.find_element(By.ID, "a")
  138. input_b = driver.find_element(By.ID, "b")
  139. input_c = driver.find_element(By.ID, "c")
  140. btn = driver.find_element(By.ID, "clear_return_c")
  141. assert input_a
  142. assert input_b
  143. assert input_c
  144. assert btn
  145. assert input_a.get_attribute("value") == "a"
  146. assert input_b.get_attribute("value") == "b"
  147. assert input_c.get_attribute("value") == "c"
  148. btn.click()
  149. time.sleep(0.2)
  150. assert input_a.get_attribute("value") == "a"
  151. assert input_b.get_attribute("value") == "b"
  152. assert input_c.get_attribute("value") == ""