Skip to content
This repository was archived by the owner on Nov 18, 2022. It is now read-only.

Commit b629400

Browse files
committed
Await active workspace being set in tests
1 parent 58ea299 commit b629400

File tree

2 files changed

+50
-15
lines changed

2 files changed

+50
-15
lines changed

src/extension.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function onDidChangeActiveTextEditor(editor: TextEditor | undefined) {
106106
return;
107107
}
108108

109-
activeWorkspace = workspace;
109+
activeWorkspace.value = workspace;
110110

111111
const updateProgress = (progress: WorkspaceProgress) => {
112112
if (progress.state === 'progress') {
@@ -121,9 +121,9 @@ function onDidChangeActiveTextEditor(editor: TextEditor | undefined) {
121121
if (progressObserver) {
122122
progressObserver.dispose();
123123
}
124-
progressObserver = activeWorkspace.progress.observe(updateProgress);
124+
progressObserver = workspace.progress.observe(updateProgress);
125125
// Update UI ourselves immediately and don't wait for value update callbacks
126-
updateProgress(activeWorkspace.progress.value);
126+
updateProgress(workspace.progress.value);
127127
}
128128

129129
function whenChangingWorkspaceFolders(e: WorkspaceFoldersChangeEvent) {
@@ -176,7 +176,7 @@ type WorkspaceProgress =
176176
// We run one RLS and one corresponding language client per workspace folder
177177
// (VSCode workspace, not Cargo workspace). This class contains all the per-client
178178
// and per-workspace stuff.
179-
class ClientWorkspace {
179+
export class ClientWorkspace {
180180
public readonly folder: WorkspaceFolder;
181181
// FIXME(#233): Don't only rely on lazily initializing it once on startup,
182182
// handle possible `rust-client.*` value changes while extension is running
@@ -440,7 +440,7 @@ class ClientWorkspace {
440440
* Tracks the most current VSCode workspace as opened by the user. Used by the
441441
* commands to know in which workspace these should be executed.
442442
*/
443-
let activeWorkspace: ClientWorkspace | null;
443+
const activeWorkspace = new Observable<ClientWorkspace | null>(null);
444444

445445
/**
446446
* Registers the VSCode [commands] used by the extension.
@@ -451,23 +451,24 @@ function registerCommands(): Disposable[] {
451451
return [
452452
commands.registerCommand(
453453
'rls.update',
454-
() => activeWorkspace && activeWorkspace.rustupUpdate(),
454+
() => activeWorkspace.value && activeWorkspace.value.rustupUpdate(),
455455
),
456456
commands.registerCommand(
457457
'rls.restart',
458-
async () => activeWorkspace && activeWorkspace.restart(),
458+
async () => activeWorkspace.value && activeWorkspace.value.restart(),
459459
),
460460
commands.registerCommand(
461461
'rls.run',
462-
(cmd: Execution) => activeWorkspace && activeWorkspace.runRlsCommand(cmd),
462+
(cmd: Execution) =>
463+
activeWorkspace.value && activeWorkspace.value.runRlsCommand(cmd),
463464
),
464465
commands.registerCommand(
465466
'rls.start',
466-
() => activeWorkspace && activeWorkspace.start(),
467+
() => activeWorkspace.value && activeWorkspace.value.start(),
467468
),
468469
commands.registerCommand(
469470
'rls.stop',
470-
() => activeWorkspace && activeWorkspace.stop(),
471+
() => activeWorkspace.value && activeWorkspace.value.stop(),
471472
),
472473
];
473474
}

test/suite/extension.test.ts

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import * as assert from 'assert';
22
import * as path from 'path';
33
import * as vscode from 'vscode';
44
// tslint:disable-next-line: no-duplicate-imports
5-
import { Uri } from 'vscode';
5+
import { Disposable, Uri } from 'vscode';
6+
7+
import * as extension from '../../src/extension';
68

79
const fixtureDir = path.resolve(
810
path.join(__dirname, '..', '..', '..', 'fixtures'),
@@ -25,6 +27,10 @@ suite('Extension Tests', () => {
2527
];
2628

2729
await vscode.commands.executeCommand('vscode.openFolder', projectUri);
30+
const whenWorkspacesActive = projects.map(path => {
31+
const fsPath = Uri.file(path).fsPath;
32+
return whenWorkspaceActive(fsPath);
33+
});
2834

2935
// This makes sure that we set the focus on the opened files (which is what
3036
// actually triggers the extension for the project)
@@ -36,9 +42,9 @@ suite('Extension Tests', () => {
3642
'workbench.action.acceptSelectedQuickOpenItem',
3743
);
3844
await vscode.commands.executeCommand('workbench.action.keepEditor');
39-
// Unfortunately, we need to wait a bit for the extension to kick in :(
40-
// FIXME: See if we can directly import our extension and await its progress
41-
await new Promise(resolve => setTimeout(resolve, 500));
45+
// Wait until the first server is ready
46+
await Promise.race([whenWorkspacesActive[0], timeoutReject(3000)]);
47+
4248
assert(await currentTasksInclude([expected[0]]));
4349

4450
// Now test for the second project
@@ -49,7 +55,8 @@ suite('Extension Tests', () => {
4955
await vscode.commands.executeCommand(
5056
'workbench.action.acceptSelectedQuickOpenItem',
5157
);
52-
await new Promise(resolve => setTimeout(resolve, 500));
58+
// Wait until the second server is ready
59+
await Promise.race([whenWorkspacesActive[1], timeoutReject(3000)]);
5360
assert(await currentTasksInclude(expected));
5461
}).timeout(0);
5562
});
@@ -77,3 +84,30 @@ async function currentTasksInclude(
7784
),
7885
);
7986
}
87+
88+
/**
89+
* Returns a promise when a client workspace will become active with a given path.
90+
* @param fsPath normalized file system path of a URI
91+
*/
92+
function whenWorkspaceActive(
93+
fsPath: string,
94+
): Promise<extension.ClientWorkspace> {
95+
return new Promise(resolve => {
96+
let disposable: Disposable | undefined;
97+
disposable = extension.activeWorkspace.observe(value => {
98+
if (value && value.folder.uri.fsPath === fsPath) {
99+
if (disposable) {
100+
disposable.dispose();
101+
disposable = undefined;
102+
}
103+
104+
resolve(value);
105+
}
106+
});
107+
});
108+
}
109+
110+
const timeoutReject = (ms: number) =>
111+
new Promise((_, reject) =>
112+
setTimeout(() => reject(new Error('Timed out')), ms),
113+
);

0 commit comments

Comments
 (0)