1+ import React from 'react'
12import { describe , test , expect , beforeEach , afterEach , mock } from 'bun:test'
23
34import { useTimeout } from '../use-timeout'
45
56/**
67 * Tests for useTimeout hook
78 *
8- * NOTE: These tests are currently skipped due to React 19 + Bun compatibility issues.
9- * The renderHook utility from React Testing Library returns null results in this environment.
10- * See cli/knowledge.md "React Testing Library + React 19 + Bun Incompatibility" section.
11- *
12- * The hook implementation follows the spec exactly and will be tested through integration
13- * tests when used in actual components (e.g., in Part 5 when used for reconnection messages).
9+ * NOTE: Tests install a minimal React dispatcher so hooks can run without a renderer.
1410 */
1511
1612describe ( 'useTimeout' , ( ) => {
13+ const reactInternals = ( React as any )
14+ . __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE
1715 let originalSetTimeout : typeof setTimeout
1816 let originalClearTimeout : typeof clearTimeout
1917 let timers : { id : number ; ms : number ; fn : Function ; cleared : boolean } [ ]
2018 let nextId : number
19+ let originalDispatcher : any
2120
2221 beforeEach ( ( ) => {
22+ originalDispatcher = reactInternals . H
23+ reactInternals . H = {
24+ useRef : ( value : any ) => ( { current : value } ) ,
25+ useCallback : ( callback : any ) => callback ,
26+ useEffect : ( effect : any ) => {
27+ effect ( )
28+ } ,
29+ }
30+
2331 timers = [ ]
2432 nextId = 1
2533 originalSetTimeout = globalThis . setTimeout
@@ -40,11 +48,12 @@ describe('useTimeout', () => {
4048 } )
4149
4250 afterEach ( ( ) => {
51+ reactInternals . H = originalDispatcher
4352 globalThis . setTimeout = originalSetTimeout
4453 globalThis . clearTimeout = originalClearTimeout
4554 } )
4655
47- test . skip ( 'setTimeout schedules a timeout with correct delay' , ( ) => {
56+ test ( 'setTimeout schedules a timeout with correct delay' , ( ) => {
4857 const { setTimeout } = useTimeout ( )
4958 const callback = mock ( ( ) => { } )
5059
@@ -55,7 +64,7 @@ describe('useTimeout', () => {
5564 expect ( timers [ 0 ] . cleared ) . toBe ( false )
5665 } )
5766
58- test . skip ( 'timeout callback executes when invoked' , ( ) => {
67+ test ( 'timeout callback executes when invoked' , ( ) => {
5968 const { setTimeout } = useTimeout ( )
6069 const callback = mock ( ( ) => { } )
6170
@@ -69,7 +78,7 @@ describe('useTimeout', () => {
6978 expect ( callback ) . toHaveBeenCalledTimes ( 1 )
7079 } )
7180
72- test . skip ( 'clearTimeout marks the timeout as cleared' , ( ) => {
81+ test ( 'clearTimeout marks the timeout as cleared' , ( ) => {
7382 const { setTimeout, clearTimeout } = useTimeout ( )
7483 const callback = mock ( ( ) => { } )
7584
@@ -80,7 +89,7 @@ describe('useTimeout', () => {
8089 expect ( timers [ 0 ] . cleared ) . toBe ( true )
8190 } )
8291
83- test . skip ( 'clearTimeout prevents callback from being used' , ( ) => {
92+ test ( 'clearTimeout prevents callback from being used' , ( ) => {
8493 const { setTimeout, clearTimeout } = useTimeout ( )
8594 const callback = mock ( ( ) => { } )
8695
@@ -92,7 +101,7 @@ describe('useTimeout', () => {
92101 expect ( timers [ 0 ] . cleared ) . toBe ( true )
93102 } )
94103
95- test . skip ( 'replacing timeout with same key clears the previous one' , ( ) => {
104+ test ( 'replacing timeout with same key clears the previous one' , ( ) => {
96105 const { setTimeout } = useTimeout ( )
97106 const callback1 = mock ( ( ) => { } )
98107 const callback2 = mock ( ( ) => { } )
@@ -108,7 +117,7 @@ describe('useTimeout', () => {
108117 expect ( timers [ 1 ] . ms ) . toBe ( 2000 )
109118 } )
110119
111- test . skip ( 'clearTimeout when no timeout is active does nothing' , ( ) => {
120+ test ( 'clearTimeout when no timeout is active does nothing' , ( ) => {
112121 const { clearTimeout } = useTimeout ( )
113122
114123 // Should not throw
@@ -117,7 +126,7 @@ describe('useTimeout', () => {
117126 expect ( timers . length ) . toBe ( 0 )
118127 } )
119128
120- test . skip ( 'multiple setTimeout calls with different keys work independently' , ( ) => {
129+ test ( 'multiple setTimeout calls with different keys work independently' , ( ) => {
121130 const { setTimeout } = useTimeout ( )
122131 const callbacks = [ mock ( ( ) => { } ) , mock ( ( ) => { } ) , mock ( ( ) => { } ) ]
123132
@@ -131,7 +140,7 @@ describe('useTimeout', () => {
131140 expect ( timers [ 2 ] . cleared ) . toBe ( false )
132141 } )
133142
134- test . skip ( 'setTimeout after clearTimeout works correctly' , ( ) => {
143+ test ( 'setTimeout after clearTimeout works correctly' , ( ) => {
135144 const { setTimeout, clearTimeout } = useTimeout ( )
136145 const callback1 = mock ( ( ) => { } )
137146 const callback2 = mock ( ( ) => { } )
@@ -145,7 +154,7 @@ describe('useTimeout', () => {
145154 expect ( timers [ 1 ] . cleared ) . toBe ( false )
146155 } )
147156
148- test . skip ( 'hook returns stable setTimeout and clearTimeout functions' , ( ) => {
157+ test ( 'hook returns distinct setTimeout and clearTimeout functions' , ( ) => {
149158 const result1 = useTimeout ( )
150159 const result2 = useTimeout ( )
151160
@@ -154,7 +163,7 @@ describe('useTimeout', () => {
154163 expect ( result1 . clearTimeout ) . not . toBe ( result2 . clearTimeout )
155164 } )
156165
157- test . skip ( 'clearTimeout without key clears all timeouts' , ( ) => {
166+ test ( 'clearTimeout without key clears all timeouts' , ( ) => {
158167 const { setTimeout, clearTimeout } = useTimeout ( )
159168 const callbacks = [ mock ( ( ) => { } ) , mock ( ( ) => { } ) , mock ( ( ) => { } ) ]
160169
@@ -174,7 +183,7 @@ describe('useTimeout', () => {
174183 expect ( timers [ 2 ] . cleared ) . toBe ( true )
175184 } )
176185
177- test . skip ( 'clearTimeout with specific key only clears that timeout' , ( ) => {
186+ test ( 'clearTimeout with specific key only clears that timeout' , ( ) => {
178187 const { setTimeout, clearTimeout } = useTimeout ( )
179188 const callbacks = [ mock ( ( ) => { } ) , mock ( ( ) => { } ) , mock ( ( ) => { } ) ]
180189
@@ -189,7 +198,7 @@ describe('useTimeout', () => {
189198 expect ( timers [ 2 ] . cleared ) . toBe ( false )
190199 } )
191200
192- test . skip ( 'timeout auto-cleans up after execution' , ( ) => {
201+ test ( 'timeout auto-cleans up after execution' , ( ) => {
193202 const { setTimeout } = useTimeout ( )
194203 const callback = mock ( ( ) => { } )
195204
@@ -203,7 +212,7 @@ describe('useTimeout', () => {
203212 // but the implementation removes the key from the Map after execution
204213 } )
205214
206- test . skip ( 'can reuse same key after timeout executes' , ( ) => {
215+ test ( 'can reuse same key after timeout executes' , ( ) => {
207216 const { setTimeout } = useTimeout ( )
208217 const callback1 = mock ( ( ) => { } )
209218 const callback2 = mock ( ( ) => { } )
@@ -222,7 +231,7 @@ describe('useTimeout', () => {
222231 expect ( timers [ 1 ] . cleared ) . toBe ( false )
223232 } )
224233
225- test . skip ( 'multiple timeouts can execute independently' , ( ) => {
234+ test ( 'multiple timeouts can execute independently' , ( ) => {
226235 const { setTimeout } = useTimeout ( )
227236 const callback1 = mock ( ( ) => { } )
228237 const callback2 = mock ( ( ) => { } )
@@ -242,7 +251,7 @@ describe('useTimeout', () => {
242251 expect ( callback3 ) . toHaveBeenCalledTimes ( 1 )
243252 } )
244253
245- test . skip ( 'replacing timeout before execution prevents old callback' , ( ) => {
254+ test ( 'replacing timeout before execution prevents old callback' , ( ) => {
246255 const { setTimeout } = useTimeout ( )
247256 const oldCallback = mock ( ( ) => { } )
248257 const newCallback = mock ( ( ) => { } )
@@ -261,7 +270,7 @@ describe('useTimeout', () => {
261270 expect ( newCallback ) . toHaveBeenCalledTimes ( 1 )
262271 } )
263272
264- test . skip ( 'clearTimeout on executed timeout does nothing' , ( ) => {
273+ test ( 'clearTimeout on executed timeout does nothing' , ( ) => {
265274 const { setTimeout, clearTimeout } = useTimeout ( )
266275 const callback = mock ( ( ) => { } )
267276
@@ -276,7 +285,7 @@ describe('useTimeout', () => {
276285 expect ( timers . length ) . toBe ( 1 )
277286 } )
278287
279- test . skip ( 'mixing set and clear operations maintains correct state' , ( ) => {
288+ test ( 'mixing set and clear operations maintains correct state' , ( ) => {
280289 const { setTimeout, clearTimeout } = useTimeout ( )
281290
282291 setTimeout (
0 commit comments