Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  client.test.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";

vi.mock("@slack/web-api", () => {
  const WebClient = vi.fn(function WebClientMock(
    this: Record<string, unknown>,
    token: string,
    options?: Record<string, unknown>,
  ) {
    this.token = token;
    this.options = options;
  });
  return { WebClient };
});

let createSlackWebClient: typeof import("./client.js").createSlackWebClient;
let createSlackWriteClient: typeof import("./client.js").createSlackWriteClient;
let createSlackTokenCacheKey: typeof import("./client.js").createSlackTokenCacheKey;
let getSlackWriteClient: typeof import("./client.js").getSlackWriteClient;
let clearSlackWriteClientCacheForTest: typeof import("./client.js").clearSlackWriteClientCacheForTest;
let resolveSlackWebClientOptions: typeof import("./client.js").resolveSlackWebClientOptions;
let resolveSlackWriteClientOptions: typeof import("./client.js").resolveSlackWriteClientOptions;
let SLACK_DEFAULT_RETRY_OPTIONS: typeof import("./client.js").SLACK_DEFAULT_RETRY_OPTIONS;
let SLACK_WRITE_RETRY_OPTIONS: typeof import("./client.js").SLACK_WRITE_RETRY_OPTIONS;
let WebClient: ReturnType<typeof vi.fn>;

beforeAll(async () => {
  const slackWebApi = await import("@slack/web-api");
  ({
    createSlackWebClient,
    createSlackWriteClient,
    createSlackTokenCacheKey,
    getSlackWriteClient,
    clearSlackWriteClientCacheForTest,
    resolveSlackWebClientOptions,
    resolveSlackWriteClientOptions,
    SLACK_DEFAULT_RETRY_OPTIONS,
    SLACK_WRITE_RETRY_OPTIONS,
  } = await import("./client.js"));
  WebClient = slackWebApi.WebClient as unknown as ReturnType<typeof vi.fn>;
});

beforeEach(() => {
  WebClient.mockClear();
  clearSlackWriteClientCacheForTest();
});

describe("slack web client config", () => {
  it("applies the default retry config when none is provided", () => {
    const options = resolveSlackWebClientOptions();

    expect(options.retryConfig).toEqual(SLACK_DEFAULT_RETRY_OPTIONS);
  });

  it("respects explicit retry config overrides", () => {
    const customRetry = { retries: 0 };
    const options = resolveSlackWebClientOptions({ retryConfig: customRetry });

    expect(options.retryConfig).toBe(customRetry);
  });

  it("passes merged options into WebClient", () => {
    createSlackWebClient("xoxb-test", { timeout: 1234 });

    expect(WebClient).toHaveBeenCalledWith(
      "xoxb-test",
      expect.objectContaining({
        timeout: 1234,
        retryConfig: SLACK_DEFAULT_RETRY_OPTIONS,
      }),
    );
  });

  it("applies the write retry config when none is provided", () => {
    const options = resolveSlackWriteClientOptions();

    expect(options.retryConfig).toEqual(SLACK_WRITE_RETRY_OPTIONS);
  });

  it("serializes write client requests by default", () => {
    const options = resolveSlackWriteClientOptions();

    expect(options.maxRequestConcurrency).toBe(1);
  });

  it("respects explicit write client concurrency overrides", () => {
    const options = resolveSlackWriteClientOptions({ maxRequestConcurrency: 5 });

    expect(options.maxRequestConcurrency).toBe(5);
  });

  it("passes no-retry config into the write client by default", () => {
    createSlackWriteClient("xoxb-test", { timeout: 4321 });

    expect(WebClient).toHaveBeenCalledWith(
      "xoxb-test",
      expect.objectContaining({
        maxRequestConcurrency: 1,
        timeout: 4321,
        retryConfig: SLACK_WRITE_RETRY_OPTIONS,
      }),
    );
  });

  it("reuses default write clients per token", () => {
    const first = getSlackWriteClient("xoxb-test");
    const second = getSlackWriteClient("xoxb-test");

    expect(second).toBe(first);
    expect(WebClient).toHaveBeenCalledTimes(1);
    expect(WebClient).toHaveBeenCalledWith(
      "xoxb-test",
      expect.objectContaining({
        maxRequestConcurrency: 1,
        retryConfig: SLACK_WRITE_RETRY_OPTIONS,
      }),
    );
  });

  it("keeps default write clients separated by token", () => {
    const first = getSlackWriteClient("xoxb-one");
    const second = getSlackWriteClient("xoxb-two");

    expect(second).not.toBe(first);
    expect(WebClient).toHaveBeenCalledTimes(2);
  });

  it("builds stable non-secret token cache keys", () => {
    const token = "xoxb-sensitive-token";
    const first = createSlackTokenCacheKey(token);
    const second = createSlackTokenCacheKey(token);

    expect(first).toBe(second);
    expect(first).toMatch(/^sha256:/);
    expect(first).not.toContain(token);
    expect(createSlackTokenCacheKey("xoxb-other-token")).not.toBe(first);
  });
});

describe("slack proxy agent", () => {
  const originalEnv = { ...process.env };

  const PROXY_KEYS = [
    "HTTPS_PROXY",
    "HTTP_PROXY",
    "https_proxy",
    "http_proxy",
    "NO_PROXY",
    "no_proxy",
  ];

  beforeEach(() => {
    for (const key of PROXY_KEYS) {
      delete process.env[key];
    }
  });

  afterEach(() => {
    for (const key of PROXY_KEYS) {
      if (originalEnv[key] !== undefined) {
        process.env[key] = originalEnv[key];
      } else {
        delete process.env[key];
      }
    }
  });

  it("sets agent from HTTPS_PROXY env var", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeDefined();
    expect(options.agent!.constructor.name).toBe("HttpsProxyAgent");
  });

  it("falls back to HTTP_PROXY when HTTPS_PROXY is not set", () => {
    process.env.HTTP_PROXY = "http://proxy.example.com:3128";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeDefined();
  });

  it("does not set agent when no proxy env var is configured", () => {
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeUndefined();
  });

  it("does not override an explicitly provided agent", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    const customAgent = {} as never;
    const options = resolveSlackWebClientOptions({ agent: customAgent });

    expect(options.agent).toBe(customAgent);
  });

  it("prefers lowercase https_proxy over uppercase", () => {
    process.env.https_proxy = "http://lower.example.com:3128";
    process.env.HTTPS_PROXY = "http://upper.example.com:3128";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeDefined();
    // HttpsProxyAgent stores the proxy URL — verify it picked the lower-case one
    expect((options.agent as unknown as { proxy: { href: string } }).proxy.href).toContain(
      "lower.example.com",
    );
  });

  it("treats empty lowercase https_proxy as authoritative over uppercase", () => {
    process.env.https_proxy = "";
    process.env.HTTPS_PROXY = "http://upper.example.com:3128";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeUndefined();
  });

  it("also applies proxy agent to write client options", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    const options = resolveSlackWriteClientOptions();

    expect(options.agent).toBeDefined();
    expect(options.agent!.constructor.name).toBe("HttpsProxyAgent");
  });

  it("respects NO_PROXY excluding slack.com", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    process.env.NO_PROXY = "localhost,slack.com,.internal.corp";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeUndefined();
  });

  it("respects no_proxy (lowercase) excluding .slack.com", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    process.env.no_proxy = ".slack.com";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeUndefined();
  });

  it("respects space-separated no_proxy entries", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    process.env.no_proxy = "localhost *.slack.com";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeUndefined();
  });

  it("respects NO_PROXY wildcard", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    process.env.NO_PROXY = "*";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeUndefined();
  });

  it("does not skip proxy when NO_PROXY excludes unrelated hosts", () => {
    process.env.HTTPS_PROXY = "http://proxy.example.com:3128";
    process.env.NO_PROXY = "localhost,.internal.corp";
    const options = resolveSlackWebClientOptions();

    expect(options.agent).toBeDefined();
  });

  it("degrades gracefully on malformed proxy URL", () => {
    process.env.HTTPS_PROXY = "not-a-valid-url://:::bad";
    const options = resolveSlackWebClientOptions();

    // Should not throw; falls back to no agent
    expect(options.agent).toBeUndefined();
  });
});

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge