1440 lines · 50.7 KB · TypeScript
RawDownload
import { describe, expect, it } from "@effect/vitest";import {  AuthTemplateSlug,  IntegrationSlug,  OAuthClientSlug,  ProviderItemId,  ProviderKey,  type OAuthProbeResult,  type Owner,} from "@executor-js/sdk/shared"; import type { AuthMethod } from "../lib/auth-placements";import type { OAuthPopupReservation } from "../plugins/oauth-sign-in";import {  connectionNameFrom,  connectionLabel,  connectionLabelForHost,  createCredentialPayloadOrigin,  DEFAULT_CONNECTION_OWNER,  hasDcr,  mergeCustomMethods,  oauthIdentityLabelFromHealth,  runAutomaticOAuthConnect,  runCimdConnect,  typedIdentityLabel,  uniqueConnectionName,} from "./add-account-modal"; const apiKeyMethod = (id: string, source: "spec" | "custom", template = id): AuthMethod => ({  id,  label: `API key (${id})`,  kind: "apikey",  source,  template: AuthTemplateSlug.make(template),  placements: [{ carrier: "header", name: "Authorization", prefix: "" }],}); type ProbeResult = OAuthProbeResult; type RegisterArgs = {  readonly owner: Owner;  readonly slug: OAuthClientSlug;  readonly issuer?: string | null;  readonly registrationEndpoint: string;  readonly authorizationUrl: string;  readonly tokenUrl: string;  readonly resource?: string | null;  readonly scopes: readonly string[];  readonly tokenEndpointAuthMethodsSupported?: readonly string[];  readonly clientName: string;  readonly redirectUri?: string;  readonly originIntegration?: IntegrationSlug;}; type StartArgs = {  readonly client: OAuthClientSlug;  readonly owner: Owner;  readonly reservation: OAuthPopupReservation;}; // A reservation the browser honoured. The desktop shape is the one that carries// no `Window`, so the orchestrators' ordering is testable without a DOM.const RESERVED: OAuthPopupReservation = {  kind: "desktop",  bridge: { openExternal: (): Promise<void> => Promise.resolve() },}; /** Records the reserve/release calls alongside the network steps, so a test can *  assert the window is claimed BEFORE the first round trip and closed again *  whenever the flow ends without signing in. */const popupSpy = (reservation: OAuthPopupReservation = RESERVED) => {  const calls: string[] = [];  return {    calls,    reserve: (): OAuthPopupReservation => {      calls.push("reserve");      return reservation;    },    release: (): void => {      calls.push("release");    },  };}; type AutomaticOAuthDeps = Parameters<typeof runAutomaticOAuthConnect>[0];type AutomaticOAuthInput = Parameters<typeof runAutomaticOAuthConnect>[1]; /** DCR-focused tests use defaults for the CIMD branch they intentionally do *  not exercise (and an always-mounted surface unless a test closes it). *  Discovery-level tests call the orchestrator directly. */const runDcrConnect = (  deps: Omit<AutomaticOAuthDeps, "createCimdClient" | "isActive"> &    Partial<Pick<AutomaticOAuthDeps, "isActive">>,  input: Omit<AutomaticOAuthInput, "cimd">,) =>  runAutomaticOAuthConnect(    {      isActive: (): boolean => true,      ...deps,      createCimdClient: (): Promise<OAuthClientSlug | null> => Promise.resolve(null),    },    {      ...input,      cimd: {        integrationName: "Test MCP",        clientIdMetadataDocumentUrl: "https://executor.example/api/oauth/client-id-metadata.json",        existingClients: [],      },    },  ); type CimdCreateArgs = {  readonly owner: Owner;  readonly slug: OAuthClientSlug;  readonly authorizationUrl: string;  readonly tokenUrl: string;  readonly resource?: string | null;  readonly grant: "authorization_code";  readonly clientId: string;  readonly clientSecret: "";}; type CimdStartArgs = {  readonly client: OAuthClientSlug;  readonly owner: Owner;  readonly reservation: OAuthPopupReservation;}; const TEST_INTEGRATION = IntegrationSlug.make("linear_mcp"); describe("connectionLabel (name placeholder derivation)", () => {  // The name field is optional but prefilled-via-derivation. With an empty  // label this is the derived name shown as the input's placeholder, so the  // intent ("leave blank ⇒ use this name") is visible.  it("derives '<owner> <integration>' for an empty label (the placeholder)", () => {    expect(connectionLabel("", "user", "GitHub")).toBe("Personal GitHub");    expect(connectionLabel("", "org", "GitHub")).toBe("Workspace GitHub");  });   it("treats whitespace-only labels as empty (still derives the placeholder)", () => {    expect(connectionLabel("   ", "user", "GitHub")).toBe("Personal GitHub");  });   it("uses the typed label (trimmed) when one is provided", () => {    expect(connectionLabel("  My Bot  ", "user", "GitHub")).toBe("My Bot");  });   it("uses Local in derived labels for non-org-scoped hosts", () => {    expect(connectionLabelForHost("", "org", "GitHub", null)).toBe("Local GitHub");    expect(connectionLabelForHost("", "org", "GitHub", "org_123")).toBe("Workspace GitHub");  });}); describe("connectionNameFrom", () => {  it("derives the JS-callable name from the display name", () => {    expect(String(connectionNameFrom("Autumn Production", "user", "Autumn", "org_123"))).toBe(      "autumnProduction",    );    expect(String(connectionNameFrom("linear-mcp-oauth", "user", "Linear MCP", "org_123"))).toBe(      "linearMcpOauth",    );  });   it("derives a callable default from owner and integration when the display name is empty", () => {    expect(String(connectionNameFrom("", "org", "GitHub", "org_123"))).toBe("workspaceGithub");    expect(String(connectionNameFrom("", "org", "GitHub", null))).toBe("localGithub");  });}); describe("uniqueConnectionName", () => {  const base = connectionNameFrom("", "user", "Gmail", "org_123");   it("keeps the derived name when it is not taken", () => {    expect(String(uniqueConnectionName(base, new Set()))).toBe("personalGmail");  });   it("suffixes past taken names so a second untyped connect mints a NEW connection", () => {    expect(String(uniqueConnectionName(base, new Set(["personalGmail"])))).toBe("personalGmail2");    expect(String(uniqueConnectionName(base, new Set(["personalGmail", "personalGmail2"])))).toBe(      "personalGmail3",    );  });}); describe("typedIdentityLabel", () => {  it("returns undefined for empty/whitespace labels so oauth.start omits the label", () => {    expect(typedIdentityLabel("")).toBeUndefined();    expect(typedIdentityLabel("   ")).toBeUndefined();  });   it("returns the trimmed label the user typed", () => {    expect(typedIdentityLabel("  Work Gmail ")).toBe("Work Gmail");  });}); describe("oauthIdentityLabelFromHealth", () => {  const healthyResult = {    status: "healthy" as const,    identity: " user@example.com ",    checkedAt: 1,  };   it("fills an unset label (untyped connect with no OIDC claims)", () => {    expect(      oauthIdentityLabelFromHealth({        result: healthyResult,        typedLabel: "",        storedIdentityLabel: null,      }),    ).toBe("user@example.com");  });   it("does not overwrite a hand-typed label", () => {    expect(      oauthIdentityLabelFromHealth({        result: healthyResult,        typedLabel: "My Google Account",        storedIdentityLabel: "My Google Account",      }),    ).toBeNull();  });   it("does not overwrite a stored custom label", () => {    expect(      oauthIdentityLabelFromHealth({        result: healthyResult,        typedLabel: "",        storedIdentityLabel: "Finance Google",      }),    ).toBeNull();  });   it("does not overwrite a label already filled from OIDC claims", () => {    expect(      oauthIdentityLabelFromHealth({        result: healthyResult,        typedLabel: "",        storedIdentityLabel: "alice@example.com",      }),    ).toBeNull();  });   it("requires a healthy result with an identity", () => {    expect(      oauthIdentityLabelFromHealth({        result: { status: "degraded", checkedAt: 1 },        typedLabel: "",        storedIdentityLabel: null,      }),    ).toBeNull();    expect(      oauthIdentityLabelFromHealth({        result: { status: "healthy", checkedAt: 1 },        typedLabel: "",        storedIdentityLabel: null,      }),    ).toBeNull();  });}); describe("DEFAULT_CONNECTION_OWNER", () => {  // The 'saved to' owner defaults to Personal: a connection is most often a  // personal credential.  it("defaults a new connection's owner to Personal (user)", () => {    expect(DEFAULT_CONNECTION_OWNER).toBe("user");  });}); describe("mergeCustomMethods (in-session custom method append)", () => {  // A just-created custom method joins the selectable list (custom last) so it  // can be selected before the catalog refresh lands.  it("appends a session-created method after the declared methods", () => {    const declared = [apiKeyMethod("spec-1", "spec")];    const created = [apiKeyMethod("custom_a", "custom")];    const merged = mergeCustomMethods(declared, created);    expect(merged.map((m: AuthMethod) => m.id)).toEqual(["spec-1", "custom_a"]);  });   it("dedupes by stable identity (a refreshed catalog method wins over its session copy)", () => {    const declared = [apiKeyMethod("spec-1", "spec"), apiKeyMethod("custom_a", "custom")];    const created = [apiKeyMethod("custom_a", "custom")];    const merged = mergeCustomMethods(declared, created);    expect(merged.map((m: AuthMethod) => m.id)).toEqual(["spec-1", "custom_a"]);  });   it("dedupes custom methods by template even when their rendered ids differ", () => {    const declared = [      apiKeyMethod("spec-1", "spec"),      apiKeyMethod("custom_a_refreshed", "custom", "custom_a"),    ];    const created = [apiKeyMethod("custom_a", "custom", "custom_a")];    const merged = mergeCustomMethods(declared, created);    expect(merged.map((m: AuthMethod) => m.id)).toEqual(["spec-1", "custom_a_refreshed"]);  });   it("returns the declared list unchanged when nothing was created", () => {    const declared = [apiKeyMethod("spec-1", "spec")];    expect(mergeCustomMethods(declared, [])).toEqual(declared);  });}); describe("createCredentialPayloadOrigin", () => {  it("creates an empty-string sentinel value for no-auth connection methods", () => {    expect(      createCredentialPayloadOrigin({        origin: "paste",        inputs: [],        values: {},        onePasswordItemId: "",        singleInput: true,      }),    ).toEqual({ values: { token: "" } });  });   it("keeps pasted credential values trimmed and keyed by input variable", () => {    expect(      createCredentialPayloadOrigin({        origin: "paste",        inputs: [{ variable: "token", label: "Authorization" }],        values: { token: "  secret-token  " },        onePasswordItemId: "",        singleInput: true,      }),    ).toEqual({ values: { token: "secret-token" } });  });   it("creates a 1Password external origin for single-input methods", () => {    expect(      createCredentialPayloadOrigin({        origin: "onepassword",        inputs: [{ variable: "token", label: "Authorization" }],        values: {},        onePasswordItemId: " op://Private/Vercel/token ",        singleInput: true,      }),    ).toEqual({      from: {        provider: ProviderKey.make("onepassword"),        id: ProviderItemId.make("op://Private/Vercel/token"),      },    });  });   it("does not allow 1Password selection for multi-input methods yet", () => {    expect(      createCredentialPayloadOrigin({        origin: "onepassword",        inputs: [          { variable: "apiKey", label: "API key" },          { variable: "appKey", label: "Application key" },        ],        values: {},        onePasswordItemId: "op://Private/Datadog/api-key",        singleInput: false,      }),    ).toBeNull();  });}); describe("runCimdConnect", () => {  it("creates a public metadata-document OAuth client and starts OAuth", async () => {    let createArgs: CimdCreateArgs | null = null;    let startArgs: CimdStartArgs | null = null;     const outcome = await runCimdConnect(      {        reserve: (): OAuthPopupReservation => RESERVED,        release: (): void => {},        createClient: (args: CimdCreateArgs): Promise<OAuthClientSlug | null> => {          createArgs = args;          return Promise.resolve(args.slug);        },        start: (args: CimdStartArgs): void => {          startArgs = args;        },      },      {        owner: "user",        integrationName: "PostHog API",        authorizationUrl: "https://us.posthog.com/oauth/authorize/",        tokenUrl: "https://us.posthog.com/oauth/token/",        resource: "https://us.posthog.com",        clientIdMetadataDocumentUrl:          "https://executor.example/api/oauth/client-id-metadata/acme.json",        existingClients: [],      },    );     expect(outcome.kind).toBe("started");    expect(createArgs).toMatchObject({      owner: "user",      authorizationUrl: "https://us.posthog.com/oauth/authorize/",      tokenUrl: "https://us.posthog.com/oauth/token/",      resource: "https://us.posthog.com",      grant: "authorization_code",      clientId: "https://executor.example/api/oauth/client-id-metadata/acme.json",      clientSecret: "",    });    expect(String(createArgs!.slug)).toBe("posthog-api-cimd");    expect(String(startArgs!.client)).toBe("posthog-api-cimd");    expect(startArgs!.owner).toBe("user");  });   it("reuses an existing matching metadata-document client", async () => {    const existingSlug = OAuthClientSlug.make("posthog-api-cimd");    let created = false;    let startArgs: CimdStartArgs | null = null;     const outcome = await runCimdConnect(      {        reserve: (): OAuthPopupReservation => RESERVED,        release: (): void => {},        createClient: (): Promise<OAuthClientSlug | null> => {          created = true;          return Promise.resolve(OAuthClientSlug.make("new-client"));        },        start: (args: CimdStartArgs): void => {          startArgs = args;        },      },      {        owner: "user",        integrationName: "PostHog API",        authorizationUrl: "https://us.posthog.com/oauth/authorize/",        tokenUrl: "https://us.posthog.com/oauth/token/",        resource: "https://us.posthog.com",        clientIdMetadataDocumentUrl: "https://executor.example/api/oauth/client-id-metadata.json",        existingClients: [          {            owner: "user",            slug: existingSlug,            grant: "authorization_code",            authorizationUrl: "https://us.posthog.com/oauth/authorize/",            tokenUrl: "https://us.posthog.com/oauth/token/",            resource: "https://us.posthog.com",            clientId: "https://executor.example/api/oauth/client-id-metadata.json",          },        ],      },    );     expect(outcome).toEqual({ kind: "started", client: existingSlug, reused: true });    expect(created).toBe(false);    expect(startArgs).toEqual({ client: existingSlug, owner: "user", reservation: RESERVED });  });}); describe("runAutomaticOAuthConnect", () => {  it("prefers advertised CIMD over DCR and keeps the original popup reservation", async () => {    const popup = popupSpy();    const calls: string[] = [];    let createArgs: CimdCreateArgs | null = null;    let startArgs: StartArgs | null = null;     const outcome = await runAutomaticOAuthConnect(      {        ...popup,        isActive: (): boolean => true,        probe: (): Promise<ProbeResult> => {          calls.push("probe");          return Promise.resolve({            authorizationUrl: "https://auth.example.com/authorize",            tokenUrl: "https://auth.example.com/token",            resource: "https://mcp.example.com/mcp",            registrationEndpoint: "https://auth.example.com/register",            clientIdMetadataDocumentSupported: true,          });        },        createCimdClient: (args: CimdCreateArgs): Promise<OAuthClientSlug> => {          calls.push("create-cimd");          createArgs = args;          return Promise.resolve(args.slug);        },        register: (): Promise<OAuthClientSlug> => {          calls.push("register-dcr");          return Promise.resolve(OAuthClientSlug.make("unexpected-dcr-client"));        },        start: (args: StartArgs): void => {          calls.push("start");          startArgs = args;        },      },      {        discoveryUrl: "https://mcp.example.com/mcp",        resourceFallback: "https://mcp.example.com/mcp",        owner: "user",        integration: TEST_INTEGRATION,        cimd: {          integrationName: "Test MCP",          clientIdMetadataDocumentUrl: "https://executor.example/api/oauth/client-id-metadata.json",          existingClients: [],        },      },    );     expect(outcome).toEqual({ kind: "started", flow: "cimd" });    expect(calls).toEqual(["probe", "create-cimd", "start"]);    expect(createArgs).toMatchObject({      clientId: "https://executor.example/api/oauth/client-id-metadata.json",      clientSecret: "",

Lines 1–500 of 1440.