
* use serializer system * add checks for unsupported operands * and and or are now supported * format * remove unnecessary call to JSON * put base before rest * fix failing testcase * add hinting to get static analysis to complain * damn * big changes * get typeguard from extensions * please darglint * dangit darglint * remove one from vars * add without data and use it in plotly * DARGLINT * change format for special props * add pyi * delete instances of Var.create * modify client state to work * fixed so much * remove every Var.create * delete all basevar stuff * checkpoint * fix pyi * get older python to work * dangit darglint * add simple fix to last failing testcase * remove var name unwrapped and put client state on immutable var * fix older python * fox event issues * change forms pyi * make test less strict * use rx state directly * add typeignore to page_id * implement foreach * delete .web states folder silly * update reflex chakra * fix issue when on mount or on unmount is not set * nuke Var * run pyi * import immutablevar in critical location * delete unwrap vars * bring back array ref * fix style props in app * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * Update find_replace (#3886) * [REF-3592]Promote `rx.progress` from radix themes (#3878) * Promote `rx.progress` from radix themes * fix pyi * add warning when accessing `rx._x.progress` * Use correct flexgen backend URL (#3891) * Remove demo template (#3888) * gitignore .web (#3885) * update overflowY in AUTO_HEIGHT_JS from hidden to scroll (#3882) * Retain mutability inside `async with self` block (#3884) When emitting a state update, restore `_self_mutable` to the value it had previously so that `yield` in the middle of `async with self` does not result in an immutable StateProxy. Fix #3869 * Include child imports in markdown component_map (#3883) If a component in the markdown component_map contains children components, use `_get_all_imports` to recursively enumerate them. Fix #3880 * [REF-3570] Remove deprecated REDIS_URL syntax (#3892) * mixin computed vars should only be applied to highest level state (#3833) * improve state hierarchy validation, drop old testing special case (#3894) * fix var dependency dicts (#3842) * Adding array to array pluck operation. (#3868) * fix initial state without cv fallback (#3670) * add fragment to foreach (#3877) * Update docker-example (#3324) * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * Merge branch 'main' into use-old-serializer-in-literalvar * [REF-3570] Remove deprecated REDIS_URL syntax (#3892) * /health endpoint for K8 Liveness and Readiness probes (#3855) * Added API Endpoint * Added API Endpoint * Added Unit Tests * Added Unit Tests * main * Apply suggestions from Code Review * Fix Ruff Formatting * Update Socket Events * Async Functions * [REF-3570] Remove deprecated REDIS_URL syntax (#3892) * remove extra var Co-authored-by: Masen Furer <m_github@0x26.net> * resolve typo * write better doc for var.create * return var value when we know it's literal var * fix unit test * less bloat for ToOperations * simplify ImmutableComputedVar.__get__ (#3902) * simplify ImmutableComputedVar.__get__ * ruff it --------- Co-authored-by: Samarth Bhadane <samarthbhadane119@gmail.com> Co-authored-by: Elijah Ahianyo <elijahahianyo@gmail.com> Co-authored-by: Masen Furer <m_github@0x26.net> Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com> Co-authored-by: Vishnu Deva <vishnu.deva12@gmail.com> Co-authored-by: abulvenz <a.eismann@senbax.de>
186 lines
5.5 KiB
Python
186 lines
5.5 KiB
Python
"""Test that DebounceInput collapses nested forms."""
|
|
|
|
import pytest
|
|
|
|
import reflex as rx
|
|
from reflex.components.core.debounce import DEFAULT_DEBOUNCE_TIMEOUT
|
|
from reflex.ivars.base import ImmutableVar, LiteralVar
|
|
from reflex.state import BaseState
|
|
|
|
|
|
def test_create_no_child():
|
|
"""DebounceInput raises RuntimeError if no child is provided."""
|
|
with pytest.raises(RuntimeError):
|
|
_ = rx.debounce_input()
|
|
|
|
|
|
def test_create_no_child_recursive():
|
|
"""DebounceInput raises RuntimeError if no child is provided."""
|
|
with pytest.raises(RuntimeError):
|
|
_ = rx.debounce_input(rx.debounce_input(rx.debounce_input()))
|
|
|
|
|
|
def test_create_many_child():
|
|
"""DebounceInput raises RuntimeError if more than 1 child is provided."""
|
|
with pytest.raises(RuntimeError):
|
|
_ = rx.debounce_input("foo", "bar")
|
|
|
|
|
|
def test_create_no_on_change():
|
|
"""DebounceInput raises ValueError if child has no on_change handler."""
|
|
with pytest.raises(ValueError):
|
|
_ = rx.debounce_input(rx.input())
|
|
|
|
|
|
class S(BaseState):
|
|
"""Example state for debounce tests."""
|
|
|
|
value: str = ""
|
|
|
|
def on_change(self, v: str):
|
|
"""Dummy on_change handler.
|
|
|
|
|
|
Args:
|
|
v: The changed value.
|
|
"""
|
|
pass
|
|
|
|
|
|
def test_render_child_props():
|
|
"""DebounceInput should render props from child component."""
|
|
tag = rx.debounce_input(
|
|
rx.input(
|
|
foo="bar",
|
|
baz="quuc",
|
|
value="real",
|
|
on_change=S.on_change,
|
|
)
|
|
)._render()
|
|
assert "css" in tag.props and isinstance(tag.props["css"], rx.Var)
|
|
for prop in ["foo", "bar", "baz", "quuc"]:
|
|
assert prop in str(tag.props["css"])
|
|
assert tag.props["value"].equals(LiteralVar.create("real"))
|
|
assert len(tag.props["onChange"].events) == 1
|
|
assert tag.props["onChange"].events[0].handler == S.on_change
|
|
assert tag.contents == ""
|
|
|
|
|
|
def test_render_with_class_name():
|
|
tag = rx.debounce_input(
|
|
rx.input(
|
|
on_change=S.on_change,
|
|
class_name="foo baz",
|
|
)
|
|
)._render()
|
|
assert isinstance(tag.props["className"], rx.Var)
|
|
assert "foo baz" in str(tag.props["className"])
|
|
|
|
|
|
def test_render_with_ref():
|
|
tag = rx.debounce_input(
|
|
rx.input(
|
|
on_change=S.on_change,
|
|
id="foo_bar",
|
|
)
|
|
)._render()
|
|
assert isinstance(tag.props["inputRef"], rx.Var)
|
|
assert "foo_bar" in str(tag.props["inputRef"])
|
|
|
|
|
|
def test_render_with_key():
|
|
tag = rx.debounce_input(
|
|
rx.input(
|
|
on_change=S.on_change,
|
|
key="foo_bar",
|
|
)
|
|
)._render()
|
|
assert isinstance(tag.props["key"], rx.Var)
|
|
assert "foo_bar" in str(tag.props["key"])
|
|
|
|
|
|
def test_render_with_special_props():
|
|
special_prop = ImmutableVar.create_safe("{foo_bar}")
|
|
tag = rx.debounce_input(
|
|
rx.input(
|
|
on_change=S.on_change,
|
|
special_props=[special_prop],
|
|
)
|
|
)._render()
|
|
assert len(tag.special_props) == 1
|
|
assert list(tag.special_props)[0].equals(special_prop)
|
|
|
|
|
|
def test_event_triggers():
|
|
debounced_input = rx.debounce_input(
|
|
rx.input(
|
|
on_change=S.on_change,
|
|
)
|
|
)
|
|
assert tuple(debounced_input.get_event_triggers()) == (
|
|
*rx.Component().get_event_triggers(), # default event triggers
|
|
"on_change",
|
|
)
|
|
|
|
|
|
def test_render_child_props_recursive():
|
|
"""DebounceInput should render props from child component.
|
|
|
|
If the child component is a DebounceInput, then props will be copied from it
|
|
recursively.
|
|
"""
|
|
tag = rx.debounce_input(
|
|
rx.debounce_input(
|
|
rx.debounce_input(
|
|
rx.debounce_input(
|
|
rx.input(
|
|
foo="bar",
|
|
baz="quuc",
|
|
value="real",
|
|
on_change=S.on_change,
|
|
),
|
|
value="inner",
|
|
debounce_timeout=666,
|
|
force_notify_on_blur=False,
|
|
),
|
|
debounce_timeout=42,
|
|
),
|
|
value="outer",
|
|
),
|
|
force_notify_by_enter=False,
|
|
)._render()
|
|
assert "css" in tag.props and isinstance(tag.props["css"], rx.Var)
|
|
for prop in ["foo", "bar", "baz", "quuc"]:
|
|
assert prop in str(tag.props["css"])
|
|
assert tag.props["value"].equals(LiteralVar.create("outer"))
|
|
assert tag.props["forceNotifyOnBlur"]._var_name == "false"
|
|
assert tag.props["forceNotifyByEnter"]._var_name == "false"
|
|
assert tag.props["debounceTimeout"]._var_name == "42"
|
|
assert len(tag.props["onChange"].events) == 1
|
|
assert tag.props["onChange"].events[0].handler == S.on_change
|
|
assert tag.contents == ""
|
|
|
|
|
|
def test_full_control_implicit_debounce():
|
|
"""DebounceInput is used when value and on_change are used together."""
|
|
tag = rx.input(
|
|
value=S.value,
|
|
on_change=S.on_change,
|
|
)._render()
|
|
assert tag.props["debounceTimeout"]._var_name == str(DEFAULT_DEBOUNCE_TIMEOUT)
|
|
assert len(tag.props["onChange"].events) == 1
|
|
assert tag.props["onChange"].events[0].handler == S.on_change
|
|
assert tag.contents == ""
|
|
|
|
|
|
def test_full_control_implicit_debounce_text_area():
|
|
"""DebounceInput is used when value and on_change are used together."""
|
|
tag = rx.text_area(
|
|
value=S.value,
|
|
on_change=S.on_change,
|
|
)._render()
|
|
assert tag.props["debounceTimeout"]._var_name == str(DEFAULT_DEBOUNCE_TIMEOUT)
|
|
assert len(tag.props["onChange"].events) == 1
|
|
assert tag.props["onChange"].events[0].handler == S.on_change
|
|
assert tag.contents == ""
|