@theia/api-tests 1.34.2 → 1.34.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +641 -641
- package/package.json +3 -3
- package/src/api-tests.d.ts +21 -21
- package/src/browser-utils.spec.js +53 -53
- package/src/contribution-filter.spec.js +36 -36
- package/src/file-search.spec.js +132 -132
- package/src/find-replace.spec.js +129 -129
- package/src/keybindings.spec.js +117 -117
- package/src/launch-preferences.spec.js +697 -697
- package/src/menus.spec.js +176 -176
- package/src/monaco-api.spec.js +188 -188
- package/src/navigator.spec.js +92 -92
- package/src/preferences.spec.js +207 -207
- package/src/saveable.spec.js +503 -503
- package/src/scm.spec.js +173 -173
- package/src/shell.spec.js +41 -41
- package/src/task-configurations.spec.js +112 -112
- package/src/typescript.spec.js +779 -779
- package/src/undo-redo-selectAll.spec.js +193 -193
- package/src/views.spec.js +76 -76
|
@@ -1,697 +1,697 @@
|
|
|
1
|
-
// *****************************************************************************
|
|
2
|
-
// Copyright (C) 2019 TypeFox and others.
|
|
3
|
-
//
|
|
4
|
-
// This program and the accompanying materials are made available under the
|
|
5
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
-
//
|
|
8
|
-
// This Source Code may also be made available under the following Secondary
|
|
9
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
-
// with the GNU Classpath Exception which is available at
|
|
12
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
-
//
|
|
14
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
-
// *****************************************************************************
|
|
16
|
-
|
|
17
|
-
// @ts-check
|
|
18
|
-
/* @typescript-eslint/no-explicit-any */
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @typedef {'.vscode' | '.theia' | ['.theia', '.vscode']} ConfigMode
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Expectations should be tested and aligned against VS Code.
|
|
26
|
-
* See https://github.com/akosyakov/vscode-launch/blob/master/src/test/extension.test.ts
|
|
27
|
-
*/
|
|
28
|
-
describe('Launch Preferences', function () {
|
|
29
|
-
this.timeout(10_000);
|
|
30
|
-
|
|
31
|
-
const { assert } = chai;
|
|
32
|
-
|
|
33
|
-
const { PreferenceProvider } = require('@theia/core/lib/browser');
|
|
34
|
-
const { PreferenceService, PreferenceScope } = require('@theia/core/lib/browser/preferences/preference-service');
|
|
35
|
-
const { WorkspaceService } = require('@theia/workspace/lib/browser/workspace-service');
|
|
36
|
-
const { FileService } = require('@theia/filesystem/lib/browser/file-service');
|
|
37
|
-
const { FileResourceResolver } = require('@theia/filesystem/lib/browser/file-resource');
|
|
38
|
-
const { AbstractResourcePreferenceProvider } = require('@theia/preferences/lib/browser/abstract-resource-preference-provider');
|
|
39
|
-
const { waitForEvent } = require('@theia/core/lib/common/promise-util');
|
|
40
|
-
|
|
41
|
-
const container = window.theia.container;
|
|
42
|
-
/** @type {import('@theia/core/lib/browser/preferences/preference-service').PreferenceService} */
|
|
43
|
-
const preferences = container.get(PreferenceService);
|
|
44
|
-
/** @type {import('@theia/preferences/lib/browser/user-configs-preference-provider').UserConfigsPreferenceProvider} */
|
|
45
|
-
const userPreferences = container.getNamed(PreferenceProvider, PreferenceScope.User);
|
|
46
|
-
/** @type {import('@theia/preferences/lib/browser/workspace-preference-provider').WorkspacePreferenceProvider} */
|
|
47
|
-
const workspacePreferences = container.getNamed(PreferenceProvider, PreferenceScope.Workspace);
|
|
48
|
-
/** @type {import('@theia/preferences/lib/browser/folders-preferences-provider').FoldersPreferencesProvider} */
|
|
49
|
-
const folderPreferences = container.getNamed(PreferenceProvider, PreferenceScope.Folder);
|
|
50
|
-
const workspaceService = container.get(WorkspaceService);
|
|
51
|
-
const fileService = container.get(FileService);
|
|
52
|
-
const fileResourceResolver = container.get(FileResourceResolver);
|
|
53
|
-
|
|
54
|
-
const defaultLaunch = {
|
|
55
|
-
'configurations': [],
|
|
56
|
-
'compounds': []
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const validConfiguration = {
|
|
60
|
-
'name': 'Launch Program',
|
|
61
|
-
'program': '${file}',
|
|
62
|
-
'request': 'launch',
|
|
63
|
-
'type': 'node',
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const validConfiguration2 = {
|
|
67
|
-
'name': 'Launch Program 2',
|
|
68
|
-
'program': '${file}',
|
|
69
|
-
'request': 'launch',
|
|
70
|
-
'type': 'node',
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const bogusConfiguration = {};
|
|
74
|
-
|
|
75
|
-
const validCompound = {
|
|
76
|
-
'name': 'Compound',
|
|
77
|
-
'configurations': [
|
|
78
|
-
'Launch Program',
|
|
79
|
-
'Launch Program 2'
|
|
80
|
-
]
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const bogusCompound = {};
|
|
84
|
-
|
|
85
|
-
const bogusCompound2 = {
|
|
86
|
-
'name': 'Compound 2',
|
|
87
|
-
'configurations': [
|
|
88
|
-
'Foo',
|
|
89
|
-
'Launch Program 2'
|
|
90
|
-
]
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const validLaunch = {
|
|
94
|
-
configurations: [validConfiguration, validConfiguration2],
|
|
95
|
-
compounds: [validCompound]
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
testSuite({
|
|
99
|
-
name: 'No Preferences',
|
|
100
|
-
expectation: defaultLaunch
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
testLaunchAndSettingsSuite({
|
|
104
|
-
name: 'Empty With Version',
|
|
105
|
-
launch: {
|
|
106
|
-
'version': '0.2.0'
|
|
107
|
-
},
|
|
108
|
-
expectation: {
|
|
109
|
-
'version': '0.2.0',
|
|
110
|
-
'configurations': [],
|
|
111
|
-
'compounds': []
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
testLaunchAndSettingsSuite({
|
|
116
|
-
name: 'Empty With Version And Configurations',
|
|
117
|
-
launch: {
|
|
118
|
-
'version': '0.2.0',
|
|
119
|
-
'configurations': [],
|
|
120
|
-
},
|
|
121
|
-
expectation: {
|
|
122
|
-
'version': '0.2.0',
|
|
123
|
-
'configurations': [],
|
|
124
|
-
'compounds': []
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
testLaunchAndSettingsSuite({
|
|
129
|
-
name: 'Empty With Version And Compounds',
|
|
130
|
-
launch: {
|
|
131
|
-
'version': '0.2.0',
|
|
132
|
-
'compounds': []
|
|
133
|
-
},
|
|
134
|
-
expectation: {
|
|
135
|
-
'version': '0.2.0',
|
|
136
|
-
'configurations': [],
|
|
137
|
-
'compounds': []
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
testLaunchAndSettingsSuite({
|
|
142
|
-
name: 'Valid Conf',
|
|
143
|
-
launch: {
|
|
144
|
-
'version': '0.2.0',
|
|
145
|
-
'configurations': [validConfiguration]
|
|
146
|
-
},
|
|
147
|
-
expectation: {
|
|
148
|
-
'version': '0.2.0',
|
|
149
|
-
'configurations': [validConfiguration],
|
|
150
|
-
'compounds': []
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
testLaunchAndSettingsSuite({
|
|
155
|
-
name: 'Bogus Conf',
|
|
156
|
-
launch: {
|
|
157
|
-
'version': '0.2.0',
|
|
158
|
-
'configurations': [validConfiguration, bogusConfiguration]
|
|
159
|
-
},
|
|
160
|
-
expectation: {
|
|
161
|
-
'version': '0.2.0',
|
|
162
|
-
'configurations': [validConfiguration, bogusConfiguration],
|
|
163
|
-
'compounds': []
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
testLaunchAndSettingsSuite({
|
|
168
|
-
name: 'Completely Bogus Conf',
|
|
169
|
-
launch: {
|
|
170
|
-
'version': '0.2.0',
|
|
171
|
-
'configurations': { 'valid': validConfiguration, 'bogus': bogusConfiguration }
|
|
172
|
-
},
|
|
173
|
-
expectation: {
|
|
174
|
-
'version': '0.2.0',
|
|
175
|
-
'configurations': { 'valid': validConfiguration, 'bogus': bogusConfiguration },
|
|
176
|
-
'compounds': []
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const arrayBogusLaunch = [
|
|
181
|
-
'version', '0.2.0',
|
|
182
|
-
'configurations', { 'valid': validConfiguration, 'bogus': bogusConfiguration }
|
|
183
|
-
];
|
|
184
|
-
testSuite({
|
|
185
|
-
name: 'Array Bogus Launch Configuration',
|
|
186
|
-
launch: arrayBogusLaunch,
|
|
187
|
-
expectation: {
|
|
188
|
-
'0': 'version',
|
|
189
|
-
'1': '0.2.0',
|
|
190
|
-
'2': 'configurations',
|
|
191
|
-
'3': { 'valid': validConfiguration, 'bogus': bogusConfiguration },
|
|
192
|
-
'compounds': [],
|
|
193
|
-
'configurations': []
|
|
194
|
-
},
|
|
195
|
-
inspectExpectation: {
|
|
196
|
-
preferenceName: 'launch',
|
|
197
|
-
defaultValue: defaultLaunch,
|
|
198
|
-
workspaceValue: {
|
|
199
|
-
'0': 'version',
|
|
200
|
-
'1': '0.2.0',
|
|
201
|
-
'2': 'configurations',
|
|
202
|
-
'3': { 'valid': validConfiguration, 'bogus': bogusConfiguration }
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
testSuite({
|
|
207
|
-
name: 'Array Bogus Settings Configuration',
|
|
208
|
-
settings: {
|
|
209
|
-
launch: arrayBogusLaunch
|
|
210
|
-
},
|
|
211
|
-
expectation: {
|
|
212
|
-
'0': 'version',
|
|
213
|
-
'1': '0.2.0',
|
|
214
|
-
'2': 'configurations',
|
|
215
|
-
'3': { 'valid': validConfiguration, 'bogus': bogusConfiguration },
|
|
216
|
-
'compounds': [],
|
|
217
|
-
'configurations': []
|
|
218
|
-
},
|
|
219
|
-
inspectExpectation: {
|
|
220
|
-
preferenceName: 'launch',
|
|
221
|
-
defaultValue: defaultLaunch,
|
|
222
|
-
workspaceValue: arrayBogusLaunch
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
testSuite({
|
|
227
|
-
name: 'Null Bogus Launch Configuration',
|
|
228
|
-
// eslint-disable-next-line no-null/no-null
|
|
229
|
-
launch: null,
|
|
230
|
-
expectation: {
|
|
231
|
-
'compounds': [],
|
|
232
|
-
'configurations': []
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
testSuite({
|
|
236
|
-
name: 'Null Bogus Settings Configuration',
|
|
237
|
-
settings: {
|
|
238
|
-
// eslint-disable-next-line no-null/no-null
|
|
239
|
-
'launch': null
|
|
240
|
-
},
|
|
241
|
-
expectation: {}
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
testLaunchAndSettingsSuite({
|
|
245
|
-
name: 'Valid Compound',
|
|
246
|
-
launch: {
|
|
247
|
-
'version': '0.2.0',
|
|
248
|
-
'configurations': [validConfiguration, validConfiguration2],
|
|
249
|
-
'compounds': [validCompound]
|
|
250
|
-
},
|
|
251
|
-
expectation: {
|
|
252
|
-
'version': '0.2.0',
|
|
253
|
-
'configurations': [validConfiguration, validConfiguration2],
|
|
254
|
-
'compounds': [validCompound]
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
testLaunchAndSettingsSuite({
|
|
259
|
-
name: 'Valid And Bogus',
|
|
260
|
-
launch: {
|
|
261
|
-
'version': '0.2.0',
|
|
262
|
-
'configurations': [validConfiguration, validConfiguration2, bogusConfiguration],
|
|
263
|
-
'compounds': [validCompound, bogusCompound, bogusCompound2]
|
|
264
|
-
},
|
|
265
|
-
expectation: {
|
|
266
|
-
'version': '0.2.0',
|
|
267
|
-
'configurations': [validConfiguration, validConfiguration2, bogusConfiguration],
|
|
268
|
-
'compounds': [validCompound, bogusCompound, bogusCompound2]
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
testSuite({
|
|
273
|
-
name: 'Mixed',
|
|
274
|
-
launch: {
|
|
275
|
-
'version': '0.2.0',
|
|
276
|
-
'configurations': [validConfiguration, bogusConfiguration],
|
|
277
|
-
'compounds': [bogusCompound, bogusCompound2]
|
|
278
|
-
},
|
|
279
|
-
settings: {
|
|
280
|
-
launch: {
|
|
281
|
-
'version': '0.2.0',
|
|
282
|
-
'configurations': [validConfiguration2],
|
|
283
|
-
'compounds': [validCompound]
|
|
284
|
-
}
|
|
285
|
-
},
|
|
286
|
-
expectation: {
|
|
287
|
-
'version': '0.2.0',
|
|
288
|
-
'configurations': [validConfiguration, bogusConfiguration],
|
|
289
|
-
'compounds': [bogusCompound, bogusCompound2]
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
testSuite({
|
|
294
|
-
name: 'Mixed Launch Without Configurations',
|
|
295
|
-
launch: {
|
|
296
|
-
'version': '0.2.0',
|
|
297
|
-
'compounds': [bogusCompound, bogusCompound2]
|
|
298
|
-
},
|
|
299
|
-
settings: {
|
|
300
|
-
launch: {
|
|
301
|
-
'version': '0.2.0',
|
|
302
|
-
'configurations': [validConfiguration2],
|
|
303
|
-
'compounds': [validCompound]
|
|
304
|
-
}
|
|
305
|
-
},
|
|
306
|
-
expectation: {
|
|
307
|
-
'version': '0.2.0',
|
|
308
|
-
'configurations': [validConfiguration2],
|
|
309
|
-
'compounds': [bogusCompound, bogusCompound2]
|
|
310
|
-
},
|
|
311
|
-
inspectExpectation: {
|
|
312
|
-
preferenceName: 'launch',
|
|
313
|
-
defaultValue: defaultLaunch,
|
|
314
|
-
workspaceValue: {
|
|
315
|
-
'version': '0.2.0',
|
|
316
|
-
'configurations': [validConfiguration2],
|
|
317
|
-
'compounds': [bogusCompound, bogusCompound2]
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* @typedef {Object} LaunchAndSettingsSuiteOptions
|
|
324
|
-
* @property {string} name
|
|
325
|
-
* @property {any} expectation
|
|
326
|
-
* @property {any} [launch]
|
|
327
|
-
* @property {boolean} [only]
|
|
328
|
-
* @property {ConfigMode} [configMode]
|
|
329
|
-
*/
|
|
330
|
-
/**
|
|
331
|
-
* @type {(options: LaunchAndSettingsSuiteOptions) => void}
|
|
332
|
-
*/
|
|
333
|
-
function testLaunchAndSettingsSuite({
|
|
334
|
-
name, expectation, launch, only, configMode
|
|
335
|
-
}) {
|
|
336
|
-
testSuite({
|
|
337
|
-
name: name + ' Launch Configuration',
|
|
338
|
-
launch,
|
|
339
|
-
expectation,
|
|
340
|
-
only,
|
|
341
|
-
configMode
|
|
342
|
-
});
|
|
343
|
-
testSuite({
|
|
344
|
-
name: name + ' Settings Configuration',
|
|
345
|
-
settings: {
|
|
346
|
-
'launch': launch
|
|
347
|
-
},
|
|
348
|
-
expectation,
|
|
349
|
-
only,
|
|
350
|
-
configMode
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* @typedef {Partial<import('@theia/core/src/browser/preferences/preference-service').PreferenceInspection<any>>} PreferenceInspection
|
|
356
|
-
*/
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* @typedef {Object} SuiteOptions
|
|
360
|
-
* @property {string} name
|
|
361
|
-
* @property {any} expectation
|
|
362
|
-
* @property {PreferenceInspection} [inspectExpectation]
|
|
363
|
-
* @property {any} [launch]
|
|
364
|
-
* @property {any} [settings]
|
|
365
|
-
* @property {boolean} [only]
|
|
366
|
-
* @property {ConfigMode} [configMode]
|
|
367
|
-
*/
|
|
368
|
-
/**
|
|
369
|
-
* @type {(options: SuiteOptions) => void}
|
|
370
|
-
*/
|
|
371
|
-
function testSuite(options) {
|
|
372
|
-
describe(options.name, () => {
|
|
373
|
-
|
|
374
|
-
if (options.configMode) {
|
|
375
|
-
testConfigSuite(options);
|
|
376
|
-
} else {
|
|
377
|
-
|
|
378
|
-
testConfigSuite({
|
|
379
|
-
...options,
|
|
380
|
-
configMode: '.theia'
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
if (options.settings || options.launch) {
|
|
384
|
-
testConfigSuite({
|
|
385
|
-
...options,
|
|
386
|
-
configMode: '.vscode'
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
testConfigSuite({
|
|
390
|
-
...options,
|
|
391
|
-
configMode: ['.theia', '.vscode']
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const rootUri = workspaceService.tryGetRoots()[0].resource;
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* @param uri the URI of the file to modify
|
|
404
|
-
* @returns {AbstractResourcePreferenceProvider | undefined} The preference provider matching the provided URI.
|
|
405
|
-
*/
|
|
406
|
-
function findProvider(uri) {
|
|
407
|
-
/**
|
|
408
|
-
* @param {PreferenceProvider} provider
|
|
409
|
-
* @returns {boolean} whether the provider matches the desired URI.
|
|
410
|
-
*/
|
|
411
|
-
const isMatch = (provider) => {
|
|
412
|
-
const configUri = provider.getConfigUri();
|
|
413
|
-
return configUri && uri.isEqual(configUri);
|
|
414
|
-
};
|
|
415
|
-
for (const provider of userPreferences['providers'].values()) {
|
|
416
|
-
if (isMatch(provider) && provider instanceof AbstractResourcePreferenceProvider) {
|
|
417
|
-
return provider;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
for (const provider of folderPreferences['providers'].values()) {
|
|
421
|
-
if (isMatch(provider) && provider instanceof AbstractResourcePreferenceProvider) {
|
|
422
|
-
return provider;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
/** @type {PreferenceProvider} */
|
|
426
|
-
const workspaceDelegate = workspacePreferences['delegate'];
|
|
427
|
-
if (workspaceDelegate !== folderPreferences) {
|
|
428
|
-
if (isMatch(workspaceDelegate) && workspaceDelegate instanceof AbstractResourcePreferenceProvider) {
|
|
429
|
-
return workspaceDelegate;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function deleteWorkspacePreferences() {
|
|
435
|
-
const promises = [];
|
|
436
|
-
for (const configPath of ['.theia', '.vscode']) {
|
|
437
|
-
for (const name of ['settings', 'launch']) {
|
|
438
|
-
promises.push((async () => {
|
|
439
|
-
const uri = rootUri.resolve(configPath + '/' + name + '.json');
|
|
440
|
-
const provider = findProvider(uri);
|
|
441
|
-
try {
|
|
442
|
-
if (provider) {
|
|
443
|
-
if (provider.valid) {
|
|
444
|
-
await waitForEvent(provider.onDidChangeValidity, 5000);
|
|
445
|
-
}
|
|
446
|
-
await provider['readPreferencesFromFile']();
|
|
447
|
-
await provider['fireDidPreferencesChanged']();
|
|
448
|
-
} else {
|
|
449
|
-
console.log('Unable to find provider for', uri.path.toString());
|
|
450
|
-
}
|
|
451
|
-
} catch (e) {
|
|
452
|
-
console.error(e);
|
|
453
|
-
}
|
|
454
|
-
})());
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
return Promise.all([
|
|
458
|
-
...promises,
|
|
459
|
-
fileService.delete(rootUri.resolve('.theia'), { fromUserGesture: false, recursive: true }).catch(() => { }),
|
|
460
|
-
fileService.delete(rootUri.resolve('.vscode'), { fromUserGesture: false, recursive: true }).catch(() => { })
|
|
461
|
-
]);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
const originalShouldOverwrite = fileResourceResolver['shouldOverwrite'];
|
|
465
|
-
|
|
466
|
-
before(async () => {
|
|
467
|
-
// fail tests if out of async happens
|
|
468
|
-
fileResourceResolver['shouldOverwrite'] = async () => (assert.fail('should be in sync'), false);
|
|
469
|
-
await deleteWorkspacePreferences();
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
after(() => {
|
|
473
|
-
fileResourceResolver['shouldOverwrite'] = originalShouldOverwrite;
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* @typedef {Object} ConfigSuiteOptions
|
|
478
|
-
* @property {any} expectation
|
|
479
|
-
* @property {any} [inspectExpectation]
|
|
480
|
-
* @property {any} [launch]
|
|
481
|
-
* @property {any} [settings]
|
|
482
|
-
* @property {boolean} [only]
|
|
483
|
-
* @property {ConfigMode} [configMode]
|
|
484
|
-
*/
|
|
485
|
-
/**
|
|
486
|
-
* @type {(options: ConfigSuiteOptions) => void}
|
|
487
|
-
*/
|
|
488
|
-
function testConfigSuite({
|
|
489
|
-
configMode, expectation, inspectExpectation, settings, launch, only
|
|
490
|
-
}) {
|
|
491
|
-
|
|
492
|
-
describe(JSON.stringify(configMode, undefined, 2), () => {
|
|
493
|
-
const configPaths = Array.isArray(configMode) ? configMode : [configMode];
|
|
494
|
-
|
|
495
|
-
/** @typedef {import('@theia/monaco-editor-core/esm/vs/base/common/lifecycle').IReference<import('@theia/monaco/lib/browser/monaco-editor-model').MonacoEditorModel>} ConfigModelReference */
|
|
496
|
-
/** @type {ConfigModelReference[]} */
|
|
497
|
-
beforeEach(async () => {
|
|
498
|
-
/** @type {Promise<void>[]} */
|
|
499
|
-
const promises = [];
|
|
500
|
-
/**
|
|
501
|
-
* @param {string} name
|
|
502
|
-
* @param {Record<string, unknown>} value
|
|
503
|
-
*/
|
|
504
|
-
const ensureConfigModel = (name, value) => {
|
|
505
|
-
for (const configPath of configPaths) {
|
|
506
|
-
promises.push((async () => {
|
|
507
|
-
try {
|
|
508
|
-
const uri = rootUri.resolve(configPath + '/' + name + '.json');
|
|
509
|
-
const provider = findProvider(uri);
|
|
510
|
-
if (provider) {
|
|
511
|
-
await provider['doSetPreference']('', [], value);
|
|
512
|
-
} else {
|
|
513
|
-
console.log('Unable to find provider for', uri.path.toString());
|
|
514
|
-
}
|
|
515
|
-
} catch (e) {
|
|
516
|
-
console.error(e);
|
|
517
|
-
}
|
|
518
|
-
})());
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
if (settings) {
|
|
522
|
-
ensureConfigModel('settings', settings);
|
|
523
|
-
}
|
|
524
|
-
if (launch) {
|
|
525
|
-
ensureConfigModel('launch', launch);
|
|
526
|
-
}
|
|
527
|
-
await Promise.all(promises);
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
after(() => deleteWorkspacePreferences());
|
|
531
|
-
|
|
532
|
-
const testItOnly = !!only ? it.only : it;
|
|
533
|
-
const testIt = testItOnly;
|
|
534
|
-
|
|
535
|
-
const settingsLaunch = settings ? settings['launch'] : undefined;
|
|
536
|
-
|
|
537
|
-
testIt('get from default', () => {
|
|
538
|
-
const config = preferences.get('launch');
|
|
539
|
-
assert.deepStrictEqual(JSON.parse(JSON.stringify(config)), expectation);
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
testIt('get from undefined', () => {
|
|
543
|
-
/** @type {any} */
|
|
544
|
-
const config = preferences.get('launch', undefined, undefined);
|
|
545
|
-
assert.deepStrictEqual(JSON.parse(JSON.stringify(config)), expectation);
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
testIt('get from rootUri', () => {
|
|
549
|
-
/** @type {any} */
|
|
550
|
-
const config = preferences.get('launch', undefined, rootUri.toString());
|
|
551
|
-
assert.deepStrictEqual(JSON.parse(JSON.stringify(config)), expectation);
|
|
552
|
-
});
|
|
553
|
-
|
|
554
|
-
testIt('inspect in undefined', () => {
|
|
555
|
-
const inspect = preferences.inspect('launch');
|
|
556
|
-
/** @type {PreferenceInspection} */
|
|
557
|
-
let expected = inspectExpectation;
|
|
558
|
-
if (!expected) {
|
|
559
|
-
expected = {
|
|
560
|
-
preferenceName: 'launch',
|
|
561
|
-
defaultValue: defaultLaunch
|
|
562
|
-
};
|
|
563
|
-
const workspaceValue = launch || settingsLaunch;
|
|
564
|
-
if (workspaceValue !== undefined) {
|
|
565
|
-
Object.assign(expected, { workspaceValue });
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
const expectedValue = expected.workspaceFolderValue || expected.workspaceValue || expected.globalValue || expected.defaultValue;
|
|
569
|
-
assert.deepStrictEqual(JSON.parse(JSON.stringify(inspect)), { ...expected, value: expectedValue });
|
|
570
|
-
});
|
|
571
|
-
|
|
572
|
-
testIt('inspect in rootUri', () => {
|
|
573
|
-
const inspect = preferences.inspect('launch', rootUri.toString());
|
|
574
|
-
/** @type {PreferenceInspection} */
|
|
575
|
-
const expected = {
|
|
576
|
-
preferenceName: 'launch',
|
|
577
|
-
defaultValue: defaultLaunch
|
|
578
|
-
};
|
|
579
|
-
if (inspectExpectation) {
|
|
580
|
-
Object.assign(expected, {
|
|
581
|
-
workspaceValue: inspectExpectation.workspaceValue,
|
|
582
|
-
workspaceFolderValue: inspectExpectation.workspaceValue
|
|
583
|
-
});
|
|
584
|
-
} else {
|
|
585
|
-
const value = launch || settingsLaunch;
|
|
586
|
-
if (value !== undefined) {
|
|
587
|
-
Object.assign(expected, {
|
|
588
|
-
workspaceValue: value,
|
|
589
|
-
workspaceFolderValue: value
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
const expectedValue = expected.workspaceFolderValue || expected.workspaceValue || expected.globalValue || expected.defaultValue;
|
|
594
|
-
assert.deepStrictEqual(JSON.parse(JSON.stringify(inspect)), { ...expected, value: expectedValue });
|
|
595
|
-
});
|
|
596
|
-
|
|
597
|
-
testIt('update launch', async () => {
|
|
598
|
-
await preferences.set('launch', validLaunch);
|
|
599
|
-
|
|
600
|
-
const inspect = preferences.inspect('launch');
|
|
601
|
-
const actual = inspect && inspect.workspaceValue;
|
|
602
|
-
const expected = settingsLaunch && !Array.isArray(settingsLaunch) ? { ...settingsLaunch, ...validLaunch } : validLaunch;
|
|
603
|
-
assert.deepStrictEqual(actual, expected);
|
|
604
|
-
});
|
|
605
|
-
|
|
606
|
-
testIt('update launch Workspace', async () => {
|
|
607
|
-
await preferences.set('launch', validLaunch, PreferenceScope.Workspace);
|
|
608
|
-
|
|
609
|
-
const inspect = preferences.inspect('launch');
|
|
610
|
-
const actual = inspect && inspect.workspaceValue;
|
|
611
|
-
const expected = settingsLaunch && !Array.isArray(settingsLaunch) ? { ...settingsLaunch, ...validLaunch } : validLaunch;
|
|
612
|
-
assert.deepStrictEqual(actual, expected);
|
|
613
|
-
});
|
|
614
|
-
|
|
615
|
-
testIt('update launch WorkspaceFolder', async () => {
|
|
616
|
-
try {
|
|
617
|
-
await preferences.set('launch', validLaunch, PreferenceScope.Folder);
|
|
618
|
-
assert.fail('should not be possible to update Workspace Folder Without resource');
|
|
619
|
-
} catch (e) {
|
|
620
|
-
assert.deepStrictEqual(e.message, 'Unable to write to Folder Settings because no resource is provided.');
|
|
621
|
-
}
|
|
622
|
-
});
|
|
623
|
-
|
|
624
|
-
testIt('update launch WorkspaceFolder with resource', async () => {
|
|
625
|
-
await preferences.set('launch', validLaunch, PreferenceScope.Folder, rootUri.toString());
|
|
626
|
-
|
|
627
|
-
const inspect = preferences.inspect('launch');
|
|
628
|
-
const actual = inspect && inspect.workspaceValue;
|
|
629
|
-
const expected = settingsLaunch && !Array.isArray(settingsLaunch) ? { ...settingsLaunch, ...validLaunch } : validLaunch;
|
|
630
|
-
assert.deepStrictEqual(actual, expected);
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
if ((launch && !Array.isArray(launch)) || (settingsLaunch && !Array.isArray(settingsLaunch))) {
|
|
634
|
-
testIt('update launch.configurations', async () => {
|
|
635
|
-
await preferences.set('launch.configurations', [validConfiguration, validConfiguration2]);
|
|
636
|
-
|
|
637
|
-
const inspect = preferences.inspect('launch');
|
|
638
|
-
const actual = inspect && inspect.workspaceValue && inspect.workspaceValue.configurations;
|
|
639
|
-
assert.deepStrictEqual(actual, [validConfiguration, validConfiguration2]);
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
testIt('delete launch', async () => {
|
|
644
|
-
await preferences.set('launch', undefined);
|
|
645
|
-
const actual = preferences.inspect('launch');
|
|
646
|
-
|
|
647
|
-
let expected = undefined;
|
|
648
|
-
if (configPaths[1]) {
|
|
649
|
-
expected = launch;
|
|
650
|
-
if (Array.isArray(expected)) {
|
|
651
|
-
expected = { ...expected };
|
|
652
|
-
}
|
|
653
|
-
if (expected && !expected.configurations && settingsLaunch && settingsLaunch.configurations !== undefined) {
|
|
654
|
-
expected.configurations = settingsLaunch.configurations;
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
expected = expected || settingsLaunch;
|
|
658
|
-
assert.deepStrictEqual(actual && actual.workspaceValue, expected);
|
|
659
|
-
});
|
|
660
|
-
|
|
661
|
-
if ((launch && !Array.isArray(launch)) || (settingsLaunch && !Array.isArray(settingsLaunch))) {
|
|
662
|
-
testIt('delete launch.configurations', async () => {
|
|
663
|
-
await preferences.set('launch.configurations', undefined);
|
|
664
|
-
|
|
665
|
-
const actual = preferences.inspect('launch');
|
|
666
|
-
const actualWorkspaceValue = actual && actual.workspaceValue;
|
|
667
|
-
|
|
668
|
-
let expected = undefined;
|
|
669
|
-
if (launch) {
|
|
670
|
-
expected = { ...launch };
|
|
671
|
-
delete expected['configurations'];
|
|
672
|
-
}
|
|
673
|
-
if (settings) {
|
|
674
|
-
let _settingsLaunch = undefined;
|
|
675
|
-
if (typeof settingsLaunch === 'object' && !Array.isArray(settings['launch']) && settings['launch'] !== null) {
|
|
676
|
-
_settingsLaunch = settingsLaunch;
|
|
677
|
-
} else {
|
|
678
|
-
_settingsLaunch = expectation;
|
|
679
|
-
}
|
|
680
|
-
if (expected) {
|
|
681
|
-
if (_settingsLaunch.configurations !== undefined) {
|
|
682
|
-
expected.configurations = _settingsLaunch.configurations;
|
|
683
|
-
}
|
|
684
|
-
} else {
|
|
685
|
-
expected = _settingsLaunch;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
assert.deepStrictEqual(actualWorkspaceValue, expected);
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
});
|
|
694
|
-
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
});
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2019 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
// @ts-check
|
|
18
|
+
/* @typescript-eslint/no-explicit-any */
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {'.vscode' | '.theia' | ['.theia', '.vscode']} ConfigMode
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Expectations should be tested and aligned against VS Code.
|
|
26
|
+
* See https://github.com/akosyakov/vscode-launch/blob/master/src/test/extension.test.ts
|
|
27
|
+
*/
|
|
28
|
+
describe('Launch Preferences', function () {
|
|
29
|
+
this.timeout(10_000);
|
|
30
|
+
|
|
31
|
+
const { assert } = chai;
|
|
32
|
+
|
|
33
|
+
const { PreferenceProvider } = require('@theia/core/lib/browser');
|
|
34
|
+
const { PreferenceService, PreferenceScope } = require('@theia/core/lib/browser/preferences/preference-service');
|
|
35
|
+
const { WorkspaceService } = require('@theia/workspace/lib/browser/workspace-service');
|
|
36
|
+
const { FileService } = require('@theia/filesystem/lib/browser/file-service');
|
|
37
|
+
const { FileResourceResolver } = require('@theia/filesystem/lib/browser/file-resource');
|
|
38
|
+
const { AbstractResourcePreferenceProvider } = require('@theia/preferences/lib/browser/abstract-resource-preference-provider');
|
|
39
|
+
const { waitForEvent } = require('@theia/core/lib/common/promise-util');
|
|
40
|
+
|
|
41
|
+
const container = window.theia.container;
|
|
42
|
+
/** @type {import('@theia/core/lib/browser/preferences/preference-service').PreferenceService} */
|
|
43
|
+
const preferences = container.get(PreferenceService);
|
|
44
|
+
/** @type {import('@theia/preferences/lib/browser/user-configs-preference-provider').UserConfigsPreferenceProvider} */
|
|
45
|
+
const userPreferences = container.getNamed(PreferenceProvider, PreferenceScope.User);
|
|
46
|
+
/** @type {import('@theia/preferences/lib/browser/workspace-preference-provider').WorkspacePreferenceProvider} */
|
|
47
|
+
const workspacePreferences = container.getNamed(PreferenceProvider, PreferenceScope.Workspace);
|
|
48
|
+
/** @type {import('@theia/preferences/lib/browser/folders-preferences-provider').FoldersPreferencesProvider} */
|
|
49
|
+
const folderPreferences = container.getNamed(PreferenceProvider, PreferenceScope.Folder);
|
|
50
|
+
const workspaceService = container.get(WorkspaceService);
|
|
51
|
+
const fileService = container.get(FileService);
|
|
52
|
+
const fileResourceResolver = container.get(FileResourceResolver);
|
|
53
|
+
|
|
54
|
+
const defaultLaunch = {
|
|
55
|
+
'configurations': [],
|
|
56
|
+
'compounds': []
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const validConfiguration = {
|
|
60
|
+
'name': 'Launch Program',
|
|
61
|
+
'program': '${file}',
|
|
62
|
+
'request': 'launch',
|
|
63
|
+
'type': 'node',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const validConfiguration2 = {
|
|
67
|
+
'name': 'Launch Program 2',
|
|
68
|
+
'program': '${file}',
|
|
69
|
+
'request': 'launch',
|
|
70
|
+
'type': 'node',
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const bogusConfiguration = {};
|
|
74
|
+
|
|
75
|
+
const validCompound = {
|
|
76
|
+
'name': 'Compound',
|
|
77
|
+
'configurations': [
|
|
78
|
+
'Launch Program',
|
|
79
|
+
'Launch Program 2'
|
|
80
|
+
]
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const bogusCompound = {};
|
|
84
|
+
|
|
85
|
+
const bogusCompound2 = {
|
|
86
|
+
'name': 'Compound 2',
|
|
87
|
+
'configurations': [
|
|
88
|
+
'Foo',
|
|
89
|
+
'Launch Program 2'
|
|
90
|
+
]
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const validLaunch = {
|
|
94
|
+
configurations: [validConfiguration, validConfiguration2],
|
|
95
|
+
compounds: [validCompound]
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
testSuite({
|
|
99
|
+
name: 'No Preferences',
|
|
100
|
+
expectation: defaultLaunch
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
testLaunchAndSettingsSuite({
|
|
104
|
+
name: 'Empty With Version',
|
|
105
|
+
launch: {
|
|
106
|
+
'version': '0.2.0'
|
|
107
|
+
},
|
|
108
|
+
expectation: {
|
|
109
|
+
'version': '0.2.0',
|
|
110
|
+
'configurations': [],
|
|
111
|
+
'compounds': []
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
testLaunchAndSettingsSuite({
|
|
116
|
+
name: 'Empty With Version And Configurations',
|
|
117
|
+
launch: {
|
|
118
|
+
'version': '0.2.0',
|
|
119
|
+
'configurations': [],
|
|
120
|
+
},
|
|
121
|
+
expectation: {
|
|
122
|
+
'version': '0.2.0',
|
|
123
|
+
'configurations': [],
|
|
124
|
+
'compounds': []
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
testLaunchAndSettingsSuite({
|
|
129
|
+
name: 'Empty With Version And Compounds',
|
|
130
|
+
launch: {
|
|
131
|
+
'version': '0.2.0',
|
|
132
|
+
'compounds': []
|
|
133
|
+
},
|
|
134
|
+
expectation: {
|
|
135
|
+
'version': '0.2.0',
|
|
136
|
+
'configurations': [],
|
|
137
|
+
'compounds': []
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
testLaunchAndSettingsSuite({
|
|
142
|
+
name: 'Valid Conf',
|
|
143
|
+
launch: {
|
|
144
|
+
'version': '0.2.0',
|
|
145
|
+
'configurations': [validConfiguration]
|
|
146
|
+
},
|
|
147
|
+
expectation: {
|
|
148
|
+
'version': '0.2.0',
|
|
149
|
+
'configurations': [validConfiguration],
|
|
150
|
+
'compounds': []
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
testLaunchAndSettingsSuite({
|
|
155
|
+
name: 'Bogus Conf',
|
|
156
|
+
launch: {
|
|
157
|
+
'version': '0.2.0',
|
|
158
|
+
'configurations': [validConfiguration, bogusConfiguration]
|
|
159
|
+
},
|
|
160
|
+
expectation: {
|
|
161
|
+
'version': '0.2.0',
|
|
162
|
+
'configurations': [validConfiguration, bogusConfiguration],
|
|
163
|
+
'compounds': []
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
testLaunchAndSettingsSuite({
|
|
168
|
+
name: 'Completely Bogus Conf',
|
|
169
|
+
launch: {
|
|
170
|
+
'version': '0.2.0',
|
|
171
|
+
'configurations': { 'valid': validConfiguration, 'bogus': bogusConfiguration }
|
|
172
|
+
},
|
|
173
|
+
expectation: {
|
|
174
|
+
'version': '0.2.0',
|
|
175
|
+
'configurations': { 'valid': validConfiguration, 'bogus': bogusConfiguration },
|
|
176
|
+
'compounds': []
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const arrayBogusLaunch = [
|
|
181
|
+
'version', '0.2.0',
|
|
182
|
+
'configurations', { 'valid': validConfiguration, 'bogus': bogusConfiguration }
|
|
183
|
+
];
|
|
184
|
+
testSuite({
|
|
185
|
+
name: 'Array Bogus Launch Configuration',
|
|
186
|
+
launch: arrayBogusLaunch,
|
|
187
|
+
expectation: {
|
|
188
|
+
'0': 'version',
|
|
189
|
+
'1': '0.2.0',
|
|
190
|
+
'2': 'configurations',
|
|
191
|
+
'3': { 'valid': validConfiguration, 'bogus': bogusConfiguration },
|
|
192
|
+
'compounds': [],
|
|
193
|
+
'configurations': []
|
|
194
|
+
},
|
|
195
|
+
inspectExpectation: {
|
|
196
|
+
preferenceName: 'launch',
|
|
197
|
+
defaultValue: defaultLaunch,
|
|
198
|
+
workspaceValue: {
|
|
199
|
+
'0': 'version',
|
|
200
|
+
'1': '0.2.0',
|
|
201
|
+
'2': 'configurations',
|
|
202
|
+
'3': { 'valid': validConfiguration, 'bogus': bogusConfiguration }
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
testSuite({
|
|
207
|
+
name: 'Array Bogus Settings Configuration',
|
|
208
|
+
settings: {
|
|
209
|
+
launch: arrayBogusLaunch
|
|
210
|
+
},
|
|
211
|
+
expectation: {
|
|
212
|
+
'0': 'version',
|
|
213
|
+
'1': '0.2.0',
|
|
214
|
+
'2': 'configurations',
|
|
215
|
+
'3': { 'valid': validConfiguration, 'bogus': bogusConfiguration },
|
|
216
|
+
'compounds': [],
|
|
217
|
+
'configurations': []
|
|
218
|
+
},
|
|
219
|
+
inspectExpectation: {
|
|
220
|
+
preferenceName: 'launch',
|
|
221
|
+
defaultValue: defaultLaunch,
|
|
222
|
+
workspaceValue: arrayBogusLaunch
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
testSuite({
|
|
227
|
+
name: 'Null Bogus Launch Configuration',
|
|
228
|
+
// eslint-disable-next-line no-null/no-null
|
|
229
|
+
launch: null,
|
|
230
|
+
expectation: {
|
|
231
|
+
'compounds': [],
|
|
232
|
+
'configurations': []
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
testSuite({
|
|
236
|
+
name: 'Null Bogus Settings Configuration',
|
|
237
|
+
settings: {
|
|
238
|
+
// eslint-disable-next-line no-null/no-null
|
|
239
|
+
'launch': null
|
|
240
|
+
},
|
|
241
|
+
expectation: {}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
testLaunchAndSettingsSuite({
|
|
245
|
+
name: 'Valid Compound',
|
|
246
|
+
launch: {
|
|
247
|
+
'version': '0.2.0',
|
|
248
|
+
'configurations': [validConfiguration, validConfiguration2],
|
|
249
|
+
'compounds': [validCompound]
|
|
250
|
+
},
|
|
251
|
+
expectation: {
|
|
252
|
+
'version': '0.2.0',
|
|
253
|
+
'configurations': [validConfiguration, validConfiguration2],
|
|
254
|
+
'compounds': [validCompound]
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
testLaunchAndSettingsSuite({
|
|
259
|
+
name: 'Valid And Bogus',
|
|
260
|
+
launch: {
|
|
261
|
+
'version': '0.2.0',
|
|
262
|
+
'configurations': [validConfiguration, validConfiguration2, bogusConfiguration],
|
|
263
|
+
'compounds': [validCompound, bogusCompound, bogusCompound2]
|
|
264
|
+
},
|
|
265
|
+
expectation: {
|
|
266
|
+
'version': '0.2.0',
|
|
267
|
+
'configurations': [validConfiguration, validConfiguration2, bogusConfiguration],
|
|
268
|
+
'compounds': [validCompound, bogusCompound, bogusCompound2]
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
testSuite({
|
|
273
|
+
name: 'Mixed',
|
|
274
|
+
launch: {
|
|
275
|
+
'version': '0.2.0',
|
|
276
|
+
'configurations': [validConfiguration, bogusConfiguration],
|
|
277
|
+
'compounds': [bogusCompound, bogusCompound2]
|
|
278
|
+
},
|
|
279
|
+
settings: {
|
|
280
|
+
launch: {
|
|
281
|
+
'version': '0.2.0',
|
|
282
|
+
'configurations': [validConfiguration2],
|
|
283
|
+
'compounds': [validCompound]
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
expectation: {
|
|
287
|
+
'version': '0.2.0',
|
|
288
|
+
'configurations': [validConfiguration, bogusConfiguration],
|
|
289
|
+
'compounds': [bogusCompound, bogusCompound2]
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
testSuite({
|
|
294
|
+
name: 'Mixed Launch Without Configurations',
|
|
295
|
+
launch: {
|
|
296
|
+
'version': '0.2.0',
|
|
297
|
+
'compounds': [bogusCompound, bogusCompound2]
|
|
298
|
+
},
|
|
299
|
+
settings: {
|
|
300
|
+
launch: {
|
|
301
|
+
'version': '0.2.0',
|
|
302
|
+
'configurations': [validConfiguration2],
|
|
303
|
+
'compounds': [validCompound]
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
expectation: {
|
|
307
|
+
'version': '0.2.0',
|
|
308
|
+
'configurations': [validConfiguration2],
|
|
309
|
+
'compounds': [bogusCompound, bogusCompound2]
|
|
310
|
+
},
|
|
311
|
+
inspectExpectation: {
|
|
312
|
+
preferenceName: 'launch',
|
|
313
|
+
defaultValue: defaultLaunch,
|
|
314
|
+
workspaceValue: {
|
|
315
|
+
'version': '0.2.0',
|
|
316
|
+
'configurations': [validConfiguration2],
|
|
317
|
+
'compounds': [bogusCompound, bogusCompound2]
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @typedef {Object} LaunchAndSettingsSuiteOptions
|
|
324
|
+
* @property {string} name
|
|
325
|
+
* @property {any} expectation
|
|
326
|
+
* @property {any} [launch]
|
|
327
|
+
* @property {boolean} [only]
|
|
328
|
+
* @property {ConfigMode} [configMode]
|
|
329
|
+
*/
|
|
330
|
+
/**
|
|
331
|
+
* @type {(options: LaunchAndSettingsSuiteOptions) => void}
|
|
332
|
+
*/
|
|
333
|
+
function testLaunchAndSettingsSuite({
|
|
334
|
+
name, expectation, launch, only, configMode
|
|
335
|
+
}) {
|
|
336
|
+
testSuite({
|
|
337
|
+
name: name + ' Launch Configuration',
|
|
338
|
+
launch,
|
|
339
|
+
expectation,
|
|
340
|
+
only,
|
|
341
|
+
configMode
|
|
342
|
+
});
|
|
343
|
+
testSuite({
|
|
344
|
+
name: name + ' Settings Configuration',
|
|
345
|
+
settings: {
|
|
346
|
+
'launch': launch
|
|
347
|
+
},
|
|
348
|
+
expectation,
|
|
349
|
+
only,
|
|
350
|
+
configMode
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* @typedef {Partial<import('@theia/core/src/browser/preferences/preference-service').PreferenceInspection<any>>} PreferenceInspection
|
|
356
|
+
*/
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* @typedef {Object} SuiteOptions
|
|
360
|
+
* @property {string} name
|
|
361
|
+
* @property {any} expectation
|
|
362
|
+
* @property {PreferenceInspection} [inspectExpectation]
|
|
363
|
+
* @property {any} [launch]
|
|
364
|
+
* @property {any} [settings]
|
|
365
|
+
* @property {boolean} [only]
|
|
366
|
+
* @property {ConfigMode} [configMode]
|
|
367
|
+
*/
|
|
368
|
+
/**
|
|
369
|
+
* @type {(options: SuiteOptions) => void}
|
|
370
|
+
*/
|
|
371
|
+
function testSuite(options) {
|
|
372
|
+
describe(options.name, () => {
|
|
373
|
+
|
|
374
|
+
if (options.configMode) {
|
|
375
|
+
testConfigSuite(options);
|
|
376
|
+
} else {
|
|
377
|
+
|
|
378
|
+
testConfigSuite({
|
|
379
|
+
...options,
|
|
380
|
+
configMode: '.theia'
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
if (options.settings || options.launch) {
|
|
384
|
+
testConfigSuite({
|
|
385
|
+
...options,
|
|
386
|
+
configMode: '.vscode'
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
testConfigSuite({
|
|
390
|
+
...options,
|
|
391
|
+
configMode: ['.theia', '.vscode']
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const rootUri = workspaceService.tryGetRoots()[0].resource;
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* @param uri the URI of the file to modify
|
|
404
|
+
* @returns {AbstractResourcePreferenceProvider | undefined} The preference provider matching the provided URI.
|
|
405
|
+
*/
|
|
406
|
+
function findProvider(uri) {
|
|
407
|
+
/**
|
|
408
|
+
* @param {PreferenceProvider} provider
|
|
409
|
+
* @returns {boolean} whether the provider matches the desired URI.
|
|
410
|
+
*/
|
|
411
|
+
const isMatch = (provider) => {
|
|
412
|
+
const configUri = provider.getConfigUri();
|
|
413
|
+
return configUri && uri.isEqual(configUri);
|
|
414
|
+
};
|
|
415
|
+
for (const provider of userPreferences['providers'].values()) {
|
|
416
|
+
if (isMatch(provider) && provider instanceof AbstractResourcePreferenceProvider) {
|
|
417
|
+
return provider;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
for (const provider of folderPreferences['providers'].values()) {
|
|
421
|
+
if (isMatch(provider) && provider instanceof AbstractResourcePreferenceProvider) {
|
|
422
|
+
return provider;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/** @type {PreferenceProvider} */
|
|
426
|
+
const workspaceDelegate = workspacePreferences['delegate'];
|
|
427
|
+
if (workspaceDelegate !== folderPreferences) {
|
|
428
|
+
if (isMatch(workspaceDelegate) && workspaceDelegate instanceof AbstractResourcePreferenceProvider) {
|
|
429
|
+
return workspaceDelegate;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function deleteWorkspacePreferences() {
|
|
435
|
+
const promises = [];
|
|
436
|
+
for (const configPath of ['.theia', '.vscode']) {
|
|
437
|
+
for (const name of ['settings', 'launch']) {
|
|
438
|
+
promises.push((async () => {
|
|
439
|
+
const uri = rootUri.resolve(configPath + '/' + name + '.json');
|
|
440
|
+
const provider = findProvider(uri);
|
|
441
|
+
try {
|
|
442
|
+
if (provider) {
|
|
443
|
+
if (provider.valid) {
|
|
444
|
+
await waitForEvent(provider.onDidChangeValidity, 5000);
|
|
445
|
+
}
|
|
446
|
+
await provider['readPreferencesFromFile']();
|
|
447
|
+
await provider['fireDidPreferencesChanged']();
|
|
448
|
+
} else {
|
|
449
|
+
console.log('Unable to find provider for', uri.path.toString());
|
|
450
|
+
}
|
|
451
|
+
} catch (e) {
|
|
452
|
+
console.error(e);
|
|
453
|
+
}
|
|
454
|
+
})());
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
return Promise.all([
|
|
458
|
+
...promises,
|
|
459
|
+
fileService.delete(rootUri.resolve('.theia'), { fromUserGesture: false, recursive: true }).catch(() => { }),
|
|
460
|
+
fileService.delete(rootUri.resolve('.vscode'), { fromUserGesture: false, recursive: true }).catch(() => { })
|
|
461
|
+
]);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const originalShouldOverwrite = fileResourceResolver['shouldOverwrite'];
|
|
465
|
+
|
|
466
|
+
before(async () => {
|
|
467
|
+
// fail tests if out of async happens
|
|
468
|
+
fileResourceResolver['shouldOverwrite'] = async () => (assert.fail('should be in sync'), false);
|
|
469
|
+
await deleteWorkspacePreferences();
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
after(() => {
|
|
473
|
+
fileResourceResolver['shouldOverwrite'] = originalShouldOverwrite;
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* @typedef {Object} ConfigSuiteOptions
|
|
478
|
+
* @property {any} expectation
|
|
479
|
+
* @property {any} [inspectExpectation]
|
|
480
|
+
* @property {any} [launch]
|
|
481
|
+
* @property {any} [settings]
|
|
482
|
+
* @property {boolean} [only]
|
|
483
|
+
* @property {ConfigMode} [configMode]
|
|
484
|
+
*/
|
|
485
|
+
/**
|
|
486
|
+
* @type {(options: ConfigSuiteOptions) => void}
|
|
487
|
+
*/
|
|
488
|
+
function testConfigSuite({
|
|
489
|
+
configMode, expectation, inspectExpectation, settings, launch, only
|
|
490
|
+
}) {
|
|
491
|
+
|
|
492
|
+
describe(JSON.stringify(configMode, undefined, 2), () => {
|
|
493
|
+
const configPaths = Array.isArray(configMode) ? configMode : [configMode];
|
|
494
|
+
|
|
495
|
+
/** @typedef {import('@theia/monaco-editor-core/esm/vs/base/common/lifecycle').IReference<import('@theia/monaco/lib/browser/monaco-editor-model').MonacoEditorModel>} ConfigModelReference */
|
|
496
|
+
/** @type {ConfigModelReference[]} */
|
|
497
|
+
beforeEach(async () => {
|
|
498
|
+
/** @type {Promise<void>[]} */
|
|
499
|
+
const promises = [];
|
|
500
|
+
/**
|
|
501
|
+
* @param {string} name
|
|
502
|
+
* @param {Record<string, unknown>} value
|
|
503
|
+
*/
|
|
504
|
+
const ensureConfigModel = (name, value) => {
|
|
505
|
+
for (const configPath of configPaths) {
|
|
506
|
+
promises.push((async () => {
|
|
507
|
+
try {
|
|
508
|
+
const uri = rootUri.resolve(configPath + '/' + name + '.json');
|
|
509
|
+
const provider = findProvider(uri);
|
|
510
|
+
if (provider) {
|
|
511
|
+
await provider['doSetPreference']('', [], value);
|
|
512
|
+
} else {
|
|
513
|
+
console.log('Unable to find provider for', uri.path.toString());
|
|
514
|
+
}
|
|
515
|
+
} catch (e) {
|
|
516
|
+
console.error(e);
|
|
517
|
+
}
|
|
518
|
+
})());
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
if (settings) {
|
|
522
|
+
ensureConfigModel('settings', settings);
|
|
523
|
+
}
|
|
524
|
+
if (launch) {
|
|
525
|
+
ensureConfigModel('launch', launch);
|
|
526
|
+
}
|
|
527
|
+
await Promise.all(promises);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
after(() => deleteWorkspacePreferences());
|
|
531
|
+
|
|
532
|
+
const testItOnly = !!only ? it.only : it;
|
|
533
|
+
const testIt = testItOnly;
|
|
534
|
+
|
|
535
|
+
const settingsLaunch = settings ? settings['launch'] : undefined;
|
|
536
|
+
|
|
537
|
+
testIt('get from default', () => {
|
|
538
|
+
const config = preferences.get('launch');
|
|
539
|
+
assert.deepStrictEqual(JSON.parse(JSON.stringify(config)), expectation);
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
testIt('get from undefined', () => {
|
|
543
|
+
/** @type {any} */
|
|
544
|
+
const config = preferences.get('launch', undefined, undefined);
|
|
545
|
+
assert.deepStrictEqual(JSON.parse(JSON.stringify(config)), expectation);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
testIt('get from rootUri', () => {
|
|
549
|
+
/** @type {any} */
|
|
550
|
+
const config = preferences.get('launch', undefined, rootUri.toString());
|
|
551
|
+
assert.deepStrictEqual(JSON.parse(JSON.stringify(config)), expectation);
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
testIt('inspect in undefined', () => {
|
|
555
|
+
const inspect = preferences.inspect('launch');
|
|
556
|
+
/** @type {PreferenceInspection} */
|
|
557
|
+
let expected = inspectExpectation;
|
|
558
|
+
if (!expected) {
|
|
559
|
+
expected = {
|
|
560
|
+
preferenceName: 'launch',
|
|
561
|
+
defaultValue: defaultLaunch
|
|
562
|
+
};
|
|
563
|
+
const workspaceValue = launch || settingsLaunch;
|
|
564
|
+
if (workspaceValue !== undefined) {
|
|
565
|
+
Object.assign(expected, { workspaceValue });
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const expectedValue = expected.workspaceFolderValue || expected.workspaceValue || expected.globalValue || expected.defaultValue;
|
|
569
|
+
assert.deepStrictEqual(JSON.parse(JSON.stringify(inspect)), { ...expected, value: expectedValue });
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
testIt('inspect in rootUri', () => {
|
|
573
|
+
const inspect = preferences.inspect('launch', rootUri.toString());
|
|
574
|
+
/** @type {PreferenceInspection} */
|
|
575
|
+
const expected = {
|
|
576
|
+
preferenceName: 'launch',
|
|
577
|
+
defaultValue: defaultLaunch
|
|
578
|
+
};
|
|
579
|
+
if (inspectExpectation) {
|
|
580
|
+
Object.assign(expected, {
|
|
581
|
+
workspaceValue: inspectExpectation.workspaceValue,
|
|
582
|
+
workspaceFolderValue: inspectExpectation.workspaceValue
|
|
583
|
+
});
|
|
584
|
+
} else {
|
|
585
|
+
const value = launch || settingsLaunch;
|
|
586
|
+
if (value !== undefined) {
|
|
587
|
+
Object.assign(expected, {
|
|
588
|
+
workspaceValue: value,
|
|
589
|
+
workspaceFolderValue: value
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
const expectedValue = expected.workspaceFolderValue || expected.workspaceValue || expected.globalValue || expected.defaultValue;
|
|
594
|
+
assert.deepStrictEqual(JSON.parse(JSON.stringify(inspect)), { ...expected, value: expectedValue });
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
testIt('update launch', async () => {
|
|
598
|
+
await preferences.set('launch', validLaunch);
|
|
599
|
+
|
|
600
|
+
const inspect = preferences.inspect('launch');
|
|
601
|
+
const actual = inspect && inspect.workspaceValue;
|
|
602
|
+
const expected = settingsLaunch && !Array.isArray(settingsLaunch) ? { ...settingsLaunch, ...validLaunch } : validLaunch;
|
|
603
|
+
assert.deepStrictEqual(actual, expected);
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
testIt('update launch Workspace', async () => {
|
|
607
|
+
await preferences.set('launch', validLaunch, PreferenceScope.Workspace);
|
|
608
|
+
|
|
609
|
+
const inspect = preferences.inspect('launch');
|
|
610
|
+
const actual = inspect && inspect.workspaceValue;
|
|
611
|
+
const expected = settingsLaunch && !Array.isArray(settingsLaunch) ? { ...settingsLaunch, ...validLaunch } : validLaunch;
|
|
612
|
+
assert.deepStrictEqual(actual, expected);
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
testIt('update launch WorkspaceFolder', async () => {
|
|
616
|
+
try {
|
|
617
|
+
await preferences.set('launch', validLaunch, PreferenceScope.Folder);
|
|
618
|
+
assert.fail('should not be possible to update Workspace Folder Without resource');
|
|
619
|
+
} catch (e) {
|
|
620
|
+
assert.deepStrictEqual(e.message, 'Unable to write to Folder Settings because no resource is provided.');
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
testIt('update launch WorkspaceFolder with resource', async () => {
|
|
625
|
+
await preferences.set('launch', validLaunch, PreferenceScope.Folder, rootUri.toString());
|
|
626
|
+
|
|
627
|
+
const inspect = preferences.inspect('launch');
|
|
628
|
+
const actual = inspect && inspect.workspaceValue;
|
|
629
|
+
const expected = settingsLaunch && !Array.isArray(settingsLaunch) ? { ...settingsLaunch, ...validLaunch } : validLaunch;
|
|
630
|
+
assert.deepStrictEqual(actual, expected);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
if ((launch && !Array.isArray(launch)) || (settingsLaunch && !Array.isArray(settingsLaunch))) {
|
|
634
|
+
testIt('update launch.configurations', async () => {
|
|
635
|
+
await preferences.set('launch.configurations', [validConfiguration, validConfiguration2]);
|
|
636
|
+
|
|
637
|
+
const inspect = preferences.inspect('launch');
|
|
638
|
+
const actual = inspect && inspect.workspaceValue && inspect.workspaceValue.configurations;
|
|
639
|
+
assert.deepStrictEqual(actual, [validConfiguration, validConfiguration2]);
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
testIt('delete launch', async () => {
|
|
644
|
+
await preferences.set('launch', undefined);
|
|
645
|
+
const actual = preferences.inspect('launch');
|
|
646
|
+
|
|
647
|
+
let expected = undefined;
|
|
648
|
+
if (configPaths[1]) {
|
|
649
|
+
expected = launch;
|
|
650
|
+
if (Array.isArray(expected)) {
|
|
651
|
+
expected = { ...expected };
|
|
652
|
+
}
|
|
653
|
+
if (expected && !expected.configurations && settingsLaunch && settingsLaunch.configurations !== undefined) {
|
|
654
|
+
expected.configurations = settingsLaunch.configurations;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
expected = expected || settingsLaunch;
|
|
658
|
+
assert.deepStrictEqual(actual && actual.workspaceValue, expected);
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
if ((launch && !Array.isArray(launch)) || (settingsLaunch && !Array.isArray(settingsLaunch))) {
|
|
662
|
+
testIt('delete launch.configurations', async () => {
|
|
663
|
+
await preferences.set('launch.configurations', undefined);
|
|
664
|
+
|
|
665
|
+
const actual = preferences.inspect('launch');
|
|
666
|
+
const actualWorkspaceValue = actual && actual.workspaceValue;
|
|
667
|
+
|
|
668
|
+
let expected = undefined;
|
|
669
|
+
if (launch) {
|
|
670
|
+
expected = { ...launch };
|
|
671
|
+
delete expected['configurations'];
|
|
672
|
+
}
|
|
673
|
+
if (settings) {
|
|
674
|
+
let _settingsLaunch = undefined;
|
|
675
|
+
if (typeof settingsLaunch === 'object' && !Array.isArray(settings['launch']) && settings['launch'] !== null) {
|
|
676
|
+
_settingsLaunch = settingsLaunch;
|
|
677
|
+
} else {
|
|
678
|
+
_settingsLaunch = expectation;
|
|
679
|
+
}
|
|
680
|
+
if (expected) {
|
|
681
|
+
if (_settingsLaunch.configurations !== undefined) {
|
|
682
|
+
expected.configurations = _settingsLaunch.configurations;
|
|
683
|
+
}
|
|
684
|
+
} else {
|
|
685
|
+
expected = _settingsLaunch;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
assert.deepStrictEqual(actualWorkspaceValue, expected);
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
});
|