diff --git a/news/3 Code Health/3684.md b/news/3 Code Health/3684.md new file mode 100644 index 000000000000..f200fa0fbef7 --- /dev/null +++ b/news/3 Code Health/3684.md @@ -0,0 +1 @@ +Fixed language server smoke tests. diff --git a/src/test/smoke/_run_first_msLanguageServer.smoke.test.ts b/src/test/smoke/_run_first_msLanguageServer.smoke.test.ts deleted file mode 100644 index ce42dc937372..000000000000 --- a/src/test/smoke/_run_first_msLanguageServer.smoke.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -// tslint:disable:max-func-body-length no-invalid-this no-any - -import * as assert from 'assert'; -import { expect } from 'chai'; -import * as fs from 'fs-extra'; -import * as glob from 'glob'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { waitForCondition } from '../common'; -import { EXTENSION_ROOT_DIR_FOR_TESTS, IS_SMOKE_TEST, SMOKE_TEST_EXTENSIONS_DIR } from '../constants'; -import { noop, sleep } from '../core'; -import { closeActiveWindows, initialize, initializeTest } from '../initialize'; - -const fileDefinitions = path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'src', 'testMultiRootWkspc', 'smokeTests', 'definitions.py'); - -suite('Smoke Test: Language Server', function () { - // Large value to allow for LS to get downloaded. - this.timeout(4 * 60000); - - suiteSetup(async function () { - if (!IS_SMOKE_TEST) { - return this.skip(); - } - await removeLanguageServerFiles(); - await enableJedi(false); - await updateSetting('linting.ignorePatterns', ['**/dir1/**']); - await initialize(); - }); - setup(initializeTest); - suiteTeardown(async () => { - await enableJedi(undefined); - await closeActiveWindows(); - await updateSetting('linting.ignorePatterns', undefined); - }); - teardown(closeActiveWindows); - async function updateSetting(setting: string, value: any) { - const resource = vscode.workspace.workspaceFolders![0].uri; - await vscode.workspace.getConfiguration('python', resource).update(setting, value, vscode.ConfigurationTarget.WorkspaceFolder); - } - async function removeLanguageServerFiles() { - const folders = await getLanaguageServerFolders(); - await Promise.all(folders.map(item => fs.remove(item).catch(noop))); - } - async function isLanguageServerDownloaded() { - // tslint:disable-next-line:no-unnecessary-local-variable - const downloaded = await getLanaguageServerFolders().then(items => items.length > 0); - return downloaded; - } - async function getLanaguageServerFolders(): Promise { - return new Promise((resolve, reject) => { - glob('languageServer.*', { cwd: SMOKE_TEST_EXTENSIONS_DIR }, (ex, matches) => { - ex ? reject(ex) : resolve(matches.map(item => path.join(SMOKE_TEST_EXTENSIONS_DIR, item))); - }); - }); - } - function isJediEnabled() { - const resource = vscode.workspace.workspaceFolders![0].uri; - const settings = vscode.workspace.getConfiguration('python', resource); - return settings.get('jediEnabled') === true; - } - async function enableJedi(enable: boolean | undefined) { - if (isJediEnabled() === enable) { - return; - } - await updateSetting('jediEnabled', enable); - } - - async function openFile(file: string): Promise { - const textDocument = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(textDocument); - assert(vscode.window.activeTextEditor, 'No active editor'); - // Make sure LS completes file loading and analysis. - // In test mode it awaits for the completion before trying - // to fetch data for completion, hover.etc. - await vscode.commands.executeCommand('vscode.executeCompletionItemProvider', textDocument.uri, new vscode.Position(0, 0)); - await waitForCondition(isLanguageServerDownloaded, 30_000, 'Language Server not downloaded'); - // For for LS to get extracted. - await sleep(10_000); - return textDocument; - } - - test('Definitions', async () => { - const startPosition = new vscode.Position(13, 6); - const textDocument = await openFile(fileDefinitions); - let tested = false; - for (let i = 0; i < 5; i += 1) { - const locations = await vscode.commands.executeCommand('vscode.executeDefinitionProvider', textDocument.uri, startPosition); - if (locations && locations.length > 0) { - expect(locations![0].uri.fsPath).to.contain(path.basename(fileDefinitions)); - tested = true; - break; - } else { - // Wait for LS to start. - await sleep(5_000); - } - } - if (!tested) { - assert.fail('Failled to test definitions'); - } - }); -}); diff --git a/src/test/smoke/common.ts b/src/test/smoke/common.ts new file mode 100644 index 000000000000..0b8bfe2e62a5 --- /dev/null +++ b/src/test/smoke/common.ts @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +// tslint:disable:no-any no-invalid-this no-default-export no-console + +import * as assert from 'assert'; +import * as fs from 'fs-extra'; +import * as glob from 'glob'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import { waitForCondition } from '../common'; +import { EXTENSION_ROOT_DIR_FOR_TESTS, IS_SMOKE_TEST, SMOKE_TEST_EXTENSIONS_DIR } from '../constants'; +import { noop, sleep } from '../core'; +import { initialize } from '../initialize'; + +let initialized = false; +const fileDefinitions = path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'src', 'testMultiRootWkspc', 'smokeTests', 'definitions.py'); + +export async function initializeSmokeTests() { + if (!IS_SMOKE_TEST || initialized) { + return; + } + await removeLanguageServerFiles(); + await enableJedi(false); + await initialize(); + await openFileAndWaitForLS(fileDefinitions); + initialized = true; +} + +export async function updateSetting(setting: string, value: any) { + const resource = vscode.workspace.workspaceFolders![0].uri; + await vscode.workspace.getConfiguration('python', resource).update(setting, value, vscode.ConfigurationTarget.WorkspaceFolder); +} +export async function removeLanguageServerFiles() { + const folders = await getLanaguageServerFolders(); + await Promise.all(folders.map(item => fs.remove(item).catch(noop))); +} +async function getLanaguageServerFolders(): Promise { + return new Promise((resolve, reject) => { + glob('languageServer.*', { cwd: SMOKE_TEST_EXTENSIONS_DIR }, (ex, matches) => { + ex ? reject(ex) : resolve(matches.map(item => path.join(SMOKE_TEST_EXTENSIONS_DIR, item))); + }); + }); +} +export function isJediEnabled() { + const resource = vscode.workspace.workspaceFolders![0].uri; + const settings = vscode.workspace.getConfiguration('python', resource); + return settings.get('jediEnabled') === true; +} +export async function enableJedi(enable: boolean | undefined) { + if (isJediEnabled() === enable) { + return; + } + await updateSetting('jediEnabled', enable); +} +export async function openFileAndWaitForLS(file: string): Promise { + const textDocument = await vscode.workspace.openTextDocument(file); + await vscode.window.showTextDocument(textDocument); + assert(vscode.window.activeTextEditor, 'No active editor'); + // Make sure LS completes file loading and analysis. + // In test mode it awaits for the completion before trying + // to fetch data for completion, hover.etc. + await vscode.commands.executeCommand('vscode.executeCompletionItemProvider', textDocument.uri, new vscode.Position(0, 0)); + await waitForCondition(isLanguageServerDownloaded, 30_000, 'Language Server not downloaded'); + // For for LS to get extracted. + await sleep(10_000); + return textDocument; +} + +async function isLanguageServerDownloaded() { + // tslint:disable-next-line:no-unnecessary-local-variable + const downloaded = await getLanaguageServerFolders().then(items => items.length > 0); + return downloaded; +} diff --git a/src/test/smoke/debugger.smoke.test.ts b/src/test/smoke/debugger.smoke.test.ts index 3d58ca8ec371..1d4f0c08c314 100644 --- a/src/test/smoke/debugger.smoke.test.ts +++ b/src/test/smoke/debugger.smoke.test.ts @@ -12,15 +12,17 @@ import * as vscode from 'vscode'; import { openFile, waitForCondition } from '../common'; import { EXTENSION_ROOT_DIR_FOR_TESTS, IS_SMOKE_TEST } from '../constants'; import { closeActiveWindows, initializeTest } from '../initialize'; +import { initializeSmokeTests } from './common'; suite('Smoke Test: Debug file', function () { // Large value to allow for LS to get downloaded. this.timeout(4 * 60_000); - suiteSetup(function () { + suiteSetup(async function () { if (!IS_SMOKE_TEST) { return this.skip(); } + await initializeSmokeTests(); }); setup(initializeTest); suiteTeardown(closeActiveWindows); diff --git a/src/test/smoke/msLanguageServer.smoke.test.ts b/src/test/smoke/msLanguageServer.smoke.test.ts new file mode 100644 index 000000000000..c409d63c459c --- /dev/null +++ b/src/test/smoke/msLanguageServer.smoke.test.ts @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +// tslint:disable:max-func-body-length no-invalid-this no-any + +import * as assert from 'assert'; +import { expect } from 'chai'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import { updateSetting } from '../common'; +import { EXTENSION_ROOT_DIR_FOR_TESTS, IS_SMOKE_TEST } from '../constants'; +import { sleep } from '../core'; +import { closeActiveWindows, initializeTest } from '../initialize'; +import { enableJedi, initializeSmokeTests, openFileAndWaitForLS } from './common'; + +const fileDefinitions = path.join(EXTENSION_ROOT_DIR_FOR_TESTS, 'src', 'testMultiRootWkspc', 'smokeTests', 'definitions.py'); + +suite('Smoke Test: Language Server', function () { + // Large value to allow for LS to get downloaded. + this.timeout(4 * 60000); + + suiteSetup(async function () { + if (!IS_SMOKE_TEST) { + return this.skip(); + } + await updateSetting('linting.ignorePatterns', ['**/dir1/**'], vscode.workspace.workspaceFolders![0].uri, vscode.ConfigurationTarget.WorkspaceFolder); + await initializeSmokeTests(); + }); + setup(async () => { + await initializeTest(); + await closeActiveWindows(); + }); + suiteTeardown(async () => { + await enableJedi(undefined); + await closeActiveWindows(); + await updateSetting('linting.ignorePatterns', undefined, vscode.workspace.workspaceFolders![0].uri, vscode.ConfigurationTarget.WorkspaceFolder); + }); + teardown(closeActiveWindows); + + test('Definitions', async () => { + const startPosition = new vscode.Position(13, 6); + const textDocument = await openFileAndWaitForLS(fileDefinitions); + let tested = false; + for (let i = 0; i < 5; i += 1) { + const locations = await vscode.commands.executeCommand('vscode.executeDefinitionProvider', textDocument.uri, startPosition); + if (locations && locations.length > 0) { + expect(locations![0].uri.fsPath).to.contain(path.basename(fileDefinitions)); + tested = true; + break; + } else { + // Wait for LS to start. + await sleep(5_000); + } + } + if (!tested) { + assert.fail('Failled to test definitions'); + } + }); +}); diff --git a/src/test/smoke/runInTerminal.smoke.test.ts b/src/test/smoke/runInTerminal.smoke.test.ts index 003073403da1..7b5ca203f711 100644 --- a/src/test/smoke/runInTerminal.smoke.test.ts +++ b/src/test/smoke/runInTerminal.smoke.test.ts @@ -11,15 +11,17 @@ import * as vscode from 'vscode'; import { openFile, waitForCondition } from '../common'; import { EXTENSION_ROOT_DIR_FOR_TESTS, IS_SMOKE_TEST } from '../constants'; import { closeActiveWindows, initializeTest } from '../initialize'; +import { initializeSmokeTests } from './common'; suite('Smoke Test: Run Python File In Terminal', function () { // Large value to allow for LS to get downloaded. this.timeout(4 * 60_000); - suiteSetup(function () { + suiteSetup(async function () { if (!IS_SMOKE_TEST) { return this.skip(); } + await initializeSmokeTests(); }); setup(initializeTest); suiteTeardown(closeActiveWindows);