Files
openclaw/src/shared/string-normalization.test.ts
Peter Steinberger 77d9ac30bb refactor: reuse shared coercion helpers (#86419)
* refactor: share talk event metric extraction

* refactor: reuse shared coercion helpers

* refactor: reuse shared primitive guards

* refactor: reuse shared record guard

* refactor: reuse shared primitive helpers

* refactor: reuse shared string guards

* refactor: reuse shared non-empty string guard

* refactor: share plugin primitive coercion helpers

* refactor: reuse plugin coercion helpers

* refactor: reuse plugin coercion helpers in more plugins

* refactor: reuse channel coercion helpers

* refactor: reuse monitor coercion helpers

* refactor: reuse provider coercion helpers

* refactor: reuse core coercion helpers

* refactor: reuse runtime coercion helpers

* refactor: reuse helper coercion in codex paths

* refactor: reuse helper coercion in runtime paths

* refactor: reuse codex app-server coercion helpers

* refactor: reuse codex record helpers

* refactor: reuse migration and qa record helpers

* refactor: reuse feishu and core helper guards

* refactor: reuse browser and policy coercion helpers

* refactor: reuse memory wiki record helper

* refactor: share boolean coercion helpers

* refactor: reuse finite number coercion

* refactor: reuse trimmed string list helpers

* refactor: reuse string list normalization

* refactor: reuse remaining string list helpers

* refactor: reuse string entry normalizer

* refactor: share sorted string helpers

* refactor: share string list normalization

* test: preserve command registry browser imports

* refactor: reuse trimmed list helpers

* refactor: reuse string dedupe helpers

* refactor: reuse local dedupe helpers

* refactor: reuse more string dedupe helpers

* refactor: reuse command string dedupe helpers

* refactor: dedupe memory path lists with helper

* refactor: expose string dedupe helpers to plugins

* refactor: reuse core string dedupe helpers

* refactor: reuse shared unique value helpers

* refactor: reuse unique helpers in agent utilities

* refactor: reuse unique helpers in config plumbing

* refactor: reuse unique helpers in extensions

* refactor: reuse unique helpers in core utilities

* refactor: reuse unique helpers in qa plugins

* refactor: reuse unique helpers in memory plugins

* refactor: reuse unique helpers in channel plugins

* refactor: reuse unique helpers in core tails

* refactor: reuse unique helper in comfy workflow

* refactor: reuse unique helpers in test utilities

* refactor: expose unique value helper to plugins

* refactor: reuse unique helpers for numeric lists

* refactor: replace index dedupe filters

* refactor: reuse string entry normalization

* refactor: reuse string normalization in plugin helpers

* refactor: reuse string normalization in extension helpers

* refactor: reuse string normalization in channel parsers

* refactor: reuse string normalization in memory search

* refactor: reuse string normalization in provider parsers

* refactor: reuse string normalization in qa helpers

* refactor: reuse string normalization in infra parsers

* refactor: reuse string normalization in messaging parsers

* refactor: reuse string normalization in core parsers

* refactor: reuse string normalization in extension parsers

* refactor: reuse string normalization in remaining parsers

* refactor: reuse string normalization in final parser spots

* refactor: reuse string normalization in qa media helpers

* refactor: reuse normalization in provider and media lists

* refactor: reuse normalization for remaining set filters

* refactor: reuse normalization in policy allowlists

* refactor: reuse normalization in session and owner lists

* refactor: centralize primitive string lists

* refactor: reuse lowercase entry helpers

* refactor: reuse sorted string helpers

* refactor: reuse unique trimmed helpers

* refactor: reuse string normalization helpers

* refactor: reuse catalog string helpers

* refactor: reuse remaining string helpers

* refactor: simplify remaining list normalization

* refactor: reuse codex auth order normalization

* chore: refresh plugin sdk api baseline

* fix: make shared string sorting deterministic

* chore: refresh plugin sdk api baseline

* fix: align host env security ordering
2026-05-25 21:20:41 +01:00

143 lines
5.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
normalizeAtHashSlug,
normalizeHyphenSlug,
normalizeSortedUniqueStringEntries,
normalizeSortedUniqueTrimmedStringList,
normalizeStringEntries,
normalizeStringEntriesLower,
normalizeUniqueSingleOrTrimmedStringList,
normalizeUniqueStringEntries,
normalizeUniqueStringEntriesLower,
normalizeUniqueTrimmedStringList,
sortUniqueStrings,
uniqueStrings,
} from "./string-normalization.js";
describe("shared/string-normalization", () => {
it("normalizes mixed allow-list entries", () => {
expect(normalizeStringEntries([" a ", 42, "", " ", "z"])).toEqual(["a", "42", "z"]);
expect(normalizeStringEntries([" ok ", null, { toString: () => " obj " }])).toEqual([
"ok",
"null",
"obj",
]);
expect(normalizeStringEntries(undefined)).toStrictEqual([]);
});
it("normalizes mixed allow-list entries to lowercase", () => {
expect(normalizeStringEntriesLower([" A ", "MiXeD", 7])).toEqual(["a", "mixed", "7"]);
});
it("sorts unique string values", () => {
expect(sortUniqueStrings(["b", "a", "b"])).toEqual(["a", "b"]);
});
it("deduplicates string values while preserving first-seen order", () => {
expect(uniqueStrings(["b", "a", "b", "c", "a"])).toEqual(["b", "a", "c"]);
});
it("normalizes unique string entries", () => {
expect(normalizeUniqueStringEntries([" b ", "a", "b", "", 4, "a"])).toEqual(["b", "a", "4"]);
});
it("normalizes unique lowercase string entries", () => {
expect(normalizeUniqueStringEntriesLower([" A ", "a", "MiXeD", "", 7])).toEqual([
"a",
"mixed",
"7",
]);
});
it("normalizes sorted unique string entries", () => {
expect(normalizeSortedUniqueStringEntries([" b ", "a", "b", "", 4])).toEqual(["4", "a", "b"]);
});
it("normalizes unique trimmed string lists", () => {
expect(normalizeUniqueTrimmedStringList([" b ", "a", "b", "", "a"])).toEqual(["b", "a"]);
expect(normalizeUniqueTrimmedStringList("b")).toEqual([]);
});
it("normalizes sorted unique trimmed string lists", () => {
expect(normalizeSortedUniqueTrimmedStringList([" b ", "a", "b", "", "a"])).toEqual(["a", "b"]);
expect(normalizeSortedUniqueTrimmedStringList(["z", 1, " a "] as unknown[])).toEqual([
"a",
"z",
]);
});
it("normalizes unique single-or-list string values", () => {
expect(normalizeUniqueSingleOrTrimmedStringList([" b ", "a", "b", "", "a"])).toEqual([
"b",
"a",
]);
expect(normalizeUniqueSingleOrTrimmedStringList(" b ")).toEqual(["b"]);
});
it("normalizes slug-like labels while preserving supported symbols", () => {
expect(normalizeHyphenSlug(" Team Room ")).toBe("team-room");
expect(normalizeHyphenSlug(" #My_Channel + Alerts ")).toBe("#my_channel-+-alerts");
expect(normalizeHyphenSlug("..foo---bar..")).toBe("foo-bar");
expect(normalizeHyphenSlug(undefined)).toBe("");
expect(normalizeHyphenSlug(null)).toBe("");
});
it("collapses repeated separators and trims leading/trailing punctuation", () => {
expect(normalizeHyphenSlug(" ...Hello / World--- ")).toBe("hello-world");
expect(normalizeHyphenSlug(" ###Team@@@Room### ")).toBe("###team@@@room###");
});
it("normalizes @/# prefixed slugs used by channel allowlists", () => {
expect(normalizeAtHashSlug(" #My_Channel + Alerts ")).toBe("my-channel-alerts");
expect(normalizeAtHashSlug("@@Room___Name")).toBe("room-name");
expect(normalizeAtHashSlug(undefined)).toBe("");
expect(normalizeAtHashSlug(null)).toBe("");
});
it("strips repeated prefixes and collapses separator-only results", () => {
expect(normalizeAtHashSlug("###__Room Name__")).toBe("room-name");
expect(normalizeAtHashSlug("@@@___")).toBe("");
});
it.each([
["技术讨论组", "技术讨论组"],
[" AI 助手群 ", "ai-助手群"],
["友達グループ", "友達グループ"],
["개발자 모임", "개발자-모임"],
["Team 技术讨论", "team-技术讨论"],
["#OpenClaw中文群", "#openclaw中文群"],
["Команда разработки", "команда-разработки"],
["فريق التطوير", "فريق-التطوير"],
])("preserves Unicode letters in normalizeHyphenSlug: %s", (input, expected) => {
expect(normalizeHyphenSlug(input)).toBe(expected);
});
it.each([
["Cafe\u0301 Team", "café-team"],
["हिन्दी चर्चा", "हिन्दी-चर्चा"],
["ห้อง แช็ต", "ห้อง-แช็ต"],
])("preserves combining marks in normalizeHyphenSlug: %s", (input, expected) => {
expect(normalizeHyphenSlug(input)).toBe(expected);
});
it.each([
["#技术频道", "技术频道"],
["@中文群组", "中文群组"],
["#日本語チャンネル", "日本語チャンネル"],
["#한국어채널", "한국어채널"],
["#Команда разработки", "команда-разработки"],
["@فريق التطوير", "فريق-التطوير"],
["#OpenClaw中文群", "openclaw中文群"],
])("preserves Unicode letters in normalizeAtHashSlug: %s", (input, expected) => {
expect(normalizeAtHashSlug(input)).toBe(expected);
});
it.each([
["#Cafe\u0301_Team", "café-team"],
["@हिन्दी चर्चा", "हिन्दी-चर्चा"],
["#ห้อง แช็ต", "ห้อง-แช็ต"],
])("preserves combining marks in normalizeAtHashSlug: %s", (input, expected) => {
expect(normalizeAtHashSlug(input)).toBe(expected);
});
});