Files
letta-code/src/tests/tools/truncation.test.ts
2025-11-01 02:04:37 -07:00

162 lines
5.7 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
LIMITS,
truncateArray,
truncateByChars,
truncateByLines,
} from "../../tools/impl/truncation";
describe("truncation utilities", () => {
describe("truncateByChars", () => {
test("does not truncate when under limit", () => {
const text = "Hello, world!";
const result = truncateByChars(text, 100, "Test");
expect(result.wasTruncated).toBe(false);
expect(result.content).toBe(text);
});
test("truncates when exceeding limit", () => {
const text = "a".repeat(1000);
const result = truncateByChars(text, 500, "Test");
expect(result.wasTruncated).toBe(true);
expect(result.content).toContain("a".repeat(500));
expect(result.content).toContain(
"[Output truncated after 500 characters: exceeded limit.]",
);
expect(result.content.length).toBeGreaterThan(500); // Due to notice
});
test("exactly at limit does not truncate", () => {
const text = "a".repeat(500);
const result = truncateByChars(text, 500, "Test");
expect(result.wasTruncated).toBe(false);
expect(result.content).toBe(text);
});
test("includes correct character count in notice", () => {
const text = "x".repeat(2000);
const result = truncateByChars(text, 1000, "Test");
expect(result.content).toContain("1,000 characters");
});
});
describe("truncateByLines", () => {
test("does not truncate when under line limit", () => {
const text = "line1\nline2\nline3";
const result = truncateByLines(text, 10, undefined, "Test");
expect(result.wasTruncated).toBe(false);
expect(result.content).toBe(text);
expect(result.originalLineCount).toBe(3);
expect(result.linesShown).toBe(3);
});
test("truncates when exceeding line limit", () => {
const lines = Array.from({ length: 100 }, (_, i) => `Line ${i + 1}`);
const text = lines.join("\n");
const result = truncateByLines(text, 50, undefined, "Test");
expect(result.wasTruncated).toBe(true);
expect(result.originalLineCount).toBe(100);
expect(result.linesShown).toBe(50);
expect(result.content).toContain("Line 1");
expect(result.content).toContain("Line 50");
expect(result.content).not.toContain("Line 51");
expect(result.content).toContain("showing 50 of 100 lines");
});
test("truncates long lines when maxCharsPerLine specified", () => {
const text = "short\n" + "a".repeat(1000) + "\nshort";
const result = truncateByLines(text, 10, 500, "Test");
expect(result.wasTruncated).toBe(true);
expect(result.content).toContain("short");
expect(result.content).toContain("a".repeat(500));
expect(result.content).toContain("... [line truncated]");
expect(result.content).toContain(
"Some lines exceeded 500 characters and were truncated",
);
});
test("handles both line count and character truncation", () => {
const lines = Array.from(
{ length: 100 },
(_, i) => `Line ${i + 1}: ${"x".repeat(2000)}`,
);
const text = lines.join("\n");
const result = truncateByLines(text, 50, 1000, "Test");
expect(result.wasTruncated).toBe(true);
expect(result.originalLineCount).toBe(100);
expect(result.linesShown).toBe(50);
expect(result.content).toContain("showing 50 of 100 lines");
expect(result.content).toContain(
"Some lines exceeded 1,000 characters and were truncated",
);
});
test("exactly at line limit does not truncate", () => {
const text = "line1\nline2\nline3";
const result = truncateByLines(text, 3, undefined, "Test");
expect(result.wasTruncated).toBe(false);
expect(result.content).toBe(text);
});
});
describe("truncateArray", () => {
test("does not truncate when under limit", () => {
const items = ["item1", "item2", "item3"];
const formatter = (arr: string[]) => arr.join("\n");
const result = truncateArray(items, 10, formatter, "items");
expect(result.wasTruncated).toBe(false);
expect(result.content).toBe("item1\nitem2\nitem3");
});
test("truncates when exceeding limit", () => {
const items = Array.from({ length: 100 }, (_, i) => `item${i + 1}`);
const formatter = (arr: string[]) => arr.join("\n");
const result = truncateArray(items, 50, formatter, "items");
expect(result.wasTruncated).toBe(true);
expect(result.content).toContain("item1");
expect(result.content).toContain("item50");
expect(result.content).not.toContain("item51");
expect(result.content).toContain("showing 50 of 100 items");
});
test("exactly at limit does not truncate", () => {
const items = ["a", "b", "c"];
const formatter = (arr: string[]) => arr.join(", ");
const result = truncateArray(items, 3, formatter, "entries");
expect(result.wasTruncated).toBe(false);
expect(result.content).toBe("a, b, c");
});
test("uses custom item type in notice", () => {
const items = Array.from({ length: 1000 }, (_, i) => `/file${i}.txt`);
const formatter = (arr: string[]) => arr.join("\n");
const result = truncateArray(items, 100, formatter, "files");
expect(result.content).toContain("showing 100 of 1,000 files");
});
});
describe("LIMITS constants", () => {
test("has expected values", () => {
expect(LIMITS.BASH_OUTPUT_CHARS).toBe(30_000);
expect(LIMITS.READ_MAX_LINES).toBe(2_000);
expect(LIMITS.READ_MAX_CHARS_PER_LINE).toBe(2_000);
expect(LIMITS.GREP_OUTPUT_CHARS).toBe(10_000);
expect(LIMITS.GLOB_MAX_FILES).toBe(2_000);
expect(LIMITS.LS_MAX_ENTRIES).toBe(1_000);
});
});
});