From 07f42d15ea3480ef2d1bcf76f1ca486c9e567751 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Mon, 25 Oct 2021 16:52:16 -0700 Subject: [PATCH] Improve test stability with `ensureEditorServicesIsConnected` This uses a newly added `ExternalApi` function `waitUntilStarted` that ensures the LSP server (PowerShell session) is started after manually activating the extension. --- src/features/ExternalApi.ts | 38 +++++++++++++++++++++----- src/main.ts | 1 + test/core/paths.test.ts | 2 +- test/features/ISECompatibility.test.ts | 2 +- test/features/RunCode.test.ts | 4 +-- test/utils.ts | 9 ++++++ 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/features/ExternalApi.ts b/src/features/ExternalApi.ts index bd3d5969e7..f83c45680c 100644 --- a/src/features/ExternalApi.ts +++ b/src/features/ExternalApi.ts @@ -18,6 +18,7 @@ export interface IPowerShellExtensionClient { registerExternalExtension(id: string, apiVersion?: string): string; unregisterExternalExtension(uuid: string): boolean; getPowerShellVersionDetails(uuid: string): Promise; + waitUntilStarted(uuid: string): Promise; } /* @@ -99,6 +100,16 @@ export class ExternalApiFeature extends LanguageClientConsumer implements IPower return true; } + private getRegisteredExtension(uuid: string = ""): IExternalExtension { + if (!ExternalApiFeature.registeredExternalExtension.has(uuid)) { + throw new Error( + "UUID provided was invalid, make sure you ran the 'powershellExtensionClient.registerExternalExtension(extensionId)' method and pass in the UUID that it returns to subsequent methods."); + } + + // TODO: When we have more than one API version, make sure to include a check here. + return ExternalApiFeature.registeredExternalExtension.get(uuid); + } + /* DESCRIPTION: This will fetch the version details of the PowerShell used to start @@ -118,13 +129,7 @@ export class ExternalApiFeature extends LanguageClientConsumer implements IPower } */ public async getPowerShellVersionDetails(uuid: string = ""): Promise { - if (!ExternalApiFeature.registeredExternalExtension.has(uuid)) { - throw new Error( - "UUID provided was invalid, make sure you ran the 'powershellExtensionClient.registerExternalExtension(extensionId)' method and pass in the UUID that it returns to subsequent methods."); - } - - // TODO: When we have more than one API version, make sure to include a check here. - const extension = ExternalApiFeature.registeredExternalExtension.get(uuid); + const extension = this.getRegisteredExtension(uuid); this.log.writeDiagnostic(`Extension '${extension.id}' called 'getPowerShellVersionDetails'`); await this.sessionManager.waitUntilStarted(); @@ -137,6 +142,25 @@ export class ExternalApiFeature extends LanguageClientConsumer implements IPower architecture: versionDetails.architecture }; } + /* + DESCRIPTION: + This will wait until the extension's PowerShell session is started. + + USAGE: + powerShellExtensionClient.waitUntilStarted( + "uuid"); // the uuid from above for tracking purposes + + RETURNS: + A void promise that resolves only once the extension is started. + + If the extension is not started by some mechanism + then this will wait indefinitely. + */ + public async waitUntilStarted(uuid: string = ""): Promise { + const extension = this.getRegisteredExtension(uuid); + this.log.writeDiagnostic(`Extension '${extension.id}' called 'waitUntilStarted'`); + return this.sessionManager.waitUntilStarted(); + } public dispose() { // Nothing to dispose. diff --git a/src/main.ts b/src/main.ts index 109dcf3afd..9d0219d4d1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -175,6 +175,7 @@ export function activate(context: vscode.ExtensionContext): IPowerShellExtension registerExternalExtension: (id: string, apiVersion: string = 'v1') => externalApi.registerExternalExtension(id, apiVersion), unregisterExternalExtension: uuid => externalApi.unregisterExternalExtension(uuid), getPowerShellVersionDetails: uuid => externalApi.getPowerShellVersionDetails(uuid), + waitUntilStarted: uuid => externalApi.waitUntilStarted(uuid), }; } diff --git a/test/core/paths.test.ts b/test/core/paths.test.ts index ecd5b12b8f..e0f27c7515 100644 --- a/test/core/paths.test.ts +++ b/test/core/paths.test.ts @@ -8,7 +8,7 @@ import * as vscode from "vscode"; import utils = require("../utils"); describe("Path assumptions", function () { - before(utils.ensureExtensionIsActivated); + before(utils.ensureEditorServicesIsConnected); // TODO: This is skipped because it intereferes with other tests. Either // need to find a way to close the opened folder via a Code API, or find diff --git a/test/features/ISECompatibility.test.ts b/test/features/ISECompatibility.test.ts index 4a37d7f7cd..d93adca2e0 100644 --- a/test/features/ISECompatibility.test.ts +++ b/test/features/ISECompatibility.test.ts @@ -15,7 +15,7 @@ describe("ISE compatibility feature", function () { before(async function () { // Save user's current theme. currentTheme = await vscode.workspace.getConfiguration("workbench").get("colorTheme"); - await utils.ensureExtensionIsActivated(); + await utils.ensureEditorServicesIsConnected(); }); after(async function () { diff --git a/test/features/RunCode.test.ts b/test/features/RunCode.test.ts index a8ca51b39c..d016436fe0 100644 --- a/test/features/RunCode.test.ts +++ b/test/features/RunCode.test.ts @@ -19,7 +19,7 @@ enum LaunchType { } describe("RunCode feature", function () { - before(utils.ensureExtensionIsActivated); + before(utils.ensureEditorServicesIsConnected); it("Creates the launch config", function () { const commandToRun: string = "Invoke-Build"; @@ -49,8 +49,6 @@ describe("RunCode feature", function () { // Open the PowerShell file with Pester tests and then wait a while for // the extension to finish connecting to the server. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(pesterTests)); - // TODO: Find a non-sleep way to wait for the connection to establish. - await sleep(15000); // Now run the Pester tests, check the debugger started, wait a bit for // it to run, and then kill it for safety's sake. diff --git a/test/utils.ts b/test/utils.ts index dd3fd01624..c9710b5b71 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -5,6 +5,7 @@ import * as path from "path"; import * as vscode from "vscode"; +import { IPowerShellExtensionClient } from "../src/features/ExternalApi"; // This lets us test the rest of our path assumptions against the baseline of // this test file existing at `/out/test/utils.js`. @@ -18,3 +19,11 @@ export async function ensureExtensionIsActivated(): Promise { + const powershellExtension = await ensureExtensionIsActivated(); + const client = powershellExtension!.exports as IPowerShellExtensionClient; + const sessionId = client.registerExternalExtension(extensionId); + await client.waitUntilStarted(sessionId); + client.unregisterExternalExtension(sessionId); +}