Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/test/browser/contributions.test.ts
4778 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 assert from 'assert';
7
import { DeferredPromise } from '../../../base/common/async.js';
8
import { DisposableStore } from '../../../base/common/lifecycle.js';
9
import { isCI } from '../../../base/common/platform.js';
10
import { URI } from '../../../base/common/uri.js';
11
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../base/test/common/utils.js';
12
import { SyncDescriptor } from '../../../platform/instantiation/common/descriptors.js';
13
import { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';
14
import { EditorPart } from '../../browser/parts/editor/editorPart.js';
15
import { WorkbenchPhase, WorkbenchContributionsRegistry } from '../../common/contributions.js';
16
import { EditorService } from '../../services/editor/browser/editorService.js';
17
import { IEditorGroupsService } from '../../services/editor/common/editorGroupsService.js';
18
import { IEditorService, SIDE_GROUP } from '../../services/editor/common/editorService.js';
19
import { LifecyclePhase } from '../../services/lifecycle/common/lifecycle.js';
20
import { ITestInstantiationService, TestFileEditorInput, TestServiceAccessor, TestSingletonFileEditorInput, createEditorPart, registerTestEditor, workbenchInstantiationService } from './workbenchTestServices.js';
21
22
suite('Contributions', () => {
23
const disposables = new DisposableStore();
24
25
let aCreated: boolean;
26
let aCreatedPromise: DeferredPromise<void>;
27
28
let bCreated: boolean;
29
let bCreatedPromise: DeferredPromise<void>;
30
31
const TEST_EDITOR_ID = 'MyTestEditorForContributions';
32
const TEST_EDITOR_INPUT_ID = 'testEditorInputForContributions';
33
34
async function createEditorService(instantiationService: ITestInstantiationService = workbenchInstantiationService(undefined, disposables)): Promise<[EditorPart, EditorService]> {
35
const part = await createEditorPart(instantiationService, disposables);
36
instantiationService.stub(IEditorGroupsService, part);
37
38
const editorService = disposables.add(instantiationService.createInstance(EditorService, undefined));
39
instantiationService.stub(IEditorService, editorService);
40
41
return [part, editorService];
42
}
43
44
setup(() => {
45
aCreated = false;
46
aCreatedPromise = new DeferredPromise<void>();
47
48
bCreated = false;
49
bCreatedPromise = new DeferredPromise<void>();
50
51
disposables.add(registerTestEditor(TEST_EDITOR_ID, [new SyncDescriptor(TestFileEditorInput), new SyncDescriptor(TestSingletonFileEditorInput)], TEST_EDITOR_INPUT_ID));
52
});
53
54
teardown(async () => {
55
disposables.clear();
56
});
57
58
class TestContributionA {
59
constructor() {
60
aCreated = true;
61
aCreatedPromise.complete();
62
}
63
}
64
class TestContributionB {
65
constructor() {
66
bCreated = true;
67
bCreatedPromise.complete();
68
}
69
}
70
class TestContributionError {
71
constructor() {
72
throw new Error();
73
}
74
}
75
76
test('getWorkbenchContribution() - with lazy contributions', () => {
77
const registry = disposables.add(new WorkbenchContributionsRegistry());
78
79
assert.throws(() => registry.getWorkbenchContribution('a'));
80
81
registry.registerWorkbenchContribution2('a', TestContributionA, { lazy: true });
82
assert.throws(() => registry.getWorkbenchContribution('a'));
83
84
registry.registerWorkbenchContribution2('b', TestContributionB, { lazy: true });
85
registry.registerWorkbenchContribution2('c', TestContributionError, { lazy: true });
86
87
const instantiationService = workbenchInstantiationService(undefined, disposables);
88
registry.start(instantiationService);
89
90
const instanceA = registry.getWorkbenchContribution('a');
91
assert.ok(instanceA instanceof TestContributionA);
92
assert.ok(aCreated);
93
assert.strictEqual(instanceA, registry.getWorkbenchContribution('a'));
94
95
const instanceB = registry.getWorkbenchContribution('b');
96
assert.ok(instanceB instanceof TestContributionB);
97
98
assert.throws(() => registry.getWorkbenchContribution('c'));
99
});
100
101
test('getWorkbenchContribution() - with non-lazy contributions', async () => {
102
const registry = disposables.add(new WorkbenchContributionsRegistry());
103
104
const instantiationService = workbenchInstantiationService(undefined, disposables);
105
const accessor = instantiationService.createInstance(TestServiceAccessor);
106
accessor.lifecycleService.usePhases = true;
107
registry.start(instantiationService);
108
109
assert.throws(() => registry.getWorkbenchContribution('a'));
110
111
registry.registerWorkbenchContribution2('a', TestContributionA, WorkbenchPhase.BlockRestore);
112
113
const instanceA = registry.getWorkbenchContribution('a');
114
assert.ok(instanceA instanceof TestContributionA);
115
assert.ok(aCreated);
116
117
accessor.lifecycleService.phase = LifecyclePhase.Ready;
118
await aCreatedPromise.p;
119
120
assert.strictEqual(instanceA, registry.getWorkbenchContribution('a'));
121
});
122
123
test('lifecycle phase instantiation works when phase changes', async () => {
124
const registry = disposables.add(new WorkbenchContributionsRegistry());
125
126
const instantiationService = workbenchInstantiationService(undefined, disposables);
127
const accessor = instantiationService.createInstance(TestServiceAccessor);
128
registry.start(instantiationService);
129
130
registry.registerWorkbenchContribution2('a', TestContributionA, WorkbenchPhase.BlockRestore);
131
assert.ok(!aCreated);
132
133
accessor.lifecycleService.phase = LifecyclePhase.Ready;
134
await aCreatedPromise.p;
135
assert.ok(aCreated);
136
});
137
138
test('lifecycle phase instantiation works when phase was already met', async () => {
139
const registry = disposables.add(new WorkbenchContributionsRegistry());
140
141
const instantiationService = workbenchInstantiationService(undefined, disposables);
142
const accessor = instantiationService.createInstance(TestServiceAccessor);
143
accessor.lifecycleService.usePhases = true;
144
accessor.lifecycleService.phase = LifecyclePhase.Restored;
145
146
registry.registerWorkbenchContribution2('a', TestContributionA, WorkbenchPhase.BlockRestore);
147
registry.start(instantiationService);
148
149
await aCreatedPromise.p;
150
assert.ok(aCreated);
151
});
152
153
(isCI ? test.skip /* runWhenIdle seems flaky in CI on Windows */ : test)('lifecycle phase instantiation works for late phases', async () => {
154
const registry = disposables.add(new WorkbenchContributionsRegistry());
155
156
const instantiationService = workbenchInstantiationService(undefined, disposables);
157
const accessor = instantiationService.createInstance(TestServiceAccessor);
158
accessor.lifecycleService.usePhases = true;
159
registry.start(instantiationService);
160
161
registry.registerWorkbenchContribution2('a', TestContributionA, WorkbenchPhase.AfterRestored);
162
registry.registerWorkbenchContribution2('b', TestContributionB, WorkbenchPhase.Eventually);
163
assert.ok(!aCreated);
164
assert.ok(!bCreated);
165
166
accessor.lifecycleService.phase = LifecyclePhase.Starting;
167
accessor.lifecycleService.phase = LifecyclePhase.Ready;
168
accessor.lifecycleService.phase = LifecyclePhase.Restored;
169
await aCreatedPromise.p;
170
assert.ok(aCreated);
171
172
accessor.lifecycleService.phase = LifecyclePhase.Eventually;
173
await bCreatedPromise.p;
174
assert.ok(bCreated);
175
});
176
177
test('contribution on editor - editor exists before start', async function () {
178
const registry = disposables.add(new WorkbenchContributionsRegistry());
179
180
const instantiationService = workbenchInstantiationService(undefined, disposables);
181
182
const [, editorService] = await createEditorService(instantiationService);
183
184
const input = disposables.add(new TestFileEditorInput(URI.parse('my://resource-basics'), TEST_EDITOR_INPUT_ID));
185
await editorService.openEditor(input, { pinned: true });
186
187
registry.registerWorkbenchContribution2('a', TestContributionA, { editorTypeId: TEST_EDITOR_ID });
188
registry.start(instantiationService.createChild(new ServiceCollection([IEditorService, editorService])));
189
190
await aCreatedPromise.p;
191
assert.ok(aCreated);
192
193
registry.registerWorkbenchContribution2('b', TestContributionB, { editorTypeId: TEST_EDITOR_ID });
194
195
const input2 = disposables.add(new TestFileEditorInput(URI.parse('my://resource-basics2'), TEST_EDITOR_INPUT_ID));
196
await editorService.openEditor(input2, { pinned: true }, SIDE_GROUP);
197
198
await bCreatedPromise.p;
199
assert.ok(bCreated);
200
});
201
202
test('contribution on editor - editor does not exist before start', async function () {
203
const registry = disposables.add(new WorkbenchContributionsRegistry());
204
205
const instantiationService = workbenchInstantiationService(undefined, disposables);
206
207
const [, editorService] = await createEditorService(instantiationService);
208
209
const input = disposables.add(new TestFileEditorInput(URI.parse('my://resource-basics'), TEST_EDITOR_INPUT_ID));
210
211
registry.registerWorkbenchContribution2('a', TestContributionA, { editorTypeId: TEST_EDITOR_ID });
212
registry.start(instantiationService.createChild(new ServiceCollection([IEditorService, editorService])));
213
214
await editorService.openEditor(input, { pinned: true });
215
216
await aCreatedPromise.p;
217
assert.ok(aCreated);
218
});
219
220
ensureNoDisposablesAreLeakedInTestSuite();
221
});
222
223