@theia/api-tests 1.65.0-next.6 → 1.66.0-next.0

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/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@theia/api-tests",
3
- "version": "1.65.0-next.6+4384a9461",
3
+ "version": "1.66.0-next.0+008c83404",
4
4
  "description": "Theia API tests",
5
5
  "dependencies": {
6
- "@theia/core": "1.65.0-next.6+4384a9461"
6
+ "@theia/core": "1.66.0-next.0+008c83404"
7
7
  },
8
8
  "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0",
9
9
  "repository": {
@@ -20,5 +20,5 @@
20
20
  "publishConfig": {
21
21
  "access": "public"
22
22
  },
23
- "gitHead": "4384a946123dd1b41e65708e58928fc1af707c8d"
23
+ "gitHead": "008c8340465f7e42298839881d814863bef0b039"
24
24
  }
@@ -26,16 +26,17 @@
26
26
  * See https://github.com/akosyakov/vscode-launch/blob/master/src/test/extension.test.ts
27
27
  */
28
28
  describe('Launch Preferences', function () {
29
- this.timeout(10_000);
29
+ this.timeout(30_000);
30
30
 
31
31
  const { assert } = chai;
32
32
 
33
- const { PreferenceProvider } = require('@theia/core/lib/browser');
34
- const { PreferenceService, PreferenceScope } = require('@theia/core/lib/browser/preferences/preference-service');
33
+ const { PreferenceProvider } = require('@theia/core/lib/common');
34
+ const { PreferenceService } = require('@theia/core/lib/common/preferences/preference-service');
35
+ const { PreferenceScope } = require('@theia/core/lib/common/preferences/preference-scope');
35
36
  const { WorkspaceService } = require('@theia/workspace/lib/browser/workspace-service');
36
37
  const { FileService } = require('@theia/filesystem/lib/browser/file-service');
37
38
  const { FileResourceResolver } = require('@theia/filesystem/lib/browser/file-resource');
38
- const { AbstractResourcePreferenceProvider } = require('@theia/preferences/lib/browser/abstract-resource-preference-provider');
39
+ const { AbstractResourcePreferenceProvider } = require('@theia/preferences/lib/common/abstract-resource-preference-provider');
39
40
  const { waitForEvent } = require('@theia/core/lib/common/promise-util');
40
41
 
41
42
  const container = window.theia.container;
@@ -431,7 +432,7 @@ describe('Launch Preferences', function () {
431
432
  }
432
433
  }
433
434
 
434
- function deleteWorkspacePreferences() {
435
+ async function deleteWorkspacePreferences() {
435
436
  const promises = [];
436
437
  for (const configPath of ['.theia', '.vscode']) {
437
438
  for (const name of ['settings', 'launch']) {
@@ -441,7 +442,11 @@ describe('Launch Preferences', function () {
441
442
  try {
442
443
  if (provider) {
443
444
  if (provider.valid) {
444
- await waitForEvent(provider.onDidChangeValidity, 5000);
445
+ try {
446
+ await waitForEvent(provider.onDidChangeValidity, 1000);
447
+ } catch (e) {
448
+ console.log('timed out waiting for validity change'); // sometimes, we seen to miss events: https://github.com/eclipse-theia/theia/issues/16088
449
+ }
445
450
  }
446
451
  await provider['readPreferencesFromFile']();
447
452
  await provider['fireDidPreferencesChanged']();
@@ -454,11 +459,10 @@ describe('Launch Preferences', function () {
454
459
  })());
455
460
  }
456
461
  }
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
+ await fileService.delete(rootUri.resolve('.theia'), { fromUserGesture: false, recursive: true }).catch(() => { });
464
+ await fileService.delete(rootUri.resolve('.vscode'), { fromUserGesture: false, recursive: true }).catch(() => { });
465
+ await Promise.all(promises);
462
466
  }
463
467
 
464
468
 
@@ -574,7 +578,7 @@ describe('Launch Preferences', function () {
574
578
  await Promise.all(promises);
575
579
  });
576
580
 
577
- after(() => deleteWorkspacePreferences());
581
+ after(async () => await deleteWorkspacePreferences());
578
582
 
579
583
  const testItOnly = !!only ? it.only : it;
580
584
  const testIt = testItOnly;
@@ -724,5 +728,4 @@ describe('Launch Preferences', function () {
724
728
  });
725
729
 
726
730
  }
727
-
728
731
  });
@@ -14,6 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+ const { timeout } = require('@theia/core/lib/common/promise-util');
17
18
  const { IOpenerService } = require('@theia/monaco-editor-core/esm/vs/platform/opener/common/opener');
18
19
 
19
20
  // @ts-check
@@ -34,7 +35,6 @@ describe('Monaco API', async function () {
34
35
  const { TokenizationRegistry } = require('@theia/monaco-editor-core/esm/vs/editor/common/languages');
35
36
  const { MonacoContextKeyService } = require('@theia/monaco/lib/browser/monaco-context-key-service');
36
37
  const { URI } = require('@theia/monaco-editor-core/esm/vs/base/common/uri');
37
- const { animationFrame } = require('@theia/core/lib/browser/browser');
38
38
 
39
39
  const container = window.theia.container;
40
40
  const editorManager = container.get(EditorManager);
@@ -190,7 +190,7 @@ describe('Monaco API', async function () {
190
190
  assert.isTrue(contextKeys.match(inQuickOpenContextKey));
191
191
 
192
192
  await commands.executeCommand(CommandThatChangesFocus);
193
- await animationFrame();
193
+ await timeout(0);
194
194
  assert.isFalse(contextKeys.match(inQuickOpenContextKey));
195
195
  }
196
196
  });
@@ -19,27 +19,29 @@
19
19
  describe('Preferences', function () {
20
20
  this.timeout(5_000);
21
21
  const { assert } = chai;
22
- const { PreferenceProvider } = require('@theia/core/lib/browser/preferences/preference-provider');
23
- const { PreferenceService, PreferenceScope } = require('@theia/core/lib/browser/preferences/preference-service');
22
+ const { PreferenceProvider } = require('@theia/core/lib/common/preferences/preference-provider');
23
+ const { PreferenceService, PreferenceScope } = require('@theia/core/lib/common/preferences');
24
24
  const { FileService } = require('@theia/filesystem/lib/browser/file-service');
25
- const { PreferenceLanguageOverrideService } = require('@theia/core/lib/browser/preferences/preference-language-override-service');
25
+ const { PreferenceLanguageOverrideService } = require('@theia/core/lib/common/preferences/preference-language-override-service');
26
26
  const { MonacoTextModelService } = require('@theia/monaco/lib/browser/monaco-text-model-service');
27
- const { PreferenceSchemaProvider } = require('@theia/core/lib/browser/preferences/preference-contribution')
27
+ const { PreferenceSchemaService } = require('@theia/core/lib/common/preferences')
28
28
  const { container } = window.theia;
29
- /** @type {import ('@theia/core/lib/browser/preferences/preference-service').PreferenceService} */
29
+ /** @type {import ('@theia/core/lib/common/preferences/preference-service').PreferenceService} */
30
30
  const preferenceService = container.get(PreferenceService);
31
- /** @type {import ('@theia/core/lib/browser/preferences/preference-language-override-service').PreferenceLanguageOverrideService} */
31
+ /** @type {import ('@theia/core/lib/common/preferences/preference-language-override-service').PreferenceLanguageOverrideService} */
32
32
  const overrideService = container.get(PreferenceLanguageOverrideService);
33
33
  const fileService = container.get(FileService);
34
34
  /** @type {import ('@theia/core/lib/common/uri').default} */
35
35
  const uri = preferenceService.getConfigUri(PreferenceScope.Workspace);
36
36
  /** @type {import('@theia/preferences/lib/browser/folders-preferences-provider').FoldersPreferencesProvider} */
37
37
  const folderPreferences = container.getNamed(PreferenceProvider, PreferenceScope.Folder);
38
- /** @type PreferenceSchemaProvider */
39
- const schemaProvider = container.get(PreferenceSchemaProvider);
38
+ /** @type PreferenceSchemaService */
39
+ const schemaService = container.get(PreferenceSchemaService);
40
40
  const modelService = container.get(MonacoTextModelService);
41
41
 
42
+
42
43
  const overrideIdentifier = 'bargle-noddle-zaus'; // Probably not in our preference files...
44
+ schemaService.registerOverrideIdentifier(overrideIdentifier);
43
45
  const tabSize = 'editor.tabSize';
44
46
  const fontSize = 'editor.fontSize';
45
47
  const override = overrideService.markLanguageOverride(overrideIdentifier);
@@ -91,7 +93,7 @@ describe('Preferences', function () {
91
93
  assert.isDefined(uri, 'The workspace config URI should be defined!');
92
94
  fileExistsBeforehand = await fileService.exists(uri);
93
95
  contentBeforehand = await fileService.read(uri).then(({ value }) => value).catch(() => '');
94
- schemaProvider.registerOverrideIdentifier(overrideIdentifier);
96
+ schemaService.registerOverrideIdentifier(overrideIdentifier);
95
97
  await deleteAllValues();
96
98
  });
97
99
 
@@ -22,14 +22,14 @@ describe('Saveable', function () {
22
22
 
23
23
  const { EditorManager } = require('@theia/editor/lib/browser/editor-manager');
24
24
  const { EditorWidget } = require('@theia/editor/lib/browser/editor-widget');
25
- const { PreferenceService } = require('@theia/core/lib/browser/preferences/preference-service');
25
+ const { PreferenceService } = require('@theia/core/lib/common/preferences/preference-service');
26
26
  const { Saveable, SaveableWidget } = require('@theia/core/lib/browser/saveable');
27
27
  const { WorkspaceService } = require('@theia/workspace/lib/browser/workspace-service');
28
28
  const { FileService } = require('@theia/filesystem/lib/browser/file-service');
29
29
  const { FileResource } = require('@theia/filesystem/lib/browser/file-resource');
30
30
  const { ETAG_DISABLED } = require('@theia/filesystem/lib/common/files');
31
31
  const { MonacoEditor } = require('@theia/monaco/lib/browser/monaco-editor');
32
- const { Deferred } = require('@theia/core/lib/common/promise-util');
32
+ const { Deferred, timeout } = require('@theia/core/lib/common/promise-util');
33
33
  const { Disposable, DisposableCollection } = require('@theia/core/lib/common/disposable');
34
34
  const { Range } = require('@theia/monaco-editor-core/esm/vs/editor/common/core/range');
35
35
 
@@ -38,7 +38,7 @@ describe('Saveable', function () {
38
38
  const editorManager = container.get(EditorManager);
39
39
  const workspaceService = container.get(WorkspaceService);
40
40
  const fileService = container.get(FileService);
41
- /** @type {import('@theia/core/lib/browser/preferences/preference-service').PreferenceService} */
41
+ /** @type {import('@theia/core/lib/common/preferences/preference-service').PreferenceService} */
42
42
  const preferences = container.get(PreferenceService);
43
43
 
44
44
  /** @type {EditorWidget & SaveableWidget} */
@@ -73,9 +73,19 @@ describe('Saveable', function () {
73
73
  await preferences.set('files.autoSave', 'off', undefined, rootUri.toString());
74
74
  await preferences.set(closeOnFileDelete, true);
75
75
  await editorManager.closeAll({ save: false });
76
+ const watcher = fileService.watch(fileUri); // create/delete events are sometimes coalesced on Mac
77
+ const gotCreate = new Deferred();
78
+ const listener = fileService.onDidFilesChange(e => {
79
+ if (e.contains(fileUri, { type: 1 })) { // FileChangeType.ADDED
80
+ gotCreate.resolve();
81
+ }
82
+ });
76
83
  await fileService.create(fileUri, 'foo', { fromUserGesture: false, overwrite: true });
77
- widget = /** @type {EditorWidget & SaveableWidget} */
78
- (await editorManager.open(fileUri, { mode: 'reveal' }));
84
+ await Promise.race([await timeout(2000), gotCreate.promise]);
85
+ watcher.dispose();
86
+ listener.dispose();
87
+
88
+ widget = /** @type {EditorWidget & SaveableWidget} */ (await editorManager.open(fileUri, { mode: 'reveal' }));
79
89
  editor = /** @type {MonacoEditor} */ (MonacoEditor.get(widget));
80
90
  });
81
91
 
@@ -499,5 +509,4 @@ describe('Saveable', function () {
499
509
  listener.dispose();
500
510
  }
501
511
  });
502
-
503
512
  });
package/src/scm.spec.js CHANGED
@@ -14,12 +14,13 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+ const { timeout } = require('@theia/core/lib/common/promise-util');
18
+
17
19
  // @ts-check
18
20
  describe('SCM', function () {
19
21
 
20
22
  const { assert } = chai;
21
23
 
22
- const { animationFrame } = require('@theia/core/lib/browser/browser');
23
24
  const { HostedPluginSupport } = require('@theia/plugin-ext/lib/hosted/browser/hosted-plugin');
24
25
  const Uri = require('@theia/core/lib/common/uri');
25
26
  const { ApplicationShell } = require('@theia/core/lib/browser/shell/application-shell');
@@ -55,30 +56,20 @@ describe('SCM', function () {
55
56
  * @param {string | undefined} [message]
56
57
  * @returns {Promise<void>}
57
58
  */
58
- function waitForAnimation(condition, timeout, message) {
59
- const success = new Promise(async (resolve, reject) => {
60
- if (timeout === undefined) {
61
- timeout = 100000;
59
+ async function waitForAnimation(condition, maxWait, message) {
60
+ if (maxWait === undefined) {
61
+ maxWait = 100000;
62
+ }
63
+ const endTime = Date.now() + maxWait;
64
+ do {
65
+ await (timeout(100));
66
+ if (condition()) {
67
+ return true;
62
68
  }
63
-
64
- let timedOut = false;
65
- const handle = setTimeout(() => {
66
- console.log(message);
67
- timedOut = true;
68
- }, timeout);
69
-
70
- do {
71
- await animationFrame();
72
- } while (!timedOut && !condition());
73
- if (timedOut) {
74
- reject(new Error(message ?? 'Wait for animation timed out.'));
75
- } else {
76
- clearTimeout(handle);
77
- resolve(undefined);
69
+ if (Date.now() > endTime) {
70
+ throw new Error(message ?? 'Wait for animation timed out.');
78
71
  }
79
-
80
- });
81
- return success;
72
+ } while (true);
82
73
  }
83
74
 
84
75
 
@@ -16,10 +16,11 @@
16
16
 
17
17
  // @ts-check
18
18
  describe('TypeScript', function () {
19
- this.timeout(200_000);
19
+ this.timeout(360_000);
20
20
 
21
21
  const { assert } = chai;
22
22
  const { timeout } = require('@theia/core/lib/common/promise-util');
23
+ const { MenuModelRegistry } = require('@theia/core/lib/common/menu/menu-model-registry');
23
24
 
24
25
  const Uri = require('@theia/core/lib/common/uri');
25
26
  const { DisposableCollection } = require('@theia/core/lib/common/disposable');
@@ -34,8 +35,8 @@ describe('TypeScript', function () {
34
35
  const { CommandRegistry } = require('@theia/core/lib/common/command');
35
36
  const { KeybindingRegistry } = require('@theia/core/lib/browser/keybinding');
36
37
  const { OpenerService, open } = require('@theia/core/lib/browser/opener-service');
37
- const { animationFrame } = require('@theia/core/lib/browser/browser');
38
- const { PreferenceService, PreferenceScope } = require('@theia/core/lib/browser/preferences/preference-service');
38
+ const { PreferenceService } = require('@theia/core/lib/common/preferences/preference-service');
39
+ const { PreferenceScope } = require('@theia/core/lib/common/preferences/preference-scope');
39
40
  const { ProgressStatusBarItem } = require('@theia/core/lib/browser/progress-status-bar-item');
40
41
  const { PluginViewRegistry } = require('@theia/plugin-ext/lib/main/browser/view/plugin-view-registry');
41
42
  const { Range } = require('@theia/monaco-editor-core/esm/vs/editor/common/core/range');
@@ -45,13 +46,14 @@ describe('TypeScript', function () {
45
46
  const editorManager = container.get(EditorManager);
46
47
  const workspaceService = container.get(WorkspaceService);
47
48
  const menuFactory = container.get(BrowserMainMenuFactory);
49
+ const menuRegistry = container.get(MenuModelRegistry);
48
50
  const pluginService = container.get(HostedPluginSupport);
49
51
  const contextKeyService = container.get(ContextKeyService);
50
52
  const commands = container.get(CommandRegistry);
51
53
  const openerService = container.get(OpenerService);
52
54
  /** @type {KeybindingRegistry} */
53
55
  const keybindings = container.get(KeybindingRegistry);
54
- /** @type {import('@theia/core/lib/browser/preferences/preference-service').PreferenceService} */
56
+ /** @type {import('@theia/core/lib/common/preferences/preference-service').PreferenceService} */
55
57
  const preferences = container.get(PreferenceService);
56
58
  const progressStatusBarItem = container.get(ProgressStatusBarItem);
57
59
  /** @type {PluginViewRegistry} */
@@ -59,7 +61,6 @@ describe('TypeScript', function () {
59
61
 
60
62
  const typescriptPluginId = 'vscode.typescript-language-features';
61
63
  const referencesPluginId = 'vscode.references-view';
62
- const eslintPluginId = 'dbaeumer.vscode-eslint';
63
64
  /** @type Uri.URI */
64
65
  const rootUri = workspaceService.tryGetRoots()[0].resource;
65
66
  const demoFileUri = rootUri.resolveToAbsolute('../api-tests/test-ts-workspace/demo-file.ts');
@@ -68,7 +69,7 @@ describe('TypeScript', function () {
68
69
 
69
70
  before(async function () {
70
71
  await pluginService.didStart;
71
- await Promise.all([typescriptPluginId, referencesPluginId, eslintPluginId].map(async pluginId => {
72
+ await Promise.all([typescriptPluginId, referencesPluginId].map(async pluginId => {
72
73
  if (!pluginService.getPlugin(pluginId)) {
73
74
  throw new Error(pluginId + ' should be started');
74
75
  }
@@ -123,43 +124,33 @@ describe('TypeScript', function () {
123
124
  assert.isDefined(editor);
124
125
  // wait till tsserver is running, see:
125
126
  // https://github.com/microsoft/vscode/blob/93cbbc5cae50e9f5f5046343c751b6d010468200/extensions/typescript-language-features/src/extension.ts#L98-L103
126
- await waitForAnimation(() => contextKeyService.match('typescript.isManagedFile'));
127
+ await waitForAnimation(() => contextKeyService.match('typescript.isManagedFile'), 1000000, 'waiting for "typescript.isManagedFile"');
127
128
 
128
129
  waitLanguageServerReady();
129
130
  return /** @type {MonacoEditor} */ (editor);
130
131
  }
131
132
 
133
+
132
134
  /**
133
- * @param {() => Promise<unknown> | unknown} condition
134
- * @param {number | undefined} [timeout]
135
- * @param {string | undefined} [message]
136
- * @returns {Promise<void>}
137
- */
138
- function waitForAnimation(condition, timeout, message) {
139
- const success = new Promise(async (resolve, reject) => {
140
- if (timeout === undefined) {
141
- timeout = 100000;
135
+ * @param {() => unknown} condition
136
+ * @param {number | undefined} [maxWait]
137
+ * @param {string | function | undefined} [message]
138
+ * @returns {Promise<void>}
139
+ */
140
+ async function waitForAnimation(condition, maxWait, message) {
141
+ if (maxWait === undefined) {
142
+ maxWait = 100000;
143
+ }
144
+ const endTime = Date.now() + maxWait;
145
+ do {
146
+ await (timeout(100));
147
+ if (condition()) {
148
+ return;
142
149
  }
143
-
144
- let timedOut = false;
145
- const handle = setTimeout(() => {
146
- console.log(message);
147
- timedOut = true;
148
- }, timeout);
149
-
150
- toTearDown.push({ dispose: () => reject(message ?? 'Test terminated before resolution.') });
151
- do {
152
- await animationFrame();
153
- } while (!timedOut && !condition());
154
- if (timedOut) {
155
- reject(new Error(message ?? 'Wait for animation timed out.'));
156
- } else {
157
- clearTimeout(handle);
158
- resolve(undefined);
150
+ if (Date.now() > endTime) {
151
+ throw new Error((typeof message === 'function' ? message() : message) ?? 'Wait for animation timed out.');
159
152
  }
160
-
161
- });
162
- return success;
153
+ } while (true);
163
154
  }
164
155
 
165
156
  /**
@@ -170,6 +161,9 @@ describe('TypeScript', function () {
170
161
  * @returns {string}
171
162
  */
172
163
  function nodeAsString(element, indentation = '') {
164
+ if (!element) {
165
+ return '';
166
+ }
173
167
  const header = element.tagName;
174
168
  let body = '';
175
169
  const childIndentation = indentation + ' ';
@@ -237,13 +231,13 @@ describe('TypeScript', function () {
237
231
 
238
232
  it('document formatting should be visible and enabled', async function () {
239
233
  await openEditor(demoFileUri);
240
- const menu = menuFactory.createContextMenu(EDITOR_CONTEXT_MENU);
234
+ const menu = menuFactory.createContextMenu(EDITOR_CONTEXT_MENU, menuRegistry.getMenu(EDITOR_CONTEXT_MENU), contextKeyService);
241
235
  const item = menu.items.find(i => i.command === 'editor.action.formatDocument');
242
236
  if (item) {
243
- assert.isTrue(item.isVisible);
244
- assert.isTrue(item.isEnabled);
237
+ assert.isTrue(item.isVisible, 'item is visible');
238
+ assert.isTrue(item.isEnabled, 'item is enabled');
245
239
  } else {
246
- assert.isDefined(item);
240
+ assert.isDefined(item, 'item is defined');
247
241
  }
248
242
  });
249
243
 
@@ -253,8 +247,8 @@ describe('TypeScript', function () {
253
247
  it('within ' + from, async function () {
254
248
  const editor = await openEditor(demoFileUri, preview);
255
249
  // const demoInstance = new Demo|Class('demo');
256
- editor.getControl().setPosition({ lineNumber: 24, column: 30 });
257
- assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'DemoClass');
250
+ editor.getControl().setPosition({ lineNumber: 28, column: 5 });
251
+ assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'demoVariable');
258
252
 
259
253
  await commands.executeCommand('editor.action.revealDefinition');
260
254
 
@@ -263,8 +257,8 @@ describe('TypeScript', function () {
263
257
  assert.equal(activeEditor.uri.toString(), demoFileUri.toString());
264
258
  // constructor(someString: string) {
265
259
  const { lineNumber, column } = activeEditor.getControl().getPosition();
266
- assert.deepEqual({ lineNumber, column }, { lineNumber: 11, column: 5 });
267
- assert.equal(activeEditor.getControl().getModel().getWordAtPosition({ lineNumber, column }).word, 'constructor');
260
+ assert.deepEqual({ lineNumber, column }, { lineNumber: 26, column: 7 });
261
+ assert.equal(activeEditor.getControl().getModel().getWordAtPosition({ lineNumber, column }).word, 'demoVariable');
268
262
  });
269
263
 
270
264
  // Note: this test generate annoying but apparently harmless error traces, during cleanup:
@@ -410,7 +404,7 @@ describe('TypeScript', function () {
410
404
  const suggestController = editor.getControl().getContribution('editor.contrib.suggestController');
411
405
 
412
406
  waitForAnimation(() => {
413
- const content = nodeAsString(suggestController ? ['_widget']?.['_value']?.['element']?.['domNode']);
407
+ const content = suggestController ? nodeAsString(suggestController['_widget']?.['_value']?.['element']?.['domNode']) : '';
414
408
  return !content.includes('loading');
415
409
  });
416
410
 
@@ -574,8 +568,8 @@ describe('TypeScript', function () {
574
568
  editor.getControl().setPosition({ lineNumber: 8, column: 7 });
575
569
  assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'DemoClass');
576
570
 
577
- /** @type {import('@theia/monaco-editor-core/src/vs/editor/contrib/hover/browser/hover').ModesHoverController} */
578
- const hover = editor.getControl().getContribution('editor.contrib.hover');
571
+ /** @type {import('@theia/monaco-editor-core/src/vs/editor/contrib/hover/browser/contentHoverController').ContentHoverController} */
572
+ const hover = editor.getControl().getContribution('editor.contrib.contentHover');
579
573
 
580
574
  assert.isTrue(contextKeyService.match('editorTextFocus'));
581
575
  assert.isFalse(contextKeyService.match('editorHoverVisible'));
@@ -586,34 +580,14 @@ describe('TypeScript', function () {
586
580
  assert.isTrue(contextKeyService.match('editorTextFocus'));
587
581
 
588
582
  waitForAnimation(() => {
589
- const content = nodeAsString(hover['_contentWidget']?.['_widget']?.['_hover']?.['contentsDomNode']);
583
+ const content = nodeAsString(hover['_contentWidget']?.['widget']?.['_hover']?.['contentsDomNode']);
590
584
  return !content.includes('loading');
591
585
  });
592
586
 
593
- assert.deepEqual(nodeAsString(hover['_contentWidget']?.['_widget']?.['_hover']?.['contentsDomNode']).trim(), `
594
- DIV {
595
- DIV {
596
- DIV {
597
- DIV {
598
- DIV {
599
- SPAN {
600
- DIV {
601
- SPAN {
602
- "class"
603
- }
604
- SPAN {
605
- " "
606
- }
607
- SPAN {
608
- "DemoClass"
609
- }
610
- }
611
- }
612
- }
613
- }
614
- }
615
- }
616
- }`.trim());
587
+ const content = nodeAsString(hover['_contentWidget']?.['widget']?.['_hover']?.['contentsDomNode']);
588
+
589
+ assert.isTrue(content.includes('class', 'did not include'));
590
+ assert.isTrue(content.includes('DemoClass', 'did not include'));
617
591
  await dismissWithEscape('editorHoverVisible');
618
592
  assert.isTrue(contextKeyService.match('editorTextFocus'));
619
593
  assert.isFalse(Boolean(hover['_contentWidget']?.['_widget']?.['_visibleData']));
@@ -751,6 +725,7 @@ SPAN {
751
725
  };
752
726
 
753
727
  await timeout(1000); // quick fix is always available: need to wait for the error fix to become available.
728
+
754
729
  await commands.executeCommand('editor.action.quickFix');
755
730
  const codeActionSelector = '.action-widget';
756
731
  assert.isFalse(!!document.querySelector(codeActionSelector), 'Failed at assert 3 - codeActionWidget should not be visible');
@@ -764,7 +739,7 @@ SPAN {
764
739
  }
765
740
  return true;
766
741
  }, 10000, 'Timed-out waiting for the QuickFix widget to appear');
767
- await animationFrame();
742
+ await timeout();
768
743
 
769
744
  assert.isTrue(lightBulbVisible(), 'Failed at assert 4');
770
745
  keybindings.dispatchKeyDown('Enter');
@@ -825,31 +800,28 @@ SPAN {
825
800
  const lightbulbVisibility = codeActionController['_lightBulbWidget'].rawValue?.['_domNode'].style.visibility;
826
801
  return lightbulbVisibility !== undefined && lightbulbVisibility !== 'hidden';
827
802
  }
828
- assert.isFalse(isActionAvailable());
829
803
  assert.strictEqual(editor.getControl().getModel().getLineContent(30), 'import { DefinedInterface } from "./demo-definitions-file";');
830
804
  editor.getControl().revealLine(30);
831
805
  editor.getControl().setSelection(new Selection(30, 1, 30, 60));
832
806
  await waitForAnimation(() => isActionAvailable(), 5000, 'No code action available. (1)');
833
807
  assert.isTrue(isActionAvailable());
834
808
 
835
- try { // for some reason, we need to wait a second here, otherwise, we run into some cancellation.
836
- await waitForAnimation(() => false, 1000);
837
- } catch (e) {
838
- }
809
+ await timeout(1000)
839
810
 
840
811
  await commands.executeCommand('editor.action.quickFix');
841
812
  await waitForAnimation(() => {
842
813
  const elements = document.querySelector('.action-widget');
843
814
  return !!elements;
844
815
  }, 5000, 'No context menu appeared. (1)');
845
- await animationFrame();
816
+
817
+ await timeout();
846
818
 
847
819
  keybindings.dispatchKeyDown('Enter');
848
820
 
849
821
  assert.isNotNull(editor.getControl());
850
822
  assert.isNotNull(editor.getControl().getModel());
851
823
  console.log(`content: ${editor.getControl().getModel().getLineContent(30)}`);
852
- await waitForAnimation(() => editor.getControl().getModel().getLineContent(30) === 'import * as demoDefinitionsFile from "./demo-definitions-file";', 5000, 'The namespace import did not take effect.');
824
+ await waitForAnimation(() => editor.getControl().getModel().getLineContent(30) === 'import * as demoDefinitionsFile from "./demo-definitions-file";', 5000, 'The namespace import did not take effect :' + editor.getControl().getModel().getLineContent(30));
853
825
 
854
826
  // momentarily toggle selection, waiting for code action to become unavailable.
855
827
  // Without doing this, the call to the quickfix command would sometimes fail because of an
@@ -875,13 +847,13 @@ SPAN {
875
847
  // Change import back: https://github.com/eclipse-theia/theia/issues/11059
876
848
  await commands.executeCommand('editor.action.quickFix');
877
849
  await waitForAnimation(() => Boolean(document.querySelector('.context-view-pointerBlock')), 5000, 'No context menu appeared. (2)');
878
- await animationFrame();
850
+ await timeout();
879
851
 
880
852
  keybindings.dispatchKeyDown('Enter');
881
853
 
882
854
  assert.isNotNull(editor.getControl());
883
855
  assert.isNotNull(editor.getControl().getModel());
884
- await waitForAnimation(() => editor.getControl().getModel().getLineContent(30) === 'import { DefinedInterface } from "./demo-definitions-file";', 5000, 'The named import did not take effect.');
856
+ await waitForAnimation(() => editor.getControl().getModel().getLineContent(30) === 'import { DefinedInterface } from "./demo-definitions-file";', 10000, () => 'The named import did not take effect.' + editor.getControl().getModel().getLineContent(30));
885
857
  });
886
858
 
887
859
  for (const referenceViewCommand of ['references-view.find', 'references-view.findImplementations']) {
@@ -14,13 +14,14 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+
17
18
  // @ts-check
18
19
  describe('Undo, Redo and Select All', function () {
19
20
  this.timeout(5000);
20
21
 
21
22
  const { assert } = chai;
22
23
 
23
- const { animationFrame } = require('@theia/core/lib/browser/browser');
24
+ const { timeout } = require('@theia/core/lib/common/promise-util');
24
25
  const { DisposableCollection } = require('@theia/core/lib/common/disposable');
25
26
  const { CommonCommands } = require('@theia/core/lib/browser/common-frontend-contribution');
26
27
  const { EditorManager } = require('@theia/editor/lib/browser/editor-manager');
@@ -51,22 +52,32 @@ describe('Undo, Redo and Select All', function () {
51
52
  const toTearDown = new DisposableCollection();
52
53
 
53
54
  /**
54
- * @template T
55
- * @param {() => Promise<T> | T} condition
56
- * @returns {Promise<T>}
57
- */
58
- function waitForAnimation(condition) {
59
- return new Promise(async (resolve, dispose) => {
60
- toTearDown.push({ dispose });
61
- do {
62
- await animationFrame();
63
- } while (!condition());
64
- resolve(undefined);
65
- });
55
+ * @param {() => unknown} condition
56
+ * @param {number | undefined} [maxWait]
57
+ * @param {string | undefined} [message]
58
+ * @returns {Promise<void>}
59
+ */
60
+ async function waitForAnimation(condition, maxWait, message) {
61
+ if (maxWait === undefined) {
62
+ maxWait = 100000;
63
+ }
64
+ const endTime = Date.now() + maxWait;
65
+ do {
66
+ await (timeout(100));
67
+ if (condition()) {
68
+ return true;
69
+ }
70
+ if (Date.now() > endTime) {
71
+ throw new reject(new Error(message ?? 'Wait for animation timed out.'));
72
+ }
73
+ } while (true);
66
74
  }
75
+
67
76
  const originalValue = preferenceService.get('files.autoSave', undefined, rootUri.toString());
68
77
  before(async () => {
69
78
  await preferenceService.set('files.autoSave', 'off', undefined, rootUri.toString());
79
+ await preferenceService.set('git.autoRepositoryDetection', true);
80
+ await preferenceService.set('git.openRepositoryInParentFolders', 'always');
70
81
  shell.leftPanelHandler.collapse();
71
82
  });
72
83
 
@@ -157,25 +168,25 @@ describe('Undo, Redo and Select All', function () {
157
168
 
158
169
  keybindings.dispatchCommand(CommonCommands.UNDO.id);
159
170
  await waitForAnimation(() => scmInput.value === originalValue);
160
- assert.equal(scmInput.value, originalValue);
171
+ assert.equal(scmInput.value, originalValue, 'value equal');
161
172
 
162
173
  keybindings.dispatchCommand(CommonCommands.REDO.id);
163
174
  await waitForAnimation(() => scmInput.value === modifiedValue);
164
- assert.equal(scmInput.value, modifiedValue);
175
+ assert.equal(scmInput.value, modifiedValue, 'value not equal');
165
176
 
166
177
  const selection = document.getSelection();
167
178
  if (!selection) {
168
- assert.isDefined(selection);
179
+ assert.isDefined(selection, 'selection defined');
169
180
  return;
170
181
  }
171
182
 
172
183
  selection.empty();
173
- assert.equal(selection.rangeCount, 0);
184
+ assert.equal(selection.rangeCount, 0, 'rangeCount equal');
174
185
 
175
186
  keybindings.dispatchCommand(CommonCommands.SELECT_ALL.id);
176
187
  await waitForAnimation(() => !!selection.rangeCount);
177
- assert.notEqual(selection.rangeCount, 0);
178
- assert.isTrue(selection.containsNode(scmInput));
188
+ assert.notEqual(selection.rangeCount, 0, 'rangeCount not equal');
189
+ assert.isTrue(selection.containsNode(scmInput), 'selection contains');
179
190
  }
180
191
 
181
192
  it('in the active scm in workspace without the current editor', async function () {
package/src/views.spec.js CHANGED
@@ -14,7 +14,6 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- const { timeout } = require('@theia/core/lib/common/promise-util');
18
17
 
19
18
  // @ts-check
20
19
  describe('Views', function () {
@@ -22,6 +21,7 @@ describe('Views', function () {
22
21
 
23
22
  const { assert } = chai;
24
23
 
24
+ const { timeout } = require('@theia/core/lib/common/promise-util');
25
25
  const { ApplicationShell } = require('@theia/core/lib/browser/shell/application-shell');
26
26
  const { FileNavigatorContribution } = require('@theia/navigator/lib/browser/navigator-contribution');
27
27
  const { ScmContribution } = require('@theia/scm/lib/browser/scm-contribution');