test_debounce.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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(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. debounce_timeout=666,
  60. force_notify_on_blur=False,
  61. ),
  62. debounce_timeout=42,
  63. ),
  64. value="outer",
  65. ),
  66. force_notify_by_enter=False,
  67. )._render()
  68. assert tag.props["sx"] == {"foo": "bar", "baz": "quuc"}
  69. assert tag.props["value"].equals(
  70. BaseVar(name="outer", type_=str, is_local=True, is_string=False)
  71. )
  72. assert tag.props["forceNotifyOnBlur"].name == "false"
  73. assert tag.props["forceNotifyByEnter"].name == "false"
  74. assert tag.props["debounceTimeout"].name == "42"
  75. assert len(tag.props["onChange"].events) == 1
  76. assert tag.props["onChange"].events[0].handler == S.on_change
  77. assert tag.contents == ""
  78. def test_full_control_implicit_debounce():
  79. """DebounceInput is used when value and on_change are used together."""
  80. tag = rx.input(
  81. value=S.value,
  82. on_change=S.on_change,
  83. )._render()
  84. assert tag.props["debounceTimeout"].name == "50"
  85. assert len(tag.props["onChange"].events) == 1
  86. assert tag.props["onChange"].events[0].handler == S.on_change
  87. assert tag.contents == ""
  88. def test_full_control_implicit_debounce_text_area():
  89. """DebounceInput is used when value and on_change are used together."""
  90. tag = rx.text_area(
  91. value=S.value,
  92. on_change=S.on_change,
  93. )._render()
  94. assert tag.props["debounceTimeout"].name == "50"
  95. assert len(tag.props["onChange"].events) == 1
  96. assert tag.props["onChange"].events[0].handler == S.on_change
  97. assert tag.contents == ""