import { describe, expect, test } from "bun:test"; import { compileQuery, matchLines, requiredLiteral } from "./text-search"; describe("workspace text search", () => { test("literal patterns are escaped and case-insensitive unless asked", () => { const content = "const a = foo.bar();\nFOO.BAR\nfooXbar"; expect(matchLines(content, compileQuery({ pattern: "foo.bar" }), 10)).toEqual([ { line: 0, text: "const a = foo.bar();", ranges: [[10, 17]] }, { line: 1, text: "FOO.BAR", ranges: [[0, 7]] }, ]); expect(matchLines(content, compileQuery({ pattern: "foo.bar", isCaseSensitive: true }), 10)).toHaveLength(1); }); test("regular expressions, whole words, every match on a line, and the limit", () => { const content = "cat concat cat\ndog\ncat"; expect(matchLines(content, compileQuery({ pattern: "cat", isWordMatch: true }), 10)[0].ranges).toEqual([ [0, 3], [11, 14], ]); expect(matchLines(content, compileQuery({ pattern: "^d.g$", isRegExp: true }), 10)).toEqual([ { line: 1, text: "dog", ranges: [[0, 3]] }, ]); expect(matchLines(content, compileQuery({ pattern: "cat" }), 1)).toHaveLength(1); expect(matchLines("abc", compileQuery({ pattern: "x*", isRegExp: true }), 10)).toEqual([]); expect(() => compileQuery({ pattern: "(", isRegExp: true })).toThrow(); }); }); describe("index prefilter literal", () => { test("literal patterns are their own prefilter once long enough", () => { expect(requiredLiteral({ pattern: "foo.bar" })).toBe("foo.bar"); expect(requiredLiteral({ pattern: "ab" })).toBeNull(); }); test("regexes yield only substrings every match must contain", () => { expect(requiredLiteral({ pattern: "function\\s+handle\\w*Request", isRegExp: true })).toBe("function"); expect(requiredLiteral({ pattern: "colou?r_name", isRegExp: true })).toBe("r_name"); expect(requiredLiteral({ pattern: "import\\.meta", isRegExp: true })).toBe("import.meta"); expect(requiredLiteral({ pattern: "[abc]+xyz(opt)?tail", isRegExp: true })).toBe("tail"); expect(requiredLiteral({ pattern: "foo|barbaz", isRegExp: true })).toBeNull(); expect(requiredLiteral({ pattern: "a.b.c", isRegExp: true })).toBeNull(); expect(requiredLiteral({ pattern: "x{2,3}abcd", isRegExp: true })).toBe("abcd"); }); });