sourcebot/packages/web/src/app/[domain]/components/searchBar/searchSuggestionsBox.test.tsx

222 lines
8 KiB
TypeScript
Raw Normal View History

import { expect, test } from 'vitest'
import { completeSuggestion, splitQuery } from './searchSuggestionsBox'
test('splitQuery returns a single element when the query is empty', () => {
const { queryParts, cursorIndex } = splitQuery('', 0);
expect(cursorIndex).toEqual(0);
expect(queryParts).toEqual(['']);
});
test('splitQuery splits on spaces', () => {
const query = String.raw`repo:^github\.com/example/example$ world`;
const { queryParts, cursorIndex } = splitQuery(query, 0);
expect(queryParts).toEqual(query.split(" "));
expect(cursorIndex).toEqual(0);
});
test('splitQuery groups parts that are in the same quote capture group into a single part', () => {
const part1 = 'lang:"1C Enterprise"';
const part2 = "hello";
const { queryParts, cursorIndex } = splitQuery(`${part1} ${part2}`, 12);
expect(queryParts).toEqual([part1, part2]);
expect(cursorIndex).toEqual(0);
});
test('splitQuery does not support nested quote capture groups', () => {
const { queryParts } = splitQuery('lang:"My language "with quotes"" hello', 0);
expect(queryParts).toEqual(['lang:"My language "with', 'quotes""', 'hello']);
});
test('splitQuery groups all parts together when a quote capture group is not closed', () => {
const query = '"hello asdf ok'
const { queryParts, cursorIndex } = splitQuery(query, 0);
expect(queryParts).toEqual([query]);
expect(cursorIndex).toBe(0);
});
test('splitQuery correctly locates the cursor index given the cursor position (1)', () => {
const query = 'foo bar "fizz buzz"';
const { queryParts: parts1, cursorIndex: index1 } = splitQuery(query, 0);
expect(parts1).toEqual(['foo', 'bar', '"fizz buzz"']);
expect(parts1[index1]).toBe('foo');
const { queryParts: parts2, cursorIndex: index2 } = splitQuery(query, 6);
expect(parts2).toEqual(['foo', 'bar', '"fizz buzz"']);
expect(parts2[index2]).toBe('bar');
const { queryParts: parts3, cursorIndex: index3 } = splitQuery(query, 15);
expect(parts3).toEqual(['foo', 'bar', '"fizz buzz"']);
expect(parts3[index3]).toBe('"fizz buzz"');
});
test('splitQuery correctly locates the cursor index given the cursor position (2)', () => {
const query = 'a b';
expect(splitQuery(query, 0).cursorIndex).toBe(0);
expect(splitQuery(query, 1).cursorIndex).toBe(0);
expect(splitQuery(query, 2).cursorIndex).toBe(1);
expect(splitQuery(query, 3).cursorIndex).toBe(1);
});
test('splitQuery can handle multiple spaces adjacent', () => {
expect(splitQuery("a b ", 0).queryParts).toEqual(['a', '', '', 'b', '', '']);
});
test('splitQuery locates the cursor index to the last query part when the cursor position is at the end of the query', () => {
const query = "as df";
const cursorPos = query.length;
const { queryParts, cursorIndex } = splitQuery(query, cursorPos);
expect(cursorIndex).toBe(queryParts.length - 1);
expect(queryParts[cursorIndex]).toBe("df");
expect(queryParts).toEqual(['as', 'df']);
});
test('splitQuery sets the cursor index to 0 when the cursor position is out of bounds', () => {
const query = "hello world";
const cursorPos = query.length + 1;
const { queryParts, cursorIndex } = splitQuery(query, cursorPos);
expect(cursorIndex).toBe(0);
expect(queryParts[cursorIndex]).toBe("hello");
expect(queryParts).toEqual(['hello', 'world']);
});
test('completeSuggestion can complete a empty query', () => {
const suggestionQuery = ``;
const query = ``;
const suggestion = "hello";
const { newQuery, newCursorPosition } = completeSuggestion({
query,
suggestionQuery,
suggestion,
trailingSpace: false,
regexEscaped: false,
cursorPosition: 0,
});
const expectedNewQuery = String.raw`hello`;
expect(newQuery).toEqual(expectedNewQuery);
expect(newCursorPosition).toBe(newQuery.length);
});
test('completeSuggestion can complete with a empty suggestion query', () => {
const suggestionQuery = ``;
const query = `case:`;
const suggestion = "auto";
const { newQuery, newCursorPosition } = completeSuggestion({
query,
suggestionQuery,
suggestion,
trailingSpace: false,
regexEscaped: false,
cursorPosition: query.length,
});
const expectedNewQuery = `case:auto`;
expect(newQuery).toEqual(expectedNewQuery);
expect(newCursorPosition).toBe(newQuery.length);
});
test('completeSuggestion inserts a trailing space when trailingSpace is true and the completion is at the end of the query', () => {
const suggestionQuery = 'a';
const part1 = String.raw`lang:Go`;
const part2 = String.raw`case:${suggestionQuery}`;
const query = `${part1} ${part2}`
const suggestion = 'auto';
const cursorPosition = query.length;
const { newQuery, newCursorPosition } = completeSuggestion({
query,
suggestionQuery,
suggestion,
trailingSpace: true,
regexEscaped: false,
cursorPosition,
});
const expectedPart2 = `case:auto`
const expectedNewQuery = `${part1} ${expectedPart2} `;
expect(newQuery).toEqual(expectedNewQuery);
expect(newCursorPosition).toBe(newQuery.length);
});
test('completeSuggestion does not insert a trailing space when trailingSpace is true and the completion is not at the end of the query', () => {
const suggestionQuery = 'G';
const part1 = String.raw`lang:${suggestionQuery}`;
const part2 = String.raw`case:auto`;
const query = `${part1} ${part2}`
const suggestion = 'Go';
const cursorPosition = part1.length;
const { newQuery, newCursorPosition } = completeSuggestion({
query,
suggestionQuery,
suggestion,
trailingSpace: true,
regexEscaped: false,
cursorPosition,
});
const expectedPart1 = `lang:Go`
const expectedNewQuery = `${expectedPart1} ${part2}`; // Notice no trailing space
expect(newQuery).toEqual(expectedNewQuery);
expect(newCursorPosition).toBe(expectedPart1.length);
});
test('completeSuggestion wraps suggestions in quotes when the suggestion contains a space and regexEscaped is false', () => {
const suggestionQuery = `m`;
const query = `lang:${suggestionQuery}`;
const suggestion = `my language`;
const { newQuery, newCursorPosition } = completeSuggestion({
query,
suggestionQuery,
suggestion,
trailingSpace: false,
regexEscaped: false,
cursorPosition: query.length,
});
const expectedNewQuery = `lang:"my language"`;
expect(newQuery).toEqual(expectedNewQuery);
expect(newCursorPosition).toBe(newQuery.length);
});
test('completeSuggestion completes on query parts that are inbetween other parts', () => {
const part1 = String.raw`repo:^github\.com/sourcebot\x2ddev/sourcebot$`;
const suggestionQuery = 'Type';
const part2 = String.raw`lang:${suggestionQuery}`;
const part3 = String.raw`case:auto`;
const query = `${part1} ${part2} ${part3}`;
const suggestion = 'TypeScript';
const cursorPosition = ([part1, part2].join(" ").length);
const { newQuery, newCursorPosition } = completeSuggestion({
query,
suggestionQuery,
suggestion,
trailingSpace: false,
regexEscaped: false,
cursorPosition,
});
const expectedPart2 = "lang:TypeScript";
const expectedNewQuery = String.raw`${part1} ${expectedPart2} ${part3}`;
expect(newQuery).toEqual(expectedNewQuery);
expect(newCursorPosition).toBe([part1, expectedPart2].join(" ").length);
});
test('completeSuggestions regex escapes suggestions when regexEscaped is true', () => {
const query = "repo:github";
const { newQuery, newCursorPosition } = completeSuggestion({
query,
suggestionQuery: "github",
suggestion: "github.com/sourcebot-dev/sourcebot",
trailingSpace: true,
regexEscaped: true,
cursorPosition: query.length,
});
const expectedNewQuery = String.raw`repo:^github\.com/sourcebot\x2ddev/sourcebot$ `;
expect(newQuery).toEqual(expectedNewQuery);
expect(newCursorPosition).toBe(newQuery.length);
});