claude-code-best/src/utils/__tests__/truncate.test.ts
2026-04-02 14:44:56 +08:00

191 lines
6.3 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
truncatePathMiddle,
truncateToWidth,
truncateStartToWidth,
truncateToWidthNoEllipsis,
truncate,
wrapText,
} from "../truncate";
// ─── truncateToWidth ────────────────────────────────────────────────────
describe("truncateToWidth", () => {
test("returns original when within limit", () => {
expect(truncateToWidth("hello", 10)).toBe("hello");
});
test("truncates long string with ellipsis", () => {
const result = truncateToWidth("hello world", 8);
expect(result).toBe("hello w…");
});
test("returns ellipsis for maxWidth 1", () => {
expect(truncateToWidth("hello", 1)).toBe("…");
});
test("handles empty string", () => {
expect(truncateToWidth("", 10)).toBe("");
});
// ── CJK / wide-character tests ──
test("truncates CJK string at width boundary (2 per char)", () => {
expect(truncateToWidth("你好世界", 4)).toBe("你…");
});
test("truncates CJK string preserving full characters", () => {
expect(truncateToWidth("你好世界", 6)).toBe("你好…");
});
test("passes through CJK string when within limit", () => {
expect(truncateToWidth("你好", 4)).toBe("你好");
});
test("handles mixed ASCII + CJK", () => {
expect(truncateToWidth("hello你好", 8)).toBe("hello你…");
});
test("passes through mixed ASCII + CJK at exact limit", () => {
expect(truncateToWidth("hello你好", 9)).toBe("hello你好");
});
test("truncates string containing emoji", () => {
const result = truncateToWidth("hello 👋 world", 10);
expect(result).toBe("hello 👋 …");
});
test("passes through single emoji at sufficient width", () => {
expect(truncateToWidth("👋", 2)).toBe("👋");
});
});
// ─── truncateStartToWidth ───────────────────────────────────────────────
describe("truncateStartToWidth", () => {
test("returns original when within limit", () => {
expect(truncateStartToWidth("hello", 10)).toBe("hello");
});
test("truncates from start with ellipsis prefix", () => {
expect(truncateStartToWidth("hello world", 8)).toBe("…o world");
});
test("returns ellipsis for maxWidth 1", () => {
expect(truncateStartToWidth("hello", 1)).toBe("…");
});
test("truncates CJK from start", () => {
expect(truncateStartToWidth("你好世界", 4)).toBe("…界");
});
test("truncates CJK from start preserving characters", () => {
expect(truncateStartToWidth("你好世界", 6)).toBe("…世界");
});
});
// ─── truncateToWidthNoEllipsis ──────────────────────────────────────────
describe("truncateToWidthNoEllipsis", () => {
test("returns original when within limit", () => {
expect(truncateToWidthNoEllipsis("hello", 10)).toBe("hello");
});
test("truncates without ellipsis", () => {
const result = truncateToWidthNoEllipsis("hello world", 5);
expect(result).toBe("hello");
expect(result.includes("…")).toBe(false);
});
test("returns empty for maxWidth 0", () => {
expect(truncateToWidthNoEllipsis("hello", 0)).toBe("");
});
test("truncates CJK without ellipsis", () => {
expect(truncateToWidthNoEllipsis("你好世界", 4)).toBe("你好");
});
});
// ─── truncatePathMiddle ─────────────────────────────────────────────────
describe("truncatePathMiddle", () => {
test("returns original when path fits", () => {
expect(truncatePathMiddle("src/index.ts", 50)).toBe("src/index.ts");
});
test("truncates middle of long path", () => {
const path = "src/components/deeply/nested/folder/MyComponent.tsx";
const result = truncatePathMiddle(path, 30);
expect(result).toContain("…");
expect(result.endsWith("MyComponent.tsx")).toBe(true);
});
test("returns ellipsis for maxLength 0", () => {
expect(truncatePathMiddle("src/index.ts", 0)).toBe("…");
});
test("handles path without slashes", () => {
const result = truncatePathMiddle("verylongfilename.ts", 10);
expect(result).toContain("…");
});
test("handles short maxLength < 5", () => {
expect(truncatePathMiddle("src/components/foo.ts", 4)).toBe("src…");
});
test("handles very short maxLength 1", () => {
expect(truncatePathMiddle("/a/b", 1)).toBe("…");
});
});
// ─── truncate ───────────────────────────────────────────────────────────
describe("truncate", () => {
test("returns original when within limit", () => {
expect(truncate("hello", 10)).toBe("hello");
});
test("truncates long string", () => {
const result = truncate("hello world foo bar", 10);
expect(result).toContain("…");
});
test("truncates at newline in singleLine mode", () => {
const result = truncate("first line\nsecond line", 50, true);
expect(result).toBe("first line…");
});
test("does not truncate at newline when singleLine is false", () => {
const result = truncate("first\nsecond", 50, false);
expect(result).toBe("first\nsecond");
});
test("truncates singleLine when first line exceeds maxWidth", () => {
const result = truncate("a very long first line\nsecond", 10, true);
expect(result).toContain("…");
expect(result).not.toContain("\n");
});
});
// ─── wrapText ───────────────────────────────────────────────────────────
describe("wrapText", () => {
test("wraps text at specified width", () => {
const result = wrapText("hello world", 6);
expect(result.length).toBeGreaterThan(1);
});
test("returns single line when text fits", () => {
expect(wrapText("hello", 10)).toEqual(["hello"]);
});
test("handles empty string", () => {
expect(wrapText("", 10)).toEqual([]);
});
test("wraps each character on width 1", () => {
const result = wrapText("abc", 1);
expect(result).toEqual(["a", "b", "c"]);
});
});