Skip to content

Commit f92ec2d

Browse files
authored
test(shared): add unit tests for surrogate-safe UTF-16 string slicing helpers (#97805)
* test(shared): add unit tests for surrogate-safe UTF-16 string slicing helpers Add unit tests for sliceUtf16Safe and truncateUtf16Safe functions in src/shared/utf16-slice.ts to verify UTF-16 string slicing behavior. Tests cover: - sliceUtf16Safe slices ASCII string normally - sliceUtf16Safe handles negative start/end - sliceUtf16Safe handles start/end beyond length - sliceUtf16Safe swaps start and end when start > end - sliceUtf16Safe preserves emoji with surrogate pairs - sliceUtf16Safe avoids splitting surrogate pair at start/end - truncateUtf16Safe returns input when shorter than limit - truncateUtf16Safe truncates when longer than limit - truncateUtf16Safe handles zero/negative limit - truncateUtf16Safe floors decimal limit - truncateUtf16Safe preserves emoji with surrogate pairs - truncateUtf16Safe avoids splitting surrogate pair * fix: replace tautological surrogate assertions with exact output checks Replace vague 'result.length >= 0' assertions with exact expected output checks for surrogate pair boundary cases. The helper returns empty string when slicing at surrogate pair boundaries.
1 parent 0916752 commit f92ec2d

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

src/shared/utf16-slice.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Tests for surrogate-safe UTF-16 string slicing helpers.
2+
import { describe, expect, it } from "vitest";
3+
import { sliceUtf16Safe, truncateUtf16Safe } from "./utf16-slice.js";
4+
5+
describe("sliceUtf16Safe", () => {
6+
it("slices ASCII string normally", () => {
7+
expect(sliceUtf16Safe("hello world", 0, 5)).toBe("hello");
8+
});
9+
10+
it("handles negative start", () => {
11+
expect(sliceUtf16Safe("hello world", -5)).toBe("world");
12+
});
13+
14+
it("handles negative end", () => {
15+
expect(sliceUtf16Safe("hello world", 0, -6)).toBe("hello");
16+
});
17+
18+
it("handles start beyond length", () => {
19+
expect(sliceUtf16Safe("hello", 10)).toBe("");
20+
});
21+
22+
it("handles end beyond length", () => {
23+
expect(sliceUtf16Safe("hello", 0, 10)).toBe("hello");
24+
});
25+
26+
it("swaps start and end when start > end", () => {
27+
expect(sliceUtf16Safe("hello", 3, 1)).toBe("el");
28+
});
29+
30+
it("preserves emoji with surrogate pairs", () => {
31+
const emoji = "👨‍👩‍👧‍👦";
32+
expect(sliceUtf16Safe(emoji, 0)).toBe(emoji);
33+
});
34+
35+
it("returns empty string when slicing middle of surrogate pair", () => {
36+
const input = "👨👩";
37+
// Slicing at position 1-3 hits middle of surrogate pairs
38+
expect(sliceUtf16Safe(input, 1, 3)).toBe("");
39+
});
40+
41+
it("returns empty string when slicing at start of surrogate pair", () => {
42+
const input = "👨👩";
43+
// Slicing at position 0-1 would cut surrogate pair, adjust to 0
44+
expect(sliceUtf16Safe(input, 0, 1)).toBe("");
45+
});
46+
47+
it("handles empty string", () => {
48+
expect(sliceUtf16Safe("", 0)).toBe("");
49+
});
50+
51+
it("handles undefined end", () => {
52+
expect(sliceUtf16Safe("hello", 2)).toBe("llo");
53+
});
54+
});
55+
56+
describe("truncateUtf16Safe", () => {
57+
it("returns input when shorter than limit", () => {
58+
expect(truncateUtf16Safe("hello", 10)).toBe("hello");
59+
});
60+
61+
it("truncates when longer than limit", () => {
62+
expect(truncateUtf16Safe("hello world", 5)).toBe("hello");
63+
});
64+
65+
it("handles zero limit", () => {
66+
expect(truncateUtf16Safe("hello", 0)).toBe("");
67+
});
68+
69+
it("handles negative limit", () => {
70+
expect(truncateUtf16Safe("hello", -1)).toBe("");
71+
});
72+
73+
it("floors decimal limit", () => {
74+
expect(truncateUtf16Safe("hello world", 5.7)).toBe("hello");
75+
});
76+
77+
it("preserves emoji with surrogate pairs", () => {
78+
const emoji = "👨‍👩‍👧‍👦";
79+
const result = truncateUtf16Safe(emoji, 10);
80+
// Should not return dangling surrogate
81+
expect(result.length).toBeLessThanOrEqual(emoji.length);
82+
});
83+
84+
it("returns empty string when truncating at surrogate pair boundary", () => {
85+
const input = "👨👩";
86+
expect(truncateUtf16Safe(input, 1)).toBe("");
87+
});
88+
});

0 commit comments

Comments
 (0)