186 lines · 6.4 KB · TypeScript
RawDownload
// ---------------------------------------------------------------------------// GraphQL plugin — `configureAuth` (custom auth method merge-append) coverage.//// `configureAuth` merge-appends apikey/oauth2 methods onto an existing// integration's opaque `authenticationTemplate`. These tests exercise the// extension method directly (the same path the HTTP `configure` handler calls)://   - round-trip: add a custom apikey method → `getConfig` shows it,//   - append: a configured method does not drop the integration's existing//     declared methods,//   - slug generation: a method with a blank slug is assigned `custom_<id>`,//   - dedupe: a matching slug replaces in place; two slug-less methods in one//     call get distinct generated slugs,//   - unknown slug is a no-op (returns []).// --------------------------------------------------------------------------- import { describe, expect, it } from "@effect/vitest";import { Effect } from "effect"; import { createExecutor } from "@executor-js/sdk";import { makeTestConfig, memoryCredentialsPlugin } from "@executor-js/sdk/testing"; import { graphqlPlugin } from "./plugin";import type { GraphqlAuthMethod } from "./types"; const makeExecutor = () =>  createExecutor(    makeTestConfig({      plugins: [memoryCredentialsPlugin(), graphqlPlugin()] as const,    }),  ); const customApiKey: GraphqlAuthMethod = {  slug: "my_custom",  kind: "apikey",  placements: [{ carrier: "header", name: "X-Api-Key" }],}; describe("GraphQL Plugin — configureAuth (custom auth method)", () => {  it.effect("adds a custom apiKey method and getConfig reflects it", () =>    Effect.gen(function* () {      const executor = yield* makeExecutor();       yield* executor.graphql.addIntegration({        endpoint: "https://x.example/graphql",        slug: "cfg_api",      });       const merged = yield* executor.graphql.configureAuth("cfg_api", {        authenticationTemplate: [customApiKey],      });       expect(merged).toHaveLength(1);      expect(merged[0]!.slug).toBe("my_custom");       const config = yield* executor.graphql.getConfig("cfg_api");      const template = config?.authenticationTemplate ?? [];      expect(template).toEqual([        {          slug: "my_custom",          kind: "apikey",          placements: [{ carrier: "header", name: "X-Api-Key" }],        },      ]);    }),  );   it.effect("appends to an existing declared template without dropping entries", () =>    Effect.gen(function* () {      const executor = yield* makeExecutor();       yield* executor.graphql.addIntegration({        endpoint: "https://x.example/graphql",        slug: "cfg_append",        authenticationTemplate: [          { slug: "seed", kind: "apikey", placements: [{ carrier: "header", name: "X-Seed" }] },        ],      });       const merged = yield* executor.graphql.configureAuth("cfg_append", {        authenticationTemplate: [customApiKey],      });       expect(merged.map((m: GraphqlAuthMethod) => m.slug)).toEqual(["seed", "my_custom"]);    }),  );   it.effect("generates a custom_<id> slug for a method submitted with a blank slug", () =>    Effect.gen(function* () {      const executor = yield* makeExecutor();       yield* executor.graphql.addIntegration({        endpoint: "https://x.example/graphql",        slug: "cfg_genslug",      });       const merged = yield* executor.graphql.configureAuth("cfg_genslug", {        authenticationTemplate: [          { slug: "", kind: "apikey", placements: [{ carrier: "header", name: "X-Api-Key" }] },        ],      });       expect(merged).toHaveLength(1);      expect(merged[0]!.slug).toMatch(/^custom_[a-z0-9]+$/);    }),  );   it.effect("dedupes: a matching slug replaces in place; two slug-less get distinct slugs", () =>    Effect.gen(function* () {      const executor = yield* makeExecutor();       yield* executor.graphql.addIntegration({        endpoint: "https://x.example/graphql",        slug: "cfg_dedupe",        authenticationTemplate: [customApiKey],      });       const merged = yield* executor.graphql.configureAuth("cfg_dedupe", {        authenticationTemplate: [          // Re-submit the same slug with a different placement → replace in place.          {            slug: "my_custom",            kind: "apikey",            placements: [{ carrier: "header", name: "X-Other" }],          },          { slug: "", kind: "apikey", placements: [{ carrier: "query", name: "api_key" }] },          { slug: "", kind: "apikey", placements: [{ carrier: "query", name: "token" }] },        ],      });       const slugs = merged.map((m: GraphqlAuthMethod) => m.slug);      expect(slugs.filter((s: string) => s === "my_custom")).toHaveLength(1);      expect(merged).toHaveLength(3);      const generated = slugs.filter((s: string) => s.startsWith("custom_"));      expect(generated).toHaveLength(2);      expect(new Set(generated).size).toBe(2);       const replaced = merged.find((m: GraphqlAuthMethod) => m.slug === "my_custom")!;      expect(replaced).toEqual({        slug: "my_custom",        kind: "apikey",        placements: [{ carrier: "header", name: "X-Other" }],      });    }),  );   it.effect("replace mode overwrites the auth template array", () =>    Effect.gen(function* () {      const executor = yield* makeExecutor();       yield* executor.graphql.addIntegration({        endpoint: "https://x.example/graphql",        slug: "cfg_replace",        authenticationTemplate: [          { slug: "seed", kind: "apikey", placements: [{ carrier: "header", name: "X-Seed" }] },          customApiKey,        ],      });       const merged = yield* executor.graphql.configureAuth("cfg_replace", {        authenticationTemplate: [          { slug: "seed", kind: "apikey", placements: [{ carrier: "header", name: "X-Seed" }] },        ],        mode: "replace",      });       expect(merged.map((m: GraphqlAuthMethod) => m.slug)).toEqual(["seed"]);    }),  );   it.effect("configureAuth is a no-op for an unknown integration", () =>    Effect.gen(function* () {      const executor = yield* makeExecutor();      const merged = yield* executor.graphql.configureAuth("nope", {        authenticationTemplate: [customApiKey],      });      expect(merged).toEqual([]);    }),  );   it.effect("getConfig returns null for an unknown integration", () =>    Effect.gen(function* () {      const executor = yield* makeExecutor();      expect(yield* executor.graphql.getConfig("nope")).toBeNull();    }),  );});