@@ -17,6 +17,8 @@ const ctx = {
1717 ask : async ( ) => { } ,
1818}
1919
20+ type TimerID = ReturnType < typeof setTimeout >
21+
2022async function withFetch (
2123 mockFetch : ( input : string | URL | Request , init ?: RequestInit ) => Promise < Response > ,
2224 fn : ( ) => Promise < void > ,
@@ -30,6 +32,32 @@ async function withFetch(
3032 }
3133}
3234
35+ async function withTimers ( fn : ( state : { ids : TimerID [ ] ; cleared : TimerID [ ] } ) => Promise < void > ) {
36+ const set = globalThis . setTimeout
37+ const clear = globalThis . clearTimeout
38+ const ids : TimerID [ ] = [ ]
39+ const cleared : TimerID [ ] = [ ]
40+
41+ globalThis . setTimeout = ( ( ...args : Parameters < typeof setTimeout > ) => {
42+ const id = set ( ...args )
43+ ids . push ( id )
44+ return id
45+ } ) as typeof setTimeout
46+
47+ globalThis . clearTimeout = ( ( id ?: TimerID ) => {
48+ if ( id !== undefined ) cleared . push ( id )
49+ return clear ( id )
50+ } ) as typeof clearTimeout
51+
52+ try {
53+ await fn ( { ids, cleared } )
54+ } finally {
55+ ids . forEach ( clear )
56+ globalThis . setTimeout = set
57+ globalThis . clearTimeout = clear
58+ }
59+ }
60+
3361describe ( "tool.webfetch" , ( ) => {
3462 test ( "returns image responses as file attachments" , async ( ) => {
3563 const bytes = new Uint8Array ( [ 137 , 80 , 78 , 71 , 13 , 10 , 26 , 10 ] )
@@ -98,4 +126,29 @@ describe("tool.webfetch", () => {
98126 } ,
99127 )
100128 } )
129+
130+ test ( "clears timeout when fetch rejects" , async ( ) => {
131+ await withTimers ( async ( { ids, cleared } ) => {
132+ await withFetch (
133+ async ( ) => {
134+ throw new Error ( "boom" )
135+ } ,
136+ async ( ) => {
137+ await Instance . provide ( {
138+ directory : projectRoot ,
139+ fn : async ( ) => {
140+ const webfetch = await WebFetchTool . init ( )
141+ await expect (
142+ webfetch . execute ( { url : "https://example.com/file.txt" , format : "text" } , ctx ) ,
143+ ) . rejects . toThrow ( "boom" )
144+ } ,
145+ } )
146+ } ,
147+ )
148+
149+ expect ( ids ) . toHaveLength ( 1 )
150+ expect ( cleared ) . toHaveLength ( 1 )
151+ expect ( cleared [ 0 ] ) . toBe ( ids [ 0 ] )
152+ } )
153+ } )
101154} )
0 commit comments