Do not stop prop is there is no prop to stop (#2116)
Check that desired event actions are defined on the object passed as the DOM event before calling them to avoid frontend errors.
This commit is contained in:
parent
6e71393ed5
commit
bf20a530df
@ -1,5 +1,6 @@
|
|||||||
"""Ensure stopPropagation and preventDefault work as expected."""
|
"""Ensure stopPropagation and preventDefault work as expected."""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
from typing import Callable, Coroutine, Generator
|
from typing import Callable, Coroutine, Generator
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -21,13 +22,31 @@ def TestEventAction():
|
|||||||
def on_click2(self):
|
def on_click2(self):
|
||||||
self.order.append("on_click2")
|
self.order.append("on_click2")
|
||||||
|
|
||||||
@rx.var
|
class EventFiringComponent(rx.Component):
|
||||||
def token(self) -> str:
|
"""A component that fires onClick event without passing DOM event."""
|
||||||
return self.get_token()
|
|
||||||
|
tag = "EventFiringComponent"
|
||||||
|
|
||||||
|
def _get_custom_code(self) -> str | None:
|
||||||
|
return """
|
||||||
|
function EventFiringComponent(props) {
|
||||||
|
return (
|
||||||
|
<div id={props.id} onClick={(e) => props.onClick("foo")}>
|
||||||
|
Event Firing Component
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}"""
|
||||||
|
|
||||||
|
def get_event_triggers(self):
|
||||||
|
return {"on_click": lambda: []}
|
||||||
|
|
||||||
def index():
|
def index():
|
||||||
return rx.vstack(
|
return rx.vstack(
|
||||||
rx.input(value=EventActionState.token, is_read_only=True, id="token"),
|
rx.input(
|
||||||
|
value=EventActionState.router.session.client_token,
|
||||||
|
is_read_only=True,
|
||||||
|
id="token",
|
||||||
|
),
|
||||||
rx.button("No events", id="btn-no-events"),
|
rx.button("No events", id="btn-no-events"),
|
||||||
rx.button(
|
rx.button(
|
||||||
"Stop Prop Only",
|
"Stop Prop Only",
|
||||||
@ -90,6 +109,18 @@ def TestEventAction():
|
|||||||
).stop_propagation.prevent_default,
|
).stop_propagation.prevent_default,
|
||||||
id="link-stop-propagation-prevent-default",
|
id="link-stop-propagation-prevent-default",
|
||||||
),
|
),
|
||||||
|
EventFiringComponent.create(
|
||||||
|
id="custom-stop-propagation",
|
||||||
|
on_click=EventActionState.on_click( # type: ignore
|
||||||
|
"custom-stop-propagation"
|
||||||
|
).stop_propagation,
|
||||||
|
),
|
||||||
|
EventFiringComponent.create(
|
||||||
|
id="custom-prevent-default",
|
||||||
|
on_click=EventActionState.on_click( # type: ignore
|
||||||
|
"custom-prevent-default"
|
||||||
|
).prevent_default,
|
||||||
|
),
|
||||||
rx.list(
|
rx.list(
|
||||||
rx.foreach(
|
rx.foreach(
|
||||||
EventActionState.order, # type: ignore
|
EventActionState.order, # type: ignore
|
||||||
@ -202,6 +233,14 @@ def poll_for_order(
|
|||||||
("link-prevent-default", ["on_click:link_prevent_default", "on_click:outer"]),
|
("link-prevent-default", ["on_click:link_prevent_default", "on_click:outer"]),
|
||||||
("link-prevent-default-only", ["on_click:outer"]),
|
("link-prevent-default-only", ["on_click:outer"]),
|
||||||
("link-stop-propagation-prevent-default", ["on_click:link_both"]),
|
("link-stop-propagation-prevent-default", ["on_click:link_both"]),
|
||||||
|
(
|
||||||
|
"custom-stop-propagation",
|
||||||
|
["on_click:custom-stop-propagation", "on_click:outer"],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"custom-prevent-default",
|
||||||
|
["on_click:custom-prevent-default", "on_click:outer"],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.usefixtures("token")
|
@pytest.mark.usefixtures("token")
|
||||||
@ -226,6 +265,9 @@ async def test_event_actions(
|
|||||||
prev_url = driver.current_url
|
prev_url = driver.current_url
|
||||||
|
|
||||||
el.click()
|
el.click()
|
||||||
|
if "on_click:outer" not in exp_order:
|
||||||
|
# really make sure the outer event is not fired
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
await poll_for_order(exp_order)
|
await poll_for_order(exp_order)
|
||||||
|
|
||||||
if element_id.startswith("link") and "prevent-default" not in element_id:
|
if element_id.startswith("link") and "prevent-default" not in element_id:
|
||||||
|
@ -488,10 +488,10 @@ export const useEventLoop = (
|
|||||||
|
|
||||||
// Function to add new events to the event queue.
|
// Function to add new events to the event queue.
|
||||||
const addEvents = (events, _e, event_actions) => {
|
const addEvents = (events, _e, event_actions) => {
|
||||||
if (event_actions?.preventDefault && _e) {
|
if (event_actions?.preventDefault && _e?.preventDefault) {
|
||||||
_e.preventDefault();
|
_e.preventDefault();
|
||||||
}
|
}
|
||||||
if (event_actions?.stopPropagation && _e) {
|
if (event_actions?.stopPropagation && _e?.stopPropagation) {
|
||||||
_e.stopPropagation();
|
_e.stopPropagation();
|
||||||
}
|
}
|
||||||
queueEvents(events, socket)
|
queueEvents(events, socket)
|
||||||
|
Loading…
Reference in New Issue
Block a user