1
0

test_debounce.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. """Test that DebounceInput collapses nested forms."""
  2. import pytest
  3. import reflex as rx
  4. from reflex.state import BaseState
  5. from reflex.vars import BaseVar
  6. def test_render_no_child():
  7. """DebounceInput raises RuntimeError if no child is provided."""
  8. with pytest.raises(RuntimeError):
  9. _ = rx.debounce_input().render()
  10. def test_render_no_child_recursive():
  11. """DebounceInput raises RuntimeError if no child is provided."""
  12. with pytest.raises(RuntimeError):
  13. _ = rx.debounce_input(rx.debounce_input(rx.debounce_input())).render()
  14. def test_render_many_child():
  15. """DebounceInput raises RuntimeError if more than 1 child is provided."""
  16. with pytest.raises(RuntimeError):
  17. _ = rx.debounce_input("foo", "bar").render()
  18. class S(BaseState):
  19. """Example state for debounce tests."""
  20. value: str = ""
  21. def on_change(self, v: str):
  22. """Dummy on_change handler.
  23. Args:
  24. v: The changed value.
  25. """
  26. pass
  27. def test_render_child_props():
  28. """DebounceInput should render props from child component."""
  29. tag = rx.debounce_input(
  30. rx.input(
  31. foo="bar",
  32. baz="quuc",
  33. value="real",
  34. on_change=S.on_change,
  35. )
  36. )._render()
  37. assert tag.props["sx"] == {"foo": "bar", "baz": "quuc"}
  38. assert tag.props["value"].equals(
  39. BaseVar(
  40. _var_name="real", _var_type=str, _var_is_local=True, _var_is_string=False
  41. )
  42. )
  43. assert len(tag.props["onChange"].events) == 1
  44. assert tag.props["onChange"].events[0].handler == S.on_change
  45. assert tag.contents == ""
  46. def test_render_child_props_recursive():
  47. """DebounceInput should render props from child component.
  48. If the child component is a DebounceInput, then props will be copied from it
  49. recursively.
  50. """
  51. tag = rx.debounce_input(
  52. rx.debounce_input(
  53. rx.debounce_input(
  54. rx.debounce_input(
  55. rx.input(
  56. foo="bar",
  57. baz="quuc",
  58. value="real",
  59. on_change=S.on_change,
  60. ),
  61. value="inner",
  62. debounce_timeout=666,
  63. force_notify_on_blur=False,
  64. ),
  65. debounce_timeout=42,
  66. ),
  67. value="outer",
  68. ),
  69. force_notify_by_enter=False,
  70. )._render()
  71. assert tag.props["sx"] == {"foo": "bar", "baz": "quuc"}
  72. assert tag.props["value"].equals(
  73. BaseVar(
  74. _var_name="outer", _var_type=str, _var_is_local=True, _var_is_string=False
  75. )
  76. )
  77. assert tag.props["forceNotifyOnBlur"]._var_name == "false"
  78. assert tag.props["forceNotifyByEnter"]._var_name == "false"
  79. assert tag.props["debounceTimeout"]._var_name == "42"
  80. assert len(tag.props["onChange"].events) == 1
  81. assert tag.props["onChange"].events[0].handler == S.on_change
  82. assert tag.contents == ""
  83. def test_full_control_implicit_debounce():
  84. """DebounceInput is used when value and on_change are used together."""
  85. tag = rx.input(
  86. value=S.value,
  87. on_change=S.on_change,
  88. )._render()
  89. assert tag.props["debounceTimeout"]._var_name == "50"
  90. assert len(tag.props["onChange"].events) == 1
  91. assert tag.props["onChange"].events[0].handler == S.on_change
  92. assert tag.contents == ""
  93. def test_full_control_implicit_debounce_text_area():
  94. """DebounceInput is used when value and on_change are used together."""
  95. tag = rx.text_area(
  96. value=S.value,
  97. on_change=S.on_change,
  98. )._render()
  99. assert tag.props["debounceTimeout"]._var_name == "50"
  100. assert len(tag.props["onChange"].events) == 1
  101. assert tag.props["onChange"].events[0].handler == S.on_change
  102. assert tag.contents == ""