152 lines · 5.1 KB · TypeScript
RawDownload
import type { OpencodeClient } from "@opencode-ai/sdk/v2";import { it as effectIt } from "@effect/vitest";import * as Effect from "effect/Effect";import * as Fiber from "effect/Fiber";import * as TestClock from "effect/testing/TestClock";import { describe, expect, it } from "vite-plus/test"; import {  OpenCodeRuntimeError,  resolveOpenCodeConfigContent,  resolveOpenCodeServerPassword,  verifyOpenCodeServerVersion,} from "./opencodeRuntime.ts"; describe("resolveOpenCodeConfigContent", () => {  it("prefers the caller environment over the inherited environment", () => {    expect(      resolveOpenCodeConfigContent(        { OPENCODE_CONFIG_CONTENT: '{"source":"caller"}' },        { OPENCODE_CONFIG_CONTENT: '{"source":"process"}' },      ),    ).toBe('{"source":"caller"}');  });   it("falls back to the inherited environment and then an empty config", () => {    expect(      resolveOpenCodeConfigContent(undefined, {        OPENCODE_CONFIG_CONTENT: '{"source":"process"}',      }),    ).toBe('{"source":"process"}');    expect(resolveOpenCodeConfigContent(undefined, {})).toBe("{}");  });}); describe("resolveOpenCodeServerPassword", () => {  it("uses the local environment password when settings do not provide one", () => {    expect(      resolveOpenCodeServerPassword(        { external: false, environment: { OPENCODE_SERVER_PASSWORD: " env password " } },        {},      ),    ).toBe(" env password ");  });   it("uses the settings password for a local server", () => {    expect(      resolveOpenCodeServerPassword({ external: false, serverPassword: " settings password " }, {}),    ).toBe(" settings password ");  });   it("uses the settings password when local settings and environment differ", () => {    expect(      resolveOpenCodeServerPassword(        {          external: false,          serverPassword: "settings-password",          environment: { OPENCODE_SERVER_PASSWORD: "environment-password" },        },        {},      ),    ).toBe("settings-password");  });   it("does not send an inherited local password to an external server", () => {    expect(      resolveOpenCodeServerPassword(        { external: true, environment: { OPENCODE_SERVER_PASSWORD: "local-secret" } },        { OPENCODE_SERVER_PASSWORD: "inherited-secret" },      ),    ).toBeUndefined();  });}); function makeHealthClient(  result: (options?: { readonly signal?: AbortSignal }) => Promise<unknown>,): OpencodeClient {  return {    global: {      health: result,    },  } as unknown as OpencodeClient;} describe("verifyOpenCodeServerVersion", () => {  effectIt.effect("accepts a supported server version", () =>    Effect.gen(function* () {      const version = yield* verifyOpenCodeServerVersion(        makeHealthClient(() => Promise.resolve({ data: { healthy: true, version: "1.14.19" } })),      );      expect(version).toBe("1.14.19");    }),  );   effectIt.effect("rejects a server below the supported version", () =>    Effect.gen(function* () {      const error = yield* verifyOpenCodeServerVersion(        makeHealthClient(() => Promise.resolve({ data: { healthy: true, version: "1.14.18" } })),      ).pipe(Effect.flip);      expect(error).toBeInstanceOf(OpenCodeRuntimeError);      expect(error.detail).toContain("v1.14.18 is too old");    }),  );   for (const data of [    { healthy: true },    { healthy: true, version: "not-a-version" },    { healthy: false, version: "1.14.19" },  ]) {    effectIt.effect(`rejects an invalid health response: ${JSON.stringify(data)}`, () =>      Effect.gen(function* () {        const error = yield* verifyOpenCodeServerVersion(          makeHealthClient(() => Promise.resolve({ data })),        ).pipe(Effect.flip);        expect(error).toBeInstanceOf(OpenCodeRuntimeError);        expect(error.detail).toContain("requires OpenCode v1.14.19 or newer");      }),    );  }   effectIt.effect("preserves an unauthorized health error", () =>    Effect.gen(function* () {      const error = yield* verifyOpenCodeServerVersion(        makeHealthClient(() =>          Promise.reject({ response: { status: 401 }, error: { message: "Unauthorized" } }),        ),      ).pipe(Effect.flip);      expect(error).toBeInstanceOf(OpenCodeRuntimeError);      expect(error.detail).toContain("status=401");      expect(error.detail).toContain("Unauthorized");    }),  );   effectIt.effect("aborts a health request when the version check times out", () =>    Effect.gen(function* () {      let requestSignal: AbortSignal | undefined;      const checkFiber = yield* verifyOpenCodeServerVersion(        makeHealthClient((options) => {          requestSignal = options?.signal;          return new Promise(() => undefined);        }),      ).pipe(Effect.flip, Effect.forkChild);       yield* Effect.yieldNow;      expect(requestSignal).toBeDefined();      yield* TestClock.adjust("6 seconds");       const error = yield* Fiber.join(checkFiber);      expect(error.detail).toBe("Timed out while checking the OpenCode server version.");      expect(requestSignal?.aborted).toBe(true);    }).pipe(Effect.provide(TestClock.layer())),  );});