1
0

test_state_inheritance.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. """Test state inheritance."""
  2. from typing import Generator
  3. import pytest
  4. from selenium.webdriver.common.by import By
  5. from reflex.testing import DEFAULT_TIMEOUT, AppHarness, WebDriver
  6. def StateInheritance():
  7. """Test that state inheritance works as expected."""
  8. import reflex as rx
  9. class ChildMixin:
  10. child_mixin: str = "child_mixin"
  11. @rx.var
  12. def computed_child_mixin(self) -> str:
  13. return "computed_child_mixin"
  14. class Mixin(ChildMixin):
  15. mixin: str = "mixin"
  16. @rx.var
  17. def computed_mixin(self) -> str:
  18. return "computed_mixin"
  19. class OtherMixin(rx.Base):
  20. other_mixin: str = "other_mixin"
  21. @rx.var
  22. def computed_other_mixin(self) -> str:
  23. return "computed_other_mixin"
  24. class Base1(rx.State, Mixin):
  25. base1: str = "base1"
  26. @rx.var
  27. def computed_basevar(self) -> str:
  28. return "computed_basevar1"
  29. class Base2(rx.State):
  30. base2: str = "base2"
  31. @rx.var
  32. def computed_basevar(self) -> str:
  33. return "computed_basevar2"
  34. class Child1(Base1, OtherMixin):
  35. pass
  36. class Child2(Base2, Mixin, OtherMixin):
  37. pass
  38. class Child3(Child2):
  39. child3: str = "child3"
  40. @rx.var
  41. def computed_childvar(self) -> str:
  42. return "computed_childvar"
  43. def index() -> rx.Component:
  44. return rx.vstack(
  45. rx.input(
  46. id="token", value=Base1.router.session.client_token, is_read_only=True
  47. ),
  48. rx.heading(Base1.computed_mixin, id="base1-computed_mixin"),
  49. rx.heading(Base1.computed_basevar, id="base1-computed_basevar"),
  50. rx.heading(Base1.computed_child_mixin, id="base1-child-mixin"),
  51. rx.heading(Base1.base1, id="base1-base1"),
  52. rx.heading(Base1.mixin, id="base1-mixin"),
  53. rx.heading(Base1.child_mixin, id="base1-child_mixin"),
  54. rx.heading(Base2.computed_basevar, id="base2-computed_basevar"),
  55. rx.heading(Base2.base2, id="base2-base2"),
  56. rx.heading(Child1.computed_basevar, id="child1-computed_basevar"),
  57. rx.heading(Child1.computed_mixin, id="child1-computed_mixin"),
  58. rx.heading(Child1.computed_other_mixin, id="child1-other-mixin"),
  59. rx.heading(Child1.computed_child_mixin, id="child1-child-mixin"),
  60. rx.heading(Child1.base1, id="child1-base1"),
  61. rx.heading(Child1.mixin, id="child1-mixin"),
  62. rx.heading(Child1.other_mixin, id="child1-other_mixin"),
  63. rx.heading(Child1.child_mixin, id="child1-child_mixin"),
  64. rx.heading(Child2.computed_basevar, id="child2-computed_basevar"),
  65. rx.heading(Child2.computed_mixin, id="child2-computed_mixin"),
  66. rx.heading(Child2.computed_other_mixin, id="child2-other-mixin"),
  67. rx.heading(Child2.computed_child_mixin, id="child2-child-mixin"),
  68. rx.heading(Child2.base2, id="child2-base2"),
  69. rx.heading(Child2.mixin, id="child2-mixin"),
  70. rx.heading(Child2.other_mixin, id="child2-other_mixin"),
  71. rx.heading(Child2.child_mixin, id="child2-child_mixin"),
  72. rx.heading(Child3.computed_basevar, id="child3-computed_basevar"),
  73. rx.heading(Child3.computed_mixin, id="child3-computed_mixin"),
  74. rx.heading(Child3.computed_other_mixin, id="child3-other-mixin"),
  75. rx.heading(Child3.computed_childvar, id="child3-computed_childvar"),
  76. rx.heading(Child3.computed_child_mixin, id="child3-child-mixin"),
  77. rx.heading(Child3.child3, id="child3-child3"),
  78. rx.heading(Child3.base2, id="child3-base2"),
  79. rx.heading(Child3.mixin, id="child3-mixin"),
  80. rx.heading(Child3.other_mixin, id="child3-other_mixin"),
  81. rx.heading(Child3.child_mixin, id="child3-child_mixin"),
  82. )
  83. app = rx.App()
  84. app.add_page(index)
  85. @pytest.fixture(scope="session")
  86. def state_inheritance(
  87. tmp_path_factory,
  88. ) -> Generator[AppHarness, None, None]:
  89. """Start StateInheritance app at tmp_path via AppHarness.
  90. Args:
  91. tmp_path_factory: pytest tmp_path_factory fixture
  92. Yields:
  93. running AppHarness instance
  94. """
  95. with AppHarness.create(
  96. root=tmp_path_factory.mktemp(f"state_inheritance"),
  97. app_source=StateInheritance, # type: ignore
  98. ) as harness:
  99. yield harness
  100. @pytest.fixture
  101. def driver(state_inheritance: AppHarness) -> Generator[WebDriver, None, None]:
  102. """Get an instance of the browser open to the state_inheritance app.
  103. Args:
  104. state_inheritance: harness for StateInheritance app
  105. Yields:
  106. WebDriver instance.
  107. """
  108. assert state_inheritance.app_instance is not None, "app is not running"
  109. driver = state_inheritance.frontend()
  110. try:
  111. yield driver
  112. finally:
  113. driver.quit()
  114. @pytest.fixture()
  115. def token(state_inheritance: AppHarness, driver: WebDriver) -> str:
  116. """Get a function that returns the active token.
  117. Args:
  118. state_inheritance: harness for StateInheritance app.
  119. driver: WebDriver instance.
  120. Returns:
  121. The token for the connected client
  122. """
  123. assert state_inheritance.app_instance is not None
  124. token_input = driver.find_element(By.ID, "token")
  125. assert token_input
  126. # wait for the backend connection to send the token
  127. token = state_inheritance.poll_for_value(token_input, timeout=DEFAULT_TIMEOUT * 2)
  128. assert token is not None
  129. return token
  130. def test_state_inheritance(
  131. state_inheritance: AppHarness,
  132. driver: WebDriver,
  133. token: str,
  134. ):
  135. """Test that background tasks work as expected.
  136. Args:
  137. state_inheritance: harness for StateInheritance app.
  138. driver: WebDriver instance.
  139. token: The token for the connected client.
  140. """
  141. assert state_inheritance.app_instance is not None
  142. base1_mixin = driver.find_element(By.ID, "base1-computed_mixin")
  143. assert base1_mixin.text == "computed_mixin"
  144. base1_computed_basevar = driver.find_element(By.ID, "base1-computed_basevar")
  145. assert base1_computed_basevar.text == "computed_basevar1"
  146. base1_computed_child_mixin = driver.find_element(By.ID, "base1-child-mixin")
  147. assert base1_computed_child_mixin.text == "computed_child_mixin"
  148. base1_base1 = driver.find_element(By.ID, "base1-base1")
  149. assert base1_base1.text == "base1"
  150. base1_mixin = driver.find_element(By.ID, "base1-mixin")
  151. assert base1_mixin.text == "mixin"
  152. base1_child_mixin = driver.find_element(By.ID, "base1-child_mixin")
  153. assert base1_child_mixin.text == "child_mixin"
  154. base2_computed_basevar = driver.find_element(By.ID, "base2-computed_basevar")
  155. assert base2_computed_basevar.text == "computed_basevar2"
  156. base2_base2 = driver.find_element(By.ID, "base2-base2")
  157. assert base2_base2.text == "base2"
  158. child1_computed_basevar = driver.find_element(By.ID, "child1-computed_basevar")
  159. assert child1_computed_basevar.text == "computed_basevar1"
  160. child1_mixin = driver.find_element(By.ID, "child1-computed_mixin")
  161. assert child1_mixin.text == "computed_mixin"
  162. child1_computed_other_mixin = driver.find_element(By.ID, "child1-other-mixin")
  163. assert child1_computed_other_mixin.text == "computed_other_mixin"
  164. child1_computed_child_mixin = driver.find_element(By.ID, "child1-child-mixin")
  165. assert child1_computed_child_mixin.text == "computed_child_mixin"
  166. child1_base1 = driver.find_element(By.ID, "child1-base1")
  167. assert child1_base1.text == "base1"
  168. child1_mixin = driver.find_element(By.ID, "child1-mixin")
  169. assert child1_mixin.text == "mixin"
  170. child1_other_mixin = driver.find_element(By.ID, "child1-other_mixin")
  171. assert child1_other_mixin.text == "other_mixin"
  172. child1_child_mixin = driver.find_element(By.ID, "child1-child_mixin")
  173. assert child1_child_mixin.text == "child_mixin"
  174. child2_computed_basevar = driver.find_element(By.ID, "child2-computed_basevar")
  175. assert child2_computed_basevar.text == "computed_basevar2"
  176. child2_mixin = driver.find_element(By.ID, "child2-computed_mixin")
  177. assert child2_mixin.text == "computed_mixin"
  178. child2_computed_other_mixin = driver.find_element(By.ID, "child2-other-mixin")
  179. assert child2_computed_other_mixin.text == "computed_other_mixin"
  180. child2_computed_child_mixin = driver.find_element(By.ID, "child2-child-mixin")
  181. assert child2_computed_child_mixin.text == "computed_child_mixin"
  182. child2_base2 = driver.find_element(By.ID, "child2-base2")
  183. assert child2_base2.text == "base2"
  184. child2_mixin = driver.find_element(By.ID, "child2-mixin")
  185. assert child2_mixin.text == "mixin"
  186. child2_other_mixin = driver.find_element(By.ID, "child2-other_mixin")
  187. assert child2_other_mixin.text == "other_mixin"
  188. child2_child_mixin = driver.find_element(By.ID, "child2-child_mixin")
  189. assert child2_child_mixin.text == "child_mixin"
  190. child3_computed_basevar = driver.find_element(By.ID, "child3-computed_basevar")
  191. assert child3_computed_basevar.text == "computed_basevar2"
  192. child3_mixin = driver.find_element(By.ID, "child3-computed_mixin")
  193. assert child3_mixin.text == "computed_mixin"
  194. child3_computed_other_mixin = driver.find_element(By.ID, "child3-other-mixin")
  195. assert child3_computed_other_mixin.text == "computed_other_mixin"
  196. child3_computed_childvar = driver.find_element(By.ID, "child3-computed_childvar")
  197. assert child3_computed_childvar.text == "computed_childvar"
  198. child3_computed_child_mixin = driver.find_element(By.ID, "child3-child-mixin")
  199. assert child3_computed_child_mixin.text == "computed_child_mixin"
  200. child3_child3 = driver.find_element(By.ID, "child3-child3")
  201. assert child3_child3.text == "child3"
  202. child3_base2 = driver.find_element(By.ID, "child3-base2")
  203. assert child3_base2.text == "base2"
  204. child3_mixin = driver.find_element(By.ID, "child3-mixin")
  205. assert child3_mixin.text == "mixin"
  206. child3_other_mixin = driver.find_element(By.ID, "child3-other_mixin")
  207. assert child3_other_mixin.text == "other_mixin"
  208. child3_child_mixin = driver.find_element(By.ID, "child3-child_mixin")
  209. assert child3_child_mixin.text == "child_mixin"