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 | +}); | |