66import idom
77from idom .core .dispatcher import render_json_patch
88from idom .core .hooks import LifeCycleHook
9- from idom .testing import HookCatcher
9+ from idom .testing import HookCatcher , assert_idom_did_log
1010from tests .general_utils import assert_same_items
1111
1212
@@ -79,89 +79,68 @@ def SimpleStatefulComponent():
7979 assert first_hook is h
8080
8181
82- def test_use_state_with_constructor (driver , display , driver_wait ):
82+ async def test_use_state_with_constructor ():
8383 constructor_call_count = idom .Ref (0 )
8484
85+ set_outer_state = idom .Ref ()
86+ set_inner_key = idom .Ref ()
87+ set_inner_state = idom .Ref ()
88+
8589 def make_default ():
8690 constructor_call_count .current += 1
8791 return 0
8892
8993 @idom .component
9094 def Outer ():
91- hook = idom .hooks .current_hook ()
92-
93- async def on_click (event ):
94- hook .schedule_render ()
95-
96- return idom .html .div (
97- idom .html .button (
98- {"onClick" : on_click , "id" : "outer" }, "update outer (rerun constructor)"
99- ),
100- Inner (),
101- )
95+ state , set_outer_state .current = idom .use_state (0 )
96+ inner_key , set_inner_key .current = idom .use_state ("first" )
97+ return idom .html .div (state , Inner (key = inner_key ))
10298
10399 @idom .component
104100 def Inner ():
105- count , set_count = idom .hooks .use_state (make_default )
101+ state , set_inner_state .current = idom .use_state (make_default )
102+ return idom .html .div (state )
106103
107- async def on_click (event ):
108- set_count (count + 1 )
109-
110- return idom .html .div (
111- idom .html .button (
112- {"onClick" : on_click , "id" : "inner" },
113- "update inner with state constructor" ,
114- ),
115- idom .html .p ({"id" : "count-view" }, count ),
116- )
117-
118- display (Outer )
104+ with idom .Layout (Outer ()) as layout :
105+ await layout .render ()
119106
120- outer = driver .find_element ("id" , "outer" )
121- inner = driver .find_element ("id" , "inner" )
122- count = driver .find_element ("id" , "count-view" )
107+ assert constructor_call_count .current == 1
123108
124- driver_wait . until ( lambda d : constructor_call_count . current == 1 )
125- driver_wait . until ( lambda d : count . get_attribute ( "innerHTML" ) == "0" )
109+ set_outer_state . current ( 1 )
110+ await layout . render ( )
126111
127- inner . click ()
112+ assert constructor_call_count . current == 1
128113
129- driver_wait . until ( lambda d : constructor_call_count . current == 1 )
130- driver_wait . until ( lambda d : count . get_attribute ( "innerHTML" ) == "1" )
114+ set_inner_state . current ( 1 )
115+ await layout . render ( )
131116
132- outer . click ()
117+ assert constructor_call_count . current == 1
133118
134- driver_wait . until ( lambda d : constructor_call_count . current == 2 )
135- driver_wait . until ( lambda d : count . get_attribute ( "innerHTML" ) == "0" )
119+ set_inner_key . current ( "second" )
120+ await layout . render ( )
136121
137- inner . click ()
122+ assert constructor_call_count . current == 2
138123
139- driver_wait .until (lambda d : constructor_call_count .current == 2 )
140- driver_wait .until (lambda d : count .get_attribute ("innerHTML" ) == "1" )
141124
125+ async def test_set_state_with_reducer_instead_of_value ():
126+ count = idom .Ref ()
127+ set_count = idom .Ref ()
142128
143- def test_set_state_with_reducer_instead_of_value (driver , display ):
144129 def increment (count ):
145130 return count + 1
146131
147132 @idom .component
148133 def Counter ():
149- count , set_count = idom .hooks .use_state (0 )
150- return idom .html .button (
151- {
152- "id" : "counter" ,
153- "onClick" : lambda event : set_count (increment ),
154- },
155- f"Count: { count } " ,
156- )
157-
158- display (Counter )
134+ count .current , set_count .current = idom .hooks .use_state (0 )
135+ return idom .html .div (count .current )
159136
160- client_counter = driver .find_element ("id" , "counter" )
137+ with idom .Layout (Counter ()) as layout :
138+ await layout .render ()
161139
162- for i in range (3 ):
163- assert client_counter .get_attribute ("innerHTML" ) == f"Count: { i } "
164- client_counter .click ()
140+ for i in range (4 ):
141+ assert count .current == i
142+ set_count .current (increment )
143+ await layout .render ()
165144
166145
167146def test_set_state_checks_identity_not_equality (driver , display , driver_wait ):
@@ -356,15 +335,15 @@ def cleanup():
356335
357336
358337async def test_use_effect_cleanup_occurs_on_will_unmount ():
359- outer_component_hook = HookCatcher ()
338+ set_key = idom . Ref ()
360339 component_did_render = idom .Ref (False )
361340 cleanup_triggered = idom .Ref (False )
362341 cleanup_triggered_before_next_render = idom .Ref (False )
363342
364343 @idom .component
365- @outer_component_hook .capture
366344 def OuterComponent ():
367- return ComponentWithEffect ()
345+ key , set_key .current = idom .use_state ("first" )
346+ return ComponentWithEffect (key = key )
368347
369348 @idom .component
370349 def ComponentWithEffect ():
@@ -387,7 +366,7 @@ def cleanup():
387366
388367 assert not cleanup_triggered .current
389368
390- outer_component_hook . latest . schedule_render ( )
369+ set_key . current ( "second" )
391370 await layout .render ()
392371
393372 assert cleanup_triggered .current
@@ -592,13 +571,13 @@ def bad_cleanup():
592571 assert re .match ("Post-render effect .*?" , first_log_line )
593572
594573
595- async def test_error_in_effect_pre_unmount_cleanup_is_gracefully_handled (caplog ):
596- outer_component_hook = HookCatcher ()
574+ async def test_error_in_effect_pre_unmount_cleanup_is_gracefully_handled ():
575+ set_key = idom . Ref ()
597576
598577 @idom .component
599- @outer_component_hook .capture
600578 def OuterComponent ():
601- return ComponentWithEffect ()
579+ key , set_key .current = idom .use_state ("first" )
580+ return ComponentWithEffect (key = key )
602581
603582 @idom .component
604583 def ComponentWithEffect ():
@@ -611,13 +590,14 @@ def bad_cleanup():
611590
612591 return idom .html .div ()
613592
614- with idom .Layout (OuterComponent ()) as layout :
615- await layout .render ()
616- outer_component_hook .latest .schedule_render ()
617- await layout .render () # no error
618-
619- first_log_line = next (iter (caplog .records )).msg .split ("\n " , 1 )[0 ]
620- assert re .match ("Pre-unmount effect .*? failed" , first_log_line )
593+ with assert_idom_did_log (
594+ match_message = r"Pre-unmount effect .*? failed" ,
595+ error_type = ValueError ,
596+ ):
597+ with idom .Layout (OuterComponent ()) as layout :
598+ await layout .render ()
599+ set_key .current ("second" )
600+ await layout .render () # no error
621601
622602
623603async def test_use_reducer ():
0 commit comments