History

Merge remote-tracking branch 'origin/codex/batch21-cli-host-test-boundaries' into codex/effect-lint-integration

Rhys Sullivan committed 6 months ago

Commit bd712692 parents ad94c1d df6f3743 files · +31 −24Browse files

Unified · Split

3 files
  1. packages/hosts/mcp/src/stdio-integration.test.ts +27 −22
  2. tests/presets-reachable.test.ts +3 −2
  3. tests/tools-cli.test.ts +1 −0
packages/hosts/mcp/src/stdio-integration.test.ts+27−22
@@ -1,6 +1,7 @@
11 import { describe, expect, it } from "@effect/vitest";
22 import { Client } from "@modelcontextprotocol/sdk/client/index.js";
33 import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
4+import { Effect } from "effect";
45 import { mkdtempSync } from "node:fs";
56 import { tmpdir } from "node:os";
67 import { join, resolve } from "node:path";
@@ -10,35 +11,39 @@ const cliEntry = resolve(repoRoot, "apps/cli/src/main.ts"); · 3 unmodified lines
1011 const testScope = resolve(repoRoot, "apps/local");
1112
1213 describe("MCP stdio integration", () => {
13− it("execute tool returns result over stdio transport", async () => {
14− // Fresh temp dir so the test doesn't migrate against the developer's
15− // real ~/.executor/data.db.
16− const dataDir = mkdtempSync(join(tmpdir(), "executor-mcp-test-"));
17−
18− const transport = new StdioClientTransport({
19− command: "bun",
20− args: ["run", cliEntry, "mcp", "--scope", testScope],
21− env: { ...process.env, EXECUTOR_DATA_DIR: dataDir },
22− });
14+ it.effect("execute tool returns result over stdio transport", () =>
15+ Effect.gen(function* () {
16+ // Fresh temp dir so the test doesn't migrate against the developer's
17+ // real ~/.executor/data.db.
18+ const dataDir = mkdtempSync(join(tmpdir(), "executor-mcp-test-"));
19+
20+ const transport = new StdioClientTransport({
21+ command: "bun",
22+ args: ["run", cliEntry, "mcp", "--scope", testScope],
23+ env: { ...process.env, EXECUTOR_DATA_DIR: dataDir },
24+ });
2325
24− const client = new Client({ name: "test-client", version: "1.0.0" }, { capabilities: {} });
26+ const client = new Client({ name: "test-client", version: "1.0.0" }, { capabilities: {} });
2527
26− await client.connect(transport);
28+ yield* Effect.acquireRelease(
29+ Effect.promise(() => client.connect(transport)),
30+ () => Effect.promise(() => transport.close()),
31+ );
2732
28− try {
29− const { tools } = await client.listTools();
33+ const { tools } = yield* Effect.promise(() => client.listTools());
3034 expect(tools.map((t) => t.name)).toContain("execute");
3135
32− const result = await client.callTool({
33− name: "execute",
34− arguments: { code: "return 2+2" },
35− });
36+ const result = yield* Effect.promise(() =>
37+ client.callTool({
38+ name: "execute",
39+ arguments: { code: "return 2+2" },
40+ }),
41+ );
3642
3743 const text = (result.content as Array<{ type: string; text: string }>)[0]?.text;
3844 expect(text).toContain("4");
3945 expect(result.isError).toBeFalsy();
40− } finally {
41− await transport.close();
42− }
43− }, 30_000);
46+ }).pipe(Effect.scoped),
47+ { timeout: 30_000 },
48+ );
4449 });
tests/presets-reachable.test.ts+3−2
@@ -62,10 +62,11 @@ describe("graphql presets are reachable endpoints", () => { · 61 unmodified lines
6262 const result = yield* introspect(preset.url).pipe(
6363 Effect.provide(FetchHttpClient.layer),
6464 Effect.map((r) => ({ ok: true as const, schema: r })),
65− Effect.catch((err) =>
65+ Effect.catchTag("GraphqlIntrospectionError", (err) =>
6666 Effect.succeed({
6767 ok: false as const,
68− message: String(err),
68+ // oxlint-disable-next-line executor/no-unknown-error-message -- boundary: catchTag narrows to GraphqlIntrospectionError whose public contract includes message
69+ message: err.message,
6970 }),
7071 ),
7172 );
tests/tools-cli.test.ts+1−0
@@ -34,6 +34,7 @@ describe("CLI tooling helpers", () => { · 33 unmodified lines
3434 it.effect("rejects non-object JSON input", () =>
3535 Effect.gen(function* () {
3636 const error = yield* parseJsonObjectInput('[1,2,3]').pipe(Effect.flip);
37+ // oxlint-disable-next-line executor/no-unknown-error-message -- boundary: helper contract returns a native Error for CLI input parsing
3738 expect(error.message).toContain("must decode to a JSON object");
3839 }),
3940 );