Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154import { expect, test } from "bun:test"import { createRoot } from "solid-js"import { createClientConnection } from "../src/solid"import { OpenCode, type OpenCodeEvent } from "../src/promise"
const connected = { id: "evt_connected", created: 1, type: "server.connected", data: {} }
// One fake server whose event streams stay open until the test writes to them or the client aborts.function server() { const encoder = new TextEncoder() const streams: { write: (text: string) => void close: () => void aborted: boolean }[] = [] const api = OpenCode.make({ baseUrl: "http://opencode.local", fetch: async (input, init) => { const request = input instanceof Request ? input : new Request(input, init) let controller!: ReadableStreamDefaultController<Uint8Array> const entry = { write: (text: string) => controller.enqueue(encoder.encode(text)), close: () => controller.close(), aborted: false, } const body = new ReadableStream<Uint8Array>({ start(value) { controller = value }, cancel() { entry.aborted = true }, }) request.signal.addEventListener("abort", () => { entry.aborted = true controller.error(request.signal.reason) }) streams.push(entry) return new Response(body, { headers: { "content-type": "text/event-stream" } }) }, }) return { api, streams }}
function setup(input: ReturnType<typeof server>, idleTimeout: number) { const events: OpenCodeEvent[] = [] return createRoot((dispose) => ({ events, dispose, connection: createClientConnection(input.api, { idleTimeout, flushInterval: 0, onEvent: (event) => events.push(event), }), }))}
async function until(check: () => boolean, timeout = 2_000) { const deadline = Date.now() + timeout while (!check()) { if (Date.now() > deadline) throw new Error("Timed out waiting for condition") await new Promise((resolve) => setTimeout(resolve, 5)) }}
test("a stream that goes silent past the idle timeout is replaced", async () => { const fake = server() const ctx = setup(fake, 60) try { await until(() => fake.streams.length === 1) fake.streams[0].write(`data: ${JSON.stringify(connected)}\n\n`) await until(() => ctx.connection.status() === "connected")
await until(() => fake.streams.length === 2) expect(fake.streams[0].aborted).toBe(true) expect(ctx.connection.internal.history().map((item) => item.data)).toContainEqual({ status: "disconnected", attempt: 1, error: "Event stream stalled", })
fake.streams[1].write(`data: ${JSON.stringify({ ...connected, id: "evt_connected_2" })}\n\n`) await until(() => ctx.connection.status() === "connected" && ctx.events.length === 2) expect(ctx.connection.error()).toBeUndefined() } finally { ctx.dispose() }})
test("keepalive comments hold a quiet stream open", async () => { const fake = server() const ctx = setup(fake, 60) try { await until(() => fake.streams.length === 1) fake.streams[0].write(`data: ${JSON.stringify(connected)}\n\n`) await until(() => ctx.connection.status() === "connected")
const heartbeat = setInterval(() => fake.streams[0].write(": heartbeat\n\n"), 20) await new Promise((resolve) => setTimeout(resolve, 250)) clearInterval(heartbeat)
expect(fake.streams).toHaveLength(1) expect(fake.streams[0].aborted).toBe(false) expect(ctx.connection.status()).toBe("connected") expect(ctx.events).toHaveLength(1) } finally { ctx.dispose() }})
test("a forced resync replaces the stream immediately and only while connected", async () => { const fake = server() const ctx = setup(fake, 10_000) try { ctx.connection.internal.resync("too early") await until(() => fake.streams.length === 1) expect(fake.streams[0].aborted).toBe(false) fake.streams[0].write(`data: ${JSON.stringify(connected)}\n\n`) await until(() => ctx.connection.status() === "connected")
const started = Date.now() ctx.connection.internal.resync("Network connection restored") await until(() => fake.streams.length === 2) expect(Date.now() - started).toBeLessThan(500) expect(fake.streams[0].aborted).toBe(true) expect(ctx.connection.internal.history().map((item) => item.data)).toContainEqual({ status: "disconnected", attempt: 1, error: "Network connection restored", }) fake.streams[1].write(`data: ${JSON.stringify(connected)}\n\n`) await until(() => ctx.connection.status() === "connected") } finally { ctx.dispose() }})
test("a stream the server closes reconnects and reports the disconnect", async () => { const fake = server() const ctx = setup(fake, 10_000) try { await until(() => fake.streams.length === 1) fake.streams[0].write(`data: ${JSON.stringify(connected)}\n\n`) await until(() => ctx.connection.status() === "connected")
fake.streams[0].close() await until(() => ctx.connection.status() === "reconnecting") expect(ctx.connection.error()).toBe("Event stream disconnected") await until(() => fake.streams.length === 2) } finally { ctx.dispose() }})