Skip to content

Commit cd87d4f

Browse files
test: update webfetch test (#21398)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
1 parent 988c989 commit cd87d4f

File tree

1 file changed

+15
-72
lines changed

1 file changed

+15
-72
lines changed

packages/opencode/test/tool/webfetch.test.ts

Lines changed: 15 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -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

6125
describe("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

Comments
 (0)