@@ -17,58 +17,25 @@ const ctx = {
1717 ask : async ( ) => { } ,
1818}
1919
20- type TimerID = ReturnType < typeof setTimeout >
21-
22- async function withFetch (
23- mockFetch : ( input : string | URL | Request , init ?: RequestInit ) => Promise < Response > ,
24- fn : ( ) => Promise < void > ,
25- ) {
26- const originalFetch = globalThis . fetch
27- globalThis . fetch = mockFetch as unknown as typeof fetch
28- try {
29- await fn ( )
30- } finally {
31- globalThis . fetch = originalFetch
32- }
33- }
34-
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- }
20+ async function withFetch ( fetch : ( req : Request ) => Response | Promise < Response > , fn : ( url : URL ) => Promise < void > ) {
21+ using server = Bun . serve ( { port : 0 , fetch } )
22+ await fn ( server . url )
5923}
6024
6125describe ( "tool.webfetch" , ( ) => {
6226 test ( "returns image responses as file attachments" , async ( ) => {
6327 const bytes = new Uint8Array ( [ 137 , 80 , 78 , 71 , 13 , 10 , 26 , 10 ] )
6428 await withFetch (
65- async ( ) => new Response ( bytes , { status : 200 , headers : { "content-type" : "IMAGE/PNG; charset=binary" } } ) ,
66- async ( ) => {
29+ ( ) => new Response ( bytes , { status : 200 , headers : { "content-type" : "IMAGE/PNG; charset=binary" } } ) ,
30+ async ( url ) => {
6731 await Instance . provide ( {
6832 directory : projectRoot ,
6933 fn : async ( ) => {
7034 const webfetch = await WebFetchTool . init ( )
71- const result = await webfetch . execute ( { url : "https://example.com/image.png" , format : "markdown" } , ctx )
35+ const result = await webfetch . execute (
36+ { url : new URL ( "/image.png" , url ) . toString ( ) , format : "markdown" } ,
37+ ctx ,
38+ )
7239 expect ( result . output ) . toBe ( "Image fetched successfully" )
7340 expect ( result . attachments ) . toBeDefined ( )
7441 expect ( result . attachments ?. length ) . toBe ( 1 )
@@ -87,17 +54,17 @@ describe("tool.webfetch", () => {
8754 test ( "keeps svg as text output" , async ( ) => {
8855 const svg = '<svg xmlns="http://www.w3.org/2000/svg"><text>hello</text></svg>'
8956 await withFetch (
90- async ( ) =>
57+ ( ) =>
9158 new Response ( svg , {
9259 status : 200 ,
9360 headers : { "content-type" : "image/svg+xml; charset=UTF-8" } ,
9461 } ) ,
95- async ( ) => {
62+ async ( url ) => {
9663 await Instance . provide ( {
9764 directory : projectRoot ,
9865 fn : async ( ) => {
9966 const webfetch = await WebFetchTool . init ( )
100- const result = await webfetch . execute ( { url : "https://example.com/ image.svg", format : "html" } , ctx )
67+ const result = await webfetch . execute ( { url : new URL ( "/ image.svg", url ) . toString ( ) , format : "html" } , ctx )
10168 expect ( result . output ) . toContain ( "<svg" )
10269 expect ( result . attachments ) . toBeUndefined ( )
10370 } ,
@@ -108,46 +75,22 @@ describe("tool.webfetch", () => {
10875
10976 test ( "keeps text responses as text output" , async ( ) => {
11077 await withFetch (
111- async ( ) =>
78+ ( ) =>
11279 new Response ( "hello from webfetch" , {
11380 status : 200 ,
11481 headers : { "content-type" : "text/plain; charset=utf-8" } ,
11582 } ) ,
116- async ( ) => {
83+ async ( url ) => {
11784 await Instance . provide ( {
11885 directory : projectRoot ,
11986 fn : async ( ) => {
12087 const webfetch = await WebFetchTool . init ( )
121- const result = await webfetch . execute ( { url : "https://example.com/ file.txt", format : "text" } , ctx )
88+ const result = await webfetch . execute ( { url : new URL ( "/ file.txt", url ) . toString ( ) , format : "text" } , ctx )
12289 expect ( result . output ) . toBe ( "hello from webfetch" )
12390 expect ( result . attachments ) . toBeUndefined ( )
12491 } ,
12592 } )
12693 } ,
12794 )
12895 } )
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 ) . toContain ( ids [ 0 ] )
151- } )
152- } )
15396} )
0 commit comments