// --------------------------------------------------------------------------- // Fidelity tests for the OAuth popup HTML generator + callback wrapper. // Locks in the escaping rules, postMessage/BroadcastChannel behavior, and // the completeOAuth-to-popup-payload conversion semantics so the google- // discovery port is provably behavior-preserving. // --------------------------------------------------------------------------- import { describe, expect, it } from "@effect/vitest"; import { Data, Effect, Schema } from "effect"; import { encodeOAuthCallbackState } from "@executor-js/sdk"; import { OAUTH_POPUP_MESSAGE_TYPE, popupDocument, runOAuthCallback, type OAuthPopupResult, } from "./oauth-popup"; type GoogleAuth = { kind: "oauth2"; accessTokenSecretId: string; refreshTokenSecretId: string | null; }; const DomainErrorShape = Schema.Struct({ _tag: Schema.Literal("DomainError"), message: Schema.String, }); const isDomainError = Schema.is(DomainErrorShape); // --------------------------------------------------------------------------- // popupDocument // --------------------------------------------------------------------------- describe("popupDocument", () => { const successPayload: OAuthPopupResult = { type: OAUTH_POPUP_MESSAGE_TYPE, ok: true, sessionId: "session-abc", kind: "oauth2", accessTokenSecretId: "secret_1", refreshTokenSecretId: "secret_2", }; it("renders a success page with Connected title and the green check icon", () => { const html = popupDocument(successPayload, "channel-x"); expect(html).toContain("Connected"); expect(html).toContain("#22c55e"); expect(html).toContain("Authentication complete"); }); it("renders a failure page with the error text escaped", () => { const html = popupDocument( { type: OAUTH_POPUP_MESSAGE_TYPE, ok: false, sessionId: null, error: "Token endpoint returned 400 ", }, "channel-x", ); expect(html).toContain("Connection failed"); expect(html).toContain("#ef4444"); expect(html).toContain("Token endpoint returned 400 <script>alert(1)</script>"); expect(html).not.toContain(""); }); it("renders a collapsible details disclosure when errorDetails is present", () => { const html = popupDocument( { type: OAUTH_POPUP_MESSAGE_TYPE, ok: false, sessionId: null, error: "Could not complete authentication", errorDetails: "HTTP 201 Created from https://api.supabase.com/v1/oauth/token", }, "channel-x", ); expect(html).toContain("Could not complete authentication"); expect(html).toContain(""); expect(html).toContain("HTTP 201 Created from https://api.supabase.com/v1/oauth/token"); }); it("escapes HTML inside errorDetails", () => { const html = popupDocument( { type: OAUTH_POPUP_MESSAGE_TYPE, ok: false, sessionId: null, error: "Failed", errorDetails: "", }, "channel-x", ); expect(html).toContain("<script>alert('xss')</script>"); // Ensure the raw script tag does not appear inside the rendered
.
    const preMatch = /]*>([^<]*)<\/pre>/.exec(html);
    expect(preMatch).not.toBeNull();
    expect(preMatch![1]).not.toContain(" breakout", () => {
    const html = popupDocument(
      {
        type: OAUTH_POPUP_MESSAGE_TYPE,
        ok: false,
        sessionId: null,
        error: "",
      },
      "channel-x",
    );
    // The raw `` must not appear in the inline script literal.
    const scriptLiteralMatch = /const p=(\{.*?\});/.exec(html);
    expect(scriptLiteralMatch).not.toBeNull();
    const scriptLiteral = scriptLiteralMatch![1]!;
    expect(scriptLiteral).not.toContain("");
    expect(scriptLiteral).toContain("\\u003c/script\\u003e");
  });

  it("escapes < > & in the serialized channel name to prevent  breakout", () => {
    const html = popupDocument(successPayload, 'channel');
    const scriptMatch = /");
    expect(script).toContain("channel\\u003c/script\\u003e");
  });

  it("posts to window.opener AND falls back to BroadcastChannel with the given channel name", () => {
    const html = popupDocument(successPayload, "executor:openapi-oauth-result");
    expect(html).toContain("window.opener.postMessage(p,window.location.origin)");
    expect(html).toContain('new BroadcastChannel("executor:openapi-oauth-result")');
    expect(html).toContain("window.close()");
  });

  it("includes dark-mode CSS", () => {
    const html = popupDocument(successPayload, "c");
    expect(html).toContain("@media(prefers-color-scheme:dark)");
  });
});

// ---------------------------------------------------------------------------
// runOAuthCallback
// ---------------------------------------------------------------------------

describe("runOAuthCallback", () => {
  it("renders a success popup when completeOAuth succeeds", async () => {
    const html = await Effect.runPromise(
      runOAuthCallback({
        complete: () =>
          Effect.succeed({
            kind: "oauth2",
            accessTokenSecretId: "s1",
            refreshTokenSecretId: "s2",
          }),
        urlParams: { state: "session-xyz", code: "abc" },
        toErrorMessage: () => ({ short: "should not reach" }),
        channelName: "channel-x",
      }),
    );
    expect(html).toContain("Connected");
    expect(html).toContain("session-xyz");
    expect(html).toContain("s1");
  });

  it("passes code, error, and the regional domain through to the complete callback", async () => {
    const received: Array<{
      state: string;
      code: string | null;
      error: string | null;
      callbackDomain: string | null;
    }> = [];
    await Effect.runPromise(
      runOAuthCallback({
        complete: (params) => {
          received.push(params);
          return Effect.succeed({
            kind: "oauth2",
            accessTokenSecretId: "s",
            refreshTokenSecretId: null,
          });
        },
        // Multi-site providers (Datadog) echo the org's region back as `domain`,
        // which `runOAuthCallback` surfaces as `callbackDomain`.
        urlParams: { state: "s1", code: "code1", error: null, domain: "us5.datadoghq.com" },
        toErrorMessage: () => ({ short: "" }),
        channelName: "c",
      }),
    );
    expect(received).toEqual([
      { state: "s1", code: "code1", error: null, callbackDomain: "us5.datadoghq.com" },
    ]);
  });

  it("completes wrapped callback state with the raw OAuth session state", async () => {
    const providerState = encodeOAuthCallbackState({ state: "session-raw", orgSlug: "default" });
    const received: Array<{ state: string }> = [];

    const html = await Effect.runPromise(
      runOAuthCallback({
        complete: (params) => {
          received.push({ state: params.state });
          return Effect.succeed({
            kind: "oauth2",
            accessTokenSecretId: "s",
            refreshTokenSecretId: null,
          });
        },
        urlParams: { state: providerState, code: "code1" },
        toErrorMessage: () => ({ short: "" }),
        channelName: "c",
      }),
    );

    expect(received).toEqual([{ state: "session-raw" }]);
    expect(html).toContain('"sessionId":"session-raw"');
    expect(html).not.toContain(`"sessionId":"${providerState}"`);
  });

  it("falls back to `site` for the regional domain and defaults to null", async () => {
    const received: Array<{ callbackDomain: string | null }> = [];
    const complete = (params: { callbackDomain: string | null }) => {
      received.push(params);
      return Effect.succeed({
        kind: "oauth2" as const,
        accessTokenSecretId: "s",
        refreshTokenSecretId: null,
      });
    };
    // `site` is the full-origin variant; used only when `domain` is absent.
    await Effect.runPromise(
      runOAuthCallback({
        complete,
        urlParams: { state: "s1", code: "c", site: "https://eu1.datadoghq.com" },
        toErrorMessage: () => ({ short: "" }),
        channelName: "c",
      }),
    );
    // No region hints at all -> null (standard single-site providers).
    await Effect.runPromise(
      runOAuthCallback({
        complete,
        urlParams: { state: "s2", code: "c" },
        toErrorMessage: () => ({ short: "" }),
        channelName: "c",
      }),
    );
    expect(received[0]!.callbackDomain).toBe("https://eu1.datadoghq.com");
    expect(received[1]!.callbackDomain).toBeNull();
  });

  it("renders provider OAuth errors without invoking completeOAuth", async () => {
    let completeCalls = 0;
    const complete = () => {
      completeCalls += 1;
      return Effect.succeed({
        kind: "oauth2" as const,
        accessTokenSecretId: "s",
        refreshTokenSecretId: null,
      });
    };
    const html = await Effect.runPromise(
      runOAuthCallback({
        complete,
        urlParams: {
          state: "s1",
          error: "invalid_scope",
          error_description: "unknown scope wizard_session:write",
        },
        toErrorMessage: () => ({ short: "" }),
        channelName: "c",
      }),
    );
    expect(completeCalls).toBe(0);
    expect(html).toContain("Connection failed");
    expect(html).toContain("OAuth provider rejected authorization");
    expect(html).toContain("invalid_scope");
    expect(html).toContain("unknown scope wizard_session:write");
  });

  it("renders a failure popup when completeOAuth fails and uses toErrorMessage", async () => {
    class DomainError extends Data.TaggedError("DomainError")<{
      readonly message: string;
    }> {}
    const html = await Effect.runPromise(
      runOAuthCallback({
        complete: () => Effect.fail(new DomainError({ message: "Code expired" })),
        urlParams: { state: "s1" },
        toErrorMessage: (error) => {
          if (!isDomainError(error)) return { short: "unknown" };
          // oxlint-disable-next-line executor/no-unknown-error-message -- boundary: schema guard narrows the unknown popup callback error to the public test message
          return { short: "Auth failed", details: error.message };
        },
        channelName: "c",
      }),
    );
    expect(html).toContain("Connection failed");
    expect(html).toContain("Auth failed");
    expect(html).toContain(" {
    class DomainError extends Data.TaggedError("DomainError")<{
      readonly message: string;
    }> {}
    const html = await Effect.runPromise(
      runOAuthCallback({
        complete: () => Effect.fail(new DomainError({ message: "boom" })),
        urlParams: { state: "s1" },
        toErrorMessage: () => ({ short: "Same", details: "Same" }),
        channelName: "c",
      }),
    );
    expect(html).toContain("Same");
    expect(html).not.toContain(" {
    const html = await Effect.runPromise(
      runOAuthCallback({
        complete: () => Effect.die("boom"),
        urlParams: { state: "s1" },
        toErrorMessage: () => ({ short: "transport error" }),
        channelName: "c",
      }),
    );
    expect(html).toContain("Connection failed");
    expect(html).toContain("transport error");
  });
});