diff --git a/packages/opencode/test/cli/effect-cmd-instance-als.test.ts b/packages/opencode/test/cli/effect-cmd-instance-als.test.ts index de6fed8daa..122b87f174 100644 --- a/packages/opencode/test/cli/effect-cmd-instance-als.test.ts +++ b/packages/opencode/test/cli/effect-cmd-instance-als.test.ts @@ -1,8 +1,13 @@ -import { afterEach, expect, test } from "bun:test" +import { afterEach, expect } from "bun:test" +import { AppFileSystem } from "@opencode-ai/core/filesystem" import { Effect } from "effect" -import fs from "fs/promises" +import { fileURLToPath } from "url" +import { InstanceRef } from "../../src/effect/instance-ref" import { Instance } from "../../src/project/instance" -import { disposeAllInstances, provideTestInstance, tmpdir } from "../fixture/fixture" +import { disposeAllInstances, TestInstance } from "../fixture/fixture" +import { testEffect } from "../lib/effect" + +const it = testEffect(AppFileSystem.defaultLayer) afterEach(async () => { await disposeAllInstances() @@ -14,35 +19,40 @@ afterEach(async () => { // has lost the outer InstanceRef. Services that read `InstanceState.context` // then fall back to `Instance.current` ALS, which must be installed at the JS // callback boundary (Node ALS persists across awaits, Effect's fiber context -// does not). `provideTestInstance` mirrors effectCmd's load + ALS-restore wrap. +// does not). `it.instance` provides the loaded InstanceRef; the explicit +// Instance.restore mirrors effectCmd's load + ALS-restore wrap. // Pins effect-cmd.ts directly: the pattern test below exercises the load + -// Instance.restore + dispose triple via the shared `provideTestInstance` fixture, +// Instance.restore boundary via the shared `it.instance` fixture, // so a regression that removed `Instance.restore` from effect-cmd.ts wouldn't // fail it. This grep guards the actual production callsite. -test("effect-cmd.ts wraps the handler body in Instance.restore", async () => { - const source = await fs.readFile(new URL("../../src/cli/effect-cmd.ts", import.meta.url), "utf8") - expect(source).toContain("Instance.restore(ctx") -}) +it.live("effect-cmd.ts wraps the handler body in Instance.restore", () => + Effect.gen(function* () { + const fs = yield* AppFileSystem.Service + const source = yield* fs.readFileString(fileURLToPath(new URL("../../src/cli/effect-cmd.ts", import.meta.url))) + expect(source).toContain("Instance.restore(ctx") + }), +) -test("Instance.current reachable from inner runPromise inside Effect.promise(async)", async () => { - await using dir = await tmpdir({ git: true }) - await provideTestInstance({ - directory: dir.path, - fn: () => - Effect.runPromise( - Effect.promise(async () => { - await new Promise((r) => setTimeout(r, 5)) - const current = await Effect.runPromise( - Effect.sync(() => { - try { - return Instance.current - } catch { - return undefined - } - }), - ) - expect(current?.directory).toBe(dir.path) +it.instance( + "Instance.current reachable after await inside restored Effect.promise(async)", + () => + Effect.gen(function* () { + const test = yield* TestInstance + const ctx = yield* InstanceRef + if (!ctx) throw new Error("InstanceRef not provided") + + const current = yield* Effect.promise(() => + Instance.restore(ctx, async () => { + await Promise.resolve() + try { + return Instance.current + } catch { + return undefined + } }), - ), - }) -}) + ) + + expect(current?.directory).toBe(test.directory) + }), + { git: true }, +)