162 lines
5.7 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|