Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/JAVA/Openclaw/src/channels/   (KI Agentensystem Version 22©)  Datei vom 26.3.2026 mit Größe 6 kB image not shown  

Quelle  channel-config.test.ts

  Sprache: JAVA
 

import { describe, expect, it } from "vitest";
import type { MsgContext } from "../auto-reply/templating.js";
import { typedCases } from "../test-utils/typed-cases.js";
import {
  type ChannelMatchSource,
  buildChannelKeyCandidates,
  normalizeChannelSlug,
  resolveChannelEntryMatch,
  resolveChannelEntryMatchWithFallback,
  resolveNestedAllowlistDecision,
  applyChannelMatchMeta,
  resolveChannelMatchConfig,
} from "./channel-config.js";
import { validateSenderIdentity } from "./sender-identity.js";

describe("buildChannelKeyCandidates", () => {
  it("dedupes and trims keys", () => {
    expect(buildChannelKeyCandidates(" a ""a""""b""b")).toEqual(["a""b"]);
  });
});

describe("normalizeChannelSlug", () => {
  it("normalizes names into slugs", () => {
    expect(normalizeChannelSlug("My Team")).toBe("my-team");
    expect(normalizeChannelSlug("#General Chat")).toBe("general-chat");
    expect(normalizeChannelSlug(" Dev__Chat ")).toBe("dev-chat");
  });
});

describe("resolveChannelEntryMatch", () => {
  it("returns matched entry and wildcard metadata", () => {
    const entries = { a: { allow: true }, "*": { allow: false } };
    const match = resolveChannelEntryMatch({
      entries,
      keys: ["missing""a"],
      wildcardKey: "*",
    });
    expect(match.entry).toBe(entries.a);
    expect(match.key).toBe("a");
    expect(match.wildcardEntry).toBe(entries["*"]);
    expect(match.wildcardKey).toBe("*");
  });
});

describe("resolveChannelEntryMatchWithFallback", () => {
  const fallbackCases = typedCases<{
    name: string;
    entries: Record<string, { allow: boolean }>;
    args: {
      keys: string[];
      parentKeys?: string[];
      wildcardKey?: string;
    };
    expectedEntryKey: string;
    expectedSource: ChannelMatchSource;
    expectedMatchKey: string;
  }>([
    {
      name: "prefers direct matches over parent and wildcard",
      entries: { a: { allow: true }, parent: { allow: false }, "*": { allow: false } },
      args: { keys: ["a"], parentKeys: ["parent"], wildcardKey: "*" },
      expectedEntryKey: "a",
      expectedSource: "direct",
      expectedMatchKey: "a",
    },
    {
      name: "falls back to parent when direct misses",
      entries: { parent: { allow: false }, "*": { allow: true } },
      args: { keys: ["missing"], parentKeys: ["parent"], wildcardKey: "*" },
      expectedEntryKey: "parent",
      expectedSource: "parent",
      expectedMatchKey: "parent",
    },
    {
      name: "falls back to wildcard when no direct or parent match",
      entries: { "*": { allow: true } },
      args: { keys: ["missing"], parentKeys: ["still-missing"], wildcardKey: "*" },
      expectedEntryKey: "*",
      expectedSource: "wildcard",
      expectedMatchKey: "*",
    },
  ]);

  it.each(fallbackCases)("$name", (testCase) => {
    const match = resolveChannelEntryMatchWithFallback({
      entries: testCase.entries,
      ...testCase.args,
    });
    expect(match.entry).toBe(testCase.entries[testCase.expectedEntryKey]);
    expect(match.matchSource).toBe(testCase.expectedSource);
    expect(match.matchKey).toBe(testCase.expectedMatchKey);
  });

  it("matches normalized keys when normalizeKey is provided", () => {
    const entries = { "My Team": { allow: true } };
    const match = resolveChannelEntryMatchWithFallback({
      entries,
      keys: ["my-team"],
      normalizeKey: normalizeChannelSlug,
    });
    expect(match.entry).toBe(entries["My Team"]);
    expect(match.matchSource).toBe("direct");
    expect(match.matchKey).toBe("My Team");
  });
});

describe("applyChannelMatchMeta", () => {
  it("copies match metadata onto resolved configs", () => {
    const base: { matchKey?: string; matchSource?: ChannelMatchSource } = {};
    const resolved = applyChannelMatchMeta(base, { matchKey: "general", matchSource: "direct" });
    expect(resolved.matchKey).toBe("general");
    expect(resolved.matchSource).toBe("direct");
  });
});

describe("resolveChannelMatchConfig", () => {
  it("returns null when no entry is matched", () => {
    const resolved = resolveChannelMatchConfig({ matchKey: "x" }, () => {
      const out: { matchKey?: string; matchSource?: ChannelMatchSource } = {};
      return out;
    });
    expect(resolved).toBeNull();
  });

  it("resolves entry and applies match metadata", () => {
    const resolved = resolveChannelMatchConfig(
      { entry: { allow: true }, matchKey: "*", matchSource: "wildcard" },
      () => {
        const out: { matchKey?: string; matchSource?: ChannelMatchSource } = {};
        return out;
      },
    );
    expect(resolved?.matchKey).toBe("*");
    expect(resolved?.matchSource).toBe("wildcard");
  });
});

describe("validateSenderIdentity", () => {
  it("allows direct messages without sender fields", () => {
    const ctx: MsgContext = { ChatType: "direct" };
    expect(validateSenderIdentity(ctx)).toEqual([]);
  });

  it("requires some sender identity for non-direct chats", () => {
    const ctx: MsgContext = { ChatType: "group" };
    expect(validateSenderIdentity(ctx)).toContain(
      "missing sender identity (SenderId/SenderName/SenderUsername/SenderE164)",
    );
  });

  it("validates SenderE164 and SenderUsername shape", () => {
    const ctx: MsgContext = {
      ChatType: "group",
      SenderE164: "123",
      SenderUsername: "@ada lovelace",
    };
    expect(validateSenderIdentity(ctx)).toEqual([
      "invalid SenderE164: 123",
      'SenderUsername should not include "@": @ada lovelace',
      "SenderUsername should not include whitespace: @ada lovelace",
    ]);
  });
});

describe("resolveNestedAllowlistDecision", () => {
  const cases = [
    {
      name: "allows when outer allowlist is disabled",
      value: {
        outerConfigured: false,
        outerMatched: false,
        innerConfigured: false,
        innerMatched: false,
      },
      expected: true,
    },
    {
      name: "blocks when outer allowlist is configured but missing match",
      value: {
        outerConfigured: true,
        outerMatched: false,
        innerConfigured: false,
        innerMatched: false,
      },
      expected: false,
    },
    {
      name: "requires inner match when inner allowlist is configured",
      value: {
        outerConfigured: true,
        outerMatched: true,
        innerConfigured: true,
        innerMatched: false,
      },
      expected: false,
    },
    {
      name: "allows when both outer and inner allowlists match",
      value: {
        outerConfigured: true,
        outerMatched: true,
        innerConfigured: true,
        innerMatched: true,
      },
      expected: true,
    },
  ] as const;

  it.each(cases)("$name", ({ value, expected }) => {
    expect(resolveNestedAllowlistDecision(value)).toBe(expected);
  });
});

Messung V0.5 in Prozent
C=98 H=98 G=97

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-05-26) ¤

*© 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.