UNPKG

@alvinveroy/codecompass

Version:

AI-powered MCP server for codebase navigation and LLM prompt optimization

191 lines (190 loc) 12.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); // Import the functions to be tested directly from the module const queryRefinementHelpers = __importStar(require("../../lib/query-refinement")); const text_utils_1 = require("../../utils/text-utils"); vitest_1.vi.mock('../../utils/text-utils'); // Mock dependencies of helpers // Mock configService and logger if they are DIRECTLY used by these helpers // If they are only used by searchWithRefinement or refineQuery (dispatcher), // then this mock might not be needed here. // For now, assuming helpers might use logger for debug/info. vitest_1.vi.mock('../../lib/config-service', () => ({ configService: { // Add any config values DIRECTLY used by extractKeywords, broadenQuery, etc. // If none, this can be simpler or removed if logger isn't used by helpers. }, logger: { info: vitest_1.vi.fn(), warn: vitest_1.vi.fn(), error: vitest_1.vi.fn(), debug: vitest_1.vi.fn() }, })); (0, vitest_1.describe)('Query Refinement Helper Utilities', () => { (0, vitest_1.beforeEach)(() => { vitest_1.vi.clearAllMocks(); vitest_1.vi.mocked(text_utils_1.preprocessText).mockImplementation(text => text.trim().replace(/\s+/g, ' ')); }); (0, vitest_1.afterEach)(() => { vitest_1.vi.restoreAllMocks(); }); (0, vitest_1.describe)('extractKeywords', () => { (0, vitest_1.it)('should extract relevant keywords and filter common words', () => { const text = "This is a sample function for user authentication with a class."; // preprocessText is mocked in beforeEach to return a simplified version // For this specific test, let's ensure it does what we expect for keyword extraction vitest_1.vi.mocked(text_utils_1.preprocessText).mockReturnValueOnce(text.toLowerCase().replace(/[.,;:!?(){}[\]"']/g, " ")); const keywords = queryRefinementHelpers.extractKeywords(text); (0, vitest_1.expect)(keywords).toEqual(vitest_1.expect.arrayContaining(['sample', 'function', 'user', 'authentication', 'class'])); (0, vitest_1.expect)(keywords).not.toContain('this'); (0, vitest_1.expect)(keywords).not.toContain('for'); }); (0, vitest_1.it)('should return unique keywords', () => { const text = "test test keyword keyword"; vitest_1.vi.mocked(text_utils_1.preprocessText).mockReturnValueOnce(text.toLowerCase().replace(/[.,;:!?(){}[\]"']/g, " ")); const keywords = queryRefinementHelpers.extractKeywords(text); // Using toHaveSameMembers because Set iteration order is not guaranteed for toEqual (0, vitest_1.expect)(keywords).toEqual(vitest_1.expect.arrayContaining(['test', 'keyword'])); (0, vitest_1.expect)(keywords.length).toBe(2); // Ensure uniqueness }); (0, vitest_1.it)('should handle empty or common-word-only strings', () => { (0, vitest_1.expect)(queryRefinementHelpers.extractKeywords("the is of and")).toEqual([]); (0, vitest_1.expect)(queryRefinementHelpers.extractKeywords("")).toEqual([]); (0, vitest_1.expect)(queryRefinementHelpers.extractKeywords(" ")).toEqual([]); }); }); (0, vitest_1.describe)('broadenQuery (direct test)', () => { (0, vitest_1.it)('should remove specific terms and file extensions', () => { const query = "exact specific search for login.ts only"; const result = queryRefinementHelpers.broadenQuery(query); (0, vitest_1.expect)(result).toBeDefined(); (0, vitest_1.expect)(typeof result).toBe('string'); (0, vitest_1.expect)(result).not.toContain('exact'); (0, vitest_1.expect)(result).not.toContain('specific'); (0, vitest_1.expect)(result).not.toContain('only'); (0, vitest_1.expect)(result).not.toContain('.ts'); (0, vitest_1.expect)(result).toContain('search for login'); }); (0, vitest_1.it)('should add generic terms if query becomes too short', () => { const query = "fix.ts"; const result = queryRefinementHelpers.broadenQuery(query); (0, vitest_1.expect)(result).toBe('fix implementation code'); }); (0, vitest_1.it)('should handle empty string input', () => { const result = queryRefinementHelpers.broadenQuery(""); (0, vitest_1.expect)(result).toBe('general code context'); // Updated expectation }); }); (0, vitest_1.describe)('focusQueryBasedOnResults (direct test)', () => { (0, vitest_1.it)('should add keywords from top results to the query', () => { const originalQuery = "find user"; const results_focusQuery = [ { id: 'id1', score: 0.8, payload: { dataType: 'file_chunk', filepath: 'user.ts', file_content_chunk: "function processUser(user: UserType)", chunk_index: 0, total_chunks: 1, last_modified: '2023-01-01' } }, { id: 'id2', score: 0.7, payload: { dataType: 'file_chunk', filepath: 'profile.ts', file_content_chunk: "class UserProfile extends BaseProfile", chunk_index: 0, total_chunks: 1, last_modified: '2023-01-01' } }, ]; // preprocessText is mocked in beforeEach // extractKeywords will be called internally by focusQueryBasedOnResults const focused = queryRefinementHelpers.focusQueryBasedOnResults(originalQuery, results_focusQuery); (0, vitest_1.expect)(focused).toBeDefined(); (0, vitest_1.expect)(typeof focused).toBe('string'); // Based on the simple preprocessText mock and extractKeywords logic: // "function processuser user usertype" -> keywords: ["function", "processuser", "user", "usertype"] (approx) // "class userprofile extends baseprofile" -> keywords: ["class", "userprofile", "extends", "baseprofile"] (approx) // Top 2 might be "function", "processuser" or similar. // The exact output depends on the keyword extraction logic and order. // Let's check for inclusion of original query and some new keywords. // If extractKeywords returns them in order of appearance and unique: // "function", "processuser", "user", "usertype", "class", "userprofile", "extends", "baseprofile" // Top 2: "function processuser" (0, vitest_1.expect)(focused).toBe("find user function processuser"); }); (0, vitest_1.it)('should not change query if no content in results', () => { const originalQuery = "find user"; const results = [ { id: 'empty1', score: 0.1, payload: { dataType: 'file_chunk', filepath: 'empty.ts', file_content_chunk: "", chunk_index: 0, total_chunks: 1, last_modified: '2023-01-01' } }, { id: 'nocontent1', score: 0.1, payload: { dataType: 'commit_info', commit_oid: 'nocontent', commit_message: "", commit_author_name: 'test', commit_author_email: 'test@example.com', commit_date: '2023-01-01', changed_files_summary: [], parent_oids: [] } } // No content property ]; const focused = queryRefinementHelpers.focusQueryBasedOnResults(originalQuery, results); (0, vitest_1.expect)(focused).toBe(originalQuery); }); (0, vitest_1.it)('should handle empty results array', () => { const originalQuery = "find user"; const results = []; const focused = queryRefinementHelpers.focusQueryBasedOnResults(originalQuery, results); (0, vitest_1.expect)(focused).toBe(originalQuery); // Should return original query if no results }); }); (0, vitest_1.describe)('tweakQuery (direct test)', () => { (0, vitest_1.it)('should add file type if not present in query', () => { const query_addFileType = "search login function"; const results_addFileType = [{ id: 't1', score: 0.9, payload: { dataType: 'file_chunk', filepath: "src/auth/login.ts", file_content_chunk: "...", chunk_index: 0, total_chunks: 1, last_modified: "date" } }]; const tweaked = queryRefinementHelpers.tweakQuery(query_addFileType, results_addFileType); (0, vitest_1.expect)(tweaked).toBeDefined(); (0, vitest_1.expect)(typeof tweaked).toBe('string'); (0, vitest_1.expect)(tweaked).toBe("search login function ts"); }); (0, vitest_1.it)('should add directory if file type present but directory not', () => { const query_addDir = "search login.ts function"; const results_addDir = [{ id: 't2', score: 0.9, payload: { dataType: 'file_chunk', filepath: "src/auth/login.ts", file_content_chunk: "...", chunk_index: 0, total_chunks: 1, last_modified: "date" } }]; const tweaked = queryRefinementHelpers.tweakQuery(query_addDir, results_addDir); (0, vitest_1.expect)(tweaked).toBeDefined(); (0, vitest_1.expect)(typeof tweaked).toBe('string'); // Since 'src' is in the exclusion list, it should not be added. (0, vitest_1.expect)(tweaked).toBe("search login.ts function"); }); (0, vitest_1.it)('should not change query if context already present or no context to add', () => { const query = "search login.ts function in src"; const results = [{ id: 'id_tweak3', score: 0.8, payload: { dataType: 'file_chunk', filepath: "src/auth/login.ts", file_content_chunk: "content", chunk_index: 0, total_chunks: 1, last_modified: "date" } }]; let tweaked = queryRefinementHelpers.tweakQuery(query, results); (0, vitest_1.expect)(tweaked).toBeDefined(); (0, vitest_1.expect)(typeof tweaked).toBe('string'); (0, vitest_1.expect)(tweaked).toBe(query); const resultsNoPath_tweakQuery = [{ id: 'id3', score: 0.6, payload: { dataType: 'commit_info', commit_oid: 'abc', commit_message: "some content", commit_author_name: 'test', commit_author_email: 'test@example.com', commit_date: '2023-01-01', changed_files_summary: [], parent_oids: [] } }]; tweaked = queryRefinementHelpers.tweakQuery("some query", resultsNoPath_tweakQuery); (0, vitest_1.expect)(tweaked).toBeDefined(); (0, vitest_1.expect)(typeof tweaked).toBe('string'); (0, vitest_1.expect)(tweaked).toBe("some query"); }); (0, vitest_1.it)('should handle empty results array', () => { const query = "some query"; const results = []; const tweaked = queryRefinementHelpers.tweakQuery(query, results); (0, vitest_1.expect)(tweaked).toBe(query); }); (0, vitest_1.it)('should handle result with no filepath', () => { const query = "some query"; const results_noFilepath_tweakQuery = [{ id: 'id4', score: 0.5, payload: { dataType: 'commit_info', commit_oid: 'def', commit_message: "content without filepath", commit_author_name: 'test', commit_author_email: 'test@example.com', commit_date: '2023-01-01', changed_files_summary: [], parent_oids: [] } }]; const tweaked = queryRefinementHelpers.tweakQuery(query, results_noFilepath_tweakQuery); (0, vitest_1.expect)(tweaked).toBe(query); }); }); });