diff --git a/Directory.Build.props b/Directory.Build.props
index 3720f4d06a..13843770d5 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -5,6 +5,7 @@
Defines the lowest supported target framework for the extension.
Used by server download / integration tests to ensure they run when only this SDK is installed.
-->
+ false
net6.0
-
\ No newline at end of file
+
diff --git a/azure-pipelines/test-matrix.yml b/azure-pipelines/test-matrix.yml
index d816d3b4a2..9ed473b712 100644
--- a/azure-pipelines/test-matrix.yml
+++ b/azure-pipelines/test-matrix.yml
@@ -21,10 +21,9 @@ jobs:
UnitTests:
npmCommand: test:unit
isIntegration: false
- ${{ if ne(parameters.os, 'windows') }}:
- CSharpIntegrationTests:
- npmCommand: test:integration:csharp
- isIntegration: true
+ CSharpIntegrationTests:
+ npmCommand: test:integration:csharp
+ isIntegration: true
DevKitTests:
npmCommand: test:integration:devkit
isIntegration: true
diff --git a/test/jestHelpers.ts b/test/jestHelpers.ts
new file mode 100644
index 0000000000..6935224baf
--- /dev/null
+++ b/test/jestHelpers.ts
@@ -0,0 +1,55 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as vscode from 'vscode';
+import { EOL, platform } from 'os';
+import { describe, expect, test } from '@jest/globals';
+import { usingDevKit } from './lsptoolshost/integrationTests/integrationHelpers';
+
+export async function expectText(document: vscode.TextDocument, expectedLines: string[]) {
+ const expectedText = expectedLines.join(EOL);
+ expect(document.getText()).toBe(expectedText);
+}
+
+export function expectPath(expected: vscode.Uri, actual: vscode.Uri) {
+ if (isLinux()) {
+ expect(actual.path).toBe(expected.path);
+ } else {
+ const actualPath = actual.path.toLowerCase();
+ const expectedPath = expected.path.toLocaleLowerCase();
+ expect(actualPath).toBe(expectedPath);
+ }
+}
+
+export const describeIfCSharp = describeIf(!usingDevKit());
+export const describeIfDevKit = describeIf(usingDevKit());
+export const describeIfNotMacOS = describeIf(!isMacOS());
+export const describeIfWindows = describeIf(isWindows());
+export const testIfCSharp = testIf(!usingDevKit());
+export const testIfDevKit = testIf(usingDevKit());
+export const testIfNotMacOS = testIf(!isMacOS());
+export const testIfWindows = testIf(isWindows());
+
+function describeIf(condition: boolean) {
+ return condition ? describe : describe.skip;
+}
+
+function testIf(condition: boolean) {
+ return condition ? test : test.skip;
+}
+
+function isMacOS() {
+ const currentPlatform = platform();
+ return currentPlatform === 'darwin';
+}
+
+function isWindows() {
+ const currentPlatform = platform();
+ return currentPlatform === 'win32';
+}
+
+function isLinux() {
+ return !(isMacOS() || isWindows());
+}
diff --git a/test/lsptoolshost/integrationTests/buildDiagnostics.integration.test.ts b/test/lsptoolshost/integrationTests/buildDiagnostics.integration.test.ts
index 7d49a91670..7e3dc5d81f 100644
--- a/test/lsptoolshost/integrationTests/buildDiagnostics.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/buildDiagnostics.integration.test.ts
@@ -12,6 +12,7 @@ import {
} from '../../../src/lsptoolshost/diagnostics/buildDiagnosticsService';
import * as integrationHelpers from './integrationHelpers';
import path from 'path';
+
describe(`Build and live diagnostics dedupe`, () => {
beforeAll(async () => {
await integrationHelpers.activateCSharpExtension();
diff --git a/test/lsptoolshost/integrationTests/codeactions.integration.test.ts b/test/lsptoolshost/integrationTests/codeactions.integration.test.ts
index e4b0c90bb5..a13a87f7ce 100644
--- a/test/lsptoolshost/integrationTests/codeactions.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/codeactions.integration.test.ts
@@ -7,12 +7,8 @@ import * as vscode from 'vscode';
import * as path from 'path';
import { describe, beforeAll, beforeEach, afterAll, test, expect, afterEach } from '@jest/globals';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
-import {
- activateCSharpExtension,
- closeAllEditorsAsync,
- expectText,
- openFileInWorkspaceAsync,
-} from './integrationHelpers';
+import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
+import { expectText } from '../../jestHelpers';
describe(`Code Actions Tests`, () => {
beforeAll(async () => {
diff --git a/test/lsptoolshost/integrationTests/commandEnablement.integration.test.ts b/test/lsptoolshost/integrationTests/commandEnablement.integration.test.ts
index c84d995fb1..ee0dbd1b54 100644
--- a/test/lsptoolshost/integrationTests/commandEnablement.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/commandEnablement.integration.test.ts
@@ -5,7 +5,7 @@
import { expect, beforeAll, afterAll, describe } from '@jest/globals';
import * as vscode from 'vscode';
-import { activateCSharpExtension, testIfCSharp, testIfDevKit } from './integrationHelpers';
+import { activateCSharpExtension } from './integrationHelpers';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
RoslynDevKitCommands,
@@ -13,6 +13,7 @@ import {
UnexpectedRoslynDevKitCommands,
UnexpectedRoslynStandaloneCommands,
} from './expectedCommands';
+import { testIfCSharp, testIfDevKit } from '../../jestHelpers';
describe(`Command Enablement Tests`, () => {
beforeAll(async () => {
diff --git a/test/lsptoolshost/integrationTests/documentDiagnostics.integration.test.ts b/test/lsptoolshost/integrationTests/documentDiagnostics.integration.test.ts
index 149d6e6b5b..a69bb8b983 100644
--- a/test/lsptoolshost/integrationTests/documentDiagnostics.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/documentDiagnostics.integration.test.ts
@@ -9,12 +9,8 @@ import testAssetWorkspace from './testAssets/testAssetWorkspace';
import { AnalysisSetting } from '../../../src/lsptoolshost/diagnostics/buildDiagnosticsService';
import path from 'path';
import { getCode, setDiagnosticSettings, waitForExpectedDiagnostics } from './diagnosticsHelpers';
-import {
- activateCSharpExtension,
- closeAllEditorsAsync,
- describeIfCSharp,
- openFileInWorkspaceAsync,
-} from './integrationHelpers';
+import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
+import { describeIfCSharp } from '../../jestHelpers';
// Restarting the server is required for these tests, but not supported with C# Dev Kit.
describeIfCSharp(`Document Diagnostics Tests`, () => {
diff --git a/test/lsptoolshost/integrationTests/formatting.integration.test.ts b/test/lsptoolshost/integrationTests/formatting.integration.test.ts
index 8549717ec6..2b9bad83b6 100644
--- a/test/lsptoolshost/integrationTests/formatting.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/formatting.integration.test.ts
@@ -6,14 +6,10 @@
import * as vscode from 'vscode';
import * as path from 'path';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
-import {
- activateCSharpExtension,
- closeAllEditorsAsync,
- expectText,
- openFileInWorkspaceAsync,
-} from './integrationHelpers';
+import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
import { describe, beforeEach, afterAll, test, afterEach } from '@jest/globals';
import { formatDocumentAsync, formatOnTypeAsync, formatRangeAsync } from './formattingTestHelpers';
+import { expectText } from '../../jestHelpers';
describe(`Formatting Tests`, () => {
beforeEach(async () => {
diff --git a/test/lsptoolshost/integrationTests/formattingEditorConfig.integration.test.ts b/test/lsptoolshost/integrationTests/formattingEditorConfig.integration.test.ts
index 67452574e1..e5f84771f7 100644
--- a/test/lsptoolshost/integrationTests/formattingEditorConfig.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/formattingEditorConfig.integration.test.ts
@@ -6,14 +6,10 @@
import * as vscode from 'vscode';
import * as path from 'path';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
-import {
- activateCSharpExtension,
- closeAllEditorsAsync,
- expectText,
- openFileInWorkspaceAsync,
-} from './integrationHelpers';
+import { activateCSharpExtension, closeAllEditorsAsync, openFileInWorkspaceAsync } from './integrationHelpers';
import { describe, beforeAll, beforeEach, afterAll, test, afterEach } from '@jest/globals';
import { formatDocumentAsync, formatOnTypeAsync, formatRangeAsync } from './formattingTestHelpers';
+import { expectText } from '../../jestHelpers';
describe(`Formatting With EditorConfig Tests`, () => {
beforeAll(async () => {
diff --git a/test/lsptoolshost/integrationTests/gotoDefinition.integration.test.ts b/test/lsptoolshost/integrationTests/gotoDefinition.integration.test.ts
index cfc31da372..983ace8ab8 100644
--- a/test/lsptoolshost/integrationTests/gotoDefinition.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/gotoDefinition.integration.test.ts
@@ -12,10 +12,9 @@ import {
findRangeOfString,
navigate,
openFileInWorkspaceAsync,
- testIfCSharp,
- testIfDevKit,
} from './integrationHelpers';
import { describe, beforeAll, beforeEach, afterAll, test, expect, afterEach } from '@jest/globals';
+import { testIfCSharp, testIfDevKit } from '../../jestHelpers';
describe(`Go To Definition Tests`, () => {
beforeAll(async () => {
diff --git a/test/lsptoolshost/integrationTests/index.ts b/test/lsptoolshost/integrationTests/index.ts
index ac2e6a90a2..4ee2cd1d3f 100644
--- a/test/lsptoolshost/integrationTests/index.ts
+++ b/test/lsptoolshost/integrationTests/index.ts
@@ -3,11 +3,73 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
+import * as vscode from 'vscode';
+import * as fsExtra from 'fs-extra';
+import path from 'path';
+import { AggregatedResult } from '@jest/test-result';
import { runIntegrationTests } from '../../runIntegrationTests';
import { jestIntegrationTestProjectName } from './jest.config';
+import { activateCSharpExtension } from './integrationHelpers';
export async function run() {
process.env.RUNNING_INTEGRATION_TESTS = 'true';
- await runIntegrationTests(jestIntegrationTestProjectName);
+ await activateCSharpExtension();
+ await moveLogs('activated');
+
+ let anyFailures = false;
+ let results: AggregatedResult | undefined;
+ if (process.env.TEST_FILE_FILTER) {
+ results = await runIntegrationTests(jestIntegrationTestProjectName);
+ await moveLogs(path.basename(process.env.TEST_FILE_FILTER, '.integration.test.ts'));
+ anyFailures = anyFailures || !results.success;
+ } else {
+ const workingDirectory = process.cwd();
+
+ const testFiles = (await fsExtra.readdir(__dirname))
+ .filter((file) => file.endsWith('.integration.test.js'))
+ .map((file) => path.join(__dirname, file));
+
+ for (let file of testFiles) {
+ // We have to fix up the file path because the test file was discovered in the /out/ directory.
+ file = file.substring(0, file.length - 2) + 'ts';
+ file = file.replace(/[\\/]out[\\/]/, path.sep);
+ file = workingDirectory[0] + file.substring(1);
+
+ console.log('');
+ console.log(`-- Running integration tests for ${path.basename(file)} --`);
+ console.log('');
+
+ process.env.TEST_FILE_FILTER = file;
+
+ results = await runIntegrationTests(jestIntegrationTestProjectName);
+ await moveLogs(path.basename(process.env.TEST_FILE_FILTER, '.integration.test.ts'));
+ anyFailures = anyFailures || !results.success;
+ }
+ }
+
+ // Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
+ // which make it look like the tests always fail. We're done with the tests at this point, so just exit.
+ process.exit(anyFailures ? 1 : 0);
+}
+
+async function moveLogs(name: string) {
+ const exports = vscode.extensions.getExtension('ms-dotnettools.csharp')?.exports;
+ if (!exports) {
+ throw new Error('Failed to get C# extension exports for cleanup');
+ }
+
+ if (!exports.logDirectory) {
+ console.warn(`Failed to get log directory from C# extension exports`);
+ return;
+ }
+
+ const targetLogDir = path.join(
+ path.dirname(exports.logDirectory),
+ `${name ?? 'unknown'}_${path.basename(exports.logDirectory)}`
+ );
+ await fsExtra.copy(exports.logDirectory, targetLogDir);
+ console.log(`Copied extension logs from ${exports.logDirectory} to ${targetLogDir}`);
+
+ await new Promise((resolve) => fsExtra.rm(path.join(exports.logDirectory, '*.log'), resolve));
}
diff --git a/test/lsptoolshost/integrationTests/integrationHelpers.ts b/test/lsptoolshost/integrationTests/integrationHelpers.ts
index b4e2e8ea90..85a1024d82 100644
--- a/test/lsptoolshost/integrationTests/integrationHelpers.ts
+++ b/test/lsptoolshost/integrationTests/integrationHelpers.ts
@@ -10,8 +10,6 @@ import { CSharpExtensionExports } from '../../../src/csharpExtensionExports';
import { existsSync } from 'fs';
import { ServerState } from '../../../src/lsptoolshost/server/languageServerEvents';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
-import { EOL, platform } from 'os';
-import { describe, expect, test } from '@jest/globals';
export async function activateCSharpExtension(): Promise {
const csharpExtension = vscode.extensions.getExtension('ms-dotnettools.csharp');
@@ -191,8 +189,6 @@ export async function navigate(
// Navigation happens asynchronously when a different file is opened, so we need to wait for the window to change.
await windowChanged;
-
- expect(vscode.window.activeTextEditor?.document.fileName).toContain(expectedFileName);
}
export function sortLocations(locations: vscode.Location[]): vscode.Location[] {
@@ -253,49 +249,3 @@ export async function waitForExpectedResult(
export async function sleep(ms = 0) {
return new Promise((r) => setTimeout(r, ms));
}
-
-export async function expectText(document: vscode.TextDocument, expectedLines: string[]) {
- const expectedText = expectedLines.join(EOL);
- expect(document.getText()).toBe(expectedText);
-}
-
-export function expectPath(expected: vscode.Uri, actual: vscode.Uri) {
- if (isLinux()) {
- expect(actual.path).toBe(expected.path);
- } else {
- const actualPath = actual.path.toLowerCase();
- const expectedPath = expected.path.toLocaleLowerCase();
- expect(actualPath).toBe(expectedPath);
- }
-}
-
-export const describeIfCSharp = describeIf(!usingDevKit());
-export const describeIfDevKit = describeIf(usingDevKit());
-export const describeIfNotMacOS = describeIf(!isMacOS());
-export const describeIfWindows = describeIf(isWindows());
-export const testIfCSharp = testIf(!usingDevKit());
-export const testIfDevKit = testIf(usingDevKit());
-export const testIfNotMacOS = testIf(!isMacOS());
-export const testIfWindows = testIf(isWindows());
-
-function describeIf(condition: boolean) {
- return condition ? describe : describe.skip;
-}
-
-function testIf(condition: boolean) {
- return condition ? test : test.skip;
-}
-
-function isMacOS() {
- const currentPlatform = platform();
- return currentPlatform === 'darwin';
-}
-
-function isWindows() {
- const currentPlatform = platform();
- return currentPlatform === 'win32';
-}
-
-function isLinux() {
- return !(isMacOS() || isWindows());
-}
diff --git a/test/lsptoolshost/integrationTests/unitTests.integration.test.ts b/test/lsptoolshost/integrationTests/unitTests.integration.test.ts
index 8753a65607..1916d52cfb 100644
--- a/test/lsptoolshost/integrationTests/unitTests.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/unitTests.integration.test.ts
@@ -10,11 +10,11 @@ import testAssetWorkspace from './testAssets/testAssetWorkspace';
import {
activateCSharpExtension,
closeAllEditorsAsync,
- describeIfCSharp,
getCodeLensesAsync,
openFileInWorkspaceAsync,
} from './integrationHelpers';
import { TestProgress } from '../../../src/lsptoolshost/server/roslynProtocol';
+import { describeIfCSharp } from '../../jestHelpers';
describeIfCSharp(`Unit Testing Tests`, () => {
beforeAll(async () => {
diff --git a/test/lsptoolshost/integrationTests/workspaceDiagnostics.integration.test.ts b/test/lsptoolshost/integrationTests/workspaceDiagnostics.integration.test.ts
index 50388aa0b7..bd1702fe2b 100644
--- a/test/lsptoolshost/integrationTests/workspaceDiagnostics.integration.test.ts
+++ b/test/lsptoolshost/integrationTests/workspaceDiagnostics.integration.test.ts
@@ -8,7 +8,8 @@ import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import { AnalysisSetting } from '../../../src/lsptoolshost/diagnostics/buildDiagnosticsService';
import { getCode, setDiagnosticSettings, waitForExpectedDiagnostics } from './diagnosticsHelpers';
-import { activateCSharpExtension, describeIfCSharp } from './integrationHelpers';
+import { activateCSharpExtension } from './integrationHelpers';
+import { describeIfCSharp } from '../../jestHelpers';
// Restarting the server is required for these tests, but not supported with C# Dev Kit.
describeIfCSharp(`Workspace Diagnostic Tests`, () => {
diff --git a/test/omnisharp/omnisharpIntegrationTests/index.ts b/test/omnisharp/omnisharpIntegrationTests/index.ts
index ac2e6a90a2..bb8b7b3372 100644
--- a/test/omnisharp/omnisharpIntegrationTests/index.ts
+++ b/test/omnisharp/omnisharpIntegrationTests/index.ts
@@ -9,5 +9,9 @@ import { jestIntegrationTestProjectName } from './jest.config';
export async function run() {
process.env.RUNNING_INTEGRATION_TESTS = 'true';
- await runIntegrationTests(jestIntegrationTestProjectName);
+ const results = await runIntegrationTests(jestIntegrationTestProjectName);
+
+ // Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
+ // which make it look like the tests always fail. We're done with the tests at this point, so just exit.
+ process.exit(results.success ? 0 : 1);
}
diff --git a/test/razor/razorIntegrationTests/index.ts b/test/razor/razorIntegrationTests/index.ts
index ac2e6a90a2..bb8b7b3372 100644
--- a/test/razor/razorIntegrationTests/index.ts
+++ b/test/razor/razorIntegrationTests/index.ts
@@ -9,5 +9,9 @@ import { jestIntegrationTestProjectName } from './jest.config';
export async function run() {
process.env.RUNNING_INTEGRATION_TESTS = 'true';
- await runIntegrationTests(jestIntegrationTestProjectName);
+ const results = await runIntegrationTests(jestIntegrationTestProjectName);
+
+ // Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
+ // which make it look like the tests always fail. We're done with the tests at this point, so just exit.
+ process.exit(results.success ? 0 : 1);
}
diff --git a/test/razor/razorIntegrationTests/reference.integration.test.ts b/test/razor/razorIntegrationTests/reference.integration.test.ts
index 5a15c3794d..4ed7d72f34 100644
--- a/test/razor/razorIntegrationTests/reference.integration.test.ts
+++ b/test/razor/razorIntegrationTests/reference.integration.test.ts
@@ -8,6 +8,7 @@ import * as vscode from 'vscode';
import { beforeAll, afterAll, test, expect, beforeEach, describe } from '@jest/globals';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import * as integrationHelpers from '../../lsptoolshost/integrationTests/integrationHelpers';
+import * as jestHelpers from '../../jestHelpers';
describe(`Razor References ${testAssetWorkspace.description}`, function () {
beforeAll(async function () {
@@ -151,9 +152,9 @@ describe(`Razor References ${testAssetWorkspace.description}`, function () {
const razorFile = integrationHelpers.getFilePath(path.join('Pages', 'References.razor'));
const csharpFile = integrationHelpers.getFilePath(path.join('Pages', 'References.razor.cs'));
- integrationHelpers.expectPath(razorFile, sortedLocations[0].uri);
- integrationHelpers.expectPath(csharpFile, sortedLocations[1].uri);
- integrationHelpers.expectPath(csharpFile, sortedLocations[2].uri);
+ jestHelpers.expectPath(razorFile, sortedLocations[0].uri);
+ jestHelpers.expectPath(csharpFile, sortedLocations[1].uri);
+ jestHelpers.expectPath(csharpFile, sortedLocations[2].uri);
}
);
});
diff --git a/test/runIntegrationTests.ts b/test/runIntegrationTests.ts
index 7acedc7156..697ad6a65b 100644
--- a/test/runIntegrationTests.ts
+++ b/test/runIntegrationTests.ts
@@ -31,11 +31,5 @@ export async function runIntegrationTests(projectName: string) {
const { results } = await jest.runCLI(jestConfig, [projectName]);
- if (!results.success) {
- console.log('Tests failed.');
- }
-
- // Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
- // which make it look like the tests always fail. We're done with the tests at this point, so just exit.
- process.exit(results.success ? 0 : 1);
+ return results;
}
diff --git a/test/untrustedWorkspace/integrationTests/index.ts b/test/untrustedWorkspace/integrationTests/index.ts
index ac2e6a90a2..bb8b7b3372 100644
--- a/test/untrustedWorkspace/integrationTests/index.ts
+++ b/test/untrustedWorkspace/integrationTests/index.ts
@@ -9,5 +9,9 @@ import { jestIntegrationTestProjectName } from './jest.config';
export async function run() {
process.env.RUNNING_INTEGRATION_TESTS = 'true';
- await runIntegrationTests(jestIntegrationTestProjectName);
+ const results = await runIntegrationTests(jestIntegrationTestProjectName);
+
+ // Explicitly exit the process - VSCode likes to write a bunch of cancellation errors to the console after this
+ // which make it look like the tests always fail. We're done with the tests at this point, so just exit.
+ process.exit(results.success ? 0 : 1);
}