mirror of
https://github.com/anomalyco/opencode.git
synced 2026-10-26 07:50:03 +00:00
73 lines
3.1 KiB
TypeScript
73 lines
3.1 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { Effect, Layer } from "effect"
|
|
import { FetchHttpClient, HttpClient, HttpClientResponse } from "effect/http"
|
|
import { AppNodeBuilder } from "@opencode/core/effect/app-node-builder"
|
|
import { LayerNodePlatform } from "@opencode/util/effect/app-node-platform"
|
|
import { it, refuseNetwork } from "./lib/effect"
|
|
|
|
describe("test harness network guard", () => {
|
|
test("refuses requests to hosts other than loopback", async () => {
|
|
const violations: string[] = []
|
|
const refused = refuseNetwork(violations)
|
|
await expect(refused("https://models.opencode.ai/api.json")).rejects.toThrow(
|
|
"test attempted network request: GET https://models.opencode.ai/api.json — provide an explicit HttpClient or disable the fetch",
|
|
)
|
|
await expect(refused(new Request("https://example.invalid/", { method: "POST" }))).rejects.toThrow(
|
|
"test attempted network request: POST https://example.invalid/",
|
|
)
|
|
expect(violations).toHaveLength(2)
|
|
})
|
|
|
|
it.live("the default http client node requests through the harness fetch", () =>
|
|
Effect.gen(function* () {
|
|
const seen: string[] = []
|
|
const response = yield* HttpClient.get("https://example.invalid/catalog").pipe(
|
|
Effect.flatMap((response) => response.text),
|
|
Effect.provide(AppNodeBuilder.build(LayerNodePlatform.httpClient)),
|
|
Effect.provideService(
|
|
FetchHttpClient.Fetch,
|
|
Object.assign(
|
|
(input: string | URL | Request) => {
|
|
seen.push(typeof input === "string" ? input : input instanceof URL ? input.href : input.url)
|
|
return Promise.resolve(new Response("from fetch"))
|
|
},
|
|
{ preconnect: fetch.preconnect },
|
|
),
|
|
),
|
|
)
|
|
expect(response).toBe("from fetch")
|
|
expect(seen).toEqual(["https://example.invalid/catalog"])
|
|
}),
|
|
)
|
|
|
|
it.live("an explicit HttpClient replacement is what the node sees", () =>
|
|
Effect.gen(function* () {
|
|
const mock = HttpClient.make((request) =>
|
|
Effect.succeed(HttpClientResponse.fromWeb(request, new Response("from mock"))),
|
|
)
|
|
const response = yield* HttpClient.get("https://example.invalid/catalog").pipe(
|
|
Effect.flatMap((response) => response.text),
|
|
Effect.provide(
|
|
AppNodeBuilder.build(LayerNodePlatform.httpClient, [
|
|
LayerNodePlatform.httpClient.replace(Layer.succeed(HttpClient.HttpClient, mock)),
|
|
]),
|
|
),
|
|
)
|
|
expect(response).toBe("from mock")
|
|
}),
|
|
)
|
|
|
|
it.live("loopback requests pass through to the real fetch", () =>
|
|
Effect.gen(function* () {
|
|
const server = yield* Effect.acquireRelease(
|
|
Effect.sync(() => Bun.serve({ hostname: "127.0.0.1", port: 0, fetch: () => new Response("local") })),
|
|
(server) => Effect.promise(() => server.stop(true)),
|
|
)
|
|
const response = yield* HttpClient.get(`http://127.0.0.1:${server.port}/`).pipe(
|
|
Effect.flatMap((response) => response.text),
|
|
Effect.provide(AppNodeBuilder.build(LayerNodePlatform.httpClient)),
|
|
)
|
|
expect(response).toBe("local")
|
|
}),
|
|
)
|
|
})
|