testing: clean up nits

- rename TestController.createRunConfiguration to .createRunProfile, and associated types
- rename TestItemCollection.remove to TestItemCollection.delete
This commit is contained in:
Connor Peet 2021-07-15 14:22:57 -07:00
parent 8a0f4763b1
commit 42c268a626
No known key found for this signature in database
GPG key ID: CF8FD2EA0DBC61BD
27 changed files with 415 additions and 413 deletions

View file

@ -1892,7 +1892,10 @@ declare module 'vscode' {
// Todo@api: this is basically the same as the TaskGroup, which is a class that // Todo@api: this is basically the same as the TaskGroup, which is a class that
// allows custom groups to be created. However I don't anticipate having any // allows custom groups to be created. However I don't anticipate having any
// UI for that, so enum for now? // UI for that, so enum for now?
export enum TestRunConfigurationGroup { /**
*
*/
export enum TestRunProfileGroup {
Run = 1, Run = 1,
Debug = 2, Debug = 2,
Coverage = 3, Coverage = 3,
@ -1914,7 +1917,10 @@ declare module 'vscode' {
// At least with that we can still do it later // At least with that we can still do it later
export type TestRunHandler = (request: TestRunRequest, token: CancellationToken) => Thenable<void> | void; export type TestRunHandler = (request: TestRunRequest, token: CancellationToken) => Thenable<void> | void;
export interface TestRunConfiguration { /**
* A TestRunProfile describes one way to execute tests in a {@link TestController}.
*/
export interface TestRunProfile {
/** /**
* Label shown to the user in the UI. * Label shown to the user in the UI.
* *
@ -1927,21 +1933,21 @@ declare module 'vscode' {
label: string; label: string;
/** /**
* Configures where this configuration is grouped in the UI. If there * Configures where this profile is grouped in the UI. If there
* are no configurations for a group, it will not be available in the UI. * are no profiles for a group, it will not be available in the UI.
*/ */
readonly group: TestRunConfigurationGroup; readonly group: TestRunProfileGroup;
/** /**
* Controls whether this configuration is the default action that will * Controls whether this profile is the default action that will
* be taken when its group is actions. For example, if the user clicks * be taken when its group is actions. For example, if the user clicks
* the generic "run all" button, then the default configuration for * the generic "run all" button, then the default profile for
* {@link TestRunConfigurationGroup.Run} will be executed. * {@link TestRunProfileGroup.Run} will be executed.
*/ */
isDefault: boolean; isDefault: boolean;
/** /**
* If this method is present a configuration gear will be present in the * If this method is present, a configuration gear will be present in the
* UI, and this method will be invoked when it's clicked. When called, * UI, and this method will be invoked when it's clicked. When called,
* you can take other editor actions, such as showing a quick pick or * you can take other editor actions, such as showing a quick pick or
* opening a configuration file. * opening a configuration file.
@ -1949,7 +1955,7 @@ declare module 'vscode' {
configureHandler?: () => void; configureHandler?: () => void;
/** /**
* Starts a test run. When called, the controller should call * Starts a test run. When called, the profile should call
* {@link TestController.createTestRun}. All tasks associated with the * {@link TestController.createTestRun}. All tasks associated with the
* run should be created before the function returns or the reutrned * run should be created before the function returns or the reutrned
* promise is resolved. * promise is resolved.
@ -1963,15 +1969,17 @@ declare module 'vscode' {
runHandler: TestRunHandler; runHandler: TestRunHandler;
/** /**
* Deletes the run configuration. * Deletes the run profile.
*/ */
dispose(): void; dispose(): void;
} }
/** /**
* Interface to discover and execute tests. * Entry point to discover and execute tests. It contains {@link items} which
* are used to populate the editor UI, and is associated with
* {@link createRunProfile | run profiles} to allow
* for tests to be executed.
*/ */
// todo@api maybe some words on this being the "entry point"
export interface TestController { export interface TestController {
/** /**
* The ID of the controller, passed in {@link vscode.test.createTestController} * The ID of the controller, passed in {@link vscode.test.createTestController}
@ -1999,14 +2007,14 @@ declare module 'vscode' {
readonly items: TestItemCollection; readonly items: TestItemCollection;
/** /**
* Creates a configuration used for running tests. Extensions must create * Creates a profile used for running tests. Extensions must create
* at least one configuration in order for tests to be run. * at least one profile in order for tests to be run.
* @param label Human-readable label for this configuration * @param label Human-readable label for this profile
* @param group Configures where this configuration is grouped in the UI. * @param group Configures where this profile is grouped in the UI.
* @param runHandler Function called to start a test run * @param runHandler Function called to start a test run
* @param isDefault Whether this is the default action for the group * @param isDefault Whether this is the default action for the group
*/ */
createRunConfiguration(label: string, group: TestRunConfigurationGroup, runHandler: TestRunHandler, isDefault?: boolean): TestRunConfiguration; createRunProfile(label: string, group: TestRunProfileGroup, runHandler: TestRunHandler, isDefault?: boolean): TestRunProfile;
/** /**
* A function provided by the extension that the editor may call to request * A function provided by the extension that the editor may call to request
@ -2075,18 +2083,18 @@ declare module 'vscode' {
exclude?: TestItem[]; exclude?: TestItem[];
/** /**
* The configuration used for this request. This will always be defined * The profile used for this request. This will always be defined
* for requests issued from the editor UI, though extensions may * for requests issued from the editor UI, though extensions may
* programmatically create requests not associated with any configuration. * programmatically create requests not associated with any profile.
*/ */
configuration?: TestRunConfiguration; profile?: TestRunProfile;
/** /**
* @param tests Array of specific tests to run, or undefined to run all tests * @param tests Array of specific tests to run, or undefined to run all tests
* @param exclude Tests to exclude from the run * @param exclude Tests to exclude from the run
* @param configuration The run configuration used for this request. * @param profile The run profile used for this request.
*/ */
constructor(include?: readonly TestItem[], exclude?: readonly TestItem[], configuration?: TestRunConfiguration); constructor(include?: readonly TestItem[], exclude?: readonly TestItem[], profile?: TestRunProfile);
} }
/** /**
@ -2108,14 +2116,14 @@ declare module 'vscode' {
/** /**
* Updates the state of the test in the run. Calling with method with nodes * Updates the state of the test in the run. Calling with method with nodes
* outside the {@link TestRunRequest.tests} or in the * outside the {@link TestRunRequest.tests} or in the {@link TestRunRequest.exclude}
* {@link TestRunRequest.exclude} array will no-op. * array will no-op. This will usually be called multiple times for a test
* as it is queued, enters the running state, and then passes or fails.
* *
* @param test The test to update * @param test The test to update
* @param state The state to assign to the test * @param state The state to assign to the test
* @param duration Optionally sets how long the test took to run, in milliseconds * @param duration Optionally sets how long the test took to run, in milliseconds
*/ */
//todo@API is this "update" state or set final state? should this be called setTestResult?
setState(test: TestItem, state: TestResultState, duration?: number): void; setState(test: TestItem, state: TestResultState, duration?: number): void;
/** /**
@ -2140,10 +2148,10 @@ declare module 'vscode' {
appendOutput(output: string): void; appendOutput(output: string): void;
/** /**
* Signals that the end of the test run. Any tests whose states have not * Signals that the end of the test run. Any tests included in the run whose
* been updated will be moved into the {@link TestResultState.Unset} state. * states have not been updated will be moved into
* the {@link TestResultState.Unset} state.
*/ */
// todo@api is the Unset logic smart and only considering those tests that are included?
end(): void; end(): void;
} }
@ -2168,8 +2176,7 @@ declare module 'vscode' {
/** /**
* Removes the a single test item from the collection. * Removes the a single test item from the collection.
*/ */
//todo@API `delete` as Map, EnvironmentVariableCollection, DiagnosticCollection delete(itemId: string): void;
remove(itemId: string): void;
/** /**
* Efficiently gets a test item by ID, if it exists, in the children. * Efficiently gets a test item by ID, if it exists, in the children.
@ -2202,10 +2209,9 @@ declare module 'vscode' {
/** /**
* The parent of this item, given in {@link vscode.test.createTestItem}. * The parent of this item, given in {@link vscode.test.createTestItem}.
* This is undefined top-level items in the `TestController`, and for * This is undefined top-level items in the `TestController` and for
* items that aren't yet assigned to a parent. * items that aren't yet included in another item's {@link children}.
*/ */
// todo@api obsolete? doc is outdated at least
readonly parent?: TestItem; readonly parent?: TestItem;
/** /**
@ -2277,7 +2283,6 @@ declare module 'vscode' {
// Test run has been skipped // Test run has been skipped
Skipped = 5, Skipped = 5,
// Test run failed for some other reason (compilation error, timeout, etc) // Test run failed for some other reason (compilation error, timeout, etc)
// todo@api could I just use `Skipped` and TestItem#error?
Errored = 6 Errored = 6
} }
@ -2344,8 +2349,6 @@ declare module 'vscode' {
* run is complete. Therefore, information such as its {@link Range} may be * run is complete. Therefore, information such as its {@link Range} may be
* out of date. If the test still exists in the workspace, consumers can use * out of date. If the test still exists in the workspace, consumers can use
* its `id` to correlate the result instance with the living test. * its `id` to correlate the result instance with the living test.
*
* @todo coverage and other info may eventually be provided here
*/ */
export interface TestRunResult { export interface TestRunResult {
/** /**

View file

@ -12,8 +12,8 @@ import { Range } from 'vs/editor/common/core/range';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { TestResultState } from 'vs/workbench/api/common/extHostTypes';
import { MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue'; import { MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
import { ExtensionRunTestsRequest, ITestItem, ITestMessage, ITestRunConfiguration, ITestRunTask, ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { ExtensionRunTestsRequest, ITestItem, ITestMessage, ITestRunProfile, ITestRunTask, ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
import { ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { TestCoverage } from 'vs/workbench/contrib/testing/common/testCoverage'; import { TestCoverage } from 'vs/workbench/contrib/testing/common/testCoverage';
import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult'; import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult';
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
@ -47,7 +47,7 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
constructor( constructor(
extHostContext: IExtHostContext, extHostContext: IExtHostContext,
@ITestService private readonly testService: ITestService, @ITestService private readonly testService: ITestService,
@ITestConfigurationService private readonly testConfiguration: ITestConfigurationService, @ITestProfileService private readonly testProfiles: ITestProfileService,
@ITestResultService private readonly resultService: ITestResultService, @ITestResultService private readonly resultService: ITestResultService,
) { ) {
super(); super();
@ -74,25 +74,25 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
/** /**
* @inheritdoc * @inheritdoc
*/ */
$publishTestRunConfig(config: ITestRunConfiguration): void { $publishTestRunProfile(profile: ITestRunProfile): void {
const controller = this.testProviderRegistrations.get(config.controllerId); const controller = this.testProviderRegistrations.get(profile.controllerId);
if (controller) { if (controller) {
this.testConfiguration.addConfiguration(controller.instance, config); this.testProfiles.addProfile(controller.instance, profile);
} }
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
$updateTestRunConfig(controllerId: string, configId: number, update: Partial<ITestRunConfiguration>): void { $updateTestRunConfig(controllerId: string, profileId: number, update: Partial<ITestRunProfile>): void {
this.testConfiguration.updateConfiguration(controllerId, configId, update); this.testProfiles.updateProfile(controllerId, profileId, update);
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
$removeTestRunConfig(controllerId: string, configId: number): void { $removeTestProfile(controllerId: string, profileId: number): void {
this.testConfiguration.removeConfiguration(controllerId, configId); this.testProfiles.removeProfile(controllerId, profileId);
} }
/** /**
@ -193,13 +193,13 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
const controller: IMainThreadTestController = { const controller: IMainThreadTestController = {
id: controllerId, id: controllerId,
label, label,
configureRunConfig: id => this.proxy.$configureRunConfig(controllerId, id), configureRunProfile: id => this.proxy.$configureRunProfile(controllerId, id),
runTests: (req, token) => this.proxy.$runControllerTests(req, token), runTests: (req, token) => this.proxy.$runControllerTests(req, token),
expandTest: (src, levels) => this.proxy.$expandTest(src, isFinite(levels) ? levels : -1), expandTest: (src, levels) => this.proxy.$expandTest(src, isFinite(levels) ? levels : -1),
}; };
disposable.add(toDisposable(() => this.testConfiguration.removeConfiguration(controllerId))); disposable.add(toDisposable(() => this.testProfiles.removeProfile(controllerId)));
disposable.add(this.testService.registerTestController(controllerId, controller)); disposable.add(this.testService.registerTestController(controllerId, controller));
this.testProviderRegistrations.set(controllerId, { this.testProviderRegistrations.set(controllerId, {

View file

@ -1273,7 +1273,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
TestResultState: extHostTypes.TestResultState, TestResultState: extHostTypes.TestResultState,
TestRunRequest: extHostTypes.TestRunRequest, TestRunRequest: extHostTypes.TestRunRequest,
TestMessage: extHostTypes.TestMessage, TestMessage: extHostTypes.TestMessage,
TestRunConfigurationGroup: extHostTypes.TestRunConfigurationGroup, TestRunProfileGroup: extHostTypes.TestRunProfileGroup,
TextSearchCompleteMessageType: TextSearchCompleteMessageType, TextSearchCompleteMessageType: TextSearchCompleteMessageType,
TestMessageSeverity: extHostTypes.TestMessageSeverity, TestMessageSeverity: extHostTypes.TestMessageSeverity,
CoveredCount: extHostTypes.CoveredCount, CoveredCount: extHostTypes.CoveredCount,

View file

@ -58,7 +58,7 @@ import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { InputValidationType } from 'vs/workbench/contrib/scm/common/scm'; import { InputValidationType } from 'vs/workbench/contrib/scm/common/scm';
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder'; import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
import { ExtensionRunTestsRequest, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, RunTestForControllerRequest, ResolvedTestRunRequest, ITestIdWithSrc, TestsDiff, IFileCoverage, CoverageDetails, ITestRunConfiguration } from 'vs/workbench/contrib/testing/common/testCollection'; import { ExtensionRunTestsRequest, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, RunTestForControllerRequest, ResolvedTestRunRequest, ITestIdWithSrc, TestsDiff, IFileCoverage, CoverageDetails, ITestRunProfile } from 'vs/workbench/contrib/testing/common/testCollection';
import { InternalTimelineOptions, Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline'; import { InternalTimelineOptions, Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline';
import { TypeHierarchyItem } from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy'; import { TypeHierarchyItem } from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
@ -2099,7 +2099,7 @@ export interface ExtHostTestingShape {
*/ */
$resolveFileCoverage(runId: string, taskId: string, fileIndex: number, token: CancellationToken): Promise<CoverageDetails[]>; $resolveFileCoverage(runId: string, taskId: string, fileIndex: number, token: CancellationToken): Promise<CoverageDetails[]>;
/** Configures a test run config. */ /** Configures a test run config. */
$configureRunConfig(controllerId: string, configId: number): void; $configureRunProfile(controllerId: string, configId: number): void;
} }
export interface MainThreadTestingShape { export interface MainThreadTestingShape {
@ -2121,11 +2121,11 @@ export interface MainThreadTestingShape {
// --- test run configurations: // --- test run configurations:
/** Called when a new test run configuration is available */ /** Called when a new test run configuration is available */
$publishTestRunConfig(config: ITestRunConfiguration): void; $publishTestRunProfile(config: ITestRunProfile): void;
/** Updates an existing test run configuration */ /** Updates an existing test run configuration */
$updateTestRunConfig(controllerId: string, configId: number, update: Partial<ITestRunConfiguration>): void; $updateTestRunConfig(controllerId: string, configId: number, update: Partial<ITestRunProfile>): void;
/** Removes a previously-published test run config */ /** Removes a previously-published test run config */
$removeTestRunConfig(controllerId: string, configId: number): void; $removeTestProfile(controllerId: string, configId: number): void;
// --- test run handling: // --- test run handling:

View file

@ -20,14 +20,14 @@ import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { TestItemImpl } from 'vs/workbench/api/common/extHostTestingPrivateApi'; import { TestItemImpl } from 'vs/workbench/api/common/extHostTestingPrivateApi';
import * as Convert from 'vs/workbench/api/common/extHostTypeConverters'; import * as Convert from 'vs/workbench/api/common/extHostTypeConverters';
import { TestRunConfigurationGroup, TestRunRequest } from 'vs/workbench/api/common/extHostTypes'; import { TestRunProfileGroup, TestRunRequest } from 'vs/workbench/api/common/extHostTypes';
import { SingleUseTestCollection, TestPosition } from 'vs/workbench/contrib/testing/common/ownedTestCollection'; import { SingleUseTestCollection, TestPosition } from 'vs/workbench/contrib/testing/common/ownedTestCollection';
import { AbstractIncrementalTestCollection, CoverageDetails, IFileCoverage, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, ISerializedTestResults, ITestIdWithSrc, ITestItem, RunTestForControllerRequest, TestRunConfigurationBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { AbstractIncrementalTestCollection, CoverageDetails, IFileCoverage, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, ISerializedTestResults, ITestIdWithSrc, ITestItem, RunTestForControllerRequest, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
import type * as vscode from 'vscode'; import type * as vscode from 'vscode';
interface ControllerInfo { interface ControllerInfo {
controller: vscode.TestController, controller: vscode.TestController,
configurations: Map<number, vscode.TestRunConfiguration>, profiles: Map<number, vscode.TestRunProfile>,
collection: SingleUseTestCollection, collection: SingleUseTestCollection,
} }
@ -59,7 +59,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
const disposable = new DisposableStore(); const disposable = new DisposableStore();
const collection = disposable.add(new SingleUseTestCollection(controllerId)); const collection = disposable.add(new SingleUseTestCollection(controllerId));
const initialExpand = disposable.add(new RunOnceScheduler(() => collection.expand(collection.root.id, 0), 0)); const initialExpand = disposable.add(new RunOnceScheduler(() => collection.expand(collection.root.id, 0), 0));
const configurations = new Map<number, vscode.TestRunConfiguration>(); const profiles = new Map<number, vscode.TestRunProfile>();
const proxy = this.proxy; const proxy = this.proxy;
const controller: vscode.TestController = { const controller: vscode.TestController = {
@ -75,17 +75,17 @@ export class ExtHostTesting implements ExtHostTestingShape {
get id() { get id() {
return controllerId; return controllerId;
}, },
createRunConfiguration: (label, group, runHandler, isDefault) => { createRunProfile: (label, group, runHandler, isDefault) => {
// Derive the config ID from a hash so that the same config will tend // Derive the profile ID from a hash so that the same profile will tend
// to have the same hashes, allowing re-run requests to work across reloads. // to have the same hashes, allowing re-run requests to work across reloads.
let configId = hash(label); let profileId = hash(label);
while (configurations.has(configId)) { while (profiles.has(profileId)) {
configId++; profileId++;
} }
const config = new TestRunConfigurationImpl(this.proxy, controllerId, configId, label, group, runHandler, isDefault); const profile = new TestRunProfileImpl(this.proxy, controllerId, profileId, label, group, runHandler, isDefault);
configurations.set(configId, config); profiles.set(profileId, profile);
return config; return profile;
}, },
createTestRun: (request, name, persist = true) => { createTestRun: (request, name, persist = true) => {
return this.runTracker.createTestRun(controllerId, collection, request, name, persist); return this.runTracker.createTestRun(controllerId, collection, request, name, persist);
@ -105,12 +105,12 @@ export class ExtHostTesting implements ExtHostTestingShape {
}; };
// back compat: // back compat:
(controller as any).createTestITem = this.createTestItem.bind(this); (controller as any).createRunConfiguration = controller.createRunProfile;
proxy.$registerTestController(controllerId, label); proxy.$registerTestController(controllerId, label);
disposable.add(toDisposable(() => proxy.$unregisterTestController(controllerId))); disposable.add(toDisposable(() => proxy.$unregisterTestController(controllerId)));
const info: ControllerInfo = { controller, collection, configurations }; const info: ControllerInfo = { controller, collection, profiles: profiles };
this.controllers.set(controllerId, info); this.controllers.set(controllerId, info);
disposable.add(toDisposable(() => this.controllers.delete(controllerId))); disposable.add(toDisposable(() => this.controllers.delete(controllerId)));
@ -138,12 +138,12 @@ export class ExtHostTesting implements ExtHostTestingShape {
* Implements vscode.test.runTests * Implements vscode.test.runTests
*/ */
public async runTests(req: vscode.TestRunRequest, token = CancellationToken.None) { public async runTests(req: vscode.TestRunRequest, token = CancellationToken.None) {
const config = tryGetConfigFromTestRunReq(req); const profile = tryGetProfileFromTestRunReq(req);
if (!config) { if (!profile) {
throw new Error('The request passed to `vscode.test.runTests` must include a configuration'); throw new Error('The request passed to `vscode.test.runTests` must include a profile');
} }
const controller = this.controllers.get(config.controllerId); const controller = this.controllers.get(profile.controllerId);
if (!controller) { if (!controller) {
throw new Error('Controller not found'); throw new Error('Controller not found');
} }
@ -151,11 +151,11 @@ export class ExtHostTesting implements ExtHostTestingShape {
await this.proxy.$runTests({ await this.proxy.$runTests({
targets: [{ targets: [{
testIds: req.include?.map(t => t.id) ?? [controller.collection.root.id], testIds: req.include?.map(t => t.id) ?? [controller.collection.root.id],
profileGroup: configGroupToBitset[config.group], profileGroup: profileGroupToBitset[profile.group],
profileId: config.configId, profileId: profile.profileId,
controllerId: config.controllerId, controllerId: profile.controllerId,
}], }],
exclude: req.exclude?.map(t => ({ testId: t.id, controllerId: config.controllerId })), exclude: req.exclude?.map(t => ({ testId: t.id, controllerId: profile.controllerId })),
}, token); }, token);
} }
@ -174,8 +174,8 @@ export class ExtHostTesting implements ExtHostTestingShape {
} }
/** @inheritdoc */ /** @inheritdoc */
$configureRunConfig(controllerId: string, configId: number) { $configureRunProfile(controllerId: string, profileId: number) {
this.controllers.get(controllerId)?.configurations.get(configId)?.configureHandler?.(); this.controllers.get(controllerId)?.profiles.get(profileId)?.configureHandler?.();
} }
/** /**
@ -225,9 +225,9 @@ export class ExtHostTesting implements ExtHostTestingShape {
return; return;
} }
const { collection, configurations } = lookup; const { collection, profiles } = lookup;
const configuration = configurations.get(req.configId); const profile = profiles.get(req.profileId);
if (!configuration) { if (!profile) {
return; return;
} }
@ -249,7 +249,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
const publicReq = new TestRunRequest( const publicReq = new TestRunRequest(
includeTests.map(t => t.actual), includeTests.map(t => t.actual),
excludeTests.map(t => t.actual), excludeTests.map(t => t.actual),
configuration, profile,
); );
const tracker = this.runTracker.prepareForMainThreadTestRun( const tracker = this.runTracker.prepareForMainThreadTestRun(
@ -259,7 +259,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
); );
try { try {
await configuration.runHandler(publicReq, token); await profile.runHandler(publicReq, token);
} finally { } finally {
if (tracker.isRunning && !token.isCancellationRequested) { if (tracker.isRunning && !token.isCancellationRequested) {
await Event.toPromise(tracker.onEnd); await Event.toPromise(tracker.onEnd);
@ -401,10 +401,10 @@ export class TestRunCoordinator {
// If there is not an existing tracked extension for the request, start // If there is not an existing tracked extension for the request, start
// a new, detached session. // a new, detached session.
const dto = TestRunDto.fromPublic(controllerId, collection, request); const dto = TestRunDto.fromPublic(controllerId, collection, request);
const config = tryGetConfigFromTestRunReq(request); const profile = tryGetProfileFromTestRunReq(request);
this.proxy.$startedExtensionTestRun({ this.proxy.$startedExtensionTestRun({
controllerId, controllerId,
config: config && { group: configGroupToBitset[config.group], id: config.configId }, profile: profile && { group: profileGroupToBitset[profile.group], id: profile.profileId },
exclude: request.exclude?.map(t => t.id) ?? [], exclude: request.exclude?.map(t => t.id) ?? [],
id: dto.id, id: dto.id,
include: request.include?.map(t => t.id) ?? [collection.root.id], include: request.include?.map(t => t.id) ?? [collection.root.id],
@ -424,16 +424,16 @@ export class TestRunCoordinator {
} }
} }
const tryGetConfigFromTestRunReq = (request: vscode.TestRunRequest) => { const tryGetProfileFromTestRunReq = (request: vscode.TestRunRequest) => {
if (!request.configuration) { if (!request.profile) {
return undefined; return undefined;
} }
if (!(request.configuration instanceof TestRunConfigurationImpl)) { if (!(request.profile instanceof TestRunProfileImpl)) {
throw new Error(`TestRunRequest.configuration is not an instance created from TestController.createRunConfiguration`); throw new Error(`TestRunRequest.profile is not an instance created from TestController.createRunProfile`);
} }
return request.configuration; return request.profile;
}; };
export class TestRunDto { export class TestRunDto {
@ -816,7 +816,7 @@ class TestObservers {
} }
} }
export class TestRunConfigurationImpl implements vscode.TestRunConfiguration { export class TestRunProfileImpl implements vscode.TestRunProfile {
readonly #proxy: MainThreadTestingShape; readonly #proxy: MainThreadTestingShape;
private _configureHandler?: (() => void); private _configureHandler?: (() => void);
@ -827,7 +827,7 @@ export class TestRunConfigurationImpl implements vscode.TestRunConfiguration {
public set label(label: string) { public set label(label: string) {
if (label !== this._label) { if (label !== this._label) {
this._label = label; this._label = label;
this.#proxy.$updateTestRunConfig(this.controllerId, this.configId, { label }); this.#proxy.$updateTestRunConfig(this.controllerId, this.profileId, { label });
} }
} }
@ -838,7 +838,7 @@ export class TestRunConfigurationImpl implements vscode.TestRunConfiguration {
public set isDefault(isDefault: boolean) { public set isDefault(isDefault: boolean) {
if (isDefault !== this._isDefault) { if (isDefault !== this._isDefault) {
this._isDefault = isDefault; this._isDefault = isDefault;
this.#proxy.$updateTestRunConfig(this.controllerId, this.configId, { isDefault }); this.#proxy.$updateTestRunConfig(this.controllerId, this.profileId, { isDefault });
} }
} }
@ -849,28 +849,28 @@ export class TestRunConfigurationImpl implements vscode.TestRunConfiguration {
public set configureHandler(handler: undefined | (() => void)) { public set configureHandler(handler: undefined | (() => void)) {
if (handler !== this._configureHandler) { if (handler !== this._configureHandler) {
this._configureHandler = handler; this._configureHandler = handler;
this.#proxy.$updateTestRunConfig(this.controllerId, this.configId, { hasConfigurationHandler: !!handler }); this.#proxy.$updateTestRunConfig(this.controllerId, this.profileId, { hasConfigurationHandler: !!handler });
} }
} }
constructor( constructor(
proxy: MainThreadTestingShape, proxy: MainThreadTestingShape,
public readonly controllerId: string, public readonly controllerId: string,
public readonly configId: number, public readonly profileId: number,
private _label: string, private _label: string,
public readonly group: vscode.TestRunConfigurationGroup, public readonly group: vscode.TestRunProfileGroup,
public runHandler: vscode.TestRunHandler, public runHandler: vscode.TestRunHandler,
private _isDefault = false, private _isDefault = false,
) { ) {
this.#proxy = proxy; this.#proxy = proxy;
const groupBitset = configGroupToBitset[group]; const groupBitset = profileGroupToBitset[group];
if (typeof groupBitset !== 'number') { if (typeof groupBitset !== 'number') {
throw new Error(`Unknown TestRunConfiguration.group ${group}`); throw new Error(`Unknown TestRunProfile.group ${group}`);
} }
this.#proxy.$publishTestRunConfig({ this.#proxy.$publishTestRunProfile({
profileId: configId, profileId: profileId,
controllerId, controllerId,
label: _label, label: _label,
group: groupBitset, group: groupBitset,
@ -880,12 +880,12 @@ export class TestRunConfigurationImpl implements vscode.TestRunConfiguration {
} }
dispose(): void { dispose(): void {
this.#proxy.$removeTestRunConfig(this.controllerId, this.configId); this.#proxy.$removeTestProfile(this.controllerId, this.profileId);
} }
} }
const configGroupToBitset: { [K in TestRunConfigurationGroup]: TestRunConfigurationBitset } = { const profileGroupToBitset: { [K in TestRunProfileGroup]: TestRunProfileBitset } = {
[TestRunConfigurationGroup.Coverage]: TestRunConfigurationBitset.Coverage, [TestRunProfileGroup.Coverage]: TestRunProfileBitset.Coverage,
[TestRunConfigurationGroup.Debug]: TestRunConfigurationBitset.Debug, [TestRunProfileGroup.Debug]: TestRunProfileBitset.Debug,
[TestRunConfigurationGroup.Run]: TestRunConfigurationBitset.Run, [TestRunProfileGroup.Run]: TestRunProfileBitset.Run,
}; };

View file

@ -205,7 +205,7 @@ export const createTestItemCollection = (owningItem: TestItemImpl):
}, },
/** @inheritdoc */ /** @inheritdoc */
remove(id: string) { delete(id: string) {
if (mapped.delete(id)) { if (mapped.delete(id)) {
all = undefined; all = undefined;
api.listener?.({ op: ExtHostTestItemEventOp.RemoveChild, id }); api.listener?.({ op: ExtHostTestItemEventOp.RemoveChild, id });

View file

@ -3302,7 +3302,7 @@ export enum TestMessageSeverity {
Hint = 3 Hint = 3
} }
export enum TestRunConfigurationGroup { export enum TestRunProfileGroup {
Run = 1, Run = 1,
Debug = 2, Debug = 2,
Coverage = 3, Coverage = 3,
@ -3313,7 +3313,7 @@ export class TestRunRequest implements vscode.TestRunRequest {
constructor( constructor(
public readonly include?: vscode.TestItem[], public readonly include?: vscode.TestItem[],
public readonly exclude?: vscode.TestItem[] | undefined, public readonly exclude?: vscode.TestItem[] | undefined,
public readonly configuration?: vscode.TestRunConfiguration, public readonly profile?: vscode.TestRunProfile,
) { } ) { }
} }

View file

@ -24,7 +24,7 @@ export const testingHiddenIcon = registerIcon('testing-hidden', Codicon.eyeClose
export const testingShowAsList = registerIcon('testing-show-as-list-icon', Codicon.listTree, localize('testingShowAsList', 'Icon shown when the test explorer is disabled as a tree.')); export const testingShowAsList = registerIcon('testing-show-as-list-icon', Codicon.listTree, localize('testingShowAsList', 'Icon shown when the test explorer is disabled as a tree.'));
export const testingShowAsTree = registerIcon('testing-show-as-list-icon', Codicon.listFlat, localize('testingShowAsTree', 'Icon shown when the test explorer is disabled as a list.')); export const testingShowAsTree = registerIcon('testing-show-as-list-icon', Codicon.listFlat, localize('testingShowAsTree', 'Icon shown when the test explorer is disabled as a list.'));
export const testingUpdateConfiguration = registerIcon('testing-update-configuration', Codicon.gear, localize('testingUpdateConfiguration', 'Icon shown to update test configurations.')); export const testingUpdateProfiles = registerIcon('testing-update-profiles', Codicon.gear, localize('testingUpdateProfiles', 'Icon shown to update test profiles.'));
export const testingStatesToIcons = new Map<TestResultState, ThemeIcon>([ export const testingStatesToIcons = new Map<TestResultState, ThemeIcon>([
[TestResultState.Errored, registerIcon('testing-error-icon', Codicon.issues, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))], [TestResultState.Errored, registerIcon('testing-error-icon', Codicon.issues, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))],

View file

@ -29,8 +29,8 @@ import { ITestExplorerFilterState } from 'vs/workbench/contrib/testing/browser/t
import type { TestingExplorerView, TestingExplorerViewModel } from 'vs/workbench/contrib/testing/browser/testingExplorerView'; import type { TestingExplorerView, TestingExplorerViewModel } from 'vs/workbench/contrib/testing/browser/testingExplorerView';
import { ITestingOutputTerminalService } from 'vs/workbench/contrib/testing/browser/testingOutputTerminalService'; import { ITestingOutputTerminalService } from 'vs/workbench/contrib/testing/browser/testingOutputTerminalService';
import { TestExplorerViewMode, TestExplorerViewSorting, Testing } from 'vs/workbench/contrib/testing/common/constants'; import { TestExplorerViewMode, TestExplorerViewSorting, Testing } from 'vs/workbench/contrib/testing/common/constants';
import { identifyTest, InternalTestItem, ITestIdWithSrc, ITestItem, ITestRunConfiguration, TestIdPath, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { identifyTest, InternalTestItem, ITestIdWithSrc, ITestItem, ITestRunProfile, TestIdPath, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { ITestingAutoRun } from 'vs/workbench/contrib/testing/common/testingAutoRun'; import { ITestingAutoRun } from 'vs/workbench/contrib/testing/common/testingAutoRun';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener'; import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
@ -129,7 +129,7 @@ export class DebugAction extends Action2 {
public override run(acessor: ServicesAccessor, ...elements: IActionableTestTreeElement[]): Promise<any> { public override run(acessor: ServicesAccessor, ...elements: IActionableTestTreeElement[]): Promise<any> {
return acessor.get(ITestService).runTests({ return acessor.get(ITestService).runTests({
tests: [...Iterable.concatNested(elements.map(e => e.tests))], tests: [...Iterable.concatNested(elements.map(e => e.tests))],
group: TestRunConfigurationBitset.Debug, group: TestRunProfileBitset.Debug,
}); });
} }
} }
@ -158,7 +158,7 @@ export class RunUsingProfileAction extends Action2 {
const commandService = acessor.get(ICommandService); const commandService = acessor.get(ICommandService);
const testService = acessor.get(ITestService); const testService = acessor.get(ITestService);
const controllerId = testElements[0].test.controllerId; const controllerId = testElements[0].test.controllerId;
const profile: ITestRunConfiguration | undefined = await commandService.executeCommand('vscode.pickTestProfile', { onlyControllerId: controllerId }); const profile: ITestRunProfile | undefined = await commandService.executeCommand('vscode.pickTestProfile', { onlyControllerId: controllerId });
if (!profile) { if (!profile) {
return; return;
} }
@ -196,7 +196,7 @@ export class RunAction extends Action2 {
public override run(acessor: ServicesAccessor, ...elements: IActionableTestTreeElement[]): Promise<any> { public override run(acessor: ServicesAccessor, ...elements: IActionableTestTreeElement[]): Promise<any> {
return acessor.get(ITestService).runTests({ return acessor.get(ITestService).runTests({
tests: [...Iterable.concatNested(elements.map(e => e.tests))], tests: [...Iterable.concatNested(elements.map(e => e.tests))],
group: TestRunConfigurationBitset.Run, group: TestRunProfileBitset.Run,
}); });
} }
} }
@ -207,22 +207,22 @@ export class SelectDefaultTestProfiles extends Action2 {
super({ super({
id: SelectDefaultTestProfiles.ID, id: SelectDefaultTestProfiles.ID,
title: localize('testing.selectDefaultTestProfiles', 'Select Default Profile'), title: localize('testing.selectDefaultTestProfiles', 'Select Default Profile'),
icon: icons.testingUpdateConfiguration, icon: icons.testingUpdateProfiles,
category, category,
}); });
} }
public override async run(acessor: ServicesAccessor, onlyGroup: TestRunConfigurationBitset) { public override async run(acessor: ServicesAccessor, onlyGroup: TestRunProfileBitset) {
const commands = acessor.get(ICommandService); const commands = acessor.get(ICommandService);
const testConfigurationService = acessor.get(ITestConfigurationService); const testProfileService = acessor.get(ITestProfileService);
const configurations = await commands.executeCommand<ITestRunConfiguration[]>('vscode.pickMultipleTestProfiles', { const profiles = await commands.executeCommand<ITestRunProfile[]>('vscode.pickMultipleTestProfiles', {
showConfigureButtons: false, showConfigureButtons: false,
selected: testConfigurationService.getGroupDefaultConfigurations(onlyGroup), selected: testProfileService.getGroupDefaultProfiles(onlyGroup),
onlyGroup, onlyGroup,
}); });
if (configurations?.length) { if (profiles?.length) {
testConfigurationService.setGroupDefaultConfigurations(onlyGroup, configurations); testProfileService.setGroupDefaultProfiles(onlyGroup, profiles);
} }
} }
} }
@ -233,34 +233,34 @@ export class ConfigureTestProfilesAction extends Action2 {
super({ super({
id: ConfigureTestProfilesAction.ID, id: ConfigureTestProfilesAction.ID,
title: localize('testing.configureProfile', 'Configure Test Profiles'), title: localize('testing.configureProfile', 'Configure Test Profiles'),
icon: icons.testingUpdateConfiguration, icon: icons.testingUpdateProfiles,
f1: true, f1: true,
category, category,
menu: { menu: {
id: MenuId.CommandPalette, id: MenuId.CommandPalette,
when: TestingContextKeys.hasConfigurableConfig.isEqualTo(true), when: TestingContextKeys.hasConfigurableProfile.isEqualTo(true),
}, },
}); });
} }
public override async run(acessor: ServicesAccessor, onlyGroup?: TestRunConfigurationBitset) { public override async run(acessor: ServicesAccessor, onlyGroup?: TestRunProfileBitset) {
const commands = acessor.get(ICommandService); const commands = acessor.get(ICommandService);
const testConfigurationService = acessor.get(ITestConfigurationService); const testProfileService = acessor.get(ITestProfileService);
const configuration = await commands.executeCommand<ITestRunConfiguration>('vscode.pickTestProfile', { const profile = await commands.executeCommand<ITestRunProfile>('vscode.pickTestProfile', {
placeholder: localize('configureProfile', 'Select a profile to update'), placeholder: localize('configureProfile', 'Select a profile to update'),
showConfigureButtons: false, showConfigureButtons: false,
onlyConfigurable: true, onlyConfigurable: true,
onlyGroup, onlyGroup,
}); });
if (configuration) { if (profile) {
testConfigurationService.configure(configuration.controllerId, configuration.profileId); testProfileService.configure(profile.controllerId, profile.profileId);
} }
} }
} }
abstract class ExecuteSelectedAction extends ViewAction<TestingExplorerView> { abstract class ExecuteSelectedAction extends ViewAction<TestingExplorerView> {
constructor(id: string, title: string, icon: ThemeIcon, private readonly group: TestRunConfigurationBitset) { constructor(id: string, title: string, icon: ThemeIcon, private readonly group: TestRunProfileBitset) {
super({ super({
id, id,
title, title,
@ -308,7 +308,7 @@ export class RunSelectedAction extends ExecuteSelectedAction {
RunSelectedAction.ID, RunSelectedAction.ID,
localize('runSelectedTests', 'Run Selected Tests'), localize('runSelectedTests', 'Run Selected Tests'),
icons.testingRunIcon, icons.testingRunIcon,
TestRunConfigurationBitset.Run, TestRunProfileBitset.Run,
); );
} }
} }
@ -320,7 +320,7 @@ export class DebugSelectedAction extends ExecuteSelectedAction {
DebugSelectedAction.ID, DebugSelectedAction.ID,
localize('debugSelectedTests', 'Debug Selected Tests'), localize('debugSelectedTests', 'Debug Selected Tests'),
icons.testingDebugIcon, icons.testingDebugIcon,
TestRunConfigurationBitset.Debug, TestRunProfileBitset.Debug,
); );
} }
} }
@ -336,15 +336,15 @@ const showDiscoveringWhile = <R>(progress: IProgressService, task: Promise<R>):
}; };
abstract class RunOrDebugAllTestsAction extends Action2 { abstract class RunOrDebugAllTestsAction extends Action2 {
constructor(options: IAction2Options, private readonly group: TestRunConfigurationBitset, private noTestsFoundError: string) { constructor(options: IAction2Options, private readonly group: TestRunProfileBitset, private noTestsFoundError: string) {
super({ super({
...options, ...options,
category, category,
menu: [{ menu: [{
id: MenuId.ViewTitle, id: MenuId.ViewTitle,
order: group === TestRunConfigurationBitset.Run order: group === TestRunProfileBitset.Run
? ActionOrder.Run ? ActionOrder.Run
: group === TestRunConfigurationBitset.Debug : group === TestRunProfileBitset.Debug
? ActionOrder.Debug ? ActionOrder.Debug
: ActionOrder.Coverage, : ActionOrder.Coverage,
group: 'navigation', group: 'navigation',
@ -387,7 +387,7 @@ export class RunAllAction extends RunOrDebugAllTestsAction {
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_A), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_A),
}, },
}, },
TestRunConfigurationBitset.Run, TestRunProfileBitset.Run,
localize('noTestProvider', 'No tests found in this workspace. You may need to install a test provider extension'), localize('noTestProvider', 'No tests found in this workspace. You may need to install a test provider extension'),
); );
} }
@ -406,7 +406,7 @@ export class DebugAllAction extends RunOrDebugAllTestsAction {
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_A), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_A),
}, },
}, },
TestRunConfigurationBitset.Debug, TestRunProfileBitset.Debug,
localize('noDebugTestProvider', 'No debuggable tests found in this workspace. You may need to install a test provider extension'), localize('noDebugTestProvider', 'No debuggable tests found in this workspace. You may need to install a test provider extension'),
); );
} }
@ -782,7 +782,7 @@ export class AutoRunOffAction extends ToggleAutoRun {
abstract class ExecuteTestAtCursor extends Action2 { abstract class ExecuteTestAtCursor extends Action2 {
constructor(options: IAction2Options, protected readonly group: TestRunConfigurationBitset) { constructor(options: IAction2Options, protected readonly group: TestRunProfileBitset) {
super({ super({
...options, ...options,
menu: { menu: {
@ -836,7 +836,7 @@ export class RunAtCursor extends ExecuteTestAtCursor {
when: EditorContextKeys.editorTextFocus, when: EditorContextKeys.editorTextFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_C), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_C),
}, },
}, TestRunConfigurationBitset.Run); }, TestRunProfileBitset.Run);
} }
} }
@ -852,12 +852,12 @@ export class DebugAtCursor extends ExecuteTestAtCursor {
when: EditorContextKeys.editorTextFocus, when: EditorContextKeys.editorTextFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_C), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_C),
}, },
}, TestRunConfigurationBitset.Debug); }, TestRunProfileBitset.Debug);
} }
} }
abstract class ExecuteTestsInCurrentFile extends Action2 { abstract class ExecuteTestsInCurrentFile extends Action2 {
constructor(options: IAction2Options, protected readonly group: TestRunConfigurationBitset) { constructor(options: IAction2Options, protected readonly group: TestRunProfileBitset) {
super({ super({
...options, ...options,
menu: { menu: {
@ -907,7 +907,7 @@ export class RunCurrentFile extends ExecuteTestsInCurrentFile {
when: EditorContextKeys.editorTextFocus, when: EditorContextKeys.editorTextFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_F), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_F),
}, },
}, TestRunConfigurationBitset.Run); }, TestRunProfileBitset.Run);
} }
} }
@ -924,7 +924,7 @@ export class DebugCurrentFile extends ExecuteTestsInCurrentFile {
when: EditorContextKeys.editorTextFocus, when: EditorContextKeys.editorTextFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_F), primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_F),
}, },
}, TestRunConfigurationBitset.Debug); }, TestRunProfileBitset.Debug);
} }
} }
@ -1042,7 +1042,7 @@ export class ReRunFailedTests extends RunOrDebugFailedTests {
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> { protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
return service.runTests({ return service.runTests({
group: TestRunConfigurationBitset.Run, group: TestRunProfileBitset.Run,
tests: internalTests.map(identifyTest), tests: internalTests.map(identifyTest),
}); });
} }
@ -1064,7 +1064,7 @@ export class DebugFailedTests extends RunOrDebugFailedTests {
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> { protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
return service.runTests({ return service.runTests({
group: TestRunConfigurationBitset.Debug, group: TestRunProfileBitset.Debug,
tests: internalTests.map(identifyTest), tests: internalTests.map(identifyTest),
}); });
} }
@ -1086,7 +1086,7 @@ export class ReRunLastRun extends RunOrDebugLastRun {
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> { protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
return service.runTests({ return service.runTests({
group: TestRunConfigurationBitset.Debug, group: TestRunProfileBitset.Debug,
tests: internalTests.map(identifyTest), tests: internalTests.map(identifyTest),
}); });
} }
@ -1108,7 +1108,7 @@ export class DebugLastRun extends RunOrDebugLastRun {
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> { protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
return service.runTests({ return service.runTests({
group: TestRunConfigurationBitset.Debug, group: TestRunProfileBitset.Debug,
tests: internalTests.map(identifyTest), tests: internalTests.map(identifyTest),
}); });
} }

View file

@ -26,8 +26,8 @@ import { ITestingProgressUiService, TestingProgressUiService } from 'vs/workbenc
import { TestingViewPaneContainer } from 'vs/workbench/contrib/testing/browser/testingViewPaneContainer'; import { TestingViewPaneContainer } from 'vs/workbench/contrib/testing/browser/testingViewPaneContainer';
import { testingConfiguation } from 'vs/workbench/contrib/testing/common/configuration'; import { testingConfiguation } from 'vs/workbench/contrib/testing/common/configuration';
import { Testing } from 'vs/workbench/contrib/testing/common/constants'; import { Testing } from 'vs/workbench/contrib/testing/common/constants';
import { identifyTest, ITestIdWithSrc, TestIdPath, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { identifyTest, ITestIdWithSrc, TestIdPath, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { ITestConfigurationService, TestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { ITestProfileService, TestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { ITestingAutoRun, TestingAutoRun } from 'vs/workbench/contrib/testing/common/testingAutoRun'; import { ITestingAutoRun, TestingAutoRun } from 'vs/workbench/contrib/testing/common/testingAutoRun';
import { TestingContentProvider } from 'vs/workbench/contrib/testing/common/testingContentProvider'; import { TestingContentProvider } from 'vs/workbench/contrib/testing/common/testingContentProvider';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
@ -42,7 +42,7 @@ import './testingConfigurationUi';
registerSingleton(ITestService, TestService, true); registerSingleton(ITestService, TestService, true);
registerSingleton(ITestResultStorage, TestResultStorage, true); registerSingleton(ITestResultStorage, TestResultStorage, true);
registerSingleton(ITestConfigurationService, TestConfigurationService, true); registerSingleton(ITestProfileService, TestProfileService, true);
registerSingleton(ITestResultService, TestResultService, true); registerSingleton(ITestResultService, TestResultService, true);
registerSingleton(ITestExplorerFilterState, TestExplorerFilterState, true); registerSingleton(ITestExplorerFilterState, TestExplorerFilterState, true);
registerSingleton(ITestingAutoRun, TestingAutoRun, true); registerSingleton(ITestingAutoRun, TestingAutoRun, true);
@ -113,7 +113,7 @@ CommandsRegistry.registerCommand({
id: 'vscode.runTests', id: 'vscode.runTests',
handler: async (accessor: ServicesAccessor, tests: ITestIdWithSrc[]) => { handler: async (accessor: ServicesAccessor, tests: ITestIdWithSrc[]) => {
const testService = accessor.get(ITestService); const testService = accessor.get(ITestService);
testService.runTests({ group: TestRunConfigurationBitset.Run, tests }); testService.runTests({ group: TestRunProfileBitset.Run, tests });
} }
}); });
@ -121,7 +121,7 @@ CommandsRegistry.registerCommand({
id: 'vscode.debugTests', id: 'vscode.debugTests',
handler: async (accessor: ServicesAccessor, tests: ITestIdWithSrc[]) => { handler: async (accessor: ServicesAccessor, tests: ITestIdWithSrc[]) => {
const testService = accessor.get(ITestService); const testService = accessor.get(ITestService);
testService.runTests({ group: TestRunConfigurationBitset.Debug, tests }); testService.runTests({ group: TestRunProfileBitset.Debug, tests });
} }
}); });
@ -145,7 +145,7 @@ CommandsRegistry.registerCommand({
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: 'vscode.runTestsByPath', id: 'vscode.runTestsByPath',
handler: async (accessor: ServicesAccessor, group: TestRunConfigurationBitset, ...pathToTests: TestIdPath[]) => { handler: async (accessor: ServicesAccessor, group: TestRunProfileBitset, ...pathToTests: TestIdPath[]) => {
const testService = accessor.get(ITestService); const testService = accessor.get(ITestService);
await runTestsByPath( await runTestsByPath(
accessor.get(ITestService).collection, accessor.get(ITestService).collection,

View file

@ -10,10 +10,10 @@ import { localize } from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { QuickPickInput, IQuickPickItem, IQuickInputService, IQuickPickItemButtonEvent } from 'vs/platform/quickinput/common/quickInput'; import { QuickPickInput, IQuickPickItem, IQuickInputService, IQuickPickItemButtonEvent } from 'vs/platform/quickinput/common/quickInput';
import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { testingUpdateConfiguration } from 'vs/workbench/contrib/testing/browser/icons'; import { testingUpdateProfiles } from 'vs/workbench/contrib/testing/browser/icons';
import { testConfigurationGroupNames } from 'vs/workbench/contrib/testing/common/constants'; import { testConfigurationGroupNames } from 'vs/workbench/contrib/testing/common/constants';
import { ITestRunConfiguration, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { ITestRunProfile, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
interface IConfigurationPickerOptions { interface IConfigurationPickerOptions {
/** Placeholder text */ /** Placeholder text */
@ -23,7 +23,7 @@ interface IConfigurationPickerOptions {
/** Only show configurations from this controller */ /** Only show configurations from this controller */
onlyControllerId?: string; onlyControllerId?: string;
/** Only show this group */ /** Only show this group */
onlyGroup?: TestRunConfigurationBitset; onlyGroup?: TestRunProfileBitset;
/** Only show items which are configurable */ /** Only show items which are configurable */
onlyConfigurable?: boolean; onlyConfigurable?: boolean;
} }
@ -33,40 +33,40 @@ function buildPicker(accessor: ServicesAccessor, {
showConfigureButtons, showConfigureButtons,
onlyControllerId, onlyControllerId,
onlyConfigurable, onlyConfigurable,
placeholder = localize('testConfigurationUi.pick', 'Pick a test configuration to use'), placeholder = localize('testConfigurationUi.pick', 'Pick a test profile to use'),
}: IConfigurationPickerOptions) { }: IConfigurationPickerOptions) {
const configService = accessor.get(ITestConfigurationService); const profileService = accessor.get(ITestProfileService);
const items: QuickPickInput<IQuickPickItem & { config: ITestRunConfiguration }>[] = []; const items: QuickPickInput<IQuickPickItem & { profile: ITestRunProfile }>[] = [];
const pushItems = (allConfigs: ITestRunConfiguration[], description?: string) => { const pushItems = (allProfiles: ITestRunProfile[], description?: string) => {
for (const configs of groupBy(allConfigs, (a, b) => a.group - b.group)) { for (const profiles of groupBy(allProfiles, (a, b) => a.group - b.group)) {
let addedHeader = false; let addedHeader = false;
if (onlyGroup) { if (onlyGroup) {
if (configs[0].group !== onlyGroup) { if (profiles[0].group !== onlyGroup) {
continue; continue;
} }
addedHeader = true; // showing one group, no need for label addedHeader = true; // showing one group, no need for label
} }
for (const config of configs) { for (const profile of profiles) {
if (onlyConfigurable && !config.hasConfigurationHandler) { if (onlyConfigurable && !profile.hasConfigurationHandler) {
continue; continue;
} }
if (!addedHeader) { if (!addedHeader) {
items.push({ type: 'separator', label: testConfigurationGroupNames[configs[0].group] }); items.push({ type: 'separator', label: testConfigurationGroupNames[profiles[0].group] });
addedHeader = true; addedHeader = true;
} }
items.push(({ items.push(({
type: 'item', type: 'item',
config, profile,
label: config.label, label: profile.label,
description, description,
alwaysShow: true, alwaysShow: true,
buttons: config.hasConfigurationHandler && showConfigureButtons buttons: profile.hasConfigurationHandler && showConfigureButtons
? [{ ? [{
iconClass: ThemeIcon.asClassName(testingUpdateConfiguration), iconClass: ThemeIcon.asClassName(testingUpdateProfiles),
tooltip: localize('updateTestConfiguration', 'Update Test Configuration') tooltip: localize('updateTestConfiguration', 'Update Test Configuration')
}] : [] }] : []
})); }));
@ -75,29 +75,29 @@ function buildPicker(accessor: ServicesAccessor, {
}; };
if (onlyControllerId !== undefined) { if (onlyControllerId !== undefined) {
const lookup = configService.getControllerConfigurations(onlyControllerId); const lookup = profileService.getControllerProfiles(onlyControllerId);
if (!lookup) { if (!lookup) {
return; return;
} }
pushItems(lookup.configs); pushItems(lookup.profiles);
} else { } else {
for (const { configs, controller } of configService.all()) { for (const { profiles, controller } of profileService.all()) {
pushItems(configs, controller.label.value); pushItems(profiles, controller.label.value);
} }
} }
const quickpick = accessor.get(IQuickInputService).createQuickPick<IQuickPickItem & { config: ITestRunConfiguration }>(); const quickpick = accessor.get(IQuickInputService).createQuickPick<IQuickPickItem & { profile: ITestRunProfile }>();
quickpick.items = items; quickpick.items = items;
quickpick.placeholder = placeholder; quickpick.placeholder = placeholder;
return quickpick; return quickpick;
} }
const triggerButtonHandler = (service: ITestConfigurationService, resolve: (arg: undefined) => void) => const triggerButtonHandler = (service: ITestProfileService, resolve: (arg: undefined) => void) =>
(evt: IQuickPickItemButtonEvent<IQuickPickItem>) => { (evt: IQuickPickItemButtonEvent<IQuickPickItem>) => {
const config = (evt.item as { config?: ITestRunConfiguration }).config; const profile = (evt.item as { profile?: ITestRunProfile }).profile;
if (config) { if (profile) {
service.configure(config.controllerId, config.profileId); service.configure(profile.controllerId, profile.profileId);
resolve(undefined); resolve(undefined);
} }
}; };
@ -105,9 +105,9 @@ const triggerButtonHandler = (service: ITestConfigurationService, resolve: (arg:
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: 'vscode.pickMultipleTestProfiles', id: 'vscode.pickMultipleTestProfiles',
handler: async (accessor: ServicesAccessor, options: IConfigurationPickerOptions & { handler: async (accessor: ServicesAccessor, options: IConfigurationPickerOptions & {
selected?: ITestRunConfiguration[], selected?: ITestRunProfile[],
}) => { }) => {
const configService = accessor.get(ITestConfigurationService); const profileService = accessor.get(ITestProfileService);
const quickpick = buildPicker(accessor, options); const quickpick = buildPicker(accessor, options);
if (!quickpick) { if (!quickpick) {
return; return;
@ -116,17 +116,17 @@ CommandsRegistry.registerCommand({
quickpick.canSelectMany = true; quickpick.canSelectMany = true;
if (options.selected) { if (options.selected) {
quickpick.selectedItems = quickpick.items quickpick.selectedItems = quickpick.items
.filter((i): i is IQuickPickItem & { config: ITestRunConfiguration } => i.type === 'item') .filter((i): i is IQuickPickItem & { profile: ITestRunProfile } => i.type === 'item')
.filter(i => options.selected!.some(s => s.controllerId === i.config.controllerId && s.profileId === i.config.profileId)); .filter(i => options.selected!.some(s => s.controllerId === i.profile.controllerId && s.profileId === i.profile.profileId));
} }
const pick = await new Promise<ITestRunConfiguration[] | undefined>(resolve => { const pick = await new Promise<ITestRunProfile[] | undefined>(resolve => {
quickpick.onDidAccept(() => { quickpick.onDidAccept(() => {
const selected = quickpick.selectedItems as readonly { config?: ITestRunConfiguration }[]; const selected = quickpick.selectedItems as readonly { profile?: ITestRunProfile }[];
resolve(selected.map(s => s.config).filter(isDefined)); resolve(selected.map(s => s.profile).filter(isDefined));
}); });
quickpick.onDidHide(() => resolve(undefined)); quickpick.onDidHide(() => resolve(undefined));
quickpick.onDidTriggerItemButton(triggerButtonHandler(configService, resolve)); quickpick.onDidTriggerItemButton(triggerButtonHandler(profileService, resolve));
quickpick.show(); quickpick.show();
}); });
@ -138,16 +138,16 @@ CommandsRegistry.registerCommand({
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: 'vscode.pickTestProfile', id: 'vscode.pickTestProfile',
handler: async (accessor: ServicesAccessor, options: IConfigurationPickerOptions) => { handler: async (accessor: ServicesAccessor, options: IConfigurationPickerOptions) => {
const configService = accessor.get(ITestConfigurationService); const profileService = accessor.get(ITestProfileService);
const quickpick = buildPicker(accessor, options); const quickpick = buildPicker(accessor, options);
if (!quickpick) { if (!quickpick) {
return; return;
} }
const pick = await new Promise<ITestRunConfiguration | undefined>(resolve => { const pick = await new Promise<ITestRunProfile | undefined>(resolve => {
quickpick.onDidAccept(() => resolve((quickpick.selectedItems[0] as { config?: ITestRunConfiguration })?.config)); quickpick.onDidAccept(() => resolve((quickpick.selectedItems[0] as { profile?: ITestRunProfile })?.profile));
quickpick.onDidHide(() => resolve(undefined)); quickpick.onDidHide(() => resolve(undefined));
quickpick.onDidTriggerItemButton(triggerButtonHandler(configService, resolve)); quickpick.onDidTriggerItemButton(triggerButtonHandler(profileService, resolve));
quickpick.show(); quickpick.show();
}); });

View file

@ -30,8 +30,8 @@ import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browse
import { testMessageSeverityColors } from 'vs/workbench/contrib/testing/browser/theme'; import { testMessageSeverityColors } from 'vs/workbench/contrib/testing/browser/theme';
import { DefaultGutterClickAction, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration'; import { DefaultGutterClickAction, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
import { labelForTestInState } from 'vs/workbench/contrib/testing/common/constants'; import { labelForTestInState } from 'vs/workbench/contrib/testing/common/constants';
import { identifyTest, IncrementalTestCollectionItem, InternalTestItem, IRichLocation, ITestMessage, ITestRunConfiguration, TestResultItem, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { identifyTest, IncrementalTestCollectionItem, InternalTestItem, IRichLocation, ITestMessage, ITestRunProfile, TestResultItem, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { maxPriority } from 'vs/workbench/contrib/testing/common/testingStates'; import { maxPriority } from 'vs/workbench/contrib/testing/common/testingStates';
import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri'; import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri';
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
@ -314,7 +314,7 @@ abstract class RunTestDecoration extends Disposable {
@IContextMenuService protected readonly contextMenuService: IContextMenuService, @IContextMenuService protected readonly contextMenuService: IContextMenuService,
@ICommandService protected readonly commandService: ICommandService, @ICommandService protected readonly commandService: ICommandService,
@IConfigurationService protected readonly configurationService: IConfigurationService, @IConfigurationService protected readonly configurationService: IConfigurationService,
@ITestConfigurationService protected readonly testConfigurationService: ITestConfigurationService, @ITestProfileService protected readonly testProfileService: ITestProfileService,
) { ) {
super(); super();
editorDecoration.options.glyphMarginHoverMessage = new MarkdownString().appendText(this.getGutterLabel()); editorDecoration.options.glyphMarginHoverMessage = new MarkdownString().appendText(this.getGutterLabel());
@ -404,33 +404,33 @@ abstract class RunTestDecoration extends Disposable {
*/ */
protected getTestContextMenuActions(collection: IMainThreadTestCollection, test: InternalTestItem) { protected getTestContextMenuActions(collection: IMainThreadTestCollection, test: InternalTestItem) {
const testActions: IAction[] = []; const testActions: IAction[] = [];
const capabilities = this.testConfigurationService.controllerCapabilities(test.controllerId); const capabilities = this.testProfileService.controllerCapabilities(test.controllerId);
if (capabilities & TestRunConfigurationBitset.Run) { if (capabilities & TestRunProfileBitset.Run) {
testActions.push(new Action('testing.gutter.run', localize('run test', 'Run Test'), undefined, undefined, () => this.testService.runTests({ testActions.push(new Action('testing.gutter.run', localize('run test', 'Run Test'), undefined, undefined, () => this.testService.runTests({
group: TestRunConfigurationBitset.Run, group: TestRunProfileBitset.Run,
tests: [identifyTest(test)], tests: [identifyTest(test)],
}))); })));
} }
if (capabilities & TestRunConfigurationBitset.Debug) { if (capabilities & TestRunProfileBitset.Debug) {
testActions.push(new Action('testing.gutter.debug', localize('debug test', 'Debug Test'), undefined, undefined, () => this.testService.runTests({ testActions.push(new Action('testing.gutter.debug', localize('debug test', 'Debug Test'), undefined, undefined, () => this.testService.runTests({
group: TestRunConfigurationBitset.Debug, group: TestRunProfileBitset.Debug,
tests: [identifyTest(test)], tests: [identifyTest(test)],
}))); })));
} }
if (capabilities & TestRunConfigurationBitset.HasNonDefaultConfig) { if (capabilities & TestRunProfileBitset.HasNonDefaultProfile) {
testActions.push(new Action('testing.runUsing', localize('testing.runUsing', 'Execute Using Profile...'), undefined, undefined, async () => { testActions.push(new Action('testing.runUsing', localize('testing.runUsing', 'Execute Using Profile...'), undefined, undefined, async () => {
const config: ITestRunConfiguration | undefined = await this.commandService.executeCommand('vscode.pickTestProfile', { onlyControllerId: test.controllerId }); const profile: ITestRunProfile | undefined = await this.commandService.executeCommand('vscode.pickTestProfile', { onlyControllerId: test.controllerId });
if (!config) { if (!profile) {
return; return;
} }
this.testService.runResolvedTests({ this.testService.runResolvedTests({
targets: [{ targets: [{
profileGroup: config.group, profileGroup: profile.group,
profileId: config.profileId, profileId: profile.profileId,
controllerId: config.controllerId, controllerId: profile.controllerId,
testIds: [test.item.extId] testIds: [test.item.extId]
}] }]
}); });
@ -467,9 +467,9 @@ class MultiRunTestDecoration extends RunTestDecoration implements ITestDecoratio
@ICommandService commandService: ICommandService, @ICommandService commandService: ICommandService,
@IContextMenuService contextMenuService: IContextMenuService, @IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService, @IConfigurationService configurationService: IConfigurationService,
@ITestConfigurationService testConfigurationService: ITestConfigurationService, @ITestProfileService testProfiles: ITestProfileService,
) { ) {
super(createRunTestDecoration(tests.map(t => t.test), tests.map(t => t.resultItem)), editor, testService, contextMenuService, commandService, configurationService, testConfigurationService); super(createRunTestDecoration(tests.map(t => t.test), tests.map(t => t.resultItem)), editor, testService, contextMenuService, commandService, configurationService, testProfiles);
} }
public override merge(test: IncrementalTestCollectionItem, resultItem: TestResultItem | undefined): RunTestDecoration { public override merge(test: IncrementalTestCollectionItem, resultItem: TestResultItem | undefined): RunTestDecoration {
@ -480,11 +480,11 @@ class MultiRunTestDecoration extends RunTestDecoration implements ITestDecoratio
protected override getContextMenuActions() { protected override getContextMenuActions() {
const allActions: IAction[] = []; const allActions: IAction[] = [];
if (this.tests.some(({ test }) => this.testConfigurationService.controllerCapabilities(test.controllerId) & TestRunConfigurationBitset.Run)) { if (this.tests.some(({ test }) => this.testProfileService.controllerCapabilities(test.controllerId) & TestRunProfileBitset.Run)) {
allActions.push(new Action('testing.gutter.runAll', localize('run all test', 'Run All Tests'), undefined, undefined, () => this.defaultRun())); allActions.push(new Action('testing.gutter.runAll', localize('run all test', 'Run All Tests'), undefined, undefined, () => this.defaultRun()));
} }
if (this.tests.some(({ test }) => this.testConfigurationService.controllerCapabilities(test.controllerId) & TestRunConfigurationBitset.Debug)) { if (this.tests.some(({ test }) => this.testProfileService.controllerCapabilities(test.controllerId) & TestRunProfileBitset.Debug)) {
allActions.push(new Action('testing.gutter.debugAll', localize('debug all test', 'Debug All Tests'), undefined, undefined, () => this.defaultDebug())); allActions.push(new Action('testing.gutter.debugAll', localize('debug all test', 'Debug All Tests'), undefined, undefined, () => this.defaultDebug()));
} }
@ -497,14 +497,14 @@ class MultiRunTestDecoration extends RunTestDecoration implements ITestDecoratio
protected override defaultRun() { protected override defaultRun() {
return this.testService.runTests({ return this.testService.runTests({
tests: this.tests.map(({ test }) => identifyTest(test)), tests: this.tests.map(({ test }) => identifyTest(test)),
group: TestRunConfigurationBitset.Run, group: TestRunProfileBitset.Run,
}); });
} }
protected override defaultDebug() { protected override defaultDebug() {
return this.testService.runTests({ return this.testService.runTests({
tests: this.tests.map(({ test }) => identifyTest(test)), tests: this.tests.map(({ test }) => identifyTest(test)),
group: TestRunConfigurationBitset.Run, group: TestRunProfileBitset.Run,
}); });
} }
} }
@ -518,16 +518,16 @@ class RunSingleTestDecoration extends RunTestDecoration implements ITestDecorati
@ICommandService commandService: ICommandService, @ICommandService commandService: ICommandService,
@IContextMenuService contextMenuService: IContextMenuService, @IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService, @IConfigurationService configurationService: IConfigurationService,
@ITestConfigurationService testConfigurationService: ITestConfigurationService, @ITestProfileService testProfiles: ITestProfileService,
) { ) {
super(createRunTestDecoration([test], [resultItem]), editor, testService, contextMenuService, commandService, configurationService, testConfigurationService); super(createRunTestDecoration([test], [resultItem]), editor, testService, contextMenuService, commandService, configurationService, testProfiles);
} }
public override merge(test: IncrementalTestCollectionItem, resultItem: TestResultItem | undefined): RunTestDecoration { public override merge(test: IncrementalTestCollectionItem, resultItem: TestResultItem | undefined): RunTestDecoration {
return new MultiRunTestDecoration([ return new MultiRunTestDecoration([
{ test: this.test, resultItem: this.resultItem }, { test: this.test, resultItem: this.resultItem },
{ test, resultItem }, { test, resultItem },
], this.editor, this.testService, this.commandService, this.contextMenuService, this.configurationService, this.testConfigurationService); ], this.editor, this.testService, this.commandService, this.contextMenuService, this.configurationService, this.testProfileService);
} }
protected override getContextMenuActions(e: IEditorMouseEvent) { protected override getContextMenuActions(e: IEditorMouseEvent) {
@ -537,14 +537,14 @@ class RunSingleTestDecoration extends RunTestDecoration implements ITestDecorati
protected override defaultRun() { protected override defaultRun() {
return this.testService.runTests({ return this.testService.runTests({
tests: [identifyTest(this.test)], tests: [identifyTest(this.test)],
group: TestRunConfigurationBitset.Run, group: TestRunProfileBitset.Run,
}); });
} }
protected override defaultDebug() { protected override defaultDebug() {
return this.testService.runTests({ return this.testService.runTests({
tests: [identifyTest(this.test)], tests: [identifyTest(this.test)],
group: TestRunConfigurationBitset.Debug, group: TestRunProfileBitset.Debug,
}); });
} }
} }

View file

@ -55,8 +55,8 @@ import { ITestExplorerFilterState, TestExplorerFilterState, TestingExplorerFilte
import { ITestingProgressUiService } from 'vs/workbench/contrib/testing/browser/testingProgressUiService'; import { ITestingProgressUiService } from 'vs/workbench/contrib/testing/browser/testingProgressUiService';
import { getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration'; import { getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
import { labelForTestInState, TestExplorerStateFilter, TestExplorerViewMode, TestExplorerViewSorting, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants'; import { labelForTestInState, TestExplorerStateFilter, TestExplorerViewMode, TestExplorerViewSorting, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants';
import { identifyTest, ITestRunConfiguration, TestIdPath, TestItemExpandState, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { identifyTest, ITestRunProfile, TestIdPath, TestItemExpandState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { capabilityContextKeys, ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { capabilityContextKeys, ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener'; import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
import { cmpPriority, isFailedState, isStateWithResult } from 'vs/workbench/contrib/testing/common/testingStates'; import { cmpPriority, isFailedState, isStateWithResult } from 'vs/workbench/contrib/testing/common/testingStates';
@ -87,7 +87,7 @@ export class TestingExplorerView extends ViewPane {
@ITestService private readonly testService: ITestService, @ITestService private readonly testService: ITestService,
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
@ITestingProgressUiService private readonly testProgressService: ITestingProgressUiService, @ITestingProgressUiService private readonly testProgressService: ITestingProgressUiService,
@ITestConfigurationService private readonly testConfigurationService: ITestConfigurationService, @ITestProfileService private readonly testProfileService: ITestProfileService,
@ICommandService private readonly commandService: ICommandService, @ICommandService private readonly commandService: ICommandService,
) { ) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
@ -104,7 +104,7 @@ export class TestingExplorerView extends ViewPane {
this.updateDiscoveryProgress(busy); this.updateDiscoveryProgress(busy);
})); }));
this._register(testConfigurationService.onDidChange(() => this.updateActions())); this._register(testProfileService.onDidChange(() => this.updateActions()));
} }
/** /**
@ -165,26 +165,26 @@ export class TestingExplorerView extends ViewPane {
case Testing.FilterActionId: case Testing.FilterActionId:
return this.instantiationService.createInstance(TestingExplorerFilter, action); return this.instantiationService.createInstance(TestingExplorerFilter, action);
case RunAllAction.ID: case RunAllAction.ID:
return this.getRunGroupDropdown(TestRunConfigurationBitset.Run, action); return this.getRunGroupDropdown(TestRunProfileBitset.Run, action);
case DebugAllAction.ID: case DebugAllAction.ID:
return this.getRunGroupDropdown(TestRunConfigurationBitset.Debug, action); return this.getRunGroupDropdown(TestRunProfileBitset.Debug, action);
default: default:
return super.getActionViewItem(action); return super.getActionViewItem(action);
} }
} }
/** @inheritdoc */ /** @inheritdoc */
private getTestConfigGroupActions(group: TestRunConfigurationBitset) { private getTestConfigGroupActions(group: TestRunProfileBitset) {
const profileActions: IAction[] = []; const profileActions: IAction[] = [];
let participatingGroups = 0; let participatingGroups = 0;
let hasConfigurable = false; let hasConfigurable = false;
const defaults = this.testConfigurationService.getGroupDefaultConfigurations(group); const defaults = this.testProfileService.getGroupDefaultProfiles(group);
for (const { configs, controller } of this.testConfigurationService.all()) { for (const { profiles, controller } of this.testProfileService.all()) {
let hasAdded = false; let hasAdded = false;
for (const config of configs) { for (const profile of profiles) {
if (config.group !== group) { if (profile.group !== group) {
continue; continue;
} }
@ -194,19 +194,19 @@ export class TestingExplorerView extends ViewPane {
profileActions.push(new Action(`${controller.id}.$root`, controller.label.value, undefined, false)); profileActions.push(new Action(`${controller.id}.$root`, controller.label.value, undefined, false));
} }
hasConfigurable = hasConfigurable || config.hasConfigurationHandler; hasConfigurable = hasConfigurable || profile.hasConfigurationHandler;
profileActions.push(new Action( profileActions.push(new Action(
`${controller.id}.${config.profileId}`, `${controller.id}.${profile.profileId}`,
defaults.includes(config) ? localize('defaultTestProfile', '{0} (Default)', config.label) : config.label, defaults.includes(profile) ? localize('defaultTestProfile', '{0} (Default)', profile.label) : profile.label,
undefined, undefined,
undefined, undefined,
() => this.testService.runResolvedTests({ () => this.testService.runResolvedTests({
targets: [{ targets: [{
profileGroup: config.group, profileGroup: profile.group,
profileId: config.profileId, profileId: profile.profileId,
controllerId: config.controllerId, controllerId: profile.controllerId,
testIds: this.getSelectedOrVisibleItems() testIds: this.getSelectedOrVisibleItems()
.filter(i => i.controllerId === config.controllerId) .filter(i => i.controllerId === profile.controllerId)
.map(i => i.item.extId), .map(i => i.item.extId),
}] }]
}), }),
@ -226,7 +226,7 @@ export class TestingExplorerView extends ViewPane {
localize('selectDefaultConfigs', 'Select Default Profile'), localize('selectDefaultConfigs', 'Select Default Profile'),
undefined, undefined,
undefined, undefined,
() => this.commandService.executeCommand<ITestRunConfiguration>(SelectDefaultTestProfiles.ID, group), () => this.commandService.executeCommand<ITestRunProfile>(SelectDefaultTestProfiles.ID, group),
)); ));
} }
@ -236,7 +236,7 @@ export class TestingExplorerView extends ViewPane {
localize('configureTestProfiles', 'Configure Test Profiles'), localize('configureTestProfiles', 'Configure Test Profiles'),
undefined, undefined,
undefined, undefined,
() => this.commandService.executeCommand<ITestRunConfiguration>(ConfigureTestProfilesAction.ID, group), () => this.commandService.executeCommand<ITestRunProfile>(ConfigureTestProfilesAction.ID, group),
)); ));
} }
@ -258,7 +258,7 @@ export class TestingExplorerView extends ViewPane {
return [...this.testService.collection.rootItems]; // todo return [...this.testService.collection.rootItems]; // todo
} }
private getRunGroupDropdown(group: TestRunConfigurationBitset, defaultAction: IAction) { private getRunGroupDropdown(group: TestRunProfileBitset, defaultAction: IAction) {
const dropdownActions = this.getTestConfigGroupActions(group); const dropdownActions = this.getTestConfigGroupActions(group);
if (dropdownActions.length < 2) { if (dropdownActions.length < 2) {
return super.getActionViewItem(defaultAction); return super.getActionViewItem(defaultAction);
@ -267,7 +267,7 @@ export class TestingExplorerView extends ViewPane {
const primaryAction = this.instantiationService.createInstance(MenuItemAction, { const primaryAction = this.instantiationService.createInstance(MenuItemAction, {
id: defaultAction.id, id: defaultAction.id,
title: defaultAction.label, title: defaultAction.label,
icon: group === TestRunConfigurationBitset.Run icon: group === TestRunProfileBitset.Run
? icons.testingRunAllIcon ? icons.testingRunAllIcon
: icons.testingDebugAllIcon, : icons.testingDebugAllIcon,
}, undefined, undefined); }, undefined, undefined);
@ -389,7 +389,7 @@ export class TestingExplorerViewModel extends Disposable {
@IContextKeyService private readonly contextKeyService: IContextKeyService, @IContextKeyService private readonly contextKeyService: IContextKeyService,
@ITestResultService private readonly testResults: ITestResultService, @ITestResultService private readonly testResults: ITestResultService,
@ITestingPeekOpener private readonly peekOpener: ITestingPeekOpener, @ITestingPeekOpener private readonly peekOpener: ITestingPeekOpener,
@ITestConfigurationService private readonly testConfigurationService: ITestConfigurationService, @ITestProfileService private readonly testProfileService: ITestProfileService,
) { ) {
super(); super();
@ -509,7 +509,7 @@ export class TestingExplorerViewModel extends Disposable {
} }
})); }));
this._register(this.testConfigurationService.onDidChange(() => { this._register(this.testProfileService.onDidChange(() => {
this.tree.rerender(); this.tree.rerender();
})); }));
} }
@ -615,7 +615,7 @@ export class TestingExplorerViewModel extends Disposable {
return; return;
} }
const actions = getActionableElementActions(this.contextKeyService, this.menuService, this.testService, this.testConfigurationService, element); const actions = getActionableElementActions(this.contextKeyService, this.menuService, this.testService, this.testProfileService, element);
this.contextMenuService.showContextMenu({ this.contextMenuService.showContextMenu({
getAnchor: () => evt.anchor, getAnchor: () => evt.anchor,
getActions: () => [ getActions: () => [
@ -645,7 +645,7 @@ export class TestingExplorerViewModel extends Disposable {
if (toRun.length) { if (toRun.length) {
this.testService.runTests({ this.testService.runTests({
group: TestRunConfigurationBitset.Run, group: TestRunProfileBitset.Run,
tests: toRun.map(t => identifyTest(t.test)), tests: toRun.map(t => identifyTest(t.test)),
}); });
} }
@ -1000,7 +1000,7 @@ abstract class ActionableItemTemplateData<T extends TestItemTreeElement> extends
private readonly actionRunner: TestExplorerActionRunner, private readonly actionRunner: TestExplorerActionRunner,
@IMenuService private readonly menuService: IMenuService, @IMenuService private readonly menuService: IMenuService,
@ITestService protected readonly testService: ITestService, @ITestService protected readonly testService: ITestService,
@ITestConfigurationService protected readonly configurations: ITestConfigurationService, @ITestProfileService protected readonly profiles: ITestProfileService,
@IContextKeyService private readonly contextKeyService: IContextKeyService, @IContextKeyService private readonly contextKeyService: IContextKeyService,
@IInstantiationService private readonly instantiationService: IInstantiationService, @IInstantiationService private readonly instantiationService: IInstantiationService,
) { ) {
@ -1058,7 +1058,7 @@ abstract class ActionableItemTemplateData<T extends TestItemTreeElement> extends
} }
private fillActionBar(element: T, data: IActionableElementTemplateData) { private fillActionBar(element: T, data: IActionableElementTemplateData) {
const actions = getActionableElementActions(this.contextKeyService, this.menuService, this.testService, this.configurations, element); const actions = getActionableElementActions(this.contextKeyService, this.menuService, this.testService, this.profiles, element);
data.elementDisposable.push(actions); data.elementDisposable.push(actions);
data.actionBar.clear(); data.actionBar.clear();
data.actionBar.context = element; data.actionBar.context = element;
@ -1130,7 +1130,7 @@ const getActionableElementActions = (
contextKeyService: IContextKeyService, contextKeyService: IContextKeyService,
menuService: IMenuService, menuService: IMenuService,
testService: ITestService, testService: ITestService,
configurations: ITestConfigurationService, profiles: ITestProfileService,
element: TestItemTreeElement, element: TestItemTreeElement,
) => { ) => {
const test = element instanceof TestItemTreeElement ? element.test : undefined; const test = element instanceof TestItemTreeElement ? element.test : undefined;
@ -1139,7 +1139,7 @@ const getActionableElementActions = (
[TestingContextKeys.testItemExtId.key, test?.item.extId], [TestingContextKeys.testItemExtId.key, test?.item.extId],
[TestingContextKeys.testItemHasUri.key, !!test?.item.uri], [TestingContextKeys.testItemHasUri.key, !!test?.item.uri],
[TestingContextKeys.testItemIsHidden.key, !!test && testService.excluded.contains(identifyTest(test))], [TestingContextKeys.testItemIsHidden.key, !!test && testService.excluded.contains(identifyTest(test))],
...(test ? capabilityContextKeys(configurations.controllerCapabilities(test.controllerId)) : []), ...(test ? capabilityContextKeys(profiles.controllerCapabilities(test.controllerId)) : []),
]); ]);
const menu = menuService.createMenu(MenuId.TestItem, contextOverlay); const menu = menuService.createMenu(MenuId.TestItem, contextOverlay);

View file

@ -58,8 +58,8 @@ import { ITestingOutputTerminalService } from 'vs/workbench/contrib/testing/brow
import { testingPeekBorder } from 'vs/workbench/contrib/testing/browser/theme'; import { testingPeekBorder } from 'vs/workbench/contrib/testing/browser/theme';
import { AutoOpenPeekViewWhen, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration'; import { AutoOpenPeekViewWhen, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
import { Testing } from 'vs/workbench/contrib/testing/common/constants'; import { Testing } from 'vs/workbench/contrib/testing/common/constants';
import { IRichLocation, ITestItem, ITestMessage, ITestRunTask, ITestTaskState, TestResultItem, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { IRichLocation, ITestItem, ITestMessage, ITestRunTask, ITestTaskState, TestResultItem, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { capabilityContextKeys, ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { capabilityContextKeys, ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener'; import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
import { isFailedState } from 'vs/workbench/contrib/testing/common/testingStates'; import { isFailedState } from 'vs/workbench/contrib/testing/common/testingStates';
@ -1270,12 +1270,12 @@ class TreeActionsProvider {
@ITestingOutputTerminalService private readonly testTerminalService: ITestingOutputTerminalService, @ITestingOutputTerminalService private readonly testTerminalService: ITestingOutputTerminalService,
@IMenuService private readonly menuService: IMenuService, @IMenuService private readonly menuService: IMenuService,
@ICommandService private readonly commandService: ICommandService, @ICommandService private readonly commandService: ICommandService,
@ITestConfigurationService private readonly testConfigurationService: ITestConfigurationService, @ITestProfileService private readonly testProfileService: ITestProfileService,
) { } ) { }
public provideActionBar(element: ITreeElement) { public provideActionBar(element: ITreeElement) {
const test = element instanceof TestCaseElement ? element.test : undefined; const test = element instanceof TestCaseElement ? element.test : undefined;
const capabilities = test ? this.testConfigurationService.controllerCapabilities(test.controllerId) : 0; const capabilities = test ? this.testProfileService.controllerCapabilities(test.controllerId) : 0;
const contextOverlay = this.contextKeyService.createOverlay([ const contextOverlay = this.contextKeyService.createOverlay([
['peek', Testing.OutputPeekContributionId], ['peek', Testing.OutputPeekContributionId],
[TestingContextKeys.peekItemType.key, element.type], [TestingContextKeys.peekItemType.key, element.type],
@ -1306,7 +1306,7 @@ class TreeActionsProvider {
() => this.commandService.executeCommand('testing.reRunLastRun', element.value.id), () => this.commandService.executeCommand('testing.reRunLastRun', element.value.id),
)); ));
if (capabilities & TestRunConfigurationBitset.Debug) { if (capabilities & TestRunProfileBitset.Debug) {
primary.push(new Action( primary.push(new Action(
'testing.outputPeek.debugLastRun', 'testing.outputPeek.debugLastRun',
localize('testing.debugLastRun', "Debug Test Run"), localize('testing.debugLastRun', "Debug Test Run"),
@ -1326,7 +1326,7 @@ class TreeActionsProvider {
() => this.commandService.executeCommand('vscode.revealTestInExplorer', element.path), () => this.commandService.executeCommand('vscode.revealTestInExplorer', element.path),
)); ));
if (capabilities & TestRunConfigurationBitset.Run) { if (capabilities & TestRunProfileBitset.Run) {
primary.push(new Action( primary.push(new Action(
'testing.outputPeek.runTest', 'testing.outputPeek.runTest',
localize('run test', 'Run Test'), localize('run test', 'Run Test'),
@ -1336,7 +1336,7 @@ class TreeActionsProvider {
)); ));
} }
if (capabilities & TestRunConfigurationBitset.Coverage) { if (capabilities & TestRunProfileBitset.Coverage) {
primary.push(new Action( primary.push(new Action(
'testing.outputPeek.debugTest', 'testing.outputPeek.debugTest',
localize('debug test', 'Debug Test'), localize('debug test', 'Debug Test'),

View file

@ -5,7 +5,7 @@
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { TestResultState } from 'vs/workbench/api/common/extHostTypes';
import { TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
export const enum Testing { export const enum Testing {
// marked as "extension" so that any existing test extensions are assigned to it. // marked as "extension" so that any existing test extensions are assigned to it.
@ -47,8 +47,8 @@ export const labelForTestInState = (label: string, state: TestResultState) => lo
comment: ['label then the unit tests state, for example "Addition Tests (Running)"'], comment: ['label then the unit tests state, for example "Addition Tests (Running)"'],
}, '{0} ({1})', label, testStateNames[state]); }, '{0} ({1})', label, testStateNames[state]);
export const testConfigurationGroupNames: { [K in TestRunConfigurationBitset]: string } = { export const testConfigurationGroupNames: { [K in TestRunProfileBitset]: string } = {
[TestRunConfigurationBitset.Debug]: localize('testGroup.debug', 'Debug'), [TestRunProfileBitset.Debug]: localize('testGroup.debug', 'Debug'),
[TestRunConfigurationBitset.Run]: localize('testGroup.run', 'Run'), [TestRunProfileBitset.Run]: localize('testGroup.run', 'Run'),
[TestRunConfigurationBitset.Coverage]: localize('testGroup.coverage', 'Coverage'), [TestRunProfileBitset.Coverage]: localize('testGroup.coverage', 'Coverage'),
}; };

View file

@ -305,7 +305,7 @@ export class SingleUseTestCollection extends Disposable {
// If the item already exists under a different parent, remove it. // If the item already exists under a different parent, remove it.
let internal = this.tree.get(actual.id); let internal = this.tree.get(actual.id);
if (internal && internal.parent !== parent?.actual.id) { if (internal && internal.parent !== parent?.actual.id) {
(internal.actual.parent ?? this.root).children.remove(actual.id); (internal.actual.parent ?? this.root).children.delete(actual.id);
internal = undefined; internal = undefined;
} }

View file

@ -20,32 +20,32 @@ export interface ITestIdWithSrc {
export const identifyTest = (test: { controllerId: string, item: { extId: string } }): ITestIdWithSrc => export const identifyTest = (test: { controllerId: string, item: { extId: string } }): ITestIdWithSrc =>
({ testId: test.item.extId, controllerId: test.controllerId }); ({ testId: test.item.extId, controllerId: test.controllerId });
export const enum TestRunConfigurationBitset { export const enum TestRunProfileBitset {
Run = 1 << 1, Run = 1 << 1,
Debug = 1 << 2, Debug = 1 << 2,
Coverage = 1 << 3, Coverage = 1 << 3,
HasNonDefaultConfig = 1 << 4, HasNonDefaultProfile = 1 << 4,
HasConfigurable = 1 << 5, HasConfigurable = 1 << 5,
} }
/** /**
* List of all test run configuration bitset values. * List of all test run profile bitset values.
*/ */
export const testRunConfigurationBitsetList = [ export const testRunProfileBitsetList = [
TestRunConfigurationBitset.Run, TestRunProfileBitset.Run,
TestRunConfigurationBitset.Debug, TestRunProfileBitset.Debug,
TestRunConfigurationBitset.Coverage, TestRunProfileBitset.Coverage,
TestRunConfigurationBitset.HasNonDefaultConfig, TestRunProfileBitset.HasNonDefaultProfile,
]; ];
/** /**
* DTO for a controller's run configurations. * DTO for a controller's run profiles.
*/ */
export interface ITestRunConfiguration { export interface ITestRunProfile {
controllerId: string; controllerId: string;
profileId: number; profileId: number;
label: string; label: string;
group: TestRunConfigurationBitset; group: TestRunProfileBitset;
isDefault: boolean; isDefault: boolean;
hasConfigurationHandler: boolean; hasConfigurationHandler: boolean;
} }
@ -64,7 +64,7 @@ export interface ResolvedTestRunRequest {
targets: { targets: {
testIds: string[]; testIds: string[];
controllerId: string; controllerId: string;
profileGroup: TestRunConfigurationBitset; profileGroup: TestRunProfileBitset;
profileId: number; profileId: number;
}[] }[]
exclude?: ITestIdWithSrc[]; exclude?: ITestIdWithSrc[];
@ -79,7 +79,7 @@ export interface ExtensionRunTestsRequest {
include: string[]; include: string[];
exclude: string[]; exclude: string[];
controllerId: string; controllerId: string;
config?: { group: TestRunConfigurationBitset, id: number }; profile?: { group: TestRunProfileBitset, id: number };
persist: boolean; persist: boolean;
} }
@ -89,7 +89,7 @@ export interface ExtensionRunTestsRequest {
export interface RunTestForControllerRequest { export interface RunTestForControllerRequest {
runId: string; runId: string;
controllerId: string; controllerId: string;
configId: number; profileId: number;
excludeExtIds: string[]; excludeExtIds: string[];
testIds: string[]; testIds: string[];
} }

View file

@ -9,47 +9,47 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue'; import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue';
import { ITestRunConfiguration, TestRunConfigurationBitset, testRunConfigurationBitsetList } from 'vs/workbench/contrib/testing/common/testCollection'; import { ITestRunProfile, TestRunProfileBitset, testRunProfileBitsetList } from 'vs/workbench/contrib/testing/common/testCollection';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
import { IMainThreadTestController } from 'vs/workbench/contrib/testing/common/testService'; import { IMainThreadTestController } from 'vs/workbench/contrib/testing/common/testService';
export const ITestConfigurationService = createDecorator<ITestConfigurationService>('testConfigurationService'); export const ITestProfileService = createDecorator<ITestProfileService>('testProfileService');
export interface ITestConfigurationService { export interface ITestProfileService {
readonly _serviceBrand: undefined; readonly _serviceBrand: undefined;
/** /**
* Fired when any configuration changes. * Fired when any profile changes.
*/ */
readonly onDidChange: Event<void>; readonly onDidChange: Event<void>;
/** /**
* Publishes a new test configuration. * Publishes a new test profile.
*/ */
addConfiguration(controller: IMainThreadTestController, config: ITestRunConfiguration): void; addProfile(controller: IMainThreadTestController, profile: ITestRunProfile): void;
/** /**
* Updates an existing test run configuration * Updates an existing test run profile
*/ */
updateConfiguration(controllerId: string, configId: number, update: Partial<ITestRunConfiguration>): void; updateProfile(controllerId: string, profileId: number, update: Partial<ITestRunProfile>): void;
/** /**
* Removes a configuration. If configId is not given, all configurations * Removes a profile. If profileId is not given, all profiles
* for the given controller will be removed. * for the given controller will be removed.
*/ */
removeConfiguration(controllerId: string, configId?: number): void; removeProfile(controllerId: string, profileId?: number): void;
/** /**
* Gets capabilities for the given controller by ID, indicating whether * Gets capabilities for the given controller by ID, indicating whether
* there's any configurations available for those groups. * there's any profiles available for those groups.
* @returns a bitset to use with {@link TestRunConfigurationBitset} * @returns a bitset to use with {@link TestRunProfileBitset}
*/ */
controllerCapabilities(controllerId: string): number; controllerCapabilities(controllerId: string): number;
/** /**
* Configures a test configuration. * Configures a test profile.
*/ */
configure(controllerId: string, configId: number): void; configure(controllerId: string, profileId: number): void;
/** /**
* Gets all registered controllers, grouping by controller. * Gets all registered controllers, grouping by controller.
@ -57,34 +57,34 @@ export interface ITestConfigurationService {
all(): Iterable<Readonly<{ all(): Iterable<Readonly<{
capabilities: number, capabilities: number,
controller: IMainThreadTestController, controller: IMainThreadTestController,
configs: ITestRunConfiguration[], profiles: ITestRunProfile[],
}>>; }>>;
/** /**
* Gets the default configurations to be run for a given run group. * Gets the default profiles to be run for a given run group.
*/ */
getGroupDefaultConfigurations(group: TestRunConfigurationBitset): ITestRunConfiguration[]; getGroupDefaultProfiles(group: TestRunProfileBitset): ITestRunProfile[];
/** /**
* Sets the default configurations to be run for a given run group. * Sets the default profiles to be run for a given run group.
*/ */
setGroupDefaultConfigurations(group: TestRunConfigurationBitset, configs: ITestRunConfiguration[]): void; setGroupDefaultProfiles(group: TestRunProfileBitset, profiles: ITestRunProfile[]): void;
/** /**
* Gets the configurations for a controller, in priority order. * Gets the profiles for a controller, in priority order.
*/ */
getControllerConfigurations(controllerId: string): undefined | { getControllerProfiles(controllerId: string): undefined | {
controller: IMainThreadTestController; controller: IMainThreadTestController;
configs: ITestRunConfiguration[]; profiles: ITestRunProfile[];
}; };
/** /**
* Gets the configurations for the group in a controller, in priorty order. * Gets the profiles for the group in a controller, in priorty order.
*/ */
getControllerGroupConfigurations(controllerId: string, group: TestRunConfigurationBitset): readonly ITestRunConfiguration[]; getControllerGroupProfiles(controllerId: string, group: TestRunProfileBitset): readonly ITestRunProfile[];
} }
const sorter = (a: ITestRunConfiguration, b: ITestRunConfiguration) => { const sorter = (a: ITestRunProfile, b: ITestRunProfile) => {
if (a.isDefault !== b.isDefault) { if (a.isDefault !== b.isDefault) {
return a.isDefault ? -1 : 1; return a.isDefault ? -1 : 1;
} }
@ -97,19 +97,19 @@ const sorter = (a: ITestRunConfiguration, b: ITestRunConfiguration) => {
* them. * them.
*/ */
export const capabilityContextKeys = (capabilities: number): [key: string, value: boolean][] => [ export const capabilityContextKeys = (capabilities: number): [key: string, value: boolean][] => [
[TestingContextKeys.hasRunnableTests.key, (capabilities & TestRunConfigurationBitset.Run) !== 0], [TestingContextKeys.hasRunnableTests.key, (capabilities & TestRunProfileBitset.Run) !== 0],
[TestingContextKeys.hasDebuggableTests.key, (capabilities & TestRunConfigurationBitset.Debug) !== 0], [TestingContextKeys.hasDebuggableTests.key, (capabilities & TestRunProfileBitset.Debug) !== 0],
[TestingContextKeys.hasCoverableTests.key, (capabilities & TestRunConfigurationBitset.Coverage) !== 0], [TestingContextKeys.hasCoverableTests.key, (capabilities & TestRunProfileBitset.Coverage) !== 0],
]; ];
export class TestConfigurationService implements ITestConfigurationService { export class TestProfileService implements ITestProfileService {
declare readonly _serviceBrand: undefined; declare readonly _serviceBrand: undefined;
private readonly preferredDefaults: StoredValue<{ [K in TestRunConfigurationBitset]?: { controllerId: string; configId: number }[] }>; private readonly preferredDefaults: StoredValue<{ [K in TestRunProfileBitset]?: { controllerId: string; profileId: number }[] }>;
private readonly capabilitiesContexts: { [K in TestRunConfigurationBitset]: IContextKey<boolean> }; private readonly capabilitiesContexts: { [K in TestRunProfileBitset]: IContextKey<boolean> };
private readonly changeEmitter = new Emitter<void>(); private readonly changeEmitter = new Emitter<void>();
private readonly controllerConfigs = new Map</* controller ID */string, { private readonly controllerProfiles = new Map</* controller ID */string, {
configs: ITestRunConfiguration[], profiles: ITestRunProfile[],
controller: IMainThreadTestController, controller: IMainThreadTestController,
capabilities: number, capabilities: number,
}>(); }>();
@ -122,40 +122,40 @@ export class TestConfigurationService implements ITestConfigurationService {
@IStorageService storageService: IStorageService, @IStorageService storageService: IStorageService,
) { ) {
this.preferredDefaults = new StoredValue({ this.preferredDefaults = new StoredValue({
key: 'testingPreferredConfigs', key: 'testingPreferredProfiles',
scope: StorageScope.WORKSPACE, scope: StorageScope.WORKSPACE,
target: StorageTarget.USER, target: StorageTarget.USER,
}, storageService); }, storageService);
this.capabilitiesContexts = { this.capabilitiesContexts = {
[TestRunConfigurationBitset.Run]: TestingContextKeys.hasRunnableTests.bindTo(contextKeyService), [TestRunProfileBitset.Run]: TestingContextKeys.hasRunnableTests.bindTo(contextKeyService),
[TestRunConfigurationBitset.Debug]: TestingContextKeys.hasDebuggableTests.bindTo(contextKeyService), [TestRunProfileBitset.Debug]: TestingContextKeys.hasDebuggableTests.bindTo(contextKeyService),
[TestRunConfigurationBitset.Coverage]: TestingContextKeys.hasCoverableTests.bindTo(contextKeyService), [TestRunProfileBitset.Coverage]: TestingContextKeys.hasCoverableTests.bindTo(contextKeyService),
[TestRunConfigurationBitset.HasNonDefaultConfig]: TestingContextKeys.hasNonDefaultProfile.bindTo(contextKeyService), [TestRunProfileBitset.HasNonDefaultProfile]: TestingContextKeys.hasNonDefaultProfile.bindTo(contextKeyService),
[TestRunConfigurationBitset.HasConfigurable]: TestingContextKeys.hasConfigurableConfig.bindTo(contextKeyService), [TestRunProfileBitset.HasConfigurable]: TestingContextKeys.hasConfigurableProfile.bindTo(contextKeyService),
}; };
this.refreshContextKeys(); this.refreshContextKeys();
} }
/** @inheritdoc */ /** @inheritdoc */
public addConfiguration(controller: IMainThreadTestController, config: ITestRunConfiguration): void { public addProfile(controller: IMainThreadTestController, profile: ITestRunProfile): void {
let record = this.controllerConfigs.get(config.controllerId); let record = this.controllerProfiles.get(profile.controllerId);
if (record) { if (record) {
record.configs.push(config); record.profiles.push(profile);
record.configs.sort(sorter); record.profiles.sort(sorter);
record.capabilities |= config.group; record.capabilities |= profile.group;
} else { } else {
record = { record = {
configs: [config], profiles: [profile],
controller, controller,
capabilities: config.group capabilities: profile.group
}; };
this.controllerConfigs.set(config.controllerId, record); this.controllerProfiles.set(profile.controllerId, record);
} }
if (!config.isDefault) { if (!profile.isDefault) {
record.capabilities |= TestRunConfigurationBitset.HasNonDefaultConfig; record.capabilities |= TestRunProfileBitset.HasNonDefaultProfile;
} }
this.refreshContextKeys(); this.refreshContextKeys();
@ -163,48 +163,48 @@ export class TestConfigurationService implements ITestConfigurationService {
} }
/** @inheritdoc */ /** @inheritdoc */
public updateConfiguration(controllerId: string, configId: number, update: Partial<ITestRunConfiguration>): void { public updateProfile(controllerId: string, profileId: number, update: Partial<ITestRunProfile>): void {
const ctrl = this.controllerConfigs.get(controllerId); const ctrl = this.controllerProfiles.get(controllerId);
if (!ctrl) { if (!ctrl) {
return; return;
} }
const config = ctrl.configs.find(c => c.controllerId === controllerId && c.profileId === configId); const profile = ctrl.profiles.find(c => c.controllerId === controllerId && c.profileId === profileId);
if (!config) { if (!profile) {
return; return;
} }
Object.assign(config, update); Object.assign(profile, update);
ctrl.configs.sort(sorter); ctrl.profiles.sort(sorter);
this.changeEmitter.fire(); this.changeEmitter.fire();
} }
/** @inheritdoc */ /** @inheritdoc */
public configure(controllerId: string, configId: number) { public configure(controllerId: string, profileId: number) {
this.controllerConfigs.get(controllerId)?.controller.configureRunConfig(configId); this.controllerProfiles.get(controllerId)?.controller.configureRunProfile(profileId);
} }
/** @inheritdoc */ /** @inheritdoc */
public removeConfiguration(controllerId: string, configId?: number): void { public removeProfile(controllerId: string, profileId?: number): void {
const ctrl = this.controllerConfigs.get(controllerId); const ctrl = this.controllerProfiles.get(controllerId);
if (!ctrl) { if (!ctrl) {
return; return;
} }
if (!configId) { if (!profileId) {
this.controllerConfigs.delete(controllerId); this.controllerProfiles.delete(controllerId);
this.changeEmitter.fire(); this.changeEmitter.fire();
return; return;
} }
const index = ctrl.configs.findIndex(c => c.profileId === configId); const index = ctrl.profiles.findIndex(c => c.profileId === profileId);
if (index === -1) { if (index === -1) {
return; return;
} }
ctrl.configs.splice(index, 1); ctrl.profiles.splice(index, 1);
ctrl.capabilities = 0; ctrl.capabilities = 0;
for (const { group } of ctrl.configs) { for (const { group } of ctrl.profiles) {
ctrl.capabilities |= group; ctrl.capabilities |= group;
} }
@ -214,55 +214,55 @@ export class TestConfigurationService implements ITestConfigurationService {
/** @inheritdoc */ /** @inheritdoc */
public controllerCapabilities(controllerId: string) { public controllerCapabilities(controllerId: string) {
return this.controllerConfigs.get(controllerId)?.capabilities || 0; return this.controllerProfiles.get(controllerId)?.capabilities || 0;
} }
/** @inheritdoc */ /** @inheritdoc */
public all() { public all() {
return this.controllerConfigs.values(); return this.controllerProfiles.values();
} }
/** @inheritdoc */ /** @inheritdoc */
public getControllerConfigurations(controllerId: string) { public getControllerProfiles(profileId: string) {
return this.controllerConfigs.get(controllerId); return this.controllerProfiles.get(profileId);
} }
/** @inheritdoc */ /** @inheritdoc */
public getControllerGroupConfigurations(controllerId: string, group: TestRunConfigurationBitset) { public getControllerGroupProfiles(controllerId: string, group: TestRunProfileBitset) {
return this.controllerConfigs.get(controllerId)?.configs.filter(c => c.group === group) ?? []; return this.controllerProfiles.get(controllerId)?.profiles.filter(c => c.group === group) ?? [];
} }
/** @inheritdoc */ /** @inheritdoc */
public getGroupDefaultConfigurations(group: TestRunConfigurationBitset) { public getGroupDefaultProfiles(group: TestRunProfileBitset) {
const preferred = this.preferredDefaults.get(); const preferred = this.preferredDefaults.get();
if (!preferred) { if (!preferred) {
return this.getBaseDefaults(group); return this.getBaseDefaults(group);
} }
const configs = preferred[group] const profiles = preferred[group]
?.map(p => this.controllerConfigs.get(p.controllerId)?.configs.find( ?.map(p => this.controllerProfiles.get(p.controllerId)?.profiles.find(
c => c.profileId === p.configId && c.group === group)) c => c.profileId === p.profileId && c.group === group))
.filter(isDefined); .filter(isDefined);
return configs?.length ? configs : this.getBaseDefaults(group); return profiles?.length ? profiles : this.getBaseDefaults(group);
} }
/** @inheritdoc */ /** @inheritdoc */
public setGroupDefaultConfigurations(group: TestRunConfigurationBitset, configs: ITestRunConfiguration[]) { public setGroupDefaultProfiles(group: TestRunProfileBitset, profiles: ITestRunProfile[]) {
this.preferredDefaults.store({ this.preferredDefaults.store({
...this.preferredDefaults.get(), ...this.preferredDefaults.get(),
[group]: configs.map(c => ({ configId: c.profileId, controllerId: c.controllerId })), [group]: profiles.map(c => ({ profileId: c.profileId, controllerId: c.controllerId })),
}); });
this.changeEmitter.fire(); this.changeEmitter.fire();
} }
private getBaseDefaults(group: TestRunConfigurationBitset) { private getBaseDefaults(group: TestRunProfileBitset) {
const defaults: ITestRunConfiguration[] = []; const defaults: ITestRunProfile[] = [];
for (const { configs } of this.controllerConfigs.values()) { for (const { profiles } of this.controllerProfiles.values()) {
const config = configs.find(c => c.group === group); const profile = profiles.find(c => c.group === group);
if (config) { if (profile) {
defaults.push(config); defaults.push(profile);
} }
} }
@ -271,11 +271,11 @@ export class TestConfigurationService implements ITestConfigurationService {
private refreshContextKeys() { private refreshContextKeys() {
let allCapabilities = 0; let allCapabilities = 0;
for (const { capabilities } of this.controllerConfigs.values()) { for (const { capabilities } of this.controllerProfiles.values()) {
allCapabilities |= capabilities; allCapabilities |= capabilities;
} }
for (const group of testRunConfigurationBitsetList) { for (const group of testRunProfileBitsetList) {
this.capabilitiesContexts[group].set((allCapabilities & group) !== 0); this.capabilitiesContexts[group].set((allCapabilities & group) !== 0);
} }
} }

View file

@ -11,8 +11,8 @@ import { generateUuid } from 'vs/base/common/uuid';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { TestResultState } from 'vs/workbench/api/common/extHostTypes';
import { ExtensionRunTestsRequest, ITestRunConfiguration, ResolvedTestRunRequest, TestResultItem, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { ExtensionRunTestsRequest, ITestRunProfile, ResolvedTestRunRequest, TestResultItem, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
import { ITestResult, LiveTestResult, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; import { ITestResult, LiveTestResult, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
import { ITestResultStorage, RETAIN_MAX_RESULTS } from 'vs/workbench/contrib/testing/common/testResultStorage'; import { ITestResultStorage, RETAIN_MAX_RESULTS } from 'vs/workbench/contrib/testing/common/testResultStorage';
@ -108,7 +108,7 @@ export class TestResultService implements ITestResultService {
constructor( constructor(
@IContextKeyService contextKeyService: IContextKeyService, @IContextKeyService contextKeyService: IContextKeyService,
@ITestResultStorage private readonly storage: ITestResultStorage, @ITestResultStorage private readonly storage: ITestResultStorage,
@ITestConfigurationService private readonly testConfiguration: ITestConfigurationService, @ITestProfileService private readonly testProfiles: ITestProfileService,
) { ) {
this.isRunning = TestingContextKeys.isRunning.bindTo(contextKeyService); this.isRunning = TestingContextKeys.isRunning.bindTo(contextKeyService);
this.hasAnyResults = TestingContextKeys.hasAnyResults.bindTo(contextKeyService); this.hasAnyResults = TestingContextKeys.hasAnyResults.bindTo(contextKeyService);
@ -137,12 +137,12 @@ export class TestResultService implements ITestResultService {
return this.push(new LiveTestResult(id, this.storage.getOutputController(id), true, req)); return this.push(new LiveTestResult(id, this.storage.getOutputController(id), true, req));
} }
let config: ITestRunConfiguration | undefined; let profile: ITestRunProfile | undefined;
if (!req.config) { if (!req.profile) {
config = this.testConfiguration.getControllerGroupConfigurations(req.controllerId, TestRunConfigurationBitset.Run)[0]; profile = this.testProfiles.getControllerGroupProfiles(req.controllerId, TestRunProfileBitset.Run)[0];
} else { } else {
const configs = this.testConfiguration.getControllerGroupConfigurations(req.controllerId, req.config.group); const profiles = this.testProfiles.getControllerGroupProfiles(req.controllerId, req.profile.group);
config = configs.find(c => c.profileId === req.config!.id) || configs[0]; profile = profiles.find(c => c.profileId === req.profile!.id) || profiles[0];
} }
const resolved: ResolvedTestRunRequest = { const resolved: ResolvedTestRunRequest = {
@ -151,10 +151,10 @@ export class TestResultService implements ITestResultService {
isAutoRun: false, isAutoRun: false,
}; };
if (config) { if (profile) {
resolved.targets.push({ resolved.targets.push({
profileGroup: config.group, profileGroup: profile.group,
profileId: config.profileId, profileId: profile.profileId,
controllerId: req.controllerId, controllerId: req.controllerId,
testIds: req.include, testIds: req.include,
}); });

View file

@ -11,7 +11,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IObservableValue } from 'vs/workbench/contrib/testing/common/observableValue'; import { IObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, ITestIdWithSrc, ResolvedTestRunRequest, RunTestForControllerRequest, TestIdPath, TestItemExpandState, TestRunConfigurationBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, ITestIdWithSrc, ResolvedTestRunRequest, RunTestForControllerRequest, TestIdPath, TestItemExpandState, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions'; import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions';
import { ITestResult } from 'vs/workbench/contrib/testing/common/testResult'; import { ITestResult } from 'vs/workbench/contrib/testing/common/testResult';
@ -20,7 +20,7 @@ export const ITestService = createDecorator<ITestService>('testService');
export interface IMainThreadTestController { export interface IMainThreadTestController {
readonly id: string; readonly id: string;
readonly label: IObservableValue<string>; readonly label: IObservableValue<string>;
configureRunConfig(configId: number): void; configureRunProfile(profileId: number): void;
expandTest(src: ITestIdWithSrc, levels: number): Promise<void>; expandTest(src: ITestIdWithSrc, levels: number): Promise<void>;
runTests(request: RunTestForControllerRequest, token: CancellationToken): Promise<void>; runTests(request: RunTestForControllerRequest, token: CancellationToken): Promise<void>;
} }
@ -171,7 +171,7 @@ export interface ITestRootProvider {
*/ */
export interface AmbiguousRunTestsRequest { export interface AmbiguousRunTestsRequest {
/** Group to run */ /** Group to run */
group: TestRunConfigurationBitset; group: TestRunProfileBitset;
/** Tests to run. Allowed to be from different controllers */ /** Tests to run. Allowed to be from different controllers */
tests: ITestIdWithSrc[]; tests: ITestIdWithSrc[];
/** Tests to exclude. If not given, the current UI excluded tests are used */ /** Tests to exclude. If not given, the current UI excluded tests are used */

View file

@ -14,7 +14,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust'; import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
import { MainThreadTestCollection } from 'vs/workbench/contrib/testing/common/mainThreadTestCollection'; import { MainThreadTestCollection } from 'vs/workbench/contrib/testing/common/mainThreadTestCollection';
import { ITestIdWithSrc, ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { ITestIdWithSrc, ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
import { ITestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions'; import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
import { ITestResult } from 'vs/workbench/contrib/testing/common/testResult'; import { ITestResult } from 'vs/workbench/contrib/testing/common/testResult';
@ -57,7 +57,7 @@ export class TestService extends Disposable implements ITestService {
constructor( constructor(
@IContextKeyService contextKeyService: IContextKeyService, @IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@ITestConfigurationService private readonly testConfigurationService: ITestConfigurationService, @ITestProfileService private readonly testProfiles: ITestProfileService,
@INotificationService private readonly notificationService: INotificationService, @INotificationService private readonly notificationService: INotificationService,
@ITestResultService private readonly testResults: ITestResultService, @ITestResultService private readonly testResults: ITestResultService,
@IWorkspaceTrustRequestService private readonly workspaceTrustRequestService: IWorkspaceTrustRequestService, @IWorkspaceTrustRequestService private readonly workspaceTrustRequestService: IWorkspaceTrustRequestService,
@ -95,33 +95,32 @@ export class TestService extends Disposable implements ITestService {
public async runTests(req: AmbiguousRunTestsRequest, token = CancellationToken.None): Promise<ITestResult> { public async runTests(req: AmbiguousRunTestsRequest, token = CancellationToken.None): Promise<ITestResult> {
const resolved: ResolvedTestRunRequest = { targets: [], exclude: req.exclude, isAutoRun: req.isAutoRun }; const resolved: ResolvedTestRunRequest = { targets: [], exclude: req.exclude, isAutoRun: req.isAutoRun };
// First, try to run the tests using the default run configurations... // First, try to run the tests using the default run profiles...
const defaultConfigs = this.testConfigurationService.getGroupDefaultConfigurations(req.group); for (const profile of this.testProfiles.getGroupDefaultProfiles(req.group)) {
for (const config of defaultConfigs) { const testIds = req.tests.filter(t => t.controllerId === profile.controllerId).map(t => t.testId);
const testIds = req.tests.filter(t => t.controllerId === config.controllerId).map(t => t.testId);
if (testIds.length) { if (testIds.length) {
resolved.targets.push({ resolved.targets.push({
testIds: testIds, testIds: testIds,
profileGroup: config.group, profileGroup: profile.group,
profileId: config.profileId, profileId: profile.profileId,
controllerId: config.controllerId, controllerId: profile.controllerId,
}); });
} }
} }
// If no tests are covered by the defaults, just use whatever the defaults // If no tests are covered by the defaults, just use whatever the defaults
// for their controller are. This can happen if the user chose specific // for their controller are. This can happen if the user chose specific
// configs for the run button, but then asked to run a single test from the // profiles for the run button, but then asked to run a single test from the
// explorer or decoration. We shouldn't no-op. // explorer or decoration. We shouldn't no-op.
if (resolved.targets.length === 0) { if (resolved.targets.length === 0) {
for (const byController of groupBy(req.tests, (a, b) => a.controllerId === b.controllerId ? 0 : 1)) { for (const byController of groupBy(req.tests, (a, b) => a.controllerId === b.controllerId ? 0 : 1)) {
const configs = this.testConfigurationService.getControllerGroupConfigurations(byController[0].controllerId, req.group); const profiles = this.testProfiles.getControllerGroupProfiles(byController[0].controllerId, req.group);
if (configs.length) { if (profiles.length) {
resolved.targets.push({ resolved.targets.push({
testIds: byController.map(t => t.testId), testIds: byController.map(t => t.testId),
profileGroup: req.group, profileGroup: req.group,
profileId: configs[0].profileId, profileId: profiles[0].profileId,
controllerId: configs[0].controllerId, controllerId: profiles[0].controllerId,
}); });
} }
} }
@ -157,7 +156,7 @@ export class TestService extends Disposable implements ITestService {
{ {
runId: result.id, runId: result.id,
excludeExtIds: req.exclude!.filter(t => t.controllerId === group.controllerId).map(t => t.testId), excludeExtIds: req.exclude!.filter(t => t.controllerId === group.controllerId).map(t => t.testId),
configId: group.profileId, profileId: group.profileId,
controllerId: group.controllerId, controllerId: group.controllerId,
testIds: group.testIds, testIds: group.testIds,
}, },

View file

@ -11,7 +11,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { AutoRunMode, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration'; import { AutoRunMode, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
import { identifyTest, ITestIdWithSrc, TestDiffOpType, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { identifyTest, ITestIdWithSrc, TestDiffOpType, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
import { TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; import { TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
import { isRunningTests, ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { isRunningTests, ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
@ -83,7 +83,7 @@ export class TestingAutoRun extends Disposable implements ITestingAutoRun {
const tests = [...rerunIds.values()]; const tests = [...rerunIds.values()];
rerunIds.clear(); rerunIds.clear();
await this.testService.runTests({ group: TestRunConfigurationBitset.Run, tests, isAutoRun: true }); await this.testService.runTests({ group: TestRunProfileBitset.Run, tests, isAutoRun: true });
if (rerunIds.size > 0) { if (rerunIds.size > 0) {
scheduler.schedule(delay); scheduler.schedule(delay);

View file

@ -7,22 +7,22 @@ import { localize } from 'vs/nls';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { ViewContainerLocation } from 'vs/workbench/common/views'; import { ViewContainerLocation } from 'vs/workbench/common/views';
import { TestExplorerViewMode, TestExplorerViewSorting } from 'vs/workbench/contrib/testing/common/constants'; import { TestExplorerViewMode, TestExplorerViewSorting } from 'vs/workbench/contrib/testing/common/constants';
import { TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
export namespace TestingContextKeys { export namespace TestingContextKeys {
export const providerCount = new RawContextKey('testing.providerCount', 0); export const providerCount = new RawContextKey('testing.providerCount', 0);
export const hasDebuggableTests = new RawContextKey('testing.hasDebuggableTests', false, { type: 'boolean', description: localize('testing.hasDebuggableTests', 'Indicates whether any test controller has registered a debug configuration') }); export const hasDebuggableTests = new RawContextKey('testing.hasDebuggableTests', false, { type: 'boolean', description: localize('testing.hasDebuggableTests', 'Indicates whether any test controller has registered a debug configuration') });
export const hasRunnableTests = new RawContextKey('testing.hasRunnableTests', false, { type: 'boolean', description: localize('testing.hasRunnableTests', 'Indicates whether any test controller has registered a run configuration') }); export const hasRunnableTests = new RawContextKey('testing.hasRunnableTests', false, { type: 'boolean', description: localize('testing.hasRunnableTests', 'Indicates whether any test controller has registered a run configuration') });
export const hasCoverableTests = new RawContextKey('testing.hasCoverableTests', false, { type: 'boolean', description: localize('testing.hasCoverableTests', 'Indicates whether any test controller has registered a coverage configuration') }); export const hasCoverableTests = new RawContextKey('testing.hasCoverableTests', false, { type: 'boolean', description: localize('testing.hasCoverableTests', 'Indicates whether any test controller has registered a coverage configuration') });
export const hasNonDefaultProfile = new RawContextKey('testing.hasNonDefaultConfig', false, { type: 'boolean', description: localize('testing.hasNonDefaultConfig', 'Indicates whether any test controller has registered a non-default configuration') }); export const hasNonDefaultProfile = new RawContextKey('testing.hasNonDefaultProfile', false, { type: 'boolean', description: localize('testing.hasNonDefaultConfig', 'Indicates whether any test controller has registered a non-default configuration') });
export const hasConfigurableConfig = new RawContextKey('testing.hasConfigurableConfig', false, { type: 'boolean', description: localize('testing.hasConfigurableConfig', 'Indicates whether any test configuration can be configured') }); export const hasConfigurableProfile = new RawContextKey('testing.hasConfigurableProfile', false, { type: 'boolean', description: localize('testing.hasConfigurableConfig', 'Indicates whether any test configuration can be configured') });
export const capabilityToContextKey: { [K in TestRunConfigurationBitset]: RawContextKey<boolean> } = { export const capabilityToContextKey: { [K in TestRunProfileBitset]: RawContextKey<boolean> } = {
[TestRunConfigurationBitset.Run]: hasRunnableTests, [TestRunProfileBitset.Run]: hasRunnableTests,
[TestRunConfigurationBitset.Coverage]: hasCoverableTests, [TestRunProfileBitset.Coverage]: hasCoverableTests,
[TestRunConfigurationBitset.Debug]: hasDebuggableTests, [TestRunProfileBitset.Debug]: hasDebuggableTests,
[TestRunConfigurationBitset.HasNonDefaultConfig]: hasNonDefaultProfile, [TestRunProfileBitset.HasNonDefaultProfile]: hasNonDefaultProfile,
[TestRunConfigurationBitset.HasConfigurable]: hasConfigurableConfig, [TestRunProfileBitset.HasConfigurable]: hasConfigurableProfile,
}; };
export const hasAnyResults = new RawContextKey('testing.hasAnyResults', false); export const hasAnyResults = new RawContextKey('testing.hasAnyResults', false);

View file

@ -92,7 +92,7 @@ suite('Workbench - Testing Explorer Hierarchal by Location Projection', () => {
{ e: 'b' } { e: 'b' }
]); ]);
harness.c.root.children.get('id-a')!.children.remove('id-ab'); harness.c.root.children.get('id-a')!.children.delete('id-ab');
assert.deepStrictEqual(harness.flush(), [ assert.deepStrictEqual(harness.flush(), [
{ e: 'a', children: [{ e: 'aa' }] }, { e: 'a', children: [{ e: 'aa' }] },

View file

@ -69,7 +69,7 @@ suite('Workbench - Testing Explorer Hierarchal by Name Projection', () => {
test('updates nodes if they remove children', async () => { test('updates nodes if they remove children', async () => {
harness.flush(); harness.flush();
harness.c.root.children.get('id-a')!.children.remove('id-ab'); harness.c.root.children.get('id-a')!.children.delete('id-ab');
assert.deepStrictEqual(harness.flush(), [ assert.deepStrictEqual(harness.flush(), [
{ e: 'aa' }, { e: 'aa' },

View file

@ -10,8 +10,8 @@ import { Lazy } from 'vs/base/common/lazy';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { NullLogService } from 'vs/platform/log/common/log'; import { NullLogService } from 'vs/platform/log/common/log';
import { SingleUseTestCollection } from 'vs/workbench/contrib/testing/common/ownedTestCollection'; import { SingleUseTestCollection } from 'vs/workbench/contrib/testing/common/ownedTestCollection';
import { ITestTaskState, ResolvedTestRunRequest, TestResultItem, TestRunConfigurationBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { ITestTaskState, ResolvedTestRunRequest, TestResultItem, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
import { TestConfigurationService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { TestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
import { TestResultState } from 'vs/workbench/contrib/testing/common/testingStates'; import { TestResultState } from 'vs/workbench/contrib/testing/common/testingStates';
import { getPathForTestInResult, HydratedTestResult, LiveOutputController, LiveTestResult, makeEmptyCounts, resultItemParents, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; import { getPathForTestInResult, HydratedTestResult, LiveOutputController, LiveTestResult, makeEmptyCounts, resultItemParents, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
import { TestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { TestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
@ -36,7 +36,7 @@ suite('Workbench - Test Results Service', () => {
const defaultOpts = (testIds: string[]): ResolvedTestRunRequest => ({ const defaultOpts = (testIds: string[]): ResolvedTestRunRequest => ({
targets: [{ targets: [{
profileGroup: TestRunConfigurationBitset.Run, profileGroup: TestRunProfileBitset.Run,
profileId: 0, profileId: 0,
controllerId: 'ctrlId', controllerId: 'ctrlId',
testIds, testIds,
@ -204,7 +204,7 @@ suite('Workbench - Test Results Service', () => {
setup(() => { setup(() => {
storage = new InMemoryResultStorage(new TestStorageService(), new NullLogService()); storage = new InMemoryResultStorage(new TestStorageService(), new NullLogService());
results = new TestTestResultService(new MockContextKeyService(), storage, new TestConfigurationService(new MockContextKeyService(), new TestStorageService())); results = new TestTestResultService(new MockContextKeyService(), storage, new TestProfileService(new MockContextKeyService(), new TestStorageService()));
}); });
test('pushes new result', () => { test('pushes new result', () => {
@ -221,7 +221,7 @@ suite('Workbench - Test Results Service', () => {
results = new TestResultService( results = new TestResultService(
new MockContextKeyService(), new MockContextKeyService(),
storage, storage,
new TestConfigurationService(new MockContextKeyService(), new TestStorageService()), new TestProfileService(new MockContextKeyService(), new TestStorageService()),
); );
assert.strictEqual(0, results.results.length); assert.strictEqual(0, results.results.length);

View file

@ -9,9 +9,9 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { Iterable } from 'vs/base/common/iterator'; import { Iterable } from 'vs/base/common/iterator';
import { mockObject, MockObject } from 'vs/base/test/common/mock'; import { mockObject, MockObject } from 'vs/base/test/common/mock';
import { MainThreadTestingShape } from 'vs/workbench/api/common/extHost.protocol'; import { MainThreadTestingShape } from 'vs/workbench/api/common/extHost.protocol';
import { TestRunConfigurationImpl, TestRunCoordinator, TestRunDto } from 'vs/workbench/api/common/extHostTesting'; import { TestRunProfileImpl, TestRunCoordinator, TestRunDto } from 'vs/workbench/api/common/extHostTesting';
import * as convert from 'vs/workbench/api/common/extHostTypeConverters'; import * as convert from 'vs/workbench/api/common/extHostTypeConverters';
import { TestMessage, TestResultState, TestRunConfigurationGroup } from 'vs/workbench/api/common/extHostTypes'; import { TestMessage, TestResultState, TestRunProfileGroup } from 'vs/workbench/api/common/extHostTypes';
import { TestDiffOpType, TestItemExpandState } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestDiffOpType, TestItemExpandState } from 'vs/workbench/contrib/testing/common/testCollection';
import { TestItemImpl, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; import { TestItemImpl, testStubs } from 'vs/workbench/contrib/testing/common/testStubs';
import { TestSingleUseCollection } from 'vs/workbench/contrib/testing/test/common/ownedTestCollection'; import { TestSingleUseCollection } from 'vs/workbench/contrib/testing/test/common/ownedTestCollection';
@ -139,7 +139,7 @@ suite('ExtHost Testing', () => {
test('removes children', () => { test('removes children', () => {
single.expand(single.root.id, Infinity); single.expand(single.root.id, Infinity);
single.collectDiff(); single.collectDiff();
single.root.children.remove('id-a'); single.root.children.delete('id-a');
assert.deepStrictEqual(single.collectDiff(), [ assert.deepStrictEqual(single.collectDiff(), [
[TestDiffOpType.Remove, 'id-a'], [TestDiffOpType.Remove, 'id-a'],
@ -412,7 +412,7 @@ suite('ExtHost Testing', () => {
let proxy: MockObject<MainThreadTestingShape>; let proxy: MockObject<MainThreadTestingShape>;
let c: TestRunCoordinator; let c: TestRunCoordinator;
let cts: CancellationTokenSource; let cts: CancellationTokenSource;
let configuration: TestRunConfigurationImpl; let configuration: TestRunProfileImpl;
let req: TestRunRequest; let req: TestRunRequest;
@ -423,17 +423,17 @@ suite('ExtHost Testing', () => {
cts = new CancellationTokenSource(); cts = new CancellationTokenSource();
c = new TestRunCoordinator(proxy); c = new TestRunCoordinator(proxy);
configuration = new TestRunConfigurationImpl(mockObject<MainThreadTestingShape, {}>(), 'ctrlId', 42, 'Do Run', TestRunConfigurationGroup.Run, () => { }, false); configuration = new TestRunProfileImpl(mockObject<MainThreadTestingShape, {}>(), 'ctrlId', 42, 'Do Run', TestRunProfileGroup.Run, () => { }, false);
req = { req = {
include: undefined, include: undefined,
exclude: [single.root.children.get('id-b')!], exclude: [single.root.children.get('id-b')!],
configuration, profile: configuration,
}; };
dto = TestRunDto.fromInternal({ dto = TestRunDto.fromInternal({
controllerId: 'ctrl', controllerId: 'ctrl',
configId: configuration.configId, profileId: configuration.profileId,
excludeExtIds: ['id-b'], excludeExtIds: ['id-b'],
runId: 'run-id', runId: 'run-id',
testIds: [single.root.id], testIds: [single.root.id],
@ -544,7 +544,7 @@ suite('ExtHost Testing', () => {
single.expand(single.root.id, Infinity); single.expand(single.root.id, Infinity);
const task = c.createTestRun('ctrl', single, { const task = c.createTestRun('ctrl', single, {
configuration, profile: configuration,
include: [single.root.children.get('id-a')!], include: [single.root.children.get('id-a')!],
exclude: [single.root.children.get('id-a')!.children.get('id-aa')!], exclude: [single.root.children.get('id-a')!.children.get('id-aa')!],
}, 'hello world', false); }, 'hello world', false);