Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/context/node/resolvers/test/vscodeContext.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 { describe, expect, it } from 'vitest';
7
import { IWorkbenchService } from '../../../../../platform/workbench/common/workbenchService';
8
import { parseSettingsAndCommands } from '../vscodeContext';
9
10
// Mock implementation of IWorkbenchService for testing
11
class MockWorkbenchService implements IWorkbenchService {
12
declare readonly _serviceBrand: undefined;
13
14
constructor(
15
private mockSettings: { [key: string]: any } = {},
16
private mockCommands: { label: string; command: string; keybinding: string }[] = []
17
) { }
18
19
getAllExtensions(): readonly any[] {
20
return [];
21
}
22
23
async getAllCommands(): Promise<{ label: string; command: string; keybinding: string }[]> {
24
return this.mockCommands;
25
}
26
27
async getAllSettings(): Promise<{ [key: string]: any }> {
28
return this.mockSettings;
29
}
30
}
31
32
describe('parseSettingsAndCommands', () => {
33
it('returns empty array for non-JSON code blocks', async () => {
34
const mockService = new MockWorkbenchService();
35
const codeBlock = '```typescript\nconsole.log("hello");\n```';
36
const result = await parseSettingsAndCommands(mockService, codeBlock);
37
expect(result).toEqual([]);
38
});
39
40
it('returns empty array for invalid JSON', async () => {
41
const mockService = new MockWorkbenchService();
42
const codeBlock = '```json\n{ invalid json\n```';
43
const result = await parseSettingsAndCommands(mockService, codeBlock);
44
expect(result).toEqual([]);
45
});
46
47
it('returns empty array for empty parsed array', async () => {
48
const mockService = new MockWorkbenchService();
49
const codeBlock = '```json\n[]\n```';
50
const result = await parseSettingsAndCommands(mockService, codeBlock);
51
expect(result).toEqual([]);
52
});
53
54
it('handles trailing commas in JSON', async () => {
55
const mockService = new MockWorkbenchService({
56
'editor.fontSize': { value: 14 }
57
});
58
const codeBlock = `\`\`\`json
59
[
60
{
61
"type": "setting",
62
"details": {
63
"key": "editor.fontSize",
64
}
65
},
66
]
67
\`\`\``;
68
69
const result = await parseSettingsAndCommands(mockService, codeBlock);
70
expect(result).toHaveLength(1);
71
expect(result[0].commandToRun?.command).toBe('workbench.action.openSettings');
72
expect(result[0].commandToRun?.arguments).toEqual(['@id:editor.fontSize ']);
73
});
74
75
it('processes settings and creates openSettings command', async () => {
76
const mockService = new MockWorkbenchService({
77
'editor.fontSize': { value: 14 },
78
'workbench.colorTheme': { value: 'Dark+' }
79
});
80
const codeBlock = `\`\`\`json
81
[
82
{
83
"type": "setting",
84
"details": {
85
"key": "editor.fontSize"
86
}
87
},
88
{
89
"type": "setting",
90
"details": {
91
"key": "workbench.colorTheme"
92
}
93
}
94
]
95
\`\`\``;
96
97
const result = await parseSettingsAndCommands(mockService, codeBlock);
98
99
expect(result).toHaveLength(1);
100
expect(result[0].commandToRun?.command).toBe('workbench.action.openSettings');
101
expect(result[0].commandToRun?.arguments).toEqual(['@id:editor.fontSize @id:workbench.colorTheme ']);
102
expect(result[0].commandToRun?.title).toBe('Show in Settings Editor');
103
});
104
105
it('filters out unknown settings', async () => {
106
const mockService = new MockWorkbenchService({
107
'editor.fontSize': { value: 14 }
108
// 'unknown.setting' is intentionally not included
109
});
110
const codeBlock = `\`\`\`json
111
[
112
{
113
"type": "setting",
114
"details": {
115
"key": "editor.fontSize"
116
}
117
},
118
{
119
"type": "setting",
120
"details": {
121
"key": "unknown.setting"
122
}
123
}
124
]
125
\`\`\``;
126
127
const result = await parseSettingsAndCommands(mockService, codeBlock);
128
129
expect(result).toHaveLength(1);
130
expect(result[0].commandToRun?.arguments).toEqual(['@id:editor.fontSize ']);
131
});
132
133
it('returns empty quickOpen for unknown command', async () => {
134
const mockService = new MockWorkbenchService({}, [
135
{ label: 'Show All Commands', command: 'workbench.action.showCommands', keybinding: 'Ctrl+Shift+P' }
136
]);
137
const codeBlock = `\`\`\`json
138
[
139
{
140
"type": "command",
141
"details": {
142
"key": "unknown.command"
143
}
144
}
145
]
146
\`\`\``;
147
148
const result = await parseSettingsAndCommands(mockService, codeBlock);
149
expect(result).toHaveLength(1);
150
expect(result[0].commandToRun?.command).toBe('workbench.action.quickOpen');
151
expect(result[0].commandToRun?.arguments).toEqual(['>']);
152
expect(result[0].commandToRun?.title).toBe('Open Command Palette');
153
});
154
155
it('processes extension search command', async () => {
156
const mockService = new MockWorkbenchService();
157
const codeBlock = `\`\`\`json
158
[
159
{
160
"type": "command",
161
"details": {
162
"key": "workbench.extensions.search",
163
"value": "python"
164
}
165
}
166
]
167
\`\`\``;
168
169
const result = await parseSettingsAndCommands(mockService, codeBlock);
170
171
expect(result).toHaveLength(1);
172
expect(result[0].commandToRun?.command).toBe('workbench.extensions.search');
173
expect(result[0].commandToRun?.arguments).toEqual(['python']);
174
expect(result[0].commandToRun?.title).toBe('Search Extension Marketplace');
175
});
176
177
it('processes extension install command', async () => {
178
const mockService = new MockWorkbenchService();
179
const codeBlock = `\`\`\`json
180
[
181
{
182
"type": "command",
183
"details": {
184
"key": "workbench.extensions.installExtension",
185
"value": ["ms-python.python"]
186
}
187
}
188
]
189
\`\`\``;
190
191
const result = await parseSettingsAndCommands(mockService, codeBlock);
192
193
expect(result).toHaveLength(1);
194
expect(result[0].commandToRun?.command).toBe('workbench.extensions.search');
195
expect(result[0].commandToRun?.arguments).toEqual(['ms-python.python']);
196
expect(result[0].commandToRun?.title).toBe('Search Extension Marketplace');
197
});
198
199
it('handles extension search with known queries', async () => {
200
const mockService = new MockWorkbenchService();
201
const codeBlock = `\`\`\`json
202
[
203
{
204
"type": "command",
205
"details": {
206
"key": "workbench.extensions.search",
207
"value": "popular"
208
}
209
}
210
]
211
\`\`\``;
212
213
const result = await parseSettingsAndCommands(mockService, codeBlock);
214
215
expect(result).toHaveLength(1);
216
expect(result[0].commandToRun?.arguments).toEqual(['@popular']);
217
});
218
219
it('handles extension search with tag', async () => {
220
const mockService = new MockWorkbenchService();
221
const codeBlock = `\`\`\`json
222
[
223
{
224
"type": "command",
225
"details": {
226
"key": "workbench.extensions.search",
227
"value": "category:themes"
228
}
229
}
230
]
231
\`\`\``;
232
233
const result = await parseSettingsAndCommands(mockService, codeBlock);
234
235
expect(result).toHaveLength(1);
236
expect(result[0].commandToRun?.arguments).toEqual(['@category:themes']);
237
});
238
239
it('processes general command with quickOpen', async () => {
240
const mockService = new MockWorkbenchService({}, [
241
{ label: 'Show All Commands', command: 'workbench.action.showCommands', keybinding: 'Ctrl+Shift+P' }
242
]);
243
const codeBlock = `\`\`\`json
244
[
245
{
246
"type": "command",
247
"details": {
248
"key": "workbench.action.showCommands"
249
}
250
}
251
]
252
\`\`\``;
253
254
const result = await parseSettingsAndCommands(mockService, codeBlock);
255
256
expect(result).toHaveLength(1);
257
expect(result[0].commandToRun?.command).toBe('workbench.action.quickOpen');
258
expect(result[0].commandToRun?.arguments).toEqual(['>Show All Commands']);
259
expect(result[0].commandToRun?.title).toBe('Show in Command Palette');
260
});
261
262
it('handles code block without language specified', async () => {
263
const mockService = new MockWorkbenchService({
264
'editor.fontSize': { value: 14 }
265
});
266
const codeBlock = `\`\`\`
267
[
268
{
269
"type": "setting",
270
"details": {
271
"key": "editor.fontSize"
272
}
273
}
274
]
275
\`\`\``;
276
277
const result = await parseSettingsAndCommands(mockService, codeBlock);
278
279
expect(result).toHaveLength(1);
280
expect(result[0].commandToRun?.command).toBe('workbench.action.openSettings');
281
});
282
283
it('handles items without details property', async () => {
284
const mockService = new MockWorkbenchService({
285
'editor.fontSize': { value: 14 }
286
});
287
const codeBlock = `\`\`\`json
288
[
289
{
290
"type": "setting"
291
}
292
]
293
\`\`\``;
294
295
const result = await parseSettingsAndCommands(mockService, codeBlock);
296
297
expect(result).toHaveLength(1);
298
expect(result[0].commandToRun?.arguments).toEqual(['']);
299
});
300
301
it('handles non-string extension arguments', async () => {
302
const mockService = new MockWorkbenchService();
303
const codeBlock = `\`\`\`json
304
[
305
{
306
"type": "command",
307
"details": {
308
"key": "workbench.extensions.search",
309
"value": [123, "python", null]
310
}
311
}
312
]
313
\`\`\``;
314
315
const result = await parseSettingsAndCommands(mockService, codeBlock);
316
317
expect(result).toHaveLength(1);
318
// Should filter out non-string values
319
expect(result[0].commandToRun?.arguments).toEqual(['python']);
320
});
321
322
it('handles command with empty label', async () => {
323
const mockService = new MockWorkbenchService({}, [
324
{ label: '', command: 'test.command', keybinding: 'Ctrl+T' }
325
]);
326
const codeBlock = `\`\`\`json
327
[
328
{
329
"type": "command",
330
"details": {
331
"key": "test.command"
332
}
333
}
334
]
335
\`\`\``;
336
337
const result = await parseSettingsAndCommands(mockService, codeBlock);
338
339
expect(result).toHaveLength(1);
340
expect(result[0].commandToRun?.arguments).toEqual(['>']);
341
expect(result[0].commandToRun?.title).toBe('Show in Command Palette');
342
});
343
});
344
345