import { describe, expect, it } from "@effect/vitest"; import { Effect, Encoding, Layer, Option } from "effect"; import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http"; import { recoverSlackConnectFile } from "./slack-connect-file"; const ACCESS_TOKEN = "xoxp-test-token"; const FILE_ID = "F012ABC3456"; const IMAGE_BYTES = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]); const httpClientLayer = ( respond: (request: Request) => Response, ): Layer.Layer => Layer.succeed(HttpClient.HttpClient)( HttpClient.make((request: HttpClientRequest.HttpClientRequest) => { const url = new URL(request.url); for (const [name, value] of request.urlParams) url.searchParams.append(name, value); return Effect.succeed( HttpClientResponse.fromWeb( request, respond(new Request(url, { method: request.method, headers: request.headers })), ), ); }), ); const recover = ( layer: Layer.Layer, overrides: Partial[0]> = {}, ) => recoverSlackConnectFile({ endpoint: "https://mcp.slack.com/mcp", toolName: "slack_read_file", args: { file_id: FILE_ID }, accessToken: ACCESS_TOKEN, upstreamErrorMessage: "execution_failed: file_not_found", ...overrides, }).pipe(Effect.provide(layer)); describe("recoverSlackConnectFile", () => { it.effect("resolves and downloads a Slack Connect image with the existing OAuth token", () => Effect.gen(function* () { const requests: Request[] = []; const layer = httpClientLayer((request) => { requests.push(request); const url = new URL(request.url); if (url.hostname === "slack.com") { return Response.json({ ok: true, file: { id: FILE_ID, name: "screenshot.png", title: "screenshot.png", mimetype: "image/png", size: IMAGE_BYTES.byteLength, url_private_download: `https://files.slack.com/files-pri/T000-${FILE_ID}/download/screenshot.png`, }, }); } return new Response(IMAGE_BYTES, { status: 200, headers: { "content-type": "image/png" }, }); }); const result = yield* recover(layer); expect(Option.isSome(result)).toBe(true); const recovered = Option.getOrThrow(result); expect(recovered.content).toEqual([ { type: "text", text: `File ID: ${FILE_ID}\nTitle: screenshot.png\nMIME Type: image/png\nSize: 8 bytes\n`, }, { type: "image", data: Encoding.encodeBase64(IMAGE_BYTES), mimeType: "image/png", }, ]); expect(requests).toHaveLength(2); expect(requests.map((request) => new URL(request.url).searchParams.get("file"))).toEqual([ FILE_ID, null, ]); expect(requests.map((request) => request.headers.get("authorization"))).toEqual([ `Bearer ${ACCESS_TOKEN}`, `Bearer ${ACCESS_TOKEN}`, ]); }), ); it.effect("does not call Slack for unrelated MCP failures", () => Effect.gen(function* () { let requestCount = 0; const layer = httpClientLayer(() => { requestCount += 1; return new Response("unexpected", { status: 500 }); }); const results = yield* Effect.all([ recover(layer, { endpoint: "https://example.com/mcp" }), recover(layer, { toolName: "another_tool" }), recover(layer, { upstreamErrorMessage: "execution_failed: permission_denied" }), recover(layer, { accessToken: null }), recover(layer, { args: { file_id: "../not-a-file-id" } }), ]); expect(results.every(Option.isNone)).toBe(true); expect(requestCount).toBe(0); }), ); it.effect("rejects non-image and untrusted download responses", () => Effect.gen(function* () { const nonImage = yield* recover( httpClientLayer(() => Response.json({ ok: true, file: { id: FILE_ID, name: "notes.txt", mimetype: "text/plain", size: 10, url_private_download: "https://files.slack.com/files-pri/file", }, }), ), ); const untrusted = yield* recover( httpClientLayer(() => Response.json({ ok: true, file: { id: FILE_ID, name: "screenshot.png", mimetype: "image/png", size: 10, url_private_download: "https://example.com/screenshot.png", }, }), ), ); let requestCount = 0; const wrongResponseType = yield* recover( httpClientLayer(() => { requestCount += 1; return requestCount === 1 ? Response.json({ ok: true, file: { id: FILE_ID, name: "screenshot.png", mimetype: "image/png", size: 10, url_private_download: "https://files.slack.com/files-pri/file", }, }) : new Response("not an image", { status: 200, headers: { "content-type": "text/html" }, }); }), ); expect(Option.isNone(nonImage)).toBe(true); expect(Option.isNone(untrusted)).toBe(true); expect(Option.isNone(wrongResponseType)).toBe(true); }), ); });