Path: blob/main/extensions/copilot/src/extension/chronicle/common/test/sessionStoreTracking.spec.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { describe, expect, it } from 'vitest';6import { extractFilePath, extractRefsFromMcpTool, extractRefsFromTerminal, extractRepoFromMcpTool, isGitHubMcpTool } from '../sessionStoreTracking';78describe('extractFilePath', () => {9it('extracts filePath from replace_string_in_file', () => {10expect(extractFilePath('replace_string_in_file', { filePath: '/src/foo.ts', oldString: 'a', newString: 'b' }))11.toBe('/src/foo.ts');12});1314it('extracts filePath from multi_replace_string_in_file replacements array', () => {15expect(extractFilePath('multi_replace_string_in_file', {16explanation: 'fix imports',17replacements: [18{ filePath: '/src/bar.ts', oldString: 'a', newString: 'b' },19{ filePath: '/src/baz.ts', oldString: 'c', newString: 'd' },20]21})).toBe('/src/bar.ts');22});2324it('extracts filePath from insert_edit_into_file', () => {25expect(extractFilePath('insert_edit_into_file', { filePath: '/src/edit.ts', code: '// new' }))26.toBe('/src/edit.ts');27});2829it('extracts filePath from create_file', () => {30expect(extractFilePath('create_file', { filePath: '/src/new.ts', content: '' }))31.toBe('/src/new.ts');32});3334it('extracts filePath from edit_notebook_file', () => {35expect(extractFilePath('edit_notebook_file', { filePath: '/nb.ipynb', editType: 'edit', cellId: 'c1' }))36.toBe('/nb.ipynb');37});3839it('extracts filePath from read_file', () => {40expect(extractFilePath('read_file', { filePath: '/src/read.ts', startLine: 1, endLine: 10 }))41.toBe('/src/read.ts');42});4344it('extracts path from list_dir', () => {45expect(extractFilePath('list_dir', { path: '/src' }))46.toBe('/src');47});4849it('extracts dirPath from create_directory', () => {50expect(extractFilePath('create_directory', { dirPath: '/src/new-dir' }))51.toBe('/src/new-dir');52});5354it('extracts file path from apply_patch input text', () => {55const input = '*** Begin Patch\n*** Update File: /src/hello.ts\n@@class Foo\n- bar\n+ baz\n*** End Patch';56expect(extractFilePath('apply_patch', { input }))57.toBe('/src/hello.ts');58});5960it('extracts file path from apply_patch Add File', () => {61const input = '*** Begin Patch\n*** Add File: /src/new.ts\n+export const x = 1;\n*** End Patch';62expect(extractFilePath('apply_patch', { input }))63.toBe('/src/new.ts');64});6566it('extracts file path from apply_patch Delete File', () => {67const input = '*** Begin Patch\n*** Delete File: /src/old.ts\n*** End Patch';68expect(extractFilePath('apply_patch', { input }))69.toBe('/src/old.ts');70});7172it('falls back to filePath arg for apply_patch when present', () => {73expect(extractFilePath('apply_patch', { filePath: '/from/arg.ts', input: '*** Update File: /from/input.ts' }))74.toBe('/from/arg.ts');75});7677it('extracts path from CLI str_replace_editor (backward compat)', () => {78expect(extractFilePath('str_replace_editor', { path: '/cli/file.py' }))79.toBe('/cli/file.py');80});8182it('extracts path from CLI create tool (backward compat)', () => {83expect(extractFilePath('create', { path: '/cli/new.py' }))84.toBe('/cli/new.py');85});8687it('returns undefined for unknown tools', () => {88expect(extractFilePath('run_in_terminal', { command: 'ls' }))89.toBeUndefined();90expect(extractFilePath('file_search', { query: '**/*.ts' }))91.toBeUndefined();92});9394it('returns undefined for null args', () => {95expect(extractFilePath('create_file', null))96.toBeUndefined();97});9899it('returns undefined when filePath is not a string', () => {100expect(extractFilePath('create_file', { filePath: 42 }))101.toBeUndefined();102});103});104105describe('isGitHubMcpTool', () => {106it('matches mcp_github_ prefix (VS Code)', () => {107expect(isGitHubMcpTool('mcp_github_issue_write')).toBe(true);108expect(isGitHubMcpTool('mcp_github_create_pull_request')).toBe(true);109expect(isGitHubMcpTool('mcp_github_search_issues')).toBe(true);110});111112it('matches github-mcp-server- prefix (CLI)', () => {113expect(isGitHubMcpTool('github-mcp-server-create_issue')).toBe(true);114});115116it('rejects non-GitHub MCP tools', () => {117expect(isGitHubMcpTool('read_file')).toBe(false);118expect(isGitHubMcpTool('mcp_perplexity_ask')).toBe(false);119expect(isGitHubMcpTool('run_in_terminal')).toBe(false);120});121});122123describe('extractRefsFromMcpTool', () => {124it('extracts PR ref from mcp_github_pull_request_read', () => {125const refs = extractRefsFromMcpTool('mcp_github_pull_request_read', { pullNumber: 42, owner: 'ms', repo: 'vscode' });126expect(refs).toEqual([{ ref_type: 'pr', ref_value: '42' }]);127});128129it('extracts issue ref from mcp_github_issue_write', () => {130const refs = extractRefsFromMcpTool('mcp_github_issue_write', { issue_number: 123, owner: 'ms', repo: 'vscode' });131expect(refs).toEqual([{ ref_type: 'issue', ref_value: '123' }]);132});133134it('extracts commit ref from mcp_github_get_commit', () => {135const refs = extractRefsFromMcpTool('mcp_github_get_commit', { sha: 'abc123', owner: 'ms', repo: 'vscode' });136expect(refs).toEqual([{ ref_type: 'commit', ref_value: 'abc123' }]);137});138139it('returns empty for non-matching tool name', () => {140expect(extractRefsFromMcpTool('mcp_github_search_code', { query: 'foo' })).toEqual([]);141});142});143144describe('extractRepoFromMcpTool', () => {145it('extracts owner/repo', () => {146expect(extractRepoFromMcpTool({ owner: 'microsoft', repo: 'vscode' }))147.toBe('microsoft/vscode');148});149150it('returns undefined when missing', () => {151expect(extractRepoFromMcpTool({ owner: 'microsoft' })).toBeUndefined();152expect(extractRepoFromMcpTool({})).toBeUndefined();153});154});155156describe('extractRefsFromTerminal', () => {157it('extracts PR ref from gh pr create output', () => {158const refs = extractRefsFromTerminal(159{ command: 'gh pr create --title "fix"' },160'https://github.com/microsoft/vscode/pull/999',161);162expect(refs).toEqual([{ ref_type: 'pr', ref_value: '999' }]);163});164165it('extracts issue ref from gh issue create output', () => {166const refs = extractRefsFromTerminal(167{ command: 'gh issue create --title "bug"' },168'https://github.com/microsoft/vscode/issues/456',169);170expect(refs).toEqual([{ ref_type: 'issue', ref_value: '456' }]);171});172173it('extracts commit SHA from git commit output', () => {174const refs = extractRefsFromTerminal(175{ command: 'git commit -m "fix"' },176'[main abc1234] fix\n 1 file changed',177);178expect(refs).toEqual([{ ref_type: 'commit', ref_value: 'abc1234' }]);179});180181it('returns empty for unrelated commands', () => {182expect(extractRefsFromTerminal({ command: 'ls -la' }, 'output')).toEqual([]);183});184});185186187