@@ -14,6 +14,7 @@ import {
1414 type HookEndPayload ,
1515} from '@google/gemini-cli-core' ;
1616import { act } from 'react' ;
17+ import { WARNING_PROMPT_DURATION_MS } from '../constants.js' ;
1718
1819describe ( 'useHookDisplayState' , ( ) => {
1920 beforeEach ( ( ) => {
@@ -53,7 +54,7 @@ describe('useHookDisplayState', () => {
5354 } ) ;
5455 } ) ;
5556
56- it ( 'should remove a hook immediately if duration > 1s ' , ( ) => {
57+ it ( 'should remove a hook immediately if duration > minimum duration ' , ( ) => {
5758 const { result } = renderHook ( ( ) => useHookDisplayState ( ) ) ;
5859
5960 const startPayload : HookStartPayload = {
@@ -65,9 +66,9 @@ describe('useHookDisplayState', () => {
6566 coreEvents . emitHookStart ( startPayload ) ;
6667 } ) ;
6768
68- // Advance time by 1.1 seconds
69+ // Advance time by slightly more than the minimum duration
6970 act ( ( ) => {
70- vi . advanceTimersByTime ( 1100 ) ;
71+ vi . advanceTimersByTime ( WARNING_PROMPT_DURATION_MS + 100 ) ;
7172 } ) ;
7273
7374 const endPayload : HookEndPayload = {
@@ -83,7 +84,7 @@ describe('useHookDisplayState', () => {
8384 expect ( result . current ) . toHaveLength ( 0 ) ;
8485 } ) ;
8586
86- it ( 'should delay removal if duration < 1s ' , ( ) => {
87+ it ( 'should delay removal if duration < minimum duration ' , ( ) => {
8788 const { result } = renderHook ( ( ) => useHookDisplayState ( ) ) ;
8889
8990 const startPayload : HookStartPayload = {
@@ -113,9 +114,9 @@ describe('useHookDisplayState', () => {
113114 // Should still be present
114115 expect ( result . current ) . toHaveLength ( 1 ) ;
115116
116- // Advance remaining time (900ms needed, let's go 950ms)
117+ // Advance remaining time + buffer
117118 act ( ( ) => {
118- vi . advanceTimersByTime ( 950 ) ;
119+ vi . advanceTimersByTime ( WARNING_PROMPT_DURATION_MS - 100 + 50 ) ;
119120 } ) ;
120121
121122 expect ( result . current ) . toHaveLength ( 0 ) ;
@@ -138,7 +139,7 @@ describe('useHookDisplayState', () => {
138139
139140 expect ( result . current ) . toHaveLength ( 2 ) ;
140141
141- // End h1 (total time 500ms -> needs 500ms delay)
142+ // End h1 (total time 500ms -> needs remaining delay)
142143 act ( ( ) => {
143144 coreEvents . emitHookEnd ( {
144145 hookName : 'h1' ,
@@ -150,15 +151,24 @@ describe('useHookDisplayState', () => {
150151 // h1 still there
151152 expect ( result . current ) . toHaveLength ( 2 ) ;
152153
153- // Advance 600ms. h1 should disappear. h2 has been running for 600ms.
154+ // Advance enough for h1 to expire.
155+ // h1 ran for 500ms. Needs WARNING_PROMPT_DURATION_MS total.
156+ // So advance WARNING_PROMPT_DURATION_MS - 500 + 100.
157+ const advanceForH1 = WARNING_PROMPT_DURATION_MS - 500 + 100 ;
154158 act ( ( ) => {
155- vi . advanceTimersByTime ( 600 ) ;
159+ vi . advanceTimersByTime ( advanceForH1 ) ;
156160 } ) ;
157161
162+ // h1 should disappear. h2 has been running for 500 (initial) + advanceForH1.
158163 expect ( result . current ) . toHaveLength ( 1 ) ;
159164 expect ( result . current [ 0 ] . name ) . toBe ( 'h2' ) ;
160165
161- // End h2 (total time 600ms -> needs 400ms delay)
166+ // End h2.
167+ // h2 duration so far: 0 (start) -> 500 (start h2) -> (end h1) -> advanceForH1.
168+ // Actually h2 started at t=500. Current time is t=500 + advanceForH1.
169+ // Duration = advanceForH1.
170+ // advanceForH1 = 3000 - 500 + 100 = 2600.
171+ // So h2 has run for 2600ms. Needs 400ms more.
162172 act ( ( ) => {
163173 coreEvents . emitHookEnd ( {
164174 hookName : 'h2' ,
@@ -169,6 +179,8 @@ describe('useHookDisplayState', () => {
169179
170180 expect ( result . current ) . toHaveLength ( 1 ) ;
171181
182+ // Advance remaining needed for h2 + buffer
183+ // 3000 - 2600 = 400.
172184 act ( ( ) => {
173185 vi . advanceTimersByTime ( 500 ) ;
174186 } ) ;
@@ -199,34 +211,42 @@ describe('useHookDisplayState', () => {
199211 expect ( result . current [ 0 ] . name ) . toBe ( 'same-hook' ) ;
200212 expect ( result . current [ 1 ] . name ) . toBe ( 'same-hook' ) ;
201213
202- // End Hook 1 at t=600 (Duration 600ms -> delay 400ms )
214+ // End Hook 1 at t=600 (Duration 600ms -> delay needed )
203215 act ( ( ) => {
204216 vi . advanceTimersByTime ( 100 ) ;
205217 coreEvents . emitHookEnd ( { ...hook , success : true } ) ;
206218 } ) ;
207219
208- // Both still visible (Hook 1 pending removal in 400ms)
220+ // Both still visible
209221 expect ( result . current ) . toHaveLength ( 2 ) ;
210222
211- // Advance 400ms (t=1000). Hook 1 should be removed.
223+ // Advance to make Hook 1 expire.
224+ // Hook 1 duration 600ms. Needs WARNING_PROMPT_DURATION_MS total.
225+ // Needs WARNING_PROMPT_DURATION_MS - 600 more.
226+ const advanceForHook1 = WARNING_PROMPT_DURATION_MS - 600 ;
212227 act ( ( ) => {
213- vi . advanceTimersByTime ( 400 ) ;
228+ vi . advanceTimersByTime ( advanceForHook1 ) ;
214229 } ) ;
215230
216231 expect ( result . current ) . toHaveLength ( 1 ) ;
217232
218- // End Hook 2 at t=1100 (Duration: 1100 - 500 = 600ms -> delay 400ms)
233+ // End Hook 2.
234+ // Hook 2 started at t=500.
235+ // Current time: t = 600 (hook 1 end) + advanceForHook1 = 600 + 3000 - 600 = 3000.
236+ // Hook 2 duration = 3000 - 500 = 2500ms.
237+ // Needs 3000 - 2500 = 500ms more.
219238 act ( ( ) => {
220- vi . advanceTimersByTime ( 100 ) ;
239+ vi . advanceTimersByTime ( 100 ) ; // just a small step before ending
221240 coreEvents . emitHookEnd ( { ...hook , success : true } ) ;
222241 } ) ;
223242
224- // Hook 2 still visible (pending removal in 400ms)
243+ // Hook 2 still visible (pending removal)
244+ // Total run time: 2500 + 100 = 2600ms. Needs 400ms.
225245 expect ( result . current ) . toHaveLength ( 1 ) ;
226246
227- // Advance 400ms (t=1500). Hook 2 should be removed.
247+ // Advance remaining
228248 act ( ( ) => {
229- vi . advanceTimersByTime ( 400 ) ;
249+ vi . advanceTimersByTime ( 500 ) ;
230250 } ) ;
231251
232252 expect ( result . current ) . toHaveLength ( 0 ) ;
0 commit comments