test_debounce.py 3.7 KB

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