mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-18 06:36:29 +00:00
Merged via squash.
Prepared head SHA: 583b22354d
Co-authored-by: Nas01010101 <156536069+Nas01010101@users.noreply.github.com>
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Reviewed-by: @vincentkoc
58 lines
2.2 KiB
TypeScript
58 lines
2.2 KiB
TypeScript
// Telegram tests cover plain-text chunk-splitting behavior.
|
|
import { describe, expect, it } from "vitest";
|
|
import { splitTelegramPlainTextChunksForTests } from "./send.js";
|
|
|
|
function containsLoneSurrogate(text: string): boolean {
|
|
for (let index = 0; index < text.length; index += 1) {
|
|
const code = text.charCodeAt(index);
|
|
const isHigh = code >= 0xd800 && code <= 0xdbff;
|
|
const isLow = code >= 0xdc00 && code <= 0xdfff;
|
|
if (isHigh) {
|
|
const next = text.charCodeAt(index + 1);
|
|
if (!(next >= 0xdc00 && next <= 0xdfff)) {
|
|
return true;
|
|
}
|
|
index += 1;
|
|
} else if (isLow) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
describe("splitTelegramPlainTextChunks", () => {
|
|
it("does not split an astral char across the chunk boundary", () => {
|
|
// Emoji surrogate pair straddles index 10 (limit): high at 9, low at 10.
|
|
const input = `${"A".repeat(9)}😀${"B".repeat(20)}`;
|
|
const chunks = splitTelegramPlainTextChunksForTests(input, 10);
|
|
expect(chunks.length).toBeGreaterThan(1);
|
|
expect(chunks.join("")).toBe(input);
|
|
for (const chunk of chunks) {
|
|
expect(containsLoneSurrogate(chunk)).toBe(false);
|
|
}
|
|
});
|
|
|
|
it("does not hang when limit=1 and text starts with an astral char", () => {
|
|
// Regression: with limit=1 the clamp would return start (no advance),
|
|
// causing the while-loop to spin forever. The surrogate pair must be
|
|
// emitted as a unit (2 code units) so the loop always advances.
|
|
const input = "😀X";
|
|
const chunks = splitTelegramPlainTextChunksForTests(input, 1);
|
|
expect(chunks.join("")).toBe(input);
|
|
for (const chunk of chunks) {
|
|
expect(containsLoneSurrogate(chunk)).toBe(false);
|
|
}
|
|
});
|
|
|
|
it("does not hang when limit=1 and an astral char appears mid-string at a chunk boundary", () => {
|
|
// 'A' + emoji: with limit=1, second iteration starts at index 1 (high
|
|
// surrogate) — same stall condition as above, now mid-string.
|
|
const input = "A😀B";
|
|
const chunks = splitTelegramPlainTextChunksForTests(input, 1);
|
|
expect(chunks.join("")).toBe(input);
|
|
for (const chunk of chunks) {
|
|
expect(containsLoneSurrogate(chunk)).toBe(false);
|
|
}
|
|
});
|
|
});
|