Unified · Split
| @@ -0,0 +1,68 @@ | |||
| 1 | import { describe, expect, it } from "@effect/vitest"; | ||
| 2 | import { Effect } from "effect"; | ||
| 3 | |||
| 4 | import type { Executor, Source } from "@executor/sdk"; | ||
| 5 | |||
| 6 | import { buildExecuteDescription } from "./description"; | ||
| 7 | |||
| 8 | const makeSource = (overrides: Partial<Source> & Pick<Source, "id" | "name">): Source => ({ | ||
| 9 | kind: "in-memory", | ||
| 10 | pluginId: "test-plugin", | ||
| 11 | canRemove: false, | ||
| 12 | canRefresh: false, | ||
| 13 | canEdit: false, | ||
| 14 | runtime: false, | ||
| 15 | ...overrides, | ||
| 16 | }); | ||
| 17 | |||
| 18 | const makeFakeExecutor = (sources: readonly Source[]): Executor => | ||
| 19 | ({ | ||
| 20 | sources: { | ||
| 21 | list: () => Effect.succeed(sources), | ||
| 22 | }, | ||
| 23 | }) as unknown as Executor; | ||
| 24 | |||
| 25 | describe("buildExecuteDescription", () => { | ||
| 26 | it.effect("includes the workflow preamble and lists sources sorted by id", () => | ||
| 27 | Effect.gen(function* () { | ||
| 28 | const sources: readonly Source[] = [ | ||
| 29 | // Intentionally out of order — the formatter is expected to sort. | ||
| 30 | makeSource({ id: "slack", name: "Slack Workspace" }), | ||
| 31 | makeSource({ id: "github", name: "GitHub" }), | ||
| 32 | ]; | ||
| 33 | const executor = makeFakeExecutor(sources); | ||
| 34 | |||
| 35 | const description = yield* buildExecuteDescription(executor); | ||
| 36 | |||
| 37 | // Stable anchor from the workflow preamble. | ||
| 38 | expect(description).toContain( | ||
| 39 | "Execute TypeScript in a sandboxed runtime", | ||
| 40 | ); | ||
| 41 | // The namespaces section header. | ||
| 42 | expect(description).toContain("## Available namespaces"); | ||
| 43 | // Both sources rendered with backticks + label-suffix rule. | ||
| 44 | expect(description).toContain("`github` — GitHub"); | ||
| 45 | expect(description).toContain("`slack` — Slack Workspace"); | ||
| 46 | |||
| 47 | // Sort order: `github` appears before `slack`. | ||
| 48 | const githubIdx = description.indexOf("`github`"); | ||
| 49 | const slackIdx = description.indexOf("`slack`"); | ||
| 50 | expect(githubIdx).toBeGreaterThan(-1); | ||
| 51 | expect(slackIdx).toBeGreaterThan(-1); | ||
| 52 | expect(githubIdx).toBeLessThan(slackIdx); | ||
| 53 | }), | ||
| 54 | ); | ||
| 55 | |||
| 56 | it.effect("omits the Available namespaces section when there are no sources", () => | ||
| 57 | Effect.gen(function* () { | ||
| 58 | const executor = makeFakeExecutor([]); | ||
| 59 | |||
| 60 | const description = yield* buildExecuteDescription(executor); | ||
| 61 | |||
| 62 | expect(description).toContain( | ||
| 63 | "Execute TypeScript in a sandboxed runtime", | ||
| 64 | ); | ||
| 65 | expect(description).not.toContain("## Available namespaces"); | ||
| 66 | }), | ||
| 67 | ); | ||
| 68 | }); | ||