test_memo.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. """Integration tests for rx.memo components."""
  2. from typing import Generator
  3. import pytest
  4. from selenium.webdriver.common.by import By
  5. from reflex.testing import AppHarness
  6. def MemoApp():
  7. """Reflex app with memo components."""
  8. import reflex as rx
  9. class FooComponent(rx.Fragment):
  10. def add_custom_code(self) -> list[str]:
  11. return [
  12. "const foo = 'bar'",
  13. ]
  14. @rx.memo
  15. def foo_component(t: str):
  16. return FooComponent.create(t, rx.Var("foo"))
  17. @rx.memo
  18. def foo_component2(t: str):
  19. return FooComponent.create(t, rx.Var("foo"))
  20. class MemoState(rx.State):
  21. last_value: str = ""
  22. @rx.event
  23. def set_last_value(self, value: str):
  24. self.last_value = value
  25. @rx.memo
  26. def my_memoed_component(
  27. some_value: str,
  28. event: rx.EventHandler[rx.event.passthrough_event_spec(str)],
  29. ) -> rx.Component:
  30. return rx.vstack(
  31. rx.button(some_value, id="memo-button", on_click=event(some_value)),
  32. rx.input(id="memo-input", on_change=event),
  33. )
  34. def index() -> rx.Component:
  35. return rx.vstack(
  36. rx.vstack(
  37. foo_component(t="foo"), foo_component2(t="bar"), id="memo-custom-code"
  38. ),
  39. rx.text(MemoState.last_value, id="memo-last-value"),
  40. my_memoed_component(
  41. some_value="memod_some_value", event=MemoState.set_last_value
  42. ),
  43. )
  44. app = rx.App()
  45. app.add_page(index)
  46. @pytest.fixture()
  47. def memo_app(tmp_path) -> Generator[AppHarness, None, None]:
  48. """Start MemoApp app at tmp_path via AppHarness.
  49. Args:
  50. tmp_path: pytest tmp_path fixture
  51. Yields:
  52. running AppHarness instance
  53. """
  54. with AppHarness.create(
  55. root=tmp_path,
  56. app_source=MemoApp,
  57. ) as harness:
  58. yield harness
  59. @pytest.mark.asyncio
  60. async def test_memo_app(memo_app: AppHarness):
  61. """Render various memo'd components and assert on the output.
  62. Args:
  63. memo_app: harness for MemoApp app
  64. """
  65. assert memo_app.app_instance is not None, "app is not running"
  66. driver = memo_app.frontend()
  67. # check that the output matches
  68. memo_custom_code_stack = driver.find_element(By.ID, "memo-custom-code")
  69. assert (
  70. memo_app.poll_for_content(memo_custom_code_stack, exp_not_equal="")
  71. == "foobarbarbar"
  72. )
  73. assert memo_custom_code_stack.text == "foobarbarbar"
  74. # click the button to trigger partial event application
  75. button = driver.find_element(By.ID, "memo-button")
  76. button.click()
  77. last_value = driver.find_element(By.ID, "memo-last-value")
  78. assert memo_app.poll_for_content(last_value, exp_not_equal="") == "memod_some_value"
  79. # enter text to trigger passed argument to event handler
  80. textbox = driver.find_element(By.ID, "memo-input")
  81. textbox.send_keys("new_value")
  82. assert memo_app._poll_for(
  83. lambda: memo_app.poll_for_content(last_value) == "new_value"
  84. )