Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/chatSessions/copilotcli/vscode-node/test/getDiagnostics.spec.ts
13406 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { beforeEach, describe, expect, it, vi } from 'vitest';
7
import { TestLogService } from '../../../../../platform/testing/common/testLogService';
8
import { MockMcpServer, parseToolResult, createMockUri, createMockDiagnostic } from './testHelpers';
9
10
const { mockGetDiagnostics } = vi.hoisted(() => ({
11
mockGetDiagnostics: vi.fn(),
12
}));
13
14
vi.mock('vscode', () => {
15
const DiagnosticSeverity = {
16
Error: 0,
17
Warning: 1,
18
Information: 2,
19
Hint: 3,
20
0: 'Error',
21
1: 'Warning',
22
2: 'Information',
23
3: 'Hint',
24
};
25
26
return {
27
Uri: {
28
parse: (str: string) => ({
29
toString: () => str,
30
fsPath: str.replace('file://', ''),
31
scheme: 'file',
32
}),
33
},
34
languages: {
35
getDiagnostics: mockGetDiagnostics,
36
},
37
DiagnosticSeverity,
38
};
39
});
40
41
import { registerGetDiagnosticsTool } from '../tools/getDiagnostics';
42
43
interface DiagnosticsFileResult {
44
uri: string;
45
filePath: string;
46
diagnostics: Array<{
47
message: string;
48
severity: string;
49
source?: string;
50
code?: string | number;
51
range: {
52
start: { line: number; character: number };
53
end: { line: number; character: number };
54
};
55
}>;
56
}
57
58
describe('getDiagnostics tool', () => {
59
const logger = new TestLogService();
60
let server: MockMcpServer;
61
62
beforeEach(() => {
63
vi.clearAllMocks();
64
server = new MockMcpServer();
65
registerGetDiagnosticsTool(server as unknown as import('@modelcontextprotocol/sdk/server/mcp.js').McpServer, logger);
66
});
67
68
it('should register the get_diagnostics tool', () => {
69
expect(server.hasToolRegistered('get_diagnostics')).toBe(true);
70
});
71
72
it('should return diagnostics for a specific URI', async () => {
73
const mockDiag = createMockDiagnostic('Test error', 0, 0, 0, 0, 10, 'test-source', 'TEST001');
74
mockGetDiagnostics.mockReturnValue([mockDiag]);
75
76
const handler = server.getToolHandler('get_diagnostics')!;
77
const result = parseToolResult<DiagnosticsFileResult[]>(await handler({ uri: 'file:///test/file.ts' }));
78
79
expect(result).toHaveLength(1);
80
expect(result[0].uri).toBe('file:///test/file.ts');
81
expect(result[0].diagnostics).toHaveLength(1);
82
});
83
84
it('should return empty array when no diagnostics exist for URI', async () => {
85
mockGetDiagnostics.mockReturnValue([]);
86
87
const handler = server.getToolHandler('get_diagnostics')!;
88
const result = parseToolResult<DiagnosticsFileResult[]>(await handler({ uri: 'file:///clean/file.ts' }));
89
90
expect(result).toHaveLength(0);
91
});
92
93
it('should return all diagnostics when no URI is provided', async () => {
94
const uri1 = createMockUri('/file1.ts');
95
const uri2 = createMockUri('/file2.ts');
96
const diag1 = createMockDiagnostic('Error in file 1', 0, 0, 0, 0, 5);
97
const diag2 = createMockDiagnostic('Warning in file 2', 1, 1, 0, 1, 5);
98
mockGetDiagnostics.mockReturnValue([
99
[uri1, [diag1]],
100
[uri2, [diag2]],
101
]);
102
103
const handler = server.getToolHandler('get_diagnostics')!;
104
const result = parseToolResult<DiagnosticsFileResult[]>(await handler({}));
105
106
expect(result).toHaveLength(2);
107
});
108
109
it('should map severity levels correctly', async () => {
110
const diagnostics = [
111
createMockDiagnostic('Error', 0, 0, 0, 0, 1),
112
createMockDiagnostic('Warning', 1, 1, 0, 1, 1),
113
createMockDiagnostic('Information', 2, 2, 0, 2, 1),
114
createMockDiagnostic('Hint', 3, 3, 0, 3, 1),
115
];
116
mockGetDiagnostics.mockReturnValue(diagnostics);
117
118
const handler = server.getToolHandler('get_diagnostics')!;
119
const result = parseToolResult<DiagnosticsFileResult[]>(await handler({ uri: 'file:///test.ts' }));
120
121
const severities = result[0].diagnostics.map(d => d.severity);
122
expect(severities).toContain('error');
123
expect(severities).toContain('warning');
124
expect(severities).toContain('information');
125
expect(severities).toContain('hint');
126
});
127
128
it('should include diagnostic range, source, and code', async () => {
129
const mockDiag = createMockDiagnostic('Test error', 0, 5, 10, 5, 20, 'test-linter', 'WARN001');
130
mockGetDiagnostics.mockReturnValue([mockDiag]);
131
132
const handler = server.getToolHandler('get_diagnostics')!;
133
const result = parseToolResult<DiagnosticsFileResult[]>(await handler({ uri: 'file:///test.ts' }));
134
135
const diag = result[0].diagnostics[0];
136
expect(diag.message).toBe('Test error');
137
expect(diag.source).toBe('test-linter');
138
expect(diag.code).toBe('WARN001');
139
expect(diag.range.start.line).toBe(5);
140
expect(diag.range.start.character).toBe(10);
141
expect(diag.range.end.line).toBe(5);
142
expect(diag.range.end.character).toBe(20);
143
});
144
145
it('should filter out files with no diagnostics when returning all', async () => {
146
const uri1 = createMockUri('/has-diagnostics.ts');
147
const uri2 = createMockUri('/no-diagnostics.ts');
148
const diag = createMockDiagnostic('Has error', 0, 0, 0, 0, 1);
149
mockGetDiagnostics.mockReturnValue([
150
[uri1, [diag]],
151
[uri2, []],
152
]);
153
154
const handler = server.getToolHandler('get_diagnostics')!;
155
const result = parseToolResult<DiagnosticsFileResult[]>(await handler({}));
156
157
expect(result).toHaveLength(1);
158
expect(result[0].uri).toBe('file:///has-diagnostics.ts');
159
});
160
161
it('should handle object-style code in diagnostics', async () => {
162
const mockDiag = {
163
message: 'Object code error',
164
severity: 0,
165
range: {
166
start: { line: 0, character: 0 },
167
end: { line: 0, character: 5 },
168
},
169
source: 'ts',
170
code: { value: 2304, target: 'https://example.com' },
171
};
172
mockGetDiagnostics.mockReturnValue([mockDiag]);
173
174
const handler = server.getToolHandler('get_diagnostics')!;
175
const result = parseToolResult<DiagnosticsFileResult[]>(await handler({ uri: 'file:///test.ts' }));
176
177
expect(result[0].diagnostics[0].code).toBe(2304);
178
});
179
});
180
181