|
13 | 13 | from reactpy import html |
14 | 14 | from reactpy.config import REACTPY_ASYNC_RENDERING, REACTPY_DEBUG |
15 | 15 | from reactpy.core.component import component |
| 16 | +from reactpy.core.events import EventHandler |
16 | 17 | from reactpy.core.hooks import use_async_effect, use_effect, use_state |
17 | 18 | from reactpy.core.layout import Layout |
18 | 19 | from reactpy.testing import ( |
@@ -1517,3 +1518,45 @@ def Comp(): |
1517 | 1518 | # Should not be 1 + 10 = 11. |
1518 | 1519 | # Likely 1 + 1 (or maybe 1 + 2 if timing is loose). |
1519 | 1520 | assert render_count.current < 5 |
| 1521 | + |
| 1522 | + |
| 1523 | +async def test_event_handler_retry_logic(): |
| 1524 | + # Setup |
| 1525 | + @component |
| 1526 | + def MyComponent(): |
| 1527 | + return html.div() |
| 1528 | + |
| 1529 | + layout = Layout(MyComponent()) |
| 1530 | + |
| 1531 | + async with layout: |
| 1532 | + # Define a target and a handler |
| 1533 | + target_id = "test-target" |
| 1534 | + |
| 1535 | + event_handled = asyncio.Event() |
| 1536 | + |
| 1537 | + async def handler_func(data): |
| 1538 | + event_handled.set() |
| 1539 | + |
| 1540 | + handler = EventHandler(handler_func, target=target_id) |
| 1541 | + |
| 1542 | + # We deliver an event to a target that doesn't exist yet |
| 1543 | + event_message = {"target": target_id, "data": []} |
| 1544 | + |
| 1545 | + # Send event |
| 1546 | + await layout.deliver(event_message) |
| 1547 | + |
| 1548 | + # The processing task should pick this up and fail to find the handler immediately. |
| 1549 | + # It will enter the retry loop. |
| 1550 | + # We wait a very short time (e.g. 10ms) to ensure it's entered the loop/sleeping |
| 1551 | + # The loop sleeps for 10ms (0.01s) each time, 3 times. |
| 1552 | + # We assume the layout's loop has started processing. |
| 1553 | + await asyncio.sleep(0.015) |
| 1554 | + |
| 1555 | + # Now we register the handler manually, simulating a late render update |
| 1556 | + layout._event_handlers[target_id] = handler |
| 1557 | + |
| 1558 | + # Wait for the handler to be called |
| 1559 | + try: |
| 1560 | + await asyncio.wait_for(event_handled.wait(), timeout=1.0) |
| 1561 | + except TimeoutError: |
| 1562 | + pytest.fail("Event handler was not called after retry") |
0 commit comments