test_input.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. """Integration tests for text input and related components."""
  2. import time
  3. from typing import Generator
  4. import pytest
  5. from selenium.webdriver.common.by import By
  6. from selenium.webdriver.common.keys import Keys
  7. from reflex.testing import AppHarness
  8. def FullyControlledInput():
  9. """App using a fully controlled input with debounce wrapper."""
  10. import reflex as rx
  11. class State(rx.State):
  12. text: str = "initial"
  13. app = rx.App(state=State)
  14. @app.add_page
  15. def index():
  16. return rx.debounce_input(
  17. rx.input(
  18. value=State.text,
  19. on_change=State.set_text, # type: ignore
  20. ),
  21. debounce_timeout=0,
  22. )
  23. app.compile()
  24. @pytest.fixture()
  25. def fully_controlled_input(tmp_path) -> Generator[AppHarness, None, None]:
  26. """Start FullyControlledInput app at tmp_path via AppHarness.
  27. Args:
  28. tmp_path: pytest tmp_path fixture
  29. Yields:
  30. running AppHarness instance
  31. """
  32. with AppHarness.create(
  33. root=tmp_path,
  34. app_source=FullyControlledInput, # type: ignore
  35. ) as harness:
  36. yield harness
  37. @pytest.mark.asyncio
  38. async def test_fully_controlled_input(fully_controlled_input: AppHarness):
  39. """Type text after moving cursor. Update text on backend.
  40. Args:
  41. fully_controlled_input: harness for FullyControlledInput app
  42. """
  43. assert fully_controlled_input.app_instance is not None, "app is not running"
  44. driver = fully_controlled_input.frontend()
  45. # get a reference to the connected client
  46. assert len(fully_controlled_input.poll_for_clients()) == 1
  47. token, backend_state = list(
  48. fully_controlled_input.app_instance.state_manager.states.items()
  49. )[0]
  50. # find the input and wait for it to have the initial state value
  51. text_input = driver.find_element(By.TAG_NAME, "input")
  52. assert fully_controlled_input.poll_for_value(text_input) == "initial"
  53. # move cursor to home, then to the right and type characters
  54. text_input.send_keys(Keys.HOME, Keys.ARROW_RIGHT)
  55. text_input.send_keys("foo")
  56. assert text_input.get_attribute("value") == "ifoonitial"
  57. assert backend_state.text == "ifoonitial"
  58. # clear the input on the backend
  59. backend_state.text = ""
  60. fully_controlled_input.app_instance.state_manager.set_state(token, backend_state)
  61. await fully_controlled_input.emit_state_updates()
  62. assert backend_state.text == ""
  63. assert (
  64. fully_controlled_input.poll_for_value(text_input, exp_not_equal="ifoonitial")
  65. == ""
  66. )
  67. # type more characters
  68. text_input.send_keys("getting testing done")
  69. time.sleep(0.1)
  70. assert text_input.get_attribute("value") == "getting testing done"
  71. assert backend_state.text == "getting testing done"