Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/label/test/browser/label.test.ts
3297 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 * as resources from '../../../../../base/common/resources.js';
7
import assert from 'assert';
8
import { TestEnvironmentService, TestLifecycleService, TestPathService, TestRemoteAgentService } from '../../../../test/browser/workbenchTestServices.js';
9
import { URI } from '../../../../../base/common/uri.js';
10
import { LabelService } from '../../common/labelService.js';
11
import { TestContextService, TestStorageService } from '../../../../test/common/workbenchTestServices.js';
12
import { WorkspaceFolder } from '../../../../../platform/workspace/common/workspace.js';
13
import { TestWorkspace, Workspace } from '../../../../../platform/workspace/test/common/testWorkspace.js';
14
import { isWindows } from '../../../../../base/common/platform.js';
15
import { StorageScope, StorageTarget } from '../../../../../platform/storage/common/storage.js';
16
import { Memento } from '../../../../common/memento.js';
17
import { ResourceLabelFormatter } from '../../../../../platform/label/common/label.js';
18
import { sep } from '../../../../../base/common/path.js';
19
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
20
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
21
22
suite('URI Label', () => {
23
let labelService: LabelService;
24
let storageService: TestStorageService;
25
26
setup(() => {
27
storageService = new TestStorageService();
28
labelService = new LabelService(TestEnvironmentService, new TestContextService(), new TestPathService(URI.file('/foobar')), new TestRemoteAgentService(), storageService, new TestLifecycleService());
29
});
30
31
ensureNoDisposablesAreLeakedInTestSuite();
32
33
test('custom scheme', function () {
34
labelService.registerFormatter({
35
scheme: 'vscode',
36
formatting: {
37
label: 'LABEL/${path}/${authority}/END',
38
separator: '/',
39
tildify: true,
40
normalizeDriveLetter: true
41
}
42
});
43
44
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
45
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'LABEL//1/2/3/4/5/microsoft.com/END');
46
assert.strictEqual(labelService.getUriBasenameLabel(uri1), 'END');
47
});
48
49
test('file scheme', function () {
50
labelService.registerFormatter({
51
scheme: 'file',
52
formatting: {
53
label: '${path}',
54
separator: sep,
55
tildify: !isWindows,
56
normalizeDriveLetter: isWindows
57
}
58
});
59
60
const uri1 = TestWorkspace.folders[0].uri.with({ path: TestWorkspace.folders[0].uri.path.concat('/a/b/c/d') });
61
assert.strictEqual(labelService.getUriLabel(uri1, { relative: true }), isWindows ? 'a\\b\\c\\d' : 'a/b/c/d');
62
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), isWindows ? 'C:\\testWorkspace\\a\\b\\c\\d' : '/testWorkspace/a/b/c/d');
63
assert.strictEqual(labelService.getUriBasenameLabel(uri1), 'd');
64
65
const uri2 = URI.file('c:\\1/2/3');
66
assert.strictEqual(labelService.getUriLabel(uri2, { relative: false }), isWindows ? 'C:\\1\\2\\3' : '/c:\\1/2/3');
67
assert.strictEqual(labelService.getUriBasenameLabel(uri2), '3');
68
});
69
70
test('separator', function () {
71
labelService.registerFormatter({
72
scheme: 'vscode',
73
formatting: {
74
label: 'LABEL\\${path}\\${authority}\\END',
75
separator: '\\',
76
tildify: true,
77
normalizeDriveLetter: true
78
}
79
});
80
81
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
82
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'LABEL\\\\1\\2\\3\\4\\5\\microsoft.com\\END');
83
assert.strictEqual(labelService.getUriBasenameLabel(uri1), 'END');
84
});
85
86
test('custom authority', function () {
87
labelService.registerFormatter({
88
scheme: 'vscode',
89
authority: 'micro*',
90
formatting: {
91
label: 'LABEL/${path}/${authority}/END',
92
separator: '/'
93
}
94
});
95
96
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
97
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'LABEL//1/2/3/4/5/microsoft.com/END');
98
assert.strictEqual(labelService.getUriBasenameLabel(uri1), 'END');
99
});
100
101
test('mulitple authority', function () {
102
labelService.registerFormatter({
103
scheme: 'vscode',
104
authority: 'not_matching_but_long',
105
formatting: {
106
label: 'first',
107
separator: '/'
108
}
109
});
110
labelService.registerFormatter({
111
scheme: 'vscode',
112
authority: 'microsof*',
113
formatting: {
114
label: 'second',
115
separator: '/'
116
}
117
});
118
labelService.registerFormatter({
119
scheme: 'vscode',
120
authority: 'mi*',
121
formatting: {
122
label: 'third',
123
separator: '/'
124
}
125
});
126
127
// Make sure the most specific authority is picked
128
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
129
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'second');
130
assert.strictEqual(labelService.getUriBasenameLabel(uri1), 'second');
131
});
132
133
test('custom query', function () {
134
labelService.registerFormatter({
135
scheme: 'vscode',
136
formatting: {
137
label: 'LABEL${query.prefix}: ${query.path}/END',
138
separator: '/',
139
tildify: true,
140
normalizeDriveLetter: true
141
}
142
});
143
144
const uri1 = URI.parse(`vscode://microsoft.com/1/2/3/4/5?${encodeURIComponent(JSON.stringify({ prefix: 'prefix', path: 'path' }))}`);
145
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'LABELprefix: path/END');
146
});
147
148
test('custom query without value', function () {
149
labelService.registerFormatter({
150
scheme: 'vscode',
151
formatting: {
152
label: 'LABEL${query.prefix}: ${query.path}/END',
153
separator: '/',
154
tildify: true,
155
normalizeDriveLetter: true
156
}
157
});
158
159
const uri1 = URI.parse(`vscode://microsoft.com/1/2/3/4/5?${encodeURIComponent(JSON.stringify({ path: 'path' }))}`);
160
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'LABEL: path/END');
161
});
162
163
test('custom query without query json', function () {
164
labelService.registerFormatter({
165
scheme: 'vscode',
166
formatting: {
167
label: 'LABEL${query.prefix}: ${query.path}/END',
168
separator: '/',
169
tildify: true,
170
normalizeDriveLetter: true
171
}
172
});
173
174
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5?path=foo');
175
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'LABEL: /END');
176
});
177
178
test('custom query without query', function () {
179
labelService.registerFormatter({
180
scheme: 'vscode',
181
formatting: {
182
label: 'LABEL${query.prefix}: ${query.path}/END',
183
separator: '/',
184
tildify: true,
185
normalizeDriveLetter: true
186
}
187
});
188
189
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
190
assert.strictEqual(labelService.getUriLabel(uri1, { relative: false }), 'LABEL: /END');
191
});
192
193
194
test('label caching', () => {
195
const m = new Memento('cachedResourceLabelFormatters2', storageService).getMemento(StorageScope.PROFILE, StorageTarget.MACHINE);
196
const makeFormatter = (scheme: string): ResourceLabelFormatter => ({ formatting: { label: `\${path} (${scheme})`, separator: '/' }, scheme });
197
assert.deepStrictEqual(m, {});
198
199
// registers a new formatter:
200
labelService.registerCachedFormatter(makeFormatter('a'));
201
assert.deepStrictEqual(m, { formatters: [makeFormatter('a')] });
202
203
// registers a 2nd formatter:
204
labelService.registerCachedFormatter(makeFormatter('b'));
205
assert.deepStrictEqual(m, { formatters: [makeFormatter('b'), makeFormatter('a')] });
206
207
// promotes a formatter on re-register:
208
labelService.registerCachedFormatter(makeFormatter('a'));
209
assert.deepStrictEqual(m, { formatters: [makeFormatter('a'), makeFormatter('b')] });
210
211
// no-ops if already in first place:
212
labelService.registerCachedFormatter(makeFormatter('a'));
213
assert.deepStrictEqual(m, { formatters: [makeFormatter('a'), makeFormatter('b')] });
214
215
// limits the cache:
216
for (let i = 0; i < 100; i++) {
217
labelService.registerCachedFormatter(makeFormatter(`i${i}`));
218
}
219
const expected: ResourceLabelFormatter[] = [];
220
for (let i = 50; i < 100; i++) {
221
expected.unshift(makeFormatter(`i${i}`));
222
}
223
assert.deepStrictEqual(m, { formatters: expected });
224
225
delete (m as any).formatters;
226
});
227
});
228
229
230
suite('multi-root workspace', () => {
231
let labelService: LabelService;
232
const disposables = new DisposableStore();
233
234
setup(() => {
235
const sources = URI.file('folder1/src');
236
const tests = URI.file('folder1/test');
237
const other = URI.file('folder2');
238
239
labelService = disposables.add(new LabelService(
240
TestEnvironmentService,
241
new TestContextService(
242
new Workspace('test-workspace', [
243
new WorkspaceFolder({ uri: sources, index: 0, name: 'Sources' }),
244
new WorkspaceFolder({ uri: tests, index: 1, name: 'Tests' }),
245
new WorkspaceFolder({ uri: other, index: 2, name: resources.basename(other) }),
246
])),
247
new TestPathService(),
248
new TestRemoteAgentService(),
249
disposables.add(new TestStorageService()),
250
disposables.add(new TestLifecycleService())
251
));
252
});
253
254
teardown(() => {
255
disposables.clear();
256
});
257
258
test('labels of files in multiroot workspaces are the foldername followed by offset from the folder', () => {
259
labelService.registerFormatter({
260
scheme: 'file',
261
formatting: {
262
label: '${authority}${path}',
263
separator: '/',
264
tildify: false,
265
normalizeDriveLetter: false,
266
authorityPrefix: '//',
267
workspaceSuffix: ''
268
}
269
});
270
271
const tests = {
272
'folder1/src/file': 'Sources • file',
273
'folder1/src/folder/file': 'Sources • folder/file',
274
'folder1/src': 'Sources',
275
'folder1/other': '/folder1/other',
276
'folder2/other': 'folder2 • other',
277
};
278
279
Object.entries(tests).forEach(([path, label]) => {
280
const generated = labelService.getUriLabel(URI.file(path), { relative: true });
281
assert.strictEqual(generated, label);
282
});
283
});
284
285
test('labels with context after path', () => {
286
labelService.registerFormatter({
287
scheme: 'file',
288
formatting: {
289
label: '${path} (${scheme})',
290
separator: '/',
291
}
292
});
293
294
const tests = {
295
'folder1/src/file': 'Sources • file (file)',
296
'folder1/src/folder/file': 'Sources • folder/file (file)',
297
'folder1/src': 'Sources',
298
'folder1/other': '/folder1/other (file)',
299
'folder2/other': 'folder2 • other (file)',
300
};
301
302
Object.entries(tests).forEach(([path, label]) => {
303
const generated = labelService.getUriLabel(URI.file(path), { relative: true });
304
assert.strictEqual(generated, label, path);
305
});
306
});
307
308
test('stripPathStartingSeparator', () => {
309
labelService.registerFormatter({
310
scheme: 'file',
311
formatting: {
312
label: '${path}',
313
separator: '/',
314
stripPathStartingSeparator: true
315
}
316
});
317
318
const tests = {
319
'folder1/src/file': 'Sources • file',
320
'other/blah': 'other/blah',
321
};
322
323
Object.entries(tests).forEach(([path, label]) => {
324
const generated = labelService.getUriLabel(URI.file(path), { relative: true });
325
assert.strictEqual(generated, label, path);
326
});
327
});
328
329
test('relative label without formatter', () => {
330
const rootFolder = URI.parse('myscheme://myauthority/');
331
332
labelService = disposables.add(new LabelService(
333
TestEnvironmentService,
334
new TestContextService(
335
new Workspace('test-workspace', [
336
new WorkspaceFolder({ uri: rootFolder, index: 0, name: 'FSProotFolder' }),
337
])),
338
new TestPathService(undefined, rootFolder.scheme),
339
new TestRemoteAgentService(),
340
disposables.add(new TestStorageService()),
341
disposables.add(new TestLifecycleService())
342
));
343
344
const generated = labelService.getUriLabel(URI.parse('myscheme://myauthority/some/folder/test.txt'), { relative: true });
345
if (isWindows) {
346
assert.strictEqual(generated, 'some\\folder\\test.txt');
347
} else {
348
assert.strictEqual(generated, 'some/folder/test.txt');
349
}
350
});
351
352
ensureNoDisposablesAreLeakedInTestSuite();
353
});
354
355
suite('workspace at FSP root', () => {
356
let labelService: LabelService;
357
358
setup(() => {
359
const rootFolder = URI.parse('myscheme://myauthority/');
360
361
labelService = new LabelService(
362
TestEnvironmentService,
363
new TestContextService(
364
new Workspace('test-workspace', [
365
new WorkspaceFolder({ uri: rootFolder, index: 0, name: 'FSProotFolder' }),
366
])),
367
new TestPathService(),
368
new TestRemoteAgentService(),
369
new TestStorageService(),
370
new TestLifecycleService()
371
);
372
labelService.registerFormatter({
373
scheme: 'myscheme',
374
formatting: {
375
label: '${scheme}://${authority}${path}',
376
separator: '/',
377
tildify: false,
378
normalizeDriveLetter: false,
379
workspaceSuffix: '',
380
authorityPrefix: '',
381
stripPathStartingSeparator: false
382
}
383
});
384
});
385
386
test('non-relative label', () => {
387
388
const tests = {
389
'myscheme://myauthority/myFile1.txt': 'myscheme://myauthority/myFile1.txt',
390
'myscheme://myauthority/folder/myFile2.txt': 'myscheme://myauthority/folder/myFile2.txt',
391
};
392
393
Object.entries(tests).forEach(([uriString, label]) => {
394
const generated = labelService.getUriLabel(URI.parse(uriString), { relative: false });
395
assert.strictEqual(generated, label);
396
});
397
});
398
399
test('relative label', () => {
400
401
const tests = {
402
'myscheme://myauthority/myFile1.txt': 'myFile1.txt',
403
'myscheme://myauthority/folder/myFile2.txt': 'folder/myFile2.txt',
404
};
405
406
Object.entries(tests).forEach(([uriString, label]) => {
407
const generated = labelService.getUriLabel(URI.parse(uriString), { relative: true });
408
assert.strictEqual(generated, label);
409
});
410
});
411
412
test('relative label with explicit path separator', () => {
413
let generated = labelService.getUriLabel(URI.parse('myscheme://myauthority/some/folder/test.txt'), { relative: true, separator: '/' });
414
assert.strictEqual(generated, 'some/folder/test.txt');
415
416
generated = labelService.getUriLabel(URI.parse('myscheme://myauthority/some/folder/test.txt'), { relative: true, separator: '\\' });
417
assert.strictEqual(generated, 'some\\folder\\test.txt');
418
});
419
420
ensureNoDisposablesAreLeakedInTestSuite();
421
});
422
423