Skip to content

Commit e521acb

Browse files
committed
add more tests
1 parent c53f331 commit e521acb

3 files changed

Lines changed: 118 additions & 11 deletions

File tree

idom/core/events.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@ def remove(self, function: Callable[..., Any]) -> None:
189189
Raises:
190190
ValueError: if not found
191191
"""
192-
self._handlers.remove(function)
192+
index = self._get_handler_index(function)
193+
if index is not None:
194+
del self._handlers[index]
195+
else:
196+
raise ValueError(f"{self} does not contain {function}")
193197

194198
def serialize(self) -> Dict[str, Any]:
195199
"""Serialize the event handler."""
@@ -205,7 +209,20 @@ async def __call__(self, data: List[Any]) -> Any:
205209
await handler(*data)
206210

207211
def __contains__(self, function: Any) -> bool:
208-
return function in self._handlers
212+
return self._get_handler_index(function) is not None
209213

210214
def __repr__(self) -> str: # pragma: no cover
211215
return f"{type(self).__name__}({self.serialize()})"
216+
217+
def _get_handler_index(self, function: Callable[..., Any]) -> Optional[int]:
218+
if asyncio.iscoroutinefunction(function):
219+
try:
220+
return self._handlers.index(function)
221+
except ValueError:
222+
return None
223+
else:
224+
for i, h in enumerate(self._handlers):
225+
if h.__wrapped__ == function:
226+
return i
227+
else:
228+
return None

tests/test_core/test_events.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ async def callback_2(event):
7676

7777

7878
def test_remove_event_handlers():
79+
async def my_coro_callback(event):
80+
...
81+
82+
events = EventHandler()
83+
events.add(my_coro_callback)
84+
assert my_coro_callback in events
85+
events.remove(my_coro_callback)
86+
assert my_coro_callback not in events
87+
7988
def my_callback(event):
8089
...
8190

@@ -108,13 +117,13 @@ def test_simple_click_event(driver, display):
108117

109118
@idom.element
110119
async def Button():
111-
update = hooks.current_hook().use_update()
120+
hook = hooks.current_hook()
112121

113122
async def on_click(event):
114-
clicked.set(True)
115-
update()
123+
clicked.current = True
124+
hook.schedule_render()
116125

117-
if not clicked.get():
126+
if not clicked.current:
118127
return idom.html.button({"onClick": on_click, "id": "click"}, ["Click Me!"])
119128
else:
120129
return idom.html.p({"id": "complete"}, ["Complete"])
@@ -126,7 +135,7 @@ async def on_click(event):
126135
driver.find_element_by_id("complete")
127136

128137
# we care what happens in the final delete when there's no value
129-
assert clicked.get()
138+
assert clicked.current
130139

131140

132141
def test_can_stop_event_propogation(driver, display):

tests/test_core/test_hooks.py

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,93 @@ async def on_click(event):
136136
assert count.get_attribute("innerHTML") == "1"
137137

138138

139-
def test_set_state_with_reducer_instead_of_value():
140-
assert False
139+
def test_set_state_with_reducer_instead_of_value(driver, display):
140+
def increment(count):
141+
return count + 1
141142

143+
@idom.element
144+
async def Counter():
145+
count, set_count = idom.hooks.use_state(0)
146+
return idom.html.button(
147+
{
148+
"id": "counter",
149+
"onClick": lambda event: set_count(increment),
150+
},
151+
f"Count: {count}",
152+
)
142153

143-
def test_set_state_checks_identity_not_equality():
144-
assert False
154+
display(Counter)
155+
156+
client_counter = driver.find_element_by_id("counter")
157+
158+
for i in range(3):
159+
assert client_counter.get_attribute("innerHTML") == f"Count: {i}"
160+
client_counter.click()
161+
162+
163+
def test_set_state_checks_identity_not_equality(driver, display, driver_wait):
164+
r_1 = idom.Ref("value")
165+
r_2 = idom.Ref("value")
166+
167+
# refs are equal but not identical
168+
assert r_1 == r_2
169+
assert r_1 is not r_2
170+
171+
render_count = idom.Ref(0)
172+
event_count = idom.Ref(0)
173+
174+
def event_count_tracker(function):
175+
def tracker(*args, **kwargs):
176+
event_count.current += 1
177+
return function(*args, **kwargs)
178+
179+
return tracker
180+
181+
@idom.element
182+
async def TestElement():
183+
state, set_state = idom.hooks.use_state(r_1)
184+
185+
render_count.current += 1
186+
return idom.html.div(
187+
idom.html.button(
188+
{
189+
"id": "r_1",
190+
"onClick": event_count_tracker(lambda event: set_state(r_1)),
191+
},
192+
"r_1",
193+
),
194+
idom.html.button(
195+
{
196+
"id": "r_2",
197+
"onClick": event_count_tracker(lambda event: set_state(r_2)),
198+
},
199+
"r_2",
200+
),
201+
f"Last state: {'r_1' if state is r_1 else 'r_2'}",
202+
)
203+
204+
display(TestElement)
205+
206+
client_r_1_button = driver.find_element_by_id("r_1")
207+
client_r_2_button = driver.find_element_by_id("r_2")
208+
209+
assert render_count.current == 1
210+
assert event_count.current == 0
211+
212+
client_r_1_button.click()
213+
214+
driver_wait.until(lambda d: event_count.current == 1)
215+
assert render_count.current == 1
216+
217+
client_r_2_button.click()
218+
219+
driver_wait.until(lambda d: event_count.current == 2)
220+
assert render_count.current == 2
221+
222+
client_r_2_button.click()
223+
224+
driver_wait.until(lambda d: event_count.current == 3)
225+
assert render_count.current == 2
145226

146227

147228
def test_simple_input_with_use_state(driver, display):

0 commit comments

Comments
 (0)