Path: blob/main/extensions/copilot/src/extension/chatSessions/claude/common/test/ideMcpServer.spec.ts
13406 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 { beforeEach, describe, expect, it } from 'vitest';6import { TestLanguageDiagnosticsService } from '../../../../../platform/languages/common/testLanguageDiagnosticsService';7import { URI } from '../../../../../util/vs/base/common/uri';8import { DiagnosticSeverity, Range } from '../../../../../vscodeTypes';9import { getDiagnosticsHandler } from '../mcpServers/ideMcpServer';1011describe('getDiagnosticsHandler', () => {12let diagnosticsService: TestLanguageDiagnosticsService;1314const fileA = URI.file('/workspace/src/fileA.ts');15const fileB = URI.file('/workspace/src/fileB.ts');16const fileC = URI.file('/workspace/src/fileC.ts');1718beforeEach(() => {19diagnosticsService = new TestLanguageDiagnosticsService();20});2122it('returns all diagnostics when no uri is provided', () => {23diagnosticsService.setDiagnostics(fileA, [24{ message: 'error in A', range: new Range(0, 0, 0, 5), severity: DiagnosticSeverity.Error },25]);26diagnosticsService.setDiagnostics(fileB, [27{ message: 'warning in B', range: new Range(1, 0, 1, 10), severity: DiagnosticSeverity.Warning },28]);2930const result = getDiagnosticsHandler(diagnosticsService, {});3132expect(result).toHaveLength(2);33expect(result[0].diagnostics[0].message).toBe('error in A');34expect(result[1].diagnostics[0].message).toBe('warning in B');35});3637it('scopes to a single file when uri is provided', () => {38diagnosticsService.setDiagnostics(fileA, [39{ message: 'error in A', range: new Range(0, 0, 0, 5), severity: DiagnosticSeverity.Error },40]);41diagnosticsService.setDiagnostics(fileB, [42{ message: 'warning in B', range: new Range(1, 0, 1, 10), severity: DiagnosticSeverity.Warning },43]);4445const result = getDiagnosticsHandler(diagnosticsService, { uri: fileA.toString() });4647expect(result).toHaveLength(1);48expect(result[0].uri).toBe(fileA.toString());49expect(result[0].diagnostics[0].message).toBe('error in A');50});5152it('returns empty array when no diagnostics exist', () => {53const result = getDiagnosticsHandler(diagnosticsService, {});54expect(result).toHaveLength(0);55});5657it('filters out files with zero diagnostics', () => {58diagnosticsService.setDiagnostics(fileA, []);59diagnosticsService.setDiagnostics(fileB, [60{ message: 'warning', range: new Range(0, 0, 0, 1), severity: DiagnosticSeverity.Warning },61]);6263const result = getDiagnosticsHandler(diagnosticsService, {});6465expect(result).toHaveLength(1);66expect(result[0].uri).toBe(fileB.toString());67});6869it('returns empty array for a file with no diagnostics when scoped by uri', () => {70diagnosticsService.setDiagnostics(fileC, []);7172const result = getDiagnosticsHandler(diagnosticsService, { uri: fileC.toString() });7374expect(result).toHaveLength(0);75});7677it('maps all severity levels correctly', () => {78diagnosticsService.setDiagnostics(fileA, [79{ message: 'err', range: new Range(0, 0, 0, 1), severity: DiagnosticSeverity.Error },80{ message: 'warn', range: new Range(1, 0, 1, 1), severity: DiagnosticSeverity.Warning },81{ message: 'info', range: new Range(2, 0, 2, 1), severity: DiagnosticSeverity.Information },82{ message: 'hint', range: new Range(3, 0, 3, 1), severity: DiagnosticSeverity.Hint },83]);8485const result = getDiagnosticsHandler(diagnosticsService, { uri: fileA.toString() });8687expect(result).toHaveLength(1);88const severities = result[0].diagnostics.map(d => d.severity);89expect(severities).toEqual(['error', 'warning', 'information', 'hint']);90});9192it('includes range, source, and code in output', () => {93diagnosticsService.setDiagnostics(fileA, [94{95message: 'unused variable',96range: new Range(5, 8, 5, 12),97severity: DiagnosticSeverity.Warning,98source: 'typescript',99code: 6133,100},101]);102103const result = getDiagnosticsHandler(diagnosticsService, { uri: fileA.toString() });104105const diag = result[0].diagnostics[0];106expect(diag.range).toEqual({107start: { line: 5, character: 8 },108end: { line: 5, character: 12 },109});110expect(diag.source).toBe('typescript');111expect(diag.code).toBe(6133);112});113114it('extracts code value from object-style codes', () => {115diagnosticsService.setDiagnostics(fileA, [116{117message: 'some lint error',118range: new Range(0, 0, 0, 1),119severity: DiagnosticSeverity.Error,120code: { value: 'no-unused-vars', target: URI.parse('https://eslint.org/rules/no-unused-vars') },121},122]);123124const result = getDiagnosticsHandler(diagnosticsService, { uri: fileA.toString() });125126expect(result[0].diagnostics[0].code).toBe('no-unused-vars');127});128129it('includes filePath in output', () => {130diagnosticsService.setDiagnostics(fileA, [131{ message: 'err', range: new Range(0, 0, 0, 1), severity: DiagnosticSeverity.Error },132]);133134const result = getDiagnosticsHandler(diagnosticsService, { uri: fileA.toString() });135136expect(result[0].filePath).toBe(fileA.fsPath);137});138139it('handles multiple diagnostics in a single file', () => {140diagnosticsService.setDiagnostics(fileA, [141{ message: 'first', range: new Range(0, 0, 0, 1), severity: DiagnosticSeverity.Error },142{ message: 'second', range: new Range(1, 0, 1, 1), severity: DiagnosticSeverity.Warning },143{ message: 'third', range: new Range(2, 0, 2, 1), severity: DiagnosticSeverity.Hint },144]);145146const result = getDiagnosticsHandler(diagnosticsService, { uri: fileA.toString() });147148expect(result).toHaveLength(1);149expect(result[0].diagnostics).toHaveLength(3);150expect(result[0].diagnostics.map(d => d.message)).toEqual(['first', 'second', 'third']);151});152153it('treats empty string uri as no filter', () => {154diagnosticsService.setDiagnostics(fileA, [155{ message: 'err', range: new Range(0, 0, 0, 1), severity: DiagnosticSeverity.Error },156]);157158const result = getDiagnosticsHandler(diagnosticsService, { uri: '' });159160expect(result).toHaveLength(1);161expect(result[0].diagnostics[0].message).toBe('err');162});163164it('accepts a non-file scheme URI', () => {165const result = getDiagnosticsHandler(diagnosticsService, { uri: 'untitled:Untitled-1' });166expect(result).toHaveLength(0);167});168169it('accepts an absolute unix path', () => {170const result = getDiagnosticsHandler(diagnosticsService, { uri: '/workspace/src/fileA.ts' });171expect(result).toHaveLength(0);172});173174it('accepts a file:// URI', () => {175const result = getDiagnosticsHandler(diagnosticsService, { uri: 'file:///workspace/src/fileA.ts' });176expect(result).toHaveLength(0);177});178});179180181