From 2192bb7eb54d8d2062a19b3e41f29640d677d1f7 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Mar 2026 20:24:35 +0000 Subject: [PATCH] test: add shared text and identity helper coverage --- src/shared/assistant-identity-values.test.ts | 17 ++++++++ ...ared-misc.test.ts => chat-content.test.ts} | 21 +++++++--- src/shared/text/code-regions.test.ts | 39 +++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 src/shared/assistant-identity-values.test.ts rename src/shared/{shared-misc.test.ts => chat-content.test.ts} (64%) create mode 100644 src/shared/text/code-regions.test.ts diff --git a/src/shared/assistant-identity-values.test.ts b/src/shared/assistant-identity-values.test.ts new file mode 100644 index 00000000000..59792dc7fd9 --- /dev/null +++ b/src/shared/assistant-identity-values.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from "vitest"; +import { coerceIdentityValue } from "./assistant-identity-values.js"; + +describe("shared/assistant-identity-values", () => { + it("returns undefined for missing or blank values", () => { + expect(coerceIdentityValue(undefined, 10)).toBeUndefined(); + expect(coerceIdentityValue(" ", 10)).toBeUndefined(); + }); + + it("trims values and preserves strings within the limit", () => { + expect(coerceIdentityValue(" OpenClaw ", 20)).toBe("OpenClaw"); + }); + + it("truncates overlong trimmed values at the exact limit", () => { + expect(coerceIdentityValue(" OpenClaw Assistant ", 8)).toBe("OpenClaw"); + }); +}); diff --git a/src/shared/shared-misc.test.ts b/src/shared/chat-content.test.ts similarity index 64% rename from src/shared/shared-misc.test.ts rename to src/shared/chat-content.test.ts index aab46b776d7..d66ec203c72 100644 --- a/src/shared/shared-misc.test.ts +++ b/src/shared/chat-content.test.ts @@ -1,30 +1,29 @@ import { describe, expect, it } from "vitest"; import { extractTextFromChatContent } from "./chat-content.js"; -describe("extractTextFromChatContent", () => { - it("normalizes string content", () => { +describe("shared/chat-content", () => { + it("normalizes plain string content", () => { expect(extractTextFromChatContent(" hello\nworld ")).toBe("hello world"); }); - it("extracts text blocks from array content", () => { + it("extracts only text blocks from array content", () => { expect( extractTextFromChatContent([ { type: "text", text: " hello " }, { type: "image_url", image_url: "https://example.com" }, { type: "text", text: "world" }, + null, ]), ).toBe("hello world"); }); - it("applies sanitizer when provided", () => { + it("applies sanitizers and custom join/normalization hooks", () => { expect( extractTextFromChatContent("Here [Tool Call: foo (ID: 1)] ok", { sanitizeText: (text) => text.replace(/\[Tool Call:[^\]]+\]\s*/g, ""), }), ).toBe("Here ok"); - }); - it("supports custom join and normalization", () => { expect( extractTextFromChatContent( [ @@ -39,4 +38,14 @@ describe("extractTextFromChatContent", () => { ), ).toBe("hello\nworld"); }); + + it("returns null for unsupported or empty content", () => { + expect(extractTextFromChatContent(123)).toBeNull(); + expect(extractTextFromChatContent([{ type: "text", text: " " }])).toBeNull(); + expect( + extractTextFromChatContent(" ", { + sanitizeText: () => "", + }), + ).toBeNull(); + }); }); diff --git a/src/shared/text/code-regions.test.ts b/src/shared/text/code-regions.test.ts new file mode 100644 index 00000000000..05934383bd2 --- /dev/null +++ b/src/shared/text/code-regions.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from "vitest"; +import { findCodeRegions, isInsideCode } from "./code-regions.js"; + +describe("shared/text/code-regions", () => { + it("finds fenced and inline code regions without double-counting inline code inside fences", () => { + const text = [ + "before `inline` after", + "```ts", + "const a = `inside fence`;", + "```", + "tail", + ].join("\n"); + + const regions = findCodeRegions(text); + + expect(regions).toHaveLength(2); + expect(text.slice(regions[0].start, regions[0].end)).toBe("`inline`"); + expect(text.slice(regions[1].start, regions[1].end)).toContain("```ts"); + }); + + it("accepts alternate fence markers and unterminated trailing fences", () => { + const text = "~~~js\nconsole.log(1)\n~~~\nplain\n```\nunterminated"; + const regions = findCodeRegions(text); + + expect(regions).toHaveLength(2); + expect(text.slice(regions[0].start, regions[0].end)).toContain("~~~js"); + expect(text.slice(regions[1].start, regions[1].end)).toBe("```\nunterminated"); + }); + + it("reports whether positions are inside discovered regions", () => { + const text = "plain `code` done"; + const regions = findCodeRegions(text); + const codeStart = text.indexOf("code"); + const plainStart = text.indexOf("plain"); + + expect(isInsideCode(codeStart, regions)).toBe(true); + expect(isInsideCode(plainStart, regions)).toBe(false); + }); +});