import { assert, it, vi } from "@effect/vitest"; import { ProjectId } from "@t3tools/contracts"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as TerminalManager from "../terminal/Manager.ts"; import * as ProjectService from "./ProjectService.ts"; import * as ProjectSetupScriptRunner from "./ProjectSetupScriptRunner.ts"; it.effect("resolves setup scripts through the standalone project service", () => { const open = vi.fn((input: Parameters[0]) => Effect.succeed({ threadId: input.threadId, terminalId: input.terminalId, cwd: input.cwd, worktreePath: input.worktreePath ?? null, status: "running" as const, pid: 123, history: "", exitCode: null, exitSignal: null, label: "Shell", updatedAt: "2026-06-20T00:00:00.000Z", }), ); const write = vi.fn( (_input: Parameters[0]) => Effect.void, ); const projectId = ProjectId.make("project:setup-runner-v2"); const project = { id: projectId, title: "Project", workspaceRoot: "/repo", repositoryIdentity: null, faviconPath: null, defaultModelSelection: null, scripts: [ { id: "setup", name: "Setup", command: "vp install", icon: "configure" as const, runOnWorktreeCreate: true, }, ], createdAt: "2026-06-20T00:00:00.000Z", updatedAt: "2026-06-20T00:00:00.000Z", deletedAt: null, }; const layer = ProjectSetupScriptRunner.layer.pipe( Layer.provide( Layer.mergeAll( Layer.mock(ProjectService.ProjectService)({ getById: () => Effect.succeed(Option.some(project)), }), Layer.mock(TerminalManager.TerminalManager)({ open, write }), ), ), ); return Effect.gen(function* () { const runner = yield* ProjectSetupScriptRunner.ProjectSetupScriptRunner; const result = yield* runner.runForThread({ threadId: "thread-1", projectId, worktreePath: "/repo-worktree", }); assert.deepEqual(result, { status: "started", scriptId: "setup", scriptName: "Setup", terminalId: "setup-setup", cwd: "/repo-worktree", }); assert.equal(open.mock.calls[0]?.[0].cwd, "/repo-worktree"); assert.equal(write.mock.calls[0]?.[0].data, "vp install\r"); }).pipe(Effect.provide(layer)); });