Files
AgentCompany/tests/unit/text-paging.test.ts
T

61 lines
3.5 KiB
TypeScript

import { describe, expect, test } from "vitest";
import { pageText, readPageArgs } from "../../src/main/services/text-paging";
const numbered = (count: number, width = 10) => Array.from({ length: count }, (_, index) => `line ${index + 1} `.padEnd(width, "."));
describe("text paging", () => {
test("a small file comes back unchanged", () => {
expect(pageText("a.md", "one\ntwo", readPageArgs({}))).toBe("one\ntwo");
});
test("a large file pages by lines and says where to continue", () => {
const content = numbered(5000).join("\n");
const first = pageText("big.ts", content, readPageArgs({}));
expect(first.startsWith("[lines 1-2181 of 5000 in big.ts]\nline 1 ")).toBe(true);
expect(first.endsWith("[more: pass start_line=2182 to continue]")).toBe(true);
const tail = pageText("big.ts", content, readPageArgs({ start_line: 4999 }));
expect(tail).toBe("[lines 4999-5000 of 5000 in big.ts]\nline 4999 \nline 5000 ");
const window = pageText("big.ts", content, readPageArgs({ start_line: 10, line_count: 2 }));
expect(window).toBe("[lines 10-11 of 5000 in big.ts]\nline 10 ..\nline 11 ..\n[more: pass start_line=12 to continue]");
});
test("search returns numbered matching lines", () => {
const content = ["alpha", "Beta release", "gamma", "beta test"].join("\n");
expect(pageText("notes.md", content, readPageArgs({ search: "beta" }))).toBe('[2 matching lines for "beta" in notes.md]\n2: Beta release\n4: beta test');
expect(pageText("notes.md", content, readPageArgs({ search: "delta" }))).toBe('No lines in notes.md contain "delta".');
});
test("an overlong single line is cut and the next line is offered", () => {
const content = `${"x".repeat(30_000)}\nsecond`;
const page = pageText("min.js", content, readPageArgs({}));
expect(page).toContain("[line 1 continues: pass start_line=1 and start_column=24001]");
expect(page.endsWith("[more: pass start_line=2 to continue]")).toBe(true);
const rest = pageText("min.js", content, readPageArgs({ start_line: 1, start_column: 24_001 }));
expect(rest).toBe(`[lines 1-2 of 2 in min.js]\n${"x".repeat(6_000)}\nsecond`);
});
test("a one-line file longer than the limit is still cut", () => {
const page = pageText("blob.txt", "y".repeat(30_000), readPageArgs({}));
expect(page.length).toBeLessThan(24_200);
expect(page.startsWith("[lines 1-1 of 1 in blob.txt]")).toBe(true);
expect(page).toContain("[line 1 continues: pass start_line=1 and start_column=24001]");
});
test("boundaries: an exact-limit line is whole, and search output stays under the cap", () => {
const exact = "z".repeat(24_000);
expect(pageText("exact.txt", exact, readPageArgs({}))).toBe(exact);
const noisy = Array.from({ length: 300 }, (_, index) => `${index} needle ${"w".repeat(600)}`).join("\n");
const found = pageText("noisy.txt", noisy, readPageArgs({ search: "needle" }));
expect(found.length).toBeLessThan(24_200);
expect(found).toMatch(/\[\d+ more matches not shown; narrow the search\]$/);
});
test("bad ranges fail loudly", () => {
expect(() => readPageArgs({ start_line: 0 })).toThrow('"start_line" must be a positive whole number.');
expect(() => readPageArgs({ line_count: 2.5 })).toThrow('"line_count" must be a positive whole number.');
expect(() => readPageArgs({ search: 123 })).toThrow('"search" is required.');
expect(() => readPageArgs({ search: " " })).toThrow('"search" is required.');
expect(() => pageText("a.md", "one", readPageArgs({ start_line: 3 }))).toThrow("a.md has only 1 lines.");
});
});