parent
40ab771cf9
commit
9125758184
49
src/vs/vscode.proposed.d.ts
vendored
49
src/vs/vscode.proposed.d.ts
vendored
|
@ -1806,6 +1806,55 @@ declare module 'vscode' {
|
|||
}
|
||||
//#endregion
|
||||
|
||||
//#region test tags https://github.com/microsoft/vscode/issues/129456
|
||||
/**
|
||||
* Tags can be associated with {@link TestItem | TestItems} and
|
||||
* {@link TestRunProfile | TestRunProfiles}. A profile with a tag can only
|
||||
* execute tests that include that tag in their {@link TestItem.tags} array.
|
||||
*/
|
||||
export class TestTag {
|
||||
/**
|
||||
* Unique ID of the test tag.
|
||||
*/
|
||||
readonly id: string;
|
||||
|
||||
/**
|
||||
* Human-readable name of the tag. If present, the tag will be visible as
|
||||
* a filter option in the UI.
|
||||
*/
|
||||
readonly label?: string;
|
||||
|
||||
/**
|
||||
* Creates a new TestTag instance.
|
||||
* @param id Unique ID of the test tag.
|
||||
* @param label Human-readable name of the tag. If present, the tag will
|
||||
* be visible as a filter option in the UI.
|
||||
*/
|
||||
constructor(id: string, label?: string);
|
||||
}
|
||||
|
||||
export interface TestRunProfile {
|
||||
/**
|
||||
* Associated tag for the profile. If this is set, only {@link TestItem}
|
||||
* instances with the same tag will be eligible to execute in this profile.
|
||||
*/
|
||||
tag?: TestTag;
|
||||
}
|
||||
|
||||
export interface TestItem {
|
||||
/**
|
||||
* Tags associated with this test item. May be used in combination with
|
||||
* {@link TestRunProfile.tags}, or simply as an organizational feature.
|
||||
*/
|
||||
tags: readonly TestTag[];
|
||||
}
|
||||
|
||||
export interface TestController {
|
||||
createRunProfile(label: string, kind: TestRunProfileKind, runHandler: (request: TestRunRequest, token: CancellationToken) => Thenable<void> | void, isDefault?: boolean, tag?: TestTag): TestRunProfile;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region proposed test APIs https://github.com/microsoft/vscode/issues/107467
|
||||
export namespace tests {
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@ import { Range } from 'vs/editor/common/core/range';
|
|||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
|
||||
import { ExtensionRunTestsRequest, ITestItem, ITestMessage, ITestRunProfile, ITestRunTask, ResolvedTestRunRequest, TestDiffOpType, TestResultState, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { TestCoverage } from 'vs/workbench/contrib/testing/common/testCoverage';
|
||||
import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
|
@ -195,8 +195,9 @@ export class MainThreadTesting extends Disposable implements MainThreadTestingSh
|
|||
id: controllerId,
|
||||
label,
|
||||
configureRunProfile: id => this.proxy.$configureRunProfile(controllerId, id),
|
||||
getTags: () => this.proxy.$getTestTags(controllerId),
|
||||
runTests: (req, token) => this.proxy.$runControllerTests(req, token),
|
||||
expandTest: (src, levels) => this.proxy.$expandTest(src, isFinite(levels) ? levels : -1),
|
||||
expandTest: (testId, levels) => this.proxy.$expandTest(testId, isFinite(levels) ? levels : -1),
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1277,6 +1277,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|||
TestResultState: extHostTypes.TestResultState,
|
||||
TestRunRequest: extHostTypes.TestRunRequest,
|
||||
TestMessage: extHostTypes.TestMessage,
|
||||
TestTag: extHostTypes.TestTag,
|
||||
TestRunProfileKind: extHostTypes.TestRunProfileKind,
|
||||
TextSearchCompleteMessageType: TextSearchCompleteMessageType,
|
||||
TestMessageSeverity: extHostTypes.TestMessageSeverity,
|
||||
|
|
|
@ -24,6 +24,7 @@ import { EndOfLineSequence, ISingleEditOperation } from 'vs/editor/common/model'
|
|||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { ILanguageStatus } from 'vs/editor/common/services/languageStatusService';
|
||||
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ConfigurationTarget, IConfigurationChange, IConfigurationData, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
|
@ -47,8 +48,8 @@ import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtens
|
|||
import { ExtHostInteractive } from 'vs/workbench/api/common/extHostInteractive';
|
||||
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { TreeDataTransferDTO } from 'vs/workbench/api/common/shared/treeDataTransfer';
|
||||
import * as tasks from 'vs/workbench/api/common/shared/tasks';
|
||||
import { TreeDataTransferDTO } from 'vs/workbench/api/common/shared/treeDataTransfer';
|
||||
import { SaveReason } from 'vs/workbench/common/editor';
|
||||
import { IRevealOptions, ITreeItem } from 'vs/workbench/common/views';
|
||||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
|
@ -58,7 +59,7 @@ import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
|||
import { InputValidationType } from 'vs/workbench/contrib/scm/common/scm';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
import { ExtensionRunTestsRequest, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, RunTestForControllerRequest, ResolvedTestRunRequest, ITestIdWithSrc, TestsDiff, IFileCoverage, CoverageDetails, ITestRunProfile, TestResultState } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { CoverageDetails, ExtensionRunTestsRequest, IFileCoverage, ISerializedTestResults, ITestItem, ITestMessage, ITestRunProfile, ITestRunTask, ITestTagDisplayInfo, ResolvedTestRunRequest, RunTestForControllerRequest, TestResultState, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTimelineOptions, Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline';
|
||||
import { TypeHierarchyItem } from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
|
||||
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
|
@ -67,7 +68,6 @@ import { createExtHostContextProxyIdentifier as createExtId, createMainContextPr
|
|||
import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import * as statusbar from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
import { ILanguageStatus } from 'vs/editor/common/services/languageStatusService';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
|
@ -2098,7 +2098,7 @@ export interface ExtHostTestingShape {
|
|||
/** Publishes that a test run finished. */
|
||||
$publishTestResults(results: ISerializedTestResults[]): void;
|
||||
/** Expands a test item's children, by the given number of levels. */
|
||||
$expandTest(src: ITestIdWithSrc, levels: number): Promise<void>;
|
||||
$expandTest(testId: string, levels: number): Promise<void>;
|
||||
/** Requests file coverage for a test run. Errors if not available. */
|
||||
$provideFileCoverage(runId: string, taskId: string, token: CancellationToken): Promise<IFileCoverage[]>;
|
||||
/**
|
||||
|
@ -2108,6 +2108,8 @@ export interface ExtHostTestingShape {
|
|||
$resolveFileCoverage(runId: string, taskId: string, fileIndex: number, token: CancellationToken): Promise<CoverageDetails[]>;
|
||||
/** Configures a test run config. */
|
||||
$configureRunProfile(controllerId: string, configId: number): void;
|
||||
/** Gets all in-use tags from the controller. */
|
||||
$getTestTags(controllerId: string): Promise<ITestTagDisplayInfo[]>;
|
||||
}
|
||||
|
||||
export interface MainThreadTestingShape {
|
||||
|
|
|
@ -21,7 +21,7 @@ import { InvalidTestItemError, TestItemImpl, TestItemRootImpl } from 'vs/workben
|
|||
import * as Convert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { TestRunProfileKind, TestRunRequest } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { SingleUseTestCollection } from 'vs/workbench/contrib/testing/common/ownedTestCollection';
|
||||
import { AbstractIncrementalTestCollection, CoverageDetails, IFileCoverage, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, ISerializedTestResults, ITestIdWithSrc, ITestItem, RunTestForControllerRequest, TestResultState, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { AbstractIncrementalTestCollection, CoverageDetails, IFileCoverage, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, ISerializedTestResults, ITestItem, ITestTagDisplayInfo, RunTestForControllerRequest, TestResultState, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestId, TestIdPathParts, TestPosition } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
|
@ -80,7 +80,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
|
|||
get id() {
|
||||
return controllerId;
|
||||
},
|
||||
createRunProfile: (label, group, runHandler, isDefault) => {
|
||||
createRunProfile: (label, group, runHandler, isDefault, tag?: vscode.TestTag | undefined) => {
|
||||
// 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.
|
||||
let profileId = hash(label);
|
||||
|
@ -88,7 +88,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
|
|||
profileId++;
|
||||
}
|
||||
|
||||
const profile = new TestRunProfileImpl(this.proxy, controllerId, profileId, label, group, runHandler, isDefault);
|
||||
const profile = new TestRunProfileImpl(this.proxy, controllerId, profileId, label, group, runHandler, isDefault, tag);
|
||||
profiles.set(profileId, profile);
|
||||
return profile;
|
||||
},
|
||||
|
@ -153,7 +153,7 @@ export class ExtHostTesting implements ExtHostTestingShape {
|
|||
profileId: profile.profileId,
|
||||
controllerId: profile.controllerId,
|
||||
}],
|
||||
exclude: req.exclude?.map(t => ({ testId: t.id, controllerId: profile.controllerId })),
|
||||
exclude: req.exclude?.map(t => t.id),
|
||||
}, token);
|
||||
}
|
||||
|
||||
|
@ -176,6 +176,29 @@ export class ExtHostTesting implements ExtHostTestingShape {
|
|||
this.controllers.get(controllerId)?.profiles.get(profileId)?.configureHandler?.();
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
$getTestTags(controllerId: string) {
|
||||
const record = this.controllers.get(controllerId);
|
||||
if (!record) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
const tags = new Map<string, ITestTagDisplayInfo>();
|
||||
for (const profile of record.profiles.values()) {
|
||||
if (profile.tag) {
|
||||
const display = Convert.TestTag.display(controllerId, profile.tag);
|
||||
tags.set(display.id, display);
|
||||
}
|
||||
}
|
||||
|
||||
for (const tag of record.collection.tags()) {
|
||||
const display = Convert.TestTag.display(controllerId, tag);
|
||||
tags.set(display.id, display);
|
||||
}
|
||||
|
||||
return Promise.resolve([...tags.values()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates test results shown to extensions.
|
||||
* @override
|
||||
|
@ -196,8 +219,8 @@ export class ExtHostTesting implements ExtHostTestingShape {
|
|||
* Expands the nodes in the test tree. If levels is less than zero, it will
|
||||
* be treated as infinite.
|
||||
*/
|
||||
public async $expandTest({ controllerId, testId }: ITestIdWithSrc, levels: number) {
|
||||
const collection = this.controllers.get(controllerId)?.collection;
|
||||
public async $expandTest(testId: string, levels: number) {
|
||||
const collection = this.controllers.get(TestId.fromString(testId).controllerId)?.collection;
|
||||
if (collection) {
|
||||
await collection.expand(testId, levels < 0 ? Infinity : levels);
|
||||
collection.flushDiff();
|
||||
|
@ -862,6 +885,19 @@ export class TestRunProfileImpl implements vscode.TestRunProfile {
|
|||
}
|
||||
}
|
||||
|
||||
public get tag() {
|
||||
return this._tag;
|
||||
}
|
||||
|
||||
public set tag(tag: vscode.TestTag | undefined) {
|
||||
if (tag?.id !== this._tag?.id) {
|
||||
this._tag = tag;
|
||||
this.#proxy.$updateTestRunConfig(this.controllerId, this.profileId, {
|
||||
tag: tag ? Convert.TestTag.namespace(this.controllerId, tag.id) : null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public get configureHandler() {
|
||||
return this._configureHandler;
|
||||
}
|
||||
|
@ -881,6 +917,7 @@ export class TestRunProfileImpl implements vscode.TestRunProfile {
|
|||
public readonly kind: vscode.TestRunProfileKind,
|
||||
public runHandler: (request: vscode.TestRunRequest, token: vscode.CancellationToken) => Thenable<void> | void,
|
||||
private _isDefault = false,
|
||||
public _tag: vscode.TestTag | undefined = undefined,
|
||||
) {
|
||||
this.#proxy = proxy;
|
||||
|
||||
|
@ -892,6 +929,7 @@ export class TestRunProfileImpl implements vscode.TestRunProfile {
|
|||
this.#proxy.$publishTestRunProfile({
|
||||
profileId: profileId,
|
||||
controllerId,
|
||||
tag: _tag ? Convert.TestTag.namespace(this.controllerId, _tag.id) : null,
|
||||
label: _label,
|
||||
group: groupBitset,
|
||||
isDefault: _isDefault,
|
||||
|
|
|
@ -88,7 +88,7 @@ const testItemPropAccessor = <K extends keyof vscode.TestItem>(
|
|||
};
|
||||
};
|
||||
|
||||
type WritableProps = Pick<vscode.TestItem, 'range' | 'label' | 'description' | 'canResolveChildren' | 'busy' | 'error'>;
|
||||
type WritableProps = Pick<vscode.TestItem, 'range' | 'label' | 'description' | 'canResolveChildren' | 'busy' | 'error' | 'tags'>;
|
||||
|
||||
const strictEqualComparator = <T>(a: T, b: T) => a === b;
|
||||
|
||||
|
@ -102,7 +102,18 @@ const propComparators: { [K in keyof Required<WritableProps>]: (a: vscode.TestIt
|
|||
description: strictEqualComparator,
|
||||
busy: strictEqualComparator,
|
||||
error: strictEqualComparator,
|
||||
canResolveChildren: strictEqualComparator
|
||||
canResolveChildren: strictEqualComparator,
|
||||
tags: (a, b) => {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.some(t1 => !b.find(t2 => t1.id === t2.id))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
const writablePropKeys = Object.keys(propComparators) as (keyof Required<WritableProps>)[];
|
||||
|
@ -114,6 +125,7 @@ const makePropDescriptors = (api: IExtHostTestItemApi, label: string): { [K in k
|
|||
canResolveChildren: testItemPropAccessor(api, 'canResolveChildren', false, propComparators.canResolveChildren),
|
||||
busy: testItemPropAccessor(api, 'busy', false, propComparators.busy),
|
||||
error: testItemPropAccessor(api, 'error', undefined, propComparators.error),
|
||||
tags: testItemPropAccessor(api, 'tags', [], propComparators.tags),
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -253,6 +265,7 @@ export class TestItemImpl implements vscode.TestItem {
|
|||
public error!: string | vscode.MarkdownString;
|
||||
public busy!: boolean;
|
||||
public canResolveChildren!: boolean;
|
||||
public tags!: readonly vscode.TestTag[];
|
||||
|
||||
/**
|
||||
* Note that data is deprecated and here for back-compat only
|
||||
|
|
|
@ -31,7 +31,7 @@ import { SaveReason } from 'vs/workbench/common/editor';
|
|||
import * as notebooks from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import * as search from 'vs/workbench/contrib/search/common/search';
|
||||
import { CoverageDetails, DetailType, ICoveredCount, IFileCoverage, ISerializedTestResults, ITestItem, ITestItemContext, ITestMessage, SerializedTestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { CoverageDetails, DetailType, ICoveredCount, IFileCoverage, ISerializedTestResults, ITestItem, ITestItemContext, ITestMessage, ITestTag, ITestTagDisplayInfo, SerializedTestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
|
||||
import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -1657,14 +1657,38 @@ export namespace TestMessage {
|
|||
}
|
||||
}
|
||||
|
||||
export namespace TestTag {
|
||||
const enum Constants {
|
||||
Delimiter = '\0',
|
||||
}
|
||||
|
||||
export const namespace = (ctrlId: string, tagId: string) =>
|
||||
ctrlId + Constants.Delimiter + tagId;
|
||||
|
||||
export function display(controllerId: string, tag: vscode.TestTag): ITestTagDisplayInfo {
|
||||
return {
|
||||
displayId: tag.id,
|
||||
id: namespace(controllerId, tag.id),
|
||||
label: tag.label,
|
||||
};
|
||||
}
|
||||
|
||||
export const denamespace = (namespaced: string) => {
|
||||
const index = namespaced.indexOf(Constants.Delimiter);
|
||||
return { ctrlId: namespaced.slice(0, index), tagId: namespaced.slice(index + 1) };
|
||||
};
|
||||
}
|
||||
|
||||
export namespace TestItem {
|
||||
export type Raw = vscode.TestItem;
|
||||
|
||||
export function from(item: TestItemImpl): ITestItem {
|
||||
const ctrlId = getPrivateApiFor(item).controllerId;
|
||||
return {
|
||||
extId: TestId.fromExtHostTestItem(item, getPrivateApiFor(item).controllerId).toString(),
|
||||
extId: TestId.fromExtHostTestItem(item, ctrlId).toString(),
|
||||
label: item.label,
|
||||
uri: item.uri,
|
||||
tags: item.tags.map(t => TestTag.namespace(ctrlId, t.id)),
|
||||
range: Range.from(item.range) || null,
|
||||
description: item.description || null,
|
||||
error: item.error ? (MarkdownString.fromStrict(item.error) || null) : null,
|
||||
|
@ -1676,6 +1700,10 @@ export namespace TestItem {
|
|||
id: TestId.fromString(item.extId).localId,
|
||||
label: item.label,
|
||||
uri: URI.revive(item.uri),
|
||||
tags: item.tags.map(t => {
|
||||
const { tagId } = TestTag.denamespace(t);
|
||||
return new types.TestTag(tagId, tagId);
|
||||
}),
|
||||
range: Range.to(item.range || undefined),
|
||||
invalidateResults: () => undefined,
|
||||
canResolveChildren: false,
|
||||
|
@ -1704,6 +1732,16 @@ export namespace TestItem {
|
|||
}
|
||||
}
|
||||
|
||||
export namespace TestTag {
|
||||
export function from(tag: vscode.TestTag): ITestTag {
|
||||
return { id: tag.id, label: tag.label };
|
||||
}
|
||||
|
||||
export function to(tag: ITestTag): vscode.TestTag {
|
||||
return new types.TestTag(tag.id, tag.label);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TestResults {
|
||||
const convertTestResultItem = (item: SerializedTestResultItem, byInternalId: Map<string, SerializedTestResultItem>): vscode.TestResultSnapshot => {
|
||||
const snapshot: vscode.TestResultSnapshot = ({
|
||||
|
|
|
@ -3339,6 +3339,14 @@ export class TestMessage implements vscode.TestMessage {
|
|||
constructor(public message: string | vscode.MarkdownString) { }
|
||||
}
|
||||
|
||||
@es5ClassCompat
|
||||
export class TestTag implements vscode.TestTag {
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
public readonly label?: string,
|
||||
) { }
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Test Coverage
|
||||
|
|
|
@ -10,7 +10,7 @@ import { IMarkdownString } from 'vs/base/common/htmlContent';
|
|||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { MarshalledId } from 'vs/base/common/marshalling';
|
||||
import { TestResultState, identifyTest, InternalTestItem, ITestIdWithSrc, ITestItemContext } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTestItem, ITestItemContext, TestResultState } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
|
||||
/**
|
||||
* Describes a rendering of tests in the explorer view. Different
|
||||
|
@ -68,7 +68,7 @@ export interface IActionableTestTreeElement {
|
|||
/**
|
||||
* Iterable of the tests this element contains.
|
||||
*/
|
||||
tests: Iterable<ITestIdWithSrc>;
|
||||
tests: Iterable<InternalTestItem>;
|
||||
|
||||
/**
|
||||
* State to show on the item. This is generally the item's computed state
|
||||
|
@ -108,7 +108,7 @@ export class TestItemTreeElement implements IActionableTestTreeElement {
|
|||
public depth: number = this.parent ? this.parent.depth + 1 : 0;
|
||||
|
||||
public get tests() {
|
||||
return Iterable.single(identifyTest(this.test));
|
||||
return Iterable.single(this.test);
|
||||
}
|
||||
|
||||
public get description() {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { InternalTestItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { capabilityContextKeys } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { capabilityContextKeys } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
|
||||
|
|
|
@ -30,12 +30,12 @@ import { ITestExplorerFilterState } from 'vs/workbench/contrib/testing/browser/t
|
|||
import type { TestingExplorerView, TestingExplorerViewModel } from 'vs/workbench/contrib/testing/browser/testingExplorerView';
|
||||
import { ITestingOutputTerminalService } from 'vs/workbench/contrib/testing/browser/testingOutputTerminalService';
|
||||
import { TestExplorerViewMode, TestExplorerViewSorting, Testing } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { identifyTest, InternalTestItem, ITestIdWithSrc, ITestItem, ITestRunProfile, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { InternalTestItem, ITestItem, ITestRunProfile, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestingAutoRun } from 'vs/workbench/contrib/testing/common/testingAutoRun';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
|
||||
import { isFailedState } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
import { canUseProfileWithTest, ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { ITestResult } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { expandAndGetTestById, IMainThreadTestCollection, ITestService, testsInFile } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
@ -80,7 +80,7 @@ export class HideTestAction extends Action2 {
|
|||
const service = accessor.get(ITestService);
|
||||
for (const element of elements) {
|
||||
if (element instanceof TestItemTreeElement) {
|
||||
service.excluded.toggle(identifyTest(element.test), true);
|
||||
service.excluded.toggle(element.test, true);
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
|
@ -105,7 +105,7 @@ export class UnhideTestAction extends Action2 {
|
|||
const service = accessor.get(ITestService);
|
||||
for (const element of elements) {
|
||||
if (element instanceof TestItemTreeElement) {
|
||||
service.excluded.toggle(identifyTest(element.test), false);
|
||||
service.excluded.toggle(element.test, false);
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
|
@ -159,8 +159,9 @@ export class RunUsingProfileAction extends Action2 {
|
|||
|
||||
const commandService = acessor.get(ICommandService);
|
||||
const testService = acessor.get(ITestService);
|
||||
const controllerId = testElements[0].test.controllerId;
|
||||
const profile: ITestRunProfile | undefined = await commandService.executeCommand('vscode.pickTestProfile', { onlyControllerId: controllerId });
|
||||
const profile: ITestRunProfile | undefined = await commandService.executeCommand('vscode.pickTestProfile', {
|
||||
onlyForTest: testElements[0].test,
|
||||
});
|
||||
if (!profile) {
|
||||
return;
|
||||
}
|
||||
|
@ -170,7 +171,7 @@ export class RunUsingProfileAction extends Action2 {
|
|||
profileGroup: profile.group,
|
||||
profileId: profile.profileId,
|
||||
controllerId: profile.controllerId,
|
||||
testIds: testElements.filter(t => controllerId === t.test.controllerId).map(t => t.test.item.extId)
|
||||
testIds: testElements.filter(t => canUseProfileWithTest(profile, t.test)).map(t => t.test.item.extId)
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
@ -288,14 +289,13 @@ abstract class ExecuteSelectedAction extends ViewAction<TestingExplorerView> {
|
|||
|
||||
private getActionableTests(testService: ITestService, viewModel: TestingExplorerViewModel) {
|
||||
const selected = viewModel.getSelectedTests();
|
||||
let tests: ITestIdWithSrc[];
|
||||
let tests: InternalTestItem[];
|
||||
if (!selected.length) {
|
||||
tests = ([...testService.collection.rootItems].map(identifyTest));
|
||||
tests = [...testService.collection.rootItems];
|
||||
} else {
|
||||
tests = selected
|
||||
.map(treeElement => treeElement instanceof TestItemTreeElement ? treeElement.test : undefined)
|
||||
.filter(isDefined)
|
||||
.map(identifyTest);
|
||||
.filter(isDefined);
|
||||
}
|
||||
|
||||
return tests;
|
||||
|
@ -372,7 +372,7 @@ abstract class RunOrDebugAllTestsAction extends Action2 {
|
|||
return;
|
||||
}
|
||||
|
||||
await testService.runTests({ tests: roots.map(identifyTest), group: this.group });
|
||||
await testService.runTests({ tests: roots, group: this.group });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -795,7 +795,7 @@ abstract class ExecuteTestAtCursor extends Action2 {
|
|||
if (bestNode) {
|
||||
await testService.runTests({
|
||||
group: this.group,
|
||||
tests: [identifyTest(bestNode)],
|
||||
tests: [bestNode],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -861,7 +861,7 @@ abstract class ExecuteTestsInCurrentFile extends Action2 {
|
|||
for (const test of testService.collection.all) {
|
||||
if (test.item.uri?.toString() === demandedUri) {
|
||||
return testService.runTests({
|
||||
tests: [identifyTest(test)],
|
||||
tests: [test],
|
||||
group: this.group,
|
||||
});
|
||||
}
|
||||
|
@ -1015,7 +1015,7 @@ export class ReRunFailedTests extends RunOrDebugFailedTests {
|
|||
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
|
||||
return service.runTests({
|
||||
group: TestRunProfileBitset.Run,
|
||||
tests: internalTests.map(identifyTest),
|
||||
tests: internalTests,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1037,7 +1037,7 @@ export class DebugFailedTests extends RunOrDebugFailedTests {
|
|||
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
|
||||
return service.runTests({
|
||||
group: TestRunProfileBitset.Debug,
|
||||
tests: internalTests.map(identifyTest),
|
||||
tests: internalTests,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1059,7 +1059,7 @@ export class ReRunLastRun extends RunOrDebugLastRun {
|
|||
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
|
||||
return service.runTests({
|
||||
group: TestRunProfileBitset.Run,
|
||||
tests: internalTests.map(identifyTest),
|
||||
tests: internalTests,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1081,7 +1081,7 @@ export class DebugLastRun extends RunOrDebugLastRun {
|
|||
protected runTest(service: ITestService, internalTests: InternalTestItem[]): Promise<ITestResult> {
|
||||
return service.runTests({
|
||||
group: TestRunProfileBitset.Debug,
|
||||
tests: internalTests.map(identifyTest),
|
||||
tests: internalTests,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,13 @@ import { ITestingProgressUiService, TestingProgressUiService } from 'vs/workbenc
|
|||
import { TestingViewPaneContainer } from 'vs/workbench/contrib/testing/browser/testingViewPaneContainer';
|
||||
import { testingConfiguation } from 'vs/workbench/contrib/testing/common/configuration';
|
||||
import { Testing } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { identifyTest, ITestIdWithSrc, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService, TestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestId, TestPosition } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { ITestingAutoRun, TestingAutoRun } from 'vs/workbench/contrib/testing/common/testingAutoRun';
|
||||
import { TestingContentProvider } from 'vs/workbench/contrib/testing/common/testingContentProvider';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
|
||||
import { ITestProfileService, TestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { ITestResultService, TestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { ITestResultStorage, TestResultStorage } from 'vs/workbench/contrib/testing/common/testResultStorage';
|
||||
import { ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
@ -115,22 +115,6 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
|||
registerEditorContribution(Testing.OutputPeekContributionId, TestingOutputPeekController);
|
||||
registerEditorContribution(Testing.DecorationsContributionId, TestingDecorations);
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'vscode.runTests',
|
||||
handler: async (accessor: ServicesAccessor, tests: ITestIdWithSrc[]) => {
|
||||
const testService = accessor.get(ITestService);
|
||||
testService.runTests({ group: TestRunProfileBitset.Run, tests });
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'vscode.debugTests',
|
||||
handler: async (accessor: ServicesAccessor, tests: ITestIdWithSrc[]) => {
|
||||
const testService = accessor.get(ITestService);
|
||||
testService.runTests({ group: TestRunProfileBitset.Debug, tests });
|
||||
}
|
||||
});
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'vscode.revealTestInExplorer',
|
||||
handler: async (accessor: ServicesAccessor, testId: string, focus?: boolean) => {
|
||||
|
@ -216,7 +200,7 @@ CommandsRegistry.registerCommand({
|
|||
accessor.get(ITestService).collection,
|
||||
accessor.get(IProgressService),
|
||||
testIds,
|
||||
tests => testService.runTests({ group, tests: tests.map(identifyTest) }),
|
||||
tests => testService.runTests({ group, tests }),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,8 +12,8 @@ import { QuickPickInput, IQuickPickItem, IQuickInputService, IQuickPickItemButto
|
|||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { testingUpdateProfiles } from 'vs/workbench/contrib/testing/browser/icons';
|
||||
import { testConfigurationGroupNames } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { ITestRunProfile, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { InternalTestItem, ITestRunProfile, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { canUseProfileWithTest, ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
|
||||
interface IConfigurationPickerOptions {
|
||||
/** Placeholder text */
|
||||
|
@ -21,7 +21,7 @@ interface IConfigurationPickerOptions {
|
|||
/** Show buttons to trigger configuration */
|
||||
showConfigureButtons?: boolean;
|
||||
/** Only show configurations from this controller */
|
||||
onlyControllerId?: string;
|
||||
onlyForTest?: InternalTestItem;
|
||||
/** Only show this group */
|
||||
onlyGroup?: TestRunProfileBitset;
|
||||
/** Only show items which are configurable */
|
||||
|
@ -31,7 +31,7 @@ interface IConfigurationPickerOptions {
|
|||
function buildPicker(accessor: ServicesAccessor, {
|
||||
onlyGroup,
|
||||
showConfigureButtons = true,
|
||||
onlyControllerId,
|
||||
onlyForTest,
|
||||
onlyConfigurable,
|
||||
placeholder = localize('testConfigurationUi.pick', 'Pick a test profile to use'),
|
||||
}: IConfigurationPickerOptions) {
|
||||
|
@ -74,13 +74,8 @@ function buildPicker(accessor: ServicesAccessor, {
|
|||
}
|
||||
};
|
||||
|
||||
if (onlyControllerId !== undefined) {
|
||||
const lookup = profileService.getControllerProfiles(onlyControllerId);
|
||||
if (!lookup) {
|
||||
return;
|
||||
}
|
||||
|
||||
pushItems(lookup.profiles);
|
||||
if (onlyForTest !== undefined) {
|
||||
pushItems(profileService.getControllerProfiles(onlyForTest.controllerId).filter(p => canUseProfileWithTest(p, onlyForTest)));
|
||||
} else {
|
||||
for (const { profiles, controller } of profileService.all()) {
|
||||
pushItems(profiles, controller.label.value);
|
||||
|
|
|
@ -34,10 +34,10 @@ import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browse
|
|||
import { testMessageSeverityColors } from 'vs/workbench/contrib/testing/browser/theme';
|
||||
import { DefaultGutterClickAction, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
|
||||
import { labelForTestInState } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { identifyTest, IncrementalTestCollectionItem, InternalTestItem, IRichLocation, ITestMessage, ITestRunProfile, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { IncrementalTestCollectionItem, InternalTestItem, IRichLocation, ITestMessage, ITestRunProfile, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { isFailedState, maxPriority } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { getContextForTestItem, ITestService, testsInFile } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
||||
|
@ -413,24 +413,24 @@ abstract class RunTestDecoration extends Disposable {
|
|||
*/
|
||||
protected getTestContextMenuActions(test: InternalTestItem, resultItem?: TestResultItem): IReference<IAction[]> {
|
||||
const testActions: IAction[] = [];
|
||||
const capabilities = this.testProfileService.controllerCapabilities(test.controllerId);
|
||||
const capabilities = this.testProfileService.capabilitiesForTest(test);
|
||||
if (capabilities & TestRunProfileBitset.Run) {
|
||||
testActions.push(new Action('testing.gutter.run', localize('run test', 'Run Test'), undefined, undefined, () => this.testService.runTests({
|
||||
group: TestRunProfileBitset.Run,
|
||||
tests: [identifyTest(test)],
|
||||
tests: [test],
|
||||
})));
|
||||
}
|
||||
|
||||
if (capabilities & TestRunProfileBitset.Debug) {
|
||||
testActions.push(new Action('testing.gutter.debug', localize('debug test', 'Debug Test'), undefined, undefined, () => this.testService.runTests({
|
||||
group: TestRunProfileBitset.Debug,
|
||||
tests: [identifyTest(test)],
|
||||
tests: [test],
|
||||
})));
|
||||
}
|
||||
|
||||
if (capabilities & TestRunProfileBitset.HasNonDefaultProfile) {
|
||||
testActions.push(new Action('testing.runUsing', localize('testing.runUsing', 'Execute Using Profile...'), undefined, undefined, async () => {
|
||||
const profile: ITestRunProfile | undefined = await this.commandService.executeCommand('vscode.pickTestProfile', { onlyControllerId: test.controllerId });
|
||||
const profile: ITestRunProfile | undefined = await this.commandService.executeCommand('vscode.pickTestProfile', { onlyForTest: test });
|
||||
if (!profile) {
|
||||
return;
|
||||
}
|
||||
|
@ -499,11 +499,11 @@ class MultiRunTestDecoration extends RunTestDecoration implements ITestDecoratio
|
|||
|
||||
protected override getContextMenuActions() {
|
||||
const allActions: IAction[] = [];
|
||||
if (this.tests.some(({ test }) => this.testProfileService.controllerCapabilities(test.controllerId) & TestRunProfileBitset.Run)) {
|
||||
if (this.tests.some(({ test }) => this.testProfileService.capabilitiesForTest(test) & TestRunProfileBitset.Run)) {
|
||||
allActions.push(new Action('testing.gutter.runAll', localize('run all test', 'Run All Tests'), undefined, undefined, () => this.defaultRun()));
|
||||
}
|
||||
|
||||
if (this.tests.some(({ test }) => this.testProfileService.controllerCapabilities(test.controllerId) & TestRunProfileBitset.Debug)) {
|
||||
if (this.tests.some(({ test }) => this.testProfileService.capabilitiesForTest(test) & TestRunProfileBitset.Debug)) {
|
||||
allActions.push(new Action('testing.gutter.debugAll', localize('debug all test', 'Debug All Tests'), undefined, undefined, () => this.defaultDebug()));
|
||||
}
|
||||
|
||||
|
@ -519,14 +519,14 @@ class MultiRunTestDecoration extends RunTestDecoration implements ITestDecoratio
|
|||
|
||||
protected override defaultRun() {
|
||||
return this.testService.runTests({
|
||||
tests: this.tests.map(({ test }) => identifyTest(test)),
|
||||
tests: this.tests.map(({ test }) => test),
|
||||
group: TestRunProfileBitset.Run,
|
||||
});
|
||||
}
|
||||
|
||||
protected override defaultDebug() {
|
||||
return this.testService.runTests({
|
||||
tests: this.tests.map(({ test }) => identifyTest(test)),
|
||||
tests: this.tests.map(({ test }) => test),
|
||||
group: TestRunProfileBitset.Run,
|
||||
});
|
||||
}
|
||||
|
@ -561,14 +561,14 @@ class RunSingleTestDecoration extends RunTestDecoration implements ITestDecorati
|
|||
|
||||
protected override defaultRun() {
|
||||
return this.testService.runTests({
|
||||
tests: [identifyTest(this.test)],
|
||||
tests: [this.test],
|
||||
group: TestRunProfileBitset.Run,
|
||||
});
|
||||
}
|
||||
|
||||
protected override defaultDebug() {
|
||||
return this.testService.runTests({
|
||||
tests: [identifyTest(this.test)],
|
||||
tests: [this.test],
|
||||
group: TestRunProfileBitset.Debug,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -56,12 +56,12 @@ import { ITestExplorerFilterState, TestExplorerFilterState, TestingExplorerFilte
|
|||
import { ITestingProgressUiService } from 'vs/workbench/contrib/testing/browser/testingProgressUiService';
|
||||
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 { identifyTest, ITestRunProfile, TestItemExpandState, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { ITestRunProfile, TestItemExpandState, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
|
||||
import { cmpPriority, isFailedState, isStateWithResult } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { IMainThreadTestCollection, ITestService, testCollectionIsEmpty } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
@ -590,7 +590,7 @@ export class TestingExplorerViewModel extends Disposable {
|
|||
// If the node or any of its children are excluded, flip on the 'show
|
||||
// excluded tests' checkbox automatically.
|
||||
for (let n: TestItemTreeElement | null = element; n instanceof TestItemTreeElement; n = n.parent) {
|
||||
if (n.test && this.testService.excluded.contains(identifyTest(n.test))) {
|
||||
if (n.test && this.testService.excluded.contains(n.test)) {
|
||||
this.filterState.showExcludedTests.value = true;
|
||||
break;
|
||||
}
|
||||
|
@ -674,7 +674,7 @@ export class TestingExplorerViewModel extends Disposable {
|
|||
if (toRun.length) {
|
||||
this.testService.runTests({
|
||||
group: TestRunProfileBitset.Run,
|
||||
tests: toRun.map(t => identifyTest(t.test)),
|
||||
tests: toRun.map(t => t.test),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -814,7 +814,7 @@ class TestsFilter implements ITreeFilter<TestExplorerTreeElement> {
|
|||
if (
|
||||
element.test
|
||||
&& !this.state.showExcludedTests.value
|
||||
&& this.testService.excluded.contains(identifyTest(element.test))
|
||||
&& this.testService.excluded.contains(element.test)
|
||||
) {
|
||||
return TreeVisibility.Hidden;
|
||||
}
|
||||
|
@ -1147,7 +1147,7 @@ class TestItemRenderer extends ActionableItemTemplateData<TestItemTreeElement> {
|
|||
const options: IResourceLabelOptions = {};
|
||||
data.label.setResource(label, options);
|
||||
|
||||
const testHidden = this.testService.excluded.contains(identifyTest(node.element.test));
|
||||
const testHidden = this.testService.excluded.contains(node.element.test);
|
||||
data.wrapper.classList.toggle('test-is-hidden', testHidden);
|
||||
|
||||
const icon = icons.testingStatesToIcons.get(
|
||||
|
@ -1197,8 +1197,8 @@ const getActionableElementActions = (
|
|||
const test = element instanceof TestItemTreeElement ? element.test : undefined;
|
||||
const contextOverlay = contextKeyService.createOverlay([
|
||||
['view', Testing.ExplorerViewId],
|
||||
[TestingContextKeys.testItemIsHidden.key, !!test && testService.excluded.contains(identifyTest(test))],
|
||||
...getTestItemContextOverlay(test, test ? profiles.controllerCapabilities(test.controllerId) : 0),
|
||||
[TestingContextKeys.testItemIsHidden.key, !!test && testService.excluded.contains(test)],
|
||||
...getTestItemContextOverlay(test, test ? profiles.capabilitiesForTest(test) : 0),
|
||||
]);
|
||||
const menu = menuService.createMenu(MenuId.TestItem, contextOverlay);
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ import { testingPeekBorder } from 'vs/workbench/contrib/testing/browser/theme';
|
|||
import { AutoOpenPeekViewWhen, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
|
||||
import { Testing } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { IRichLocation, ITestItem, ITestMessage, ITestRunTask, ITestTaskState, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
|
||||
import { isFailedState } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
|
@ -1368,7 +1368,7 @@ class TreeActionsProvider {
|
|||
|
||||
public provideActionBar(element: ITreeElement) {
|
||||
const test = element instanceof TestCaseElement ? element.test : undefined;
|
||||
const capabilities = test ? this.testProfileService.controllerCapabilities(test.controllerId) : 0;
|
||||
const capabilities = test ? this.testProfileService.capabilitiesForTest(test) : 0;
|
||||
const contextOverlay = this.contextKeyService.createOverlay([
|
||||
['peek', Testing.OutputPeekContributionId],
|
||||
[TestingContextKeys.peekItemType.key, element.type],
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, TestDiffOpType, ITestIdWithSrc, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { IMainThreadTestCollection } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
||||
export class MainThreadTestCollection extends AbstractIncrementalTestCollection<IncrementalTestCollectionItem> implements IMainThreadTestCollection {
|
||||
|
@ -45,7 +45,7 @@ export class MainThreadTestCollection extends AbstractIncrementalTestCollection<
|
|||
public readonly onBusyProvidersChange = this.busyProvidersChangeEmitter.event;
|
||||
public readonly onDidRetireTest = this.retireTestEmitter.event;
|
||||
|
||||
constructor(private readonly expandActual: (src: ITestIdWithSrc, levels: number) => Promise<void>) {
|
||||
constructor(private readonly expandActual: (id: string, levels: number) => Promise<void>) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ export class MainThreadTestCollection extends AbstractIncrementalTestCollection<
|
|||
return existing.prom;
|
||||
}
|
||||
|
||||
const prom = this.expandActual({ controllerId: test.controllerId, testId: test.item.extId }, levels);
|
||||
const prom = this.expandActual(test.item.extId, levels);
|
||||
const record = { doneLvl: existing ? existing.doneLvl : -1, pendingLvl: levels, prom };
|
||||
this.expandPromises.set(test, record);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
|||
import { assertNever } from 'vs/base/common/types';
|
||||
import { diffTestItems, ExtHostTestItemEvent, ExtHostTestItemEventOp, getPrivateApiFor, TestItemImpl, TestItemRootImpl } from 'vs/workbench/api/common/extHostTestingPrivateApi';
|
||||
import * as Convert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { applyTestItemUpdate, TestDiffOpType, TestItemExpandState, TestsDiff, TestsDiffOp } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { applyTestItemUpdate, ITestTag, TestDiffOpType, TestItemExpandState, TestsDiff, TestsDiffOp } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
|
||||
type TestItemRaw = Convert.TestItem.Raw;
|
||||
|
@ -78,6 +78,21 @@ export class SingleUseTestCollection extends Disposable {
|
|||
return diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all tags associated with items in the collection.
|
||||
*/
|
||||
public *tags() {
|
||||
const seen = new Set<string>();
|
||||
for (const item of this.tree.values()) {
|
||||
for (const tag of item.actual.tags) {
|
||||
if (!seen.has(tag.id)) {
|
||||
seen.add(tag.id);
|
||||
yield tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a new diff entry onto the collected diff list.
|
||||
*/
|
||||
|
@ -169,6 +184,9 @@ export class SingleUseTestCollection extends Disposable {
|
|||
case 'canResolveChildren':
|
||||
this.updateExpandability(internal);
|
||||
break;
|
||||
case 'tags':
|
||||
this.pushDiff([TestDiffOpType.Update, { extId, item: { tags: (value as ITestTag[]).map(v => v.id) }, }]);
|
||||
break;
|
||||
case 'range':
|
||||
this.pushDiff([TestDiffOpType.Update, { extId, item: { range: Convert.Range.from(value) }, }]);
|
||||
break;
|
||||
|
|
|
@ -10,11 +10,6 @@ import { IPosition } from 'vs/editor/common/core/position';
|
|||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { TestMessageSeverity } from 'vs/workbench/api/common/extHostTypes';
|
||||
|
||||
export interface ITestIdWithSrc {
|
||||
testId: string;
|
||||
controllerId: string;
|
||||
}
|
||||
|
||||
export const enum TestResultState {
|
||||
Unset = 0,
|
||||
Queued = 1,
|
||||
|
@ -25,9 +20,6 @@ export const enum TestResultState {
|
|||
Errored = 6
|
||||
}
|
||||
|
||||
export const identifyTest = (test: { controllerId: string, item: { extId: string } }): ITestIdWithSrc =>
|
||||
({ testId: test.item.extId, controllerId: test.controllerId });
|
||||
|
||||
export const enum TestRunProfileBitset {
|
||||
Run = 1 << 1,
|
||||
Debug = 1 << 2,
|
||||
|
@ -55,6 +47,7 @@ export interface ITestRunProfile {
|
|||
label: string;
|
||||
group: TestRunProfileBitset;
|
||||
isDefault: boolean;
|
||||
tag: string | null;
|
||||
hasConfigurationHandler: boolean;
|
||||
}
|
||||
|
||||
|
@ -69,7 +62,7 @@ export interface ResolvedTestRunRequest {
|
|||
profileGroup: TestRunProfileBitset;
|
||||
profileId: number;
|
||||
}[]
|
||||
exclude?: ITestIdWithSrc[];
|
||||
exclude?: string[];
|
||||
isAutoRun?: boolean;
|
||||
}
|
||||
|
||||
|
@ -125,6 +118,17 @@ export interface ITestRunTask {
|
|||
running: boolean;
|
||||
}
|
||||
|
||||
export interface ITestTag {
|
||||
id: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export interface ITestTagDisplayInfo {
|
||||
id: string;
|
||||
displayId: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The TestItem from .d.ts, as a plain object without children.
|
||||
*/
|
||||
|
@ -132,6 +136,7 @@ export interface ITestItem {
|
|||
/** ID of the test given by the test controller */
|
||||
extId: string;
|
||||
label: string;
|
||||
tags: string[];
|
||||
busy?: boolean;
|
||||
children?: never;
|
||||
uri?: URI;
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
|||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
|
||||
import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue';
|
||||
import { ITestIdWithSrc } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTestItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
|
||||
export class TestExclusions extends Disposable {
|
||||
private readonly excluded = this._register(
|
||||
|
@ -43,30 +43,26 @@ export class TestExclusions extends Disposable {
|
|||
/**
|
||||
* Gets all excluded tests.
|
||||
*/
|
||||
public get all() {
|
||||
return Iterable.map(this.excluded.value, v => {
|
||||
const [controllerId, testId] = JSON.parse(v);
|
||||
return { controllerId, testId };
|
||||
});
|
||||
public get all(): Iterable<string> {
|
||||
return this.excluded.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether a test is excluded.
|
||||
*/
|
||||
public toggle(test: ITestIdWithSrc, exclude?: boolean): void {
|
||||
const slug = this.identify(test);
|
||||
if (exclude !== true && this.excluded.value.has(slug)) {
|
||||
this.excluded.value = new Set(Iterable.filter(this.excluded.value, e => e !== slug));
|
||||
} else if (exclude !== false && !this.excluded.value.has(slug)) {
|
||||
this.excluded.value = new Set([...this.excluded.value, slug]);
|
||||
public toggle(test: InternalTestItem, exclude?: boolean): void {
|
||||
if (exclude !== true && this.excluded.value.has(test.item.extId)) {
|
||||
this.excluded.value = new Set(Iterable.filter(this.excluded.value, e => e !== test.item.extId));
|
||||
} else if (exclude !== false && !this.excluded.value.has(test.item.extId)) {
|
||||
this.excluded.value = new Set([...this.excluded.value, test.item.extId]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a test is excluded.
|
||||
*/
|
||||
public contains(test: ITestIdWithSrc): boolean {
|
||||
return this.excluded.value.has(this.identify(test));
|
||||
public contains(test: InternalTestItem): boolean {
|
||||
return this.excluded.value.has(test.item.extId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,8 +71,4 @@ export class TestExclusions extends Disposable {
|
|||
public clear(): void {
|
||||
this.excluded.value = new Set();
|
||||
}
|
||||
|
||||
private identify(test: ITestIdWithSrc) {
|
||||
return JSON.stringify([test.controllerId, test.testId]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,13 @@ export class TestId {
|
|||
return new TestId(path.reverse());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cheaply ets whether the ID refers to the root .
|
||||
*/
|
||||
public static isRoot(idString: string) {
|
||||
return !idString.includes(TestIdPathParts.Delimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test ID from a serialized TestId instance.
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,8 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
|
|||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue';
|
||||
import { ITestRunProfile, TestRunProfileBitset, testRunProfileBitsetList } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTestItem, ITestRunProfile, TestRunProfileBitset, testRunProfileBitsetList } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { IMainThreadTestController } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
||||
|
@ -40,11 +41,11 @@ export interface ITestProfileService {
|
|||
removeProfile(controllerId: string, profileId?: number): void;
|
||||
|
||||
/**
|
||||
* Gets capabilities for the given controller by ID, indicating whether
|
||||
* there's any profiles available for those groups.
|
||||
* Gets capabilities for the given test, indicating whether
|
||||
* there's any usable profiles available for those groups.
|
||||
* @returns a bitset to use with {@link TestRunProfileBitset}
|
||||
*/
|
||||
controllerCapabilities(controllerId: string): number;
|
||||
capabilitiesForTest(test: InternalTestItem): number;
|
||||
|
||||
/**
|
||||
* Configures a test profile.
|
||||
|
@ -55,7 +56,6 @@ export interface ITestProfileService {
|
|||
* Gets all registered controllers, grouping by controller.
|
||||
*/
|
||||
all(): Iterable<Readonly<{
|
||||
capabilities: number,
|
||||
controller: IMainThreadTestController,
|
||||
profiles: ITestRunProfile[],
|
||||
}>>;
|
||||
|
@ -73,17 +73,15 @@ export interface ITestProfileService {
|
|||
/**
|
||||
* Gets the profiles for a controller, in priority order.
|
||||
*/
|
||||
getControllerProfiles(controllerId: string): undefined | {
|
||||
controller: IMainThreadTestController;
|
||||
profiles: ITestRunProfile[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the profiles for the group in a controller, in priorty order.
|
||||
*/
|
||||
getControllerGroupProfiles(controllerId: string, group: TestRunProfileBitset): readonly ITestRunProfile[];
|
||||
getControllerProfiles(controllerId: string): ITestRunProfile[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the given profile can be used to run the test.
|
||||
*/
|
||||
export const canUseProfileWithTest = (profile: ITestRunProfile, test: InternalTestItem) =>
|
||||
profile.controllerId === test.controllerId && (TestId.isRoot(test.item.extId) || !profile.tag || test.item.tags.includes(profile.tag));
|
||||
|
||||
const sorter = (a: ITestRunProfile, b: ITestRunProfile) => {
|
||||
if (a.isDefault !== b.isDefault) {
|
||||
return a.isDefault ? -1 : 1;
|
||||
|
@ -102,7 +100,6 @@ export const capabilityContextKeys = (capabilities: number): [key: string, value
|
|||
[TestingContextKeys.hasCoverableTests.key, (capabilities & TestRunProfileBitset.Coverage) !== 0],
|
||||
];
|
||||
|
||||
|
||||
export class TestProfileService implements ITestProfileService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
private readonly preferredDefaults: StoredValue<{ [K in TestRunProfileBitset]?: { controllerId: string; profileId: number }[] }>;
|
||||
|
@ -111,7 +108,6 @@ export class TestProfileService implements ITestProfileService {
|
|||
private readonly controllerProfiles = new Map</* controller ID */string, {
|
||||
profiles: ITestRunProfile[],
|
||||
controller: IMainThreadTestController,
|
||||
capabilities: number,
|
||||
}>();
|
||||
|
||||
/** @inheritdoc */
|
||||
|
@ -144,20 +140,14 @@ export class TestProfileService implements ITestProfileService {
|
|||
if (record) {
|
||||
record.profiles.push(profile);
|
||||
record.profiles.sort(sorter);
|
||||
record.capabilities |= profile.group;
|
||||
} else {
|
||||
record = {
|
||||
profiles: [profile],
|
||||
controller,
|
||||
capabilities: profile.group
|
||||
};
|
||||
this.controllerProfiles.set(profile.controllerId, record);
|
||||
}
|
||||
|
||||
if (!profile.isDefault) {
|
||||
record.capabilities |= TestRunProfileBitset.HasNonDefaultProfile;
|
||||
}
|
||||
|
||||
this.refreshContextKeys();
|
||||
this.changeEmitter.fire();
|
||||
}
|
||||
|
@ -203,18 +193,25 @@ export class TestProfileService implements ITestProfileService {
|
|||
}
|
||||
|
||||
ctrl.profiles.splice(index, 1);
|
||||
ctrl.capabilities = 0;
|
||||
for (const { group } of ctrl.profiles) {
|
||||
ctrl.capabilities |= group;
|
||||
}
|
||||
|
||||
this.refreshContextKeys();
|
||||
this.changeEmitter.fire();
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public controllerCapabilities(controllerId: string) {
|
||||
return this.controllerProfiles.get(controllerId)?.capabilities || 0;
|
||||
public capabilitiesForTest(test: InternalTestItem) {
|
||||
const ctrl = this.controllerProfiles.get(test.controllerId);
|
||||
if (!ctrl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let capabilities = 0;
|
||||
for (const profile of ctrl.profiles) {
|
||||
if (!profile.tag || test.item.tags.includes(profile.tag)) {
|
||||
capabilities |= capabilities & profile.group ? TestRunProfileBitset.HasNonDefaultProfile : profile.group;
|
||||
}
|
||||
}
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
@ -224,12 +221,7 @@ export class TestProfileService implements ITestProfileService {
|
|||
|
||||
/** @inheritdoc */
|
||||
public getControllerProfiles(profileId: string) {
|
||||
return this.controllerProfiles.get(profileId);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public getControllerGroupProfiles(controllerId: string, group: TestRunProfileBitset) {
|
||||
return this.controllerProfiles.get(controllerId)?.profiles.filter(c => c.group === group) ?? [];
|
||||
return this.controllerProfiles.get(profileId)?.profiles ?? [];
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
@ -271,8 +263,10 @@ export class TestProfileService implements ITestProfileService {
|
|||
|
||||
private refreshContextKeys() {
|
||||
let allCapabilities = 0;
|
||||
for (const { capabilities } of this.controllerProfiles.values()) {
|
||||
allCapabilities |= capabilities;
|
||||
for (const { profiles } of this.controllerProfiles.values()) {
|
||||
for (const profile of profiles) {
|
||||
allCapabilities |= allCapabilities & profile.group ? TestRunProfileBitset.HasNonDefaultProfile : profile.group;
|
||||
}
|
||||
}
|
||||
|
||||
for (const group of testRunProfileBitsetList) {
|
|
@ -10,9 +10,9 @@ import { once } from 'vs/base/common/functional';
|
|||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ExtensionRunTestsRequest, ITestRunProfile, ResolvedTestRunRequest, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { ExtensionRunTestsRequest, ITestRunProfile, ResolvedTestRunRequest, TestResultItem, TestResultState } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { ITestResult, LiveTestResult, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultStorage, RETAIN_MAX_RESULTS } from 'vs/workbench/contrib/testing/common/testResultStorage';
|
||||
|
||||
|
@ -137,16 +137,14 @@ export class TestResultService implements ITestResultService {
|
|||
}
|
||||
|
||||
let profile: ITestRunProfile | undefined;
|
||||
if (!req.profile) {
|
||||
profile = this.testProfiles.getControllerGroupProfiles(req.controllerId, TestRunProfileBitset.Run)[0];
|
||||
} else {
|
||||
const profiles = this.testProfiles.getControllerGroupProfiles(req.controllerId, req.profile.group);
|
||||
profile = profiles.find(c => c.profileId === req.profile!.id) || profiles[0];
|
||||
if (req.profile) {
|
||||
const profiles = this.testProfiles.getControllerProfiles(req.controllerId);
|
||||
profile = profiles.find(c => c.profileId === req.profile!.id);
|
||||
}
|
||||
|
||||
const resolved: ResolvedTestRunRequest = {
|
||||
targets: [],
|
||||
exclude: req.exclude.map(testId => ({ testId, controllerId: req.controllerId })),
|
||||
exclude: req.exclude,
|
||||
isAutoRun: false,
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { MarshalledId } from 'vs/base/common/marshalling';
|
|||
import { URI } from 'vs/base/common/uri';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
|
||||
import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, ITestIdWithSrc, ITestItemContext, ResolvedTestRunRequest, RunTestForControllerRequest, TestItemExpandState, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, ITestItemContext, ITestTagDisplayInfo, ResolvedTestRunRequest, RunTestForControllerRequest, TestItemExpandState, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { ITestResult } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
|
@ -22,8 +22,9 @@ export const ITestService = createDecorator<ITestService>('testService');
|
|||
export interface IMainThreadTestController {
|
||||
readonly id: string;
|
||||
readonly label: IObservableValue<string>;
|
||||
getTags(): Promise<ITestTagDisplayInfo[]>;
|
||||
configureRunProfile(profileId: number): void;
|
||||
expandTest(src: ITestIdWithSrc, levels: number): Promise<void>;
|
||||
expandTest(id: string, levels: number): Promise<void>;
|
||||
runTests(request: RunTestForControllerRequest, token: CancellationToken): Promise<void>;
|
||||
}
|
||||
|
||||
|
@ -194,9 +195,9 @@ export interface AmbiguousRunTestsRequest {
|
|||
/** Group to run */
|
||||
group: TestRunProfileBitset;
|
||||
/** Tests to run. Allowed to be from different controllers */
|
||||
tests: ITestIdWithSrc[];
|
||||
tests: readonly InternalTestItem[];
|
||||
/** Tests to exclude. If not given, the current UI excluded tests are used */
|
||||
exclude?: ITestIdWithSrc[];
|
||||
exclude?: InternalTestItem[];
|
||||
/** Whether this was triggered from an auto run. */
|
||||
isAutoRun?: boolean;
|
||||
}
|
||||
|
|
|
@ -13,10 +13,11 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { MainThreadTestCollection } from 'vs/workbench/contrib/testing/common/mainThreadTestCollection';
|
||||
import { ITestIdWithSrc, ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { canUseProfileWithTest, ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { ITestResult } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { AmbiguousRunTestsRequest, IMainThreadTestController, ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
@ -70,8 +71,8 @@ export class TestService extends Disposable implements ITestService {
|
|||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public async expandTest(test: ITestIdWithSrc, levels: number) {
|
||||
await this.testControllers.get(test.controllerId)?.expandTest(test, levels);
|
||||
public async expandTest(id: string, levels: number) {
|
||||
await this.testControllers.get(TestId.fromString(id).controllerId)?.expandTest(id, levels);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,11 +94,15 @@ export class TestService extends Disposable implements ITestService {
|
|||
* @inheritdoc
|
||||
*/
|
||||
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?.map(t => t.item.extId),
|
||||
isAutoRun: req.isAutoRun,
|
||||
};
|
||||
|
||||
// First, try to run the tests using the default run profiles...
|
||||
for (const profile of this.testProfiles.getGroupDefaultProfiles(req.group)) {
|
||||
const testIds = req.tests.filter(t => t.controllerId === profile.controllerId).map(t => t.testId);
|
||||
const testIds = req.tests.filter(t => canUseProfileWithTest(profile, t)).map(t => t.item.extId);
|
||||
if (testIds.length) {
|
||||
resolved.targets.push({
|
||||
testIds: testIds,
|
||||
|
@ -114,14 +119,22 @@ export class TestService extends Disposable implements ITestService {
|
|||
// explorer or decoration. We shouldn't no-op.
|
||||
if (resolved.targets.length === 0) {
|
||||
for (const byController of groupBy(req.tests, (a, b) => a.controllerId === b.controllerId ? 0 : 1)) {
|
||||
const profiles = this.testProfiles.getControllerGroupProfiles(byController[0].controllerId, req.group);
|
||||
if (profiles.length) {
|
||||
resolved.targets.push({
|
||||
testIds: byController.map(t => t.testId),
|
||||
profileGroup: req.group,
|
||||
profileId: profiles[0].profileId,
|
||||
controllerId: profiles[0].controllerId,
|
||||
});
|
||||
const profiles = this.testProfiles.getControllerProfiles(byController[0].controllerId);
|
||||
const withControllers = byController.map(test => ({
|
||||
profile: profiles.find(p => p.group === req.group && canUseProfileWithTest(p, test)),
|
||||
test,
|
||||
}));
|
||||
|
||||
for (const byProfile of groupBy(withControllers, (a, b) => a.profile === b.profile ? 0 : 1)) {
|
||||
const profile = byProfile[0].profile;
|
||||
if (profile) {
|
||||
resolved.targets.push({
|
||||
testIds: byProfile.map(t => t.test.item.extId),
|
||||
profileGroup: req.group,
|
||||
profileId: profile.profileId,
|
||||
controllerId: profile.controllerId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,9 +168,7 @@ export class TestService extends Disposable implements ITestService {
|
|||
group => this.testControllers.get(group.controllerId)?.runTests(
|
||||
{
|
||||
runId: result.id,
|
||||
excludeExtIds: req.exclude!
|
||||
.filter(t => t.controllerId === group.controllerId && !group.testIds.includes(t.testId))
|
||||
.map(t => t.testId),
|
||||
excludeExtIds: req.exclude!.filter(t => !group.testIds.includes(t)),
|
||||
profileId: group.profileId,
|
||||
controllerId: group.controllerId,
|
||||
testIds: group.testIds,
|
||||
|
|
|
@ -16,7 +16,7 @@ export { TestItemImpl } from 'vs/workbench/api/common/extHostTestingPrivateApi';
|
|||
* roots/stubs.
|
||||
*/
|
||||
export const getInitializedMainTestCollection = async (singleUse = testStubs.nested()) => {
|
||||
const c = new MainThreadTestCollection(async (t, l) => singleUse.expand(t.testId, l));
|
||||
const c = new MainThreadTestCollection(async (t, l) => singleUse.expand(t, l));
|
||||
await singleUse.expand(singleUse.root.id, Infinity);
|
||||
c.apply(singleUse.collectDiff());
|
||||
return c;
|
||||
|
|
|
@ -11,7 +11,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { AutoRunMode, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
|
||||
import { identifyTest, ITestIdWithSrc, TestDiffOpType, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { InternalTestItem, TestDiffOpType, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { isRunningTests, ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
|
@ -65,7 +65,7 @@ export class TestingAutoRun extends Disposable implements ITestingAutoRun {
|
|||
* Runs them on a debounce.
|
||||
*/
|
||||
private makeRunner() {
|
||||
const rerunIds = new Map<string, ITestIdWithSrc>();
|
||||
const rerunIds = new Map<string, InternalTestItem>();
|
||||
const store = new DisposableStore();
|
||||
const cts = new CancellationTokenSource();
|
||||
store.add(toDisposable(() => cts.dispose(true)));
|
||||
|
@ -90,15 +90,15 @@ export class TestingAutoRun extends Disposable implements ITestingAutoRun {
|
|||
}
|
||||
}, delay));
|
||||
|
||||
const addToRerun = (test: ITestIdWithSrc) => {
|
||||
rerunIds.set(getTestKey(test), test);
|
||||
const addToRerun = (test: InternalTestItem) => {
|
||||
rerunIds.set(test.item.extId, test);
|
||||
if (!isRunningTests(this.results)) {
|
||||
scheduler.schedule(delay);
|
||||
}
|
||||
};
|
||||
|
||||
const removeFromRerun = (test: ITestIdWithSrc) => {
|
||||
rerunIds.delete(getTestKey(test));
|
||||
const removeFromRerun = (test: InternalTestItem) => {
|
||||
rerunIds.delete(test.item.extId);
|
||||
if (rerunIds.size === 0) {
|
||||
scheduler.cancel();
|
||||
}
|
||||
|
@ -106,9 +106,9 @@ export class TestingAutoRun extends Disposable implements ITestingAutoRun {
|
|||
|
||||
store.add(this.results.onTestChanged(evt => {
|
||||
if (evt.reason === TestResultItemChangeReason.Retired) {
|
||||
addToRerun(identifyTest(evt.item));
|
||||
addToRerun(evt.item);
|
||||
} else if ((evt.reason === TestResultItemChangeReason.OwnStateChange || evt.reason === TestResultItemChangeReason.ComputedStateChange)) {
|
||||
removeFromRerun(identifyTest(evt.item));
|
||||
removeFromRerun(evt.item);
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -126,12 +126,12 @@ export class TestingAutoRun extends Disposable implements ITestingAutoRun {
|
|||
const test = entry[1];
|
||||
const isQueued = Iterable.some(
|
||||
getCollectionItemParents(this.testService.collection, test),
|
||||
t => rerunIds.has(getTestKey(identifyTest(test))),
|
||||
t => rerunIds.has(test.item.extId),
|
||||
);
|
||||
|
||||
const state = this.results.getStateById(test.item.extId);
|
||||
if (!isQueued && (!state || state[1].retired)) {
|
||||
addToRerun(identifyTest(test));
|
||||
addToRerun(test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,12 +139,10 @@ export class TestingAutoRun extends Disposable implements ITestingAutoRun {
|
|||
|
||||
|
||||
for (const root of this.testService.collection.rootItems) {
|
||||
addToRerun(identifyTest(root));
|
||||
addToRerun(root);
|
||||
}
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
}
|
||||
|
||||
const getTestKey = (test: ITestIdWithSrc) => `${test.controllerId}\0${test.testId}`;
|
||||
|
|
|
@ -87,8 +87,8 @@ export class TestTreeTestHarness<T extends ITestTreeProjection = ITestTreeProjec
|
|||
this._register(c);
|
||||
this.c.onDidGenerateDiff(d => this.c.setDiff(d /* don't clear during testing */));
|
||||
|
||||
const collection = new MainThreadTestCollection((src, levels) => {
|
||||
this.c.expand(src.testId, levels);
|
||||
const collection = new MainThreadTestCollection((testId, levels) => {
|
||||
this.c.expand(testId, levels);
|
||||
if (!this.isProcessingDiff) {
|
||||
this.onDiff.fire(this.c.collectDiff());
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKe
|
|||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { SingleUseTestCollection } from 'vs/workbench/contrib/testing/common/ownedTestCollection';
|
||||
import { ITestTaskState, ResolvedTestRunRequest, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService';
|
||||
import { TestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
import { HydratedTestResult, LiveOutputController, LiveTestResult, makeEmptyCounts, resultItemParents, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { TestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
|
|
Loading…
Reference in a new issue