test_debounce.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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"] == BaseVar(
  38. name="real", type_=str, is_local=True, is_string=False
  39. )
  40. assert len(tag.props["onChange"].events) == 1
  41. assert tag.props["onChange"].events[0].handler == S.on_change
  42. assert tag.contents == ""
  43. def test_render_child_props_recursive():
  44. """DebounceInput should render props from child component.
  45. If the child component is a DebounceInput, then props will be copied from it
  46. recursively.
  47. """
  48. tag = rx.debounce_input(
  49. rx.debounce_input(
  50. rx.debounce_input(
  51. rx.debounce_input(
  52. rx.input(
  53. foo="bar",
  54. baz="quuc",
  55. value="real",
  56. on_change=S.on_change,
  57. ),
  58. value="inner",
  59. force_notify_on_blur=False,
  60. ),
  61. debounce_timeout=42,
  62. ),
  63. value="outer",
  64. ),
  65. force_notify_by_enter=False,
  66. )._render()
  67. assert tag.props["sx"] == {"foo": "bar", "baz": "quuc"}
  68. assert tag.props["value"] == BaseVar(
  69. name="real", type_=str, is_local=True, is_string=False
  70. )
  71. assert tag.props["forceNotifyOnBlur"].name == "false"
  72. assert tag.props["forceNotifyByEnter"].name == "false"
  73. assert tag.props["debounceTimeout"].name == "42"
  74. assert len(tag.props["onChange"].events) == 1
  75. assert tag.props["onChange"].events[0].handler == S.on_change
  76. assert tag.contents == ""
  77. def test_full_control_implicit_debounce():
  78. """DebounceInput is used when value and on_change are used together."""
  79. tag = rx.input(
  80. value=S.value,
  81. on_change=S.on_change,
  82. )._render()
  83. assert tag.props["debounceTimeout"].name == "50"
  84. assert len(tag.props["onChange"].events) == 1
  85. assert tag.props["onChange"].events[0].handler == S.on_change
  86. assert tag.contents == ""
  87. def test_full_control_implicit_debounce_text_area():
  88. """DebounceInput is used when value and on_change are used together."""
  89. tag = rx.text_area(
  90. value=S.value,
  91. on_change=S.on_change,
  92. )._render()
  93. assert tag.props["debounceTimeout"].name == "50"
  94. assert len(tag.props["onChange"].events) == 1
  95. assert tag.props["onChange"].events[0].handler == S.on_change
  96. assert tag.contents == ""