diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 28f9ac7f7de..c5e1ac28c9d 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1761,7 +1761,7 @@ declare module 'vscode' { //#region https://github.com/microsoft/vscode/issues/107467 // todo@API test or tests? - export namespace test { + export namespace tests { /** * Creates a new test controller. * @@ -1782,18 +1782,6 @@ declare module 'vscode' { * @stability experimental */ export function createTestObserver(): TestObserver; - - /** - * Creates a new managed {@link TestItem} instance. It can be added into - * the {@link TestItem.children} of an existing item, or into the - * {@link TestController.items}. - * @param id Unique identifier for the TestItem. - * @param label Human-readable label of the test item. - * @param uri URI this TestItem is associated with. May be a file or directory. - */ - // todo@API move into TestController - export function createTestItem(id: string, label: string, uri?: Uri): TestItem; - /** * List of test results stored by the editor, sorted in descending * order by their `completedAt` time. @@ -1851,13 +1839,10 @@ declare module 'vscode' { readonly removed: ReadonlyArray; } - // 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 - // UI for that, so enum for now? /** - * + * The kind of executions that {@link TestRunProfile | TestRunProfiles} control. */ - export enum TestRunProfileGroup { + export enum TestRunProfileKind { Run = 1, Debug = 2, Coverage = 3, @@ -1879,16 +1864,16 @@ declare module 'vscode' { label: string; /** - * Configures where this profile is grouped in the UI. If there - * are no profiles for a group, it will not be available in the UI. + * Configures what kind of execution this profile controls. If there + * are no profiles for a kind, it will not be available in the UI. */ - readonly group: TestRunProfileGroup; + readonly kind: TestRunProfileKind; /** * Controls whether this profile is the default action that will * be taken when its group is actions. For example, if the user clicks * the generic "run all" button, then the default profile for - * {@link TestRunProfileGroup.Run} will be executed. + * {@link TestRunProfileKind.Run} will be executed. */ isDefault: boolean; @@ -1928,9 +1913,9 @@ declare module 'vscode' { */ export interface TestController { /** - * The ID of the controller, passed in {@link vscode.test.createTestController} + * The ID of the controller, passed in {@link vscode.tests.createTestController}. + * This must be globally unique, */ - // todo@api maybe explain what the id is used for and iff it must be globally unique or only unique within the extension readonly id: string; /** @@ -1960,13 +1945,13 @@ declare module 'vscode' { * @param runHandler Function called to start a test run * @param isDefault Whether this is the default action for the group */ - createRunProfile(label: string, group: TestRunProfileGroup, runHandler: (request: TestRunRequest, token: CancellationToken) => Thenable | void, isDefault?: boolean): TestRunProfile; + createRunProfile(label: string, group: TestRunProfileKind, runHandler: (request: TestRunRequest, token: CancellationToken) => Thenable | void, isDefault?: boolean): TestRunProfile; /** * A function provided by the extension that the editor may call to request * children of a test item, if the {@link TestItem.canResolveChildren} is * `true`. When called, the item should discover children and call - * {@link vscode.test.createTestItem} as children are discovered. + * {@link vscode.tests.createTestItem} as children are discovered. * * The item in the explorer will automatically be marked as "busy" until * the function returns or the returned thenable resolves. @@ -1984,7 +1969,7 @@ declare module 'vscode' { * {@link TestRunner} when a request is made to execute tests, and may also * be called if a test run is detected externally. Once created, tests * that are included in the results will be moved into the - * {@link TestResultState.Pending} state. todo@API there is no Pending + * {@link TestResultState.Queued} state. * * All runs created using the same `request` instance will be grouped * together. This is useful if, for example, a single suite of tests is @@ -2001,6 +1986,17 @@ declare module 'vscode' { */ createTestRun(request: TestRunRequest, name?: string, persist?: boolean): TestRun; + /** + * Creates a new managed {@link TestItem} instance. It can be added into + * the {@link TestItem.children} of an existing item, or into the + * {@link TestController.items}. + * @param id Identifier for the TestItem. The test item's ID must be unique + * in the {@link TestItemCollection} it's added to. + * @param label Human-readable label of the test item. + * @param uri URI this TestItem is associated with. May be a file or directory. + */ + createTestItem(id: string, label: string, uri?: Uri): TestItem; + /** * Unregisters the test controller, disposing of its associated tests * and unpersisted results. @@ -2009,7 +2005,7 @@ declare module 'vscode' { } /** - * Options given to {@link test.runTests}. + * Options given to {@link tests.runTests}. */ export class TestRunRequest { /** @@ -2017,16 +2013,19 @@ declare module 'vscode' { * of the given tests and all children of the given tests, excluding * any tests that appear in {@link TestRunRequest.exclude}. If this is * not given, then the extension should simply run all tests. + * + * The process of running tests should resolve the children of any test + * items who have not yet been resolved. */ - // todo@API "...run all tests." which can mean resolve all tests first include?: TestItem[]; /** - * An array of tests the user has marked as excluded in the editor. May be - * omitted if no exclusions were requested. Test controllers should not run - * excluded tests or any children of excluded tests. + * An array of tests the user has marked as excluded from the test included + * in this run; exclusions should apply after inclusions. + * + * May be omitted if no exclusions were requested. Test controllers should + * not run excluded tests or any children of excluded tests. */ - // @todo@API say that exclude is more important than include! exclude?: TestItem[]; /** @@ -2047,7 +2046,6 @@ declare module 'vscode' { /** * Options given to {@link TestController.runTests} */ - // todo@API add readonly or rw `isPersisted: boolean` export interface TestRun { /** * The human-readable name of the run. This can be used to @@ -2062,6 +2060,11 @@ declare module 'vscode' { */ readonly token: CancellationToken; + /** + * Whether the test run will be persisteded across reloads by the editor UI. + */ + readonly isPersisted: boolean; + /** * Updates the state of the test in the run. Calling with method with nodes * outside the {@link TestRunRequest.tests} or in the {@link TestRunRequest.exclude} @@ -2070,10 +2073,20 @@ declare module 'vscode' { * * @param test The test to update * @param state The state to assign to the test + */ + setState(test: TestItem, state: TestResultState): void; + + /** + * Updates the state of the test in the run. Calling with method with nodes + * outside the {@link TestRunRequest.tests} or in the {@link TestRunRequest.exclude} + * array will no-op. This override moves the test into a terminal state and + * indicates how long it ran for. + * + * @param test The terminal test state + * @param state The state to assign to the test * @param duration Optionally sets how long the test took to run, in milliseconds */ - // todo@API clarify duration, either add doc or new composite type - setState(test: TestItem, state: TestResultState, duration?: number): void; + setState(test: TestItem, state: TestResultState.Passed | TestResultState.Failed | TestResultState.Errored, duration: number): void; /** * Appends a message, such as an assertion error, to the test item. @@ -2084,7 +2097,6 @@ declare module 'vscode' { * @param test The test to update * @param message The message to add */ - // todo@API can this called many times, should this be part of setState? appendMessage(test: TestItem, message: TestMessage): void; /** @@ -2098,8 +2110,7 @@ declare module 'vscode' { /** * Signals that the end of the test run. Any tests included in the run whose - * states have not been updated will be moved into - * the {@link TestResultState.Unset} state. + * states have not been updated will have their state reset. */ end(): void; } @@ -2110,13 +2121,10 @@ declare module 'vscode' { */ export interface TestItemCollection { /** - * Updates the items stored by the collection. + * Replaces the items stored by the collection. * @param items Items to store, can be an array or other iterable. */ - // todo@API better names: reset, update... - // todo@API no Iterable - // @ts-ignore - set(items: Iterable): void; + replace(items: readonly TestItem[]): void; /** * Iterate over each entry in this collection. @@ -2170,7 +2178,7 @@ declare module 'vscode' { readonly children: TestItemCollection; /** - * The parent of this item, given in {@link vscode.test.createTestItem}. + * The parent of this item, given in {@link vscode.tests.createTestItem}. * This is undefined top-level items in the `TestController` and for * items that aren't yet included in another item's {@link children}. */ @@ -2233,9 +2241,6 @@ declare module 'vscode' { * Possible states of tests in a test run. */ export enum TestResultState { - // Initial state - // todo@API what is this state for? not needed, has no references - Unset = 0, // Test will be run, but is not currently running. Queued = 1, // Test is currently running @@ -2249,17 +2254,6 @@ declare module 'vscode' { // Test run failed for some other reason (compilation error, timeout, etc) Errored = 6 } - - /** - * Represents the severity of test messages. - */ - export enum TestMessageSeverity { - Error = 0, - Warning = 1, - Information = 2, - Hint = 3 - } - /** * Message associated with the test state. Can be linked to a specific * source range -- useful for assertion failures, for example. @@ -2270,12 +2264,6 @@ declare module 'vscode' { */ message: string | MarkdownString; - /** - * Message severity. Defaults to "Error". - */ - // todo@API maybe not needed? what does it change? - severity: TestMessageSeverity; - /** * Expected test output. If given with `actualOutput`, a diff view will be shown. */ @@ -2307,8 +2295,8 @@ declare module 'vscode' { } /** - * TestResults can be provided to the editor in {@link test.publishTestResult}, - * or read from it in {@link test.testResults}. + * TestResults can be provided to the editor in {@link tests.publishTestResult}, + * or read from it in {@link tests.testResults}. * * The results contain a 'snapshot' of the tests at the point when the test * run is complete. Therefore, information such as its {@link Range} may be @@ -2328,7 +2316,7 @@ declare module 'vscode' { /** * List of test results. The items in this array are the items that - * were passed in the {@link test.runTests} method. + * were passed in the {@link tests.runTests} method. */ results: ReadonlyArray>; } diff --git a/src/vs/workbench/api/browser/mainThreadTesting.ts b/src/vs/workbench/api/browser/mainThreadTesting.ts index 74b6c20913b..efed1d862cb 100644 --- a/src/vs/workbench/api/browser/mainThreadTesting.ts +++ b/src/vs/workbench/api/browser/mainThreadTesting.ts @@ -10,9 +10,8 @@ import { isDefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { Range } from 'vs/editor/common/core/range'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue'; -import { ExtensionRunTestsRequest, ITestItem, ITestMessage, ITestRunProfile, ITestRunTask, ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +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 { TestCoverage } from 'vs/workbench/contrib/testing/common/testCoverage'; import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult'; diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b2f9bbac361..9c2d5a17358 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -341,15 +341,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ? extHostTypes.ExtensionKind.Workspace : extHostTypes.ExtensionKind.UI; - const test: typeof vscode.test = { + const tests: typeof vscode.tests = { createTestController(provider, label) { checkProposedApiEnabled(extension); return extHostTesting.createTestController(provider, label); }, - createTestItem(id, label, uri) { - checkProposedApiEnabled(extension); - return extHostTesting.createTestItem(id, label, uri); - }, createTestObserver() { checkProposedApiEnabled(extension); return extHostTesting.createTestObserver(); @@ -1127,7 +1123,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I notebooks, scm, tasks, - test, + tests, window, workspace, // types @@ -1272,7 +1268,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I TestResultState: extHostTypes.TestResultState, TestRunRequest: extHostTypes.TestRunRequest, TestMessage: extHostTypes.TestMessage, - TestRunProfileGroup: extHostTypes.TestRunProfileGroup, + TestRunProfileKind: extHostTypes.TestRunProfileKind, TextSearchCompleteMessageType: TextSearchCompleteMessageType, TestMessageSeverity: extHostTypes.TestMessageSeverity, CoveredCount: extHostTypes.CoveredCount, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 2478a77de03..1314b999a47 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -46,7 +46,7 @@ import { WorkspaceTrustRequestOptions } from 'vs/platform/workspace/common/works import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator'; import { ExtHostInteractive } from 'vs/workbench/api/common/extHostInteractive'; import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; -import { DebugConfigurationProviderTriggerKind, TestResultState } from 'vs/workbench/api/common/extHostTypes'; +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 { SaveReason } from 'vs/workbench/common/editor'; @@ -58,7 +58,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 } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ExtensionRunTestsRequest, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, RunTestForControllerRequest, ResolvedTestRunRequest, ITestIdWithSrc, TestsDiff, IFileCoverage, CoverageDetails, ITestRunProfile, TestResultState } 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'; diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts index 7e67594dda6..3b52860190d 100644 --- a/src/vs/workbench/api/common/extHostTesting.ts +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -17,11 +17,11 @@ import { generateUuid } from 'vs/base/common/uuid'; import { ExtHostTestingShape, MainContext, MainThreadTestingShape } from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; -import { TestItemImpl, TestItemRootImpl } from 'vs/workbench/api/common/extHostTestingPrivateApi'; +import { InvalidTestItemError, TestItemImpl, TestItemRootImpl } from 'vs/workbench/api/common/extHostTestingPrivateApi'; import * as Convert from 'vs/workbench/api/common/extHostTypeConverters'; -import { TestRunProfileGroup, TestRunRequest } from 'vs/workbench/api/common/extHostTypes'; +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, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { AbstractIncrementalTestCollection, CoverageDetails, IFileCoverage, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, ISerializedTestResults, ITestIdWithSrc, ITestItem, 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'; @@ -86,6 +86,9 @@ export class ExtHostTesting implements ExtHostTestingShape { profiles.set(profileId, profile); return profile; }, + createTestItem(id, label, uri) { + return new TestItemImpl(controllerId, id, label, uri); + }, createTestRun: (request, name, persist = true) => { return this.runTracker.createTestRun(controllerId, collection, request, name, persist); }, @@ -115,13 +118,6 @@ export class ExtHostTesting implements ExtHostTestingShape { return controller; } - /** - * Implements vscode.test.createTestItem - */ - public createTestItem(id: string, label: string, uri?: vscode.Uri) { - return new TestItemImpl(id, label, uri); - } - /** * Implements vscode.test.createTestObserver */ @@ -147,7 +143,7 @@ export class ExtHostTesting implements ExtHostTestingShape { await this.proxy.$runTests({ targets: [{ testIds: req.include?.map(t => t.id) ?? [controller.collection.root.id], - profileGroup: profileGroupToBitset[profile.group], + profileGroup: profileGroupToBitset[profile.kind], profileId: profile.profileId, controllerId: profile.controllerId, }], @@ -396,11 +392,11 @@ export class TestRunCoordinator { // If there is not an existing tracked extension for the request, start // a new, detached session. - const dto = TestRunDto.fromPublic(controllerId, collection, request); + const dto = TestRunDto.fromPublic(controllerId, collection, request, persist); const profile = tryGetProfileFromTestRunReq(request); this.proxy.$startedExtensionTestRun({ controllerId, - profile: profile && { group: profileGroupToBitset[profile.group], id: profile.profileId }, + profile: profile && { group: profileGroupToBitset[profile.kind], id: profile.profileId }, exclude: request.exclude?.map(t => t.id) ?? [], id: dto.id, include: request.include?.map(t => t.id) ?? [collection.root.id], @@ -436,12 +432,13 @@ export class TestRunDto { private readonly includePrefix: string[]; private readonly excludePrefix: string[]; - public static fromPublic(controllerId: string, collection: SingleUseTestCollection, request: vscode.TestRunRequest) { + public static fromPublic(controllerId: string, collection: SingleUseTestCollection, request: vscode.TestRunRequest, persist: boolean) { return new TestRunDto( controllerId, generateUuid(), request.include?.map(t => TestId.fromExtHostTestItem(t, controllerId).toString()) ?? [controllerId], request.exclude?.map(t => TestId.fromExtHostTestItem(t, controllerId).toString()) ?? [], + persist, collection, ); } @@ -452,6 +449,7 @@ export class TestRunDto { request.runId, request.testIds, request.excludeExtIds, + true, collection, ); } @@ -461,6 +459,7 @@ export class TestRunDto { public readonly id: string, include: string[], exclude: string[], + public readonly isPersisted: boolean, public readonly colllection: SingleUseTestCollection, ) { this.includePrefix = include.map(id => id + TestIdPathParts.Delimiter); @@ -562,6 +561,10 @@ class TestRunImpl implements vscode.TestRun { return this.#coverage.coverageProvider; } + public get isPersisted() { + return this.#req.isPersisted; + } + constructor( public readonly name: string | undefined, public readonly token: CancellationToken, @@ -584,7 +587,7 @@ class TestRunImpl implements vscode.TestRun { const req = this.#req; if (!this.#ended && req.isIncluded(test)) { this.ensureTestIsKnown(test); - this.#proxy.$updateTestStateInRun(req.id, this.taskId, TestId.fromExtHostTestItem(test, req.controllerId).toString(), state, duration); + this.#proxy.$updateTestStateInRun(req.id, this.taskId, TestId.fromExtHostTestItem(test, req.controllerId).toString(), state as number as TestResultState, duration); } } @@ -611,15 +614,18 @@ class TestRunImpl implements vscode.TestRun { } private ensureTestIsKnown(test: vscode.TestItem) { + if (!(test instanceof TestItemImpl)) { + throw new InvalidTestItemError(test.id); + } + const sent = this.#sharedIds; if (sent.has(test.id)) { return; } const chain: ITestItem[] = []; - const root = this.#req.colllection.root; while (true) { - chain.unshift(Convert.TestItem.from(test, root.id)); + chain.unshift(Convert.TestItem.from(test as TestItemImpl)); if (sent.has(test.id)) { break; @@ -633,9 +639,10 @@ class TestRunImpl implements vscode.TestRun { test = test.parent; } + const root = this.#req.colllection.root; if (!sent.has(root.id)) { sent.add(root.id); - chain.unshift(Convert.TestItem.from(root, root.id)); + chain.unshift(Convert.TestItem.from(root)); } this.#proxy.$addTestsToRun(this.#req.controllerId, this.#req.id, chain); @@ -867,15 +874,15 @@ export class TestRunProfileImpl implements vscode.TestRunProfile { public readonly controllerId: string, public readonly profileId: number, private _label: string, - public readonly group: vscode.TestRunProfileGroup, + public readonly kind: vscode.TestRunProfileKind, public runHandler: (request: vscode.TestRunRequest, token: vscode.CancellationToken) => Thenable | void, private _isDefault = false, ) { this.#proxy = proxy; - const groupBitset = profileGroupToBitset[group]; + const groupBitset = profileGroupToBitset[kind]; if (typeof groupBitset !== 'number') { - throw new Error(`Unknown TestRunProfile.group ${group}`); + throw new Error(`Unknown TestRunProfile.group ${kind}`); } this.#proxy.$publishTestRunProfile({ @@ -893,8 +900,8 @@ export class TestRunProfileImpl implements vscode.TestRunProfile { } } -const profileGroupToBitset: { [K in TestRunProfileGroup]: TestRunProfileBitset } = { - [TestRunProfileGroup.Coverage]: TestRunProfileBitset.Coverage, - [TestRunProfileGroup.Debug]: TestRunProfileBitset.Debug, - [TestRunProfileGroup.Run]: TestRunProfileBitset.Run, +const profileGroupToBitset: { [K in TestRunProfileKind]: TestRunProfileBitset } = { + [TestRunProfileKind.Coverage]: TestRunProfileBitset.Coverage, + [TestRunProfileKind.Debug]: TestRunProfileBitset.Debug, + [TestRunProfileKind.Run]: TestRunProfileBitset.Run, }; diff --git a/src/vs/workbench/api/common/extHostTestingPrivateApi.ts b/src/vs/workbench/api/common/extHostTestingPrivateApi.ts index 9c7a10a1bc4..2f6c84e9f0b 100644 --- a/src/vs/workbench/api/common/extHostTestingPrivateApi.ts +++ b/src/vs/workbench/api/common/extHostTestingPrivateApi.ts @@ -46,26 +46,25 @@ export type ExtHostTestItemEvent = | ITestItemBulkReplace; export interface IExtHostTestItemApi { + controllerId: string; parent?: TestItemImpl; listener?: (evt: ExtHostTestItemEvent) => void; } const eventPrivateApis = new WeakMap(); +export const createPrivateApiFor = (impl: TestItemImpl, controllerId: string) => { + const api: IExtHostTestItemApi = { controllerId }; + eventPrivateApis.set(impl, api); + return api; +}; + /** * Gets the private API for a test item implementation. This implementation * is a managed object, but we keep a weakmap to avoid exposing any of the * internals to extensions. */ -export const getPrivateApiFor = (impl: TestItemImpl) => { - let api = eventPrivateApis.get(impl); - if (!api) { - api = {}; - eventPrivateApis.set(impl, api); - } - - return api; -}; +export const getPrivateApiFor = (impl: TestItemImpl) => eventPrivateApis.get(impl)!; const testItemPropAccessor = ( api: IExtHostTestItemApi, @@ -145,9 +144,16 @@ export class InvalidTestItemError extends Error { } } +export class MixedTestItemController extends Error { + constructor(id: string, ctrlA: string, ctrlB: string) { + super(`TestItem with ID "${id}" is from controller "${ctrlA}" and cannot be added as a child of an item from controller "${ctrlB}".`); + } +} + + export type TestItemCollectionImpl = vscode.TestItemCollection & { toJSON(): readonly TestItemImpl[] } & Iterable; -export const createTestItemCollection = (owningItem: TestItemImpl): TestItemCollectionImpl => { +const createTestItemCollection = (owningItem: TestItemImpl): TestItemCollectionImpl => { const api = getPrivateApiFor(owningItem); let mapped = new Map(); @@ -160,7 +166,7 @@ export const createTestItemCollection = (owningItem: TestItemImpl): TestItemColl }, /** @inheritdoc */ - set(items: Iterable) { + replace(items: Iterable) { const newMapped = new Map(); const toDelete = new Set(mapped.keys()); const bulk: ITestItemBulkReplace = { op: ExtHostTestItemEventOp.Bulk, ops: [] }; @@ -170,6 +176,11 @@ export const createTestItemCollection = (owningItem: TestItemImpl): TestItemColl throw new InvalidTestItemError(item.id); } + const itemController = getPrivateApiFor(item).controllerId; + if (itemController !== api.controllerId) { + throw new MixedTestItemController(item.id, itemController, api.controllerId); + } + if (newMapped.has(item.id)) { throw new DuplicateTestItemError(item.id); } @@ -241,12 +252,12 @@ export class TestItemImpl implements vscode.TestItem { /** * Note that data is deprecated and here for back-compat only */ - constructor(id: string, label: string, uri: vscode.Uri | undefined) { - const api = getPrivateApiFor(this); + constructor(controllerId: string, id: string, label: string, uri: vscode.Uri | undefined) { if (id.includes(TestIdPathParts.Delimiter)) { throw new Error(`Test IDs may not include the ${JSON.stringify(id)} symbol`); } + const api = createPrivateApiFor(this, controllerId); Object.defineProperties(this, { id: { value: id, @@ -281,6 +292,6 @@ export class TestItemImpl implements vscode.TestItem { export class TestItemRootImpl extends TestItemImpl { constructor(controllerId: string, label: string) { - super(controllerId, label, undefined); + super(controllerId, controllerId, label, undefined); } } diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 769a05510ad..91f265f21ad 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1642,7 +1642,7 @@ export namespace TestMessage { export function from(message: vscode.TestMessage): ITestMessage { return { message: MarkdownString.fromStrict(message.message) || '', - severity: message.severity, + severity: types.TestMessageSeverity.Error, expectedOutput: message.expectedOutput, actualOutput: message.actualOutput, location: message.location ? location.from(message.location) as any : undefined, @@ -1651,7 +1651,6 @@ export namespace TestMessage { export function to(item: ITestMessage): vscode.TestMessage { const message = new types.TestMessage(typeof item.message === 'string' ? item.message : MarkdownString.to(item.message)); - message.severity = item.severity; message.actualOutput = item.actualOutput; message.expectedOutput = item.expectedOutput; return message; @@ -1661,9 +1660,9 @@ export namespace TestMessage { export namespace TestItem { export type Raw = vscode.TestItem; - export function from(item: vscode.TestItem, controllerId: string): ITestItem { + export function from(item: TestItemImpl): ITestItem { return { - extId: TestId.fromExtHostTestItem(item, controllerId).toString(), + extId: TestId.fromExtHostTestItem(item, getPrivateApiFor(item).controllerId).toString(), label: item.label, uri: item.uri, range: Range.from(item.range) || null, @@ -1686,7 +1685,8 @@ export namespace TestItem { } function to(item: ITestItem): TestItemImpl { - const testItem = new TestItemImpl(TestId.fromString(item.extId).localId, item.label, URI.revive(item.uri)); + const testId = TestId.fromString(item.extId); + const testItem = new TestItemImpl(testId.controllerId, testId.localId, item.label, URI.revive(item.uri)); testItem.range = Range.to(item.range || undefined); testItem.description = item.description || undefined; return testItem; @@ -1710,7 +1710,7 @@ export namespace TestResults { ...TestItem.toPlain(item.item), parent: undefined, taskStates: item.tasks.map(t => ({ - state: t.state, + state: t.state as number as types.TestResultState, duration: t.duration, messages: t.messages.map(TestMessage.to), })), diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index fc676d84adc..54b63602bc1 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3286,7 +3286,6 @@ export class PortAttributes { //#region Testing export enum TestResultState { - Unset = 0, Queued = 1, Running = 2, Passed = 3, @@ -3302,7 +3301,7 @@ export enum TestMessageSeverity { Hint = 3 } -export enum TestRunProfileGroup { +export enum TestRunProfileKind { Run = 1, Debug = 2, Coverage = 3, @@ -3319,7 +3318,6 @@ export class TestRunRequest implements vscode.TestRunRequest { @es5ClassCompat export class TestMessage implements vscode.TestMessage { - public severity = TestMessageSeverity.Error; public expectedOutput?: string; public actualOutput?: string; diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts index 0816013c65c..7587d96b5e0 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation.ts @@ -9,12 +9,11 @@ import { FuzzyScore } from 'vs/base/common/filters'; import { Iterable } from 'vs/base/common/iterator'; import { Disposable } from 'vs/base/common/lifecycle'; import { isDefined } from 'vs/base/common/types'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { ByLocationTestItemElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; import { IActionableTestTreeElement, ITestTreeProjection, TestExplorerTreeElement, TestItemTreeElement, TestTreeErrorMessage } from 'vs/workbench/contrib/testing/browser/explorerProjections/index'; import { NodeChangeList, NodeRenderDirective, NodeRenderFn, peersHaveChildren } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; import { IComputedStateAndDurationAccessor, refreshComputedState } from 'vs/workbench/contrib/testing/common/getComputedState'; -import { InternalTestItem, TestDiffOpType, TestItemExpandState, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; +import { InternalTestItem, TestDiffOpType, TestItemExpandState, TestResultState, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { ITestService } from 'vs/workbench/contrib/testing/common/testService'; diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts index 77c47e7e6f6..de6f154b00c 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/index.ts @@ -10,8 +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 } from 'vs/workbench/api/common/extHostTypes'; -import { identifyTest, InternalTestItem, ITestIdWithSrc, ITestItemContext } from 'vs/workbench/contrib/testing/common/testCollection'; +import { TestResultState, identifyTest, InternalTestItem, ITestIdWithSrc, ITestItemContext } from 'vs/workbench/contrib/testing/common/testCollection'; /** * Describes a rendering of tests in the explorer view. Different diff --git a/src/vs/workbench/contrib/testing/browser/icons.ts b/src/vs/workbench/contrib/testing/browser/icons.ts index 0d41f755b26..6e393e106d2 100644 --- a/src/vs/workbench/contrib/testing/browser/icons.ts +++ b/src/vs/workbench/contrib/testing/browser/icons.ts @@ -7,8 +7,9 @@ import { Codicon } from 'vs/base/common/codicons'; import { localize } from 'vs/nls'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { TestMessageSeverity, TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { TestMessageSeverity } from 'vs/workbench/api/common/extHostTypes'; import { testingColorRunAction, testMessageSeverityColors, testStatesToIconColors } from 'vs/workbench/contrib/testing/browser/theme'; +import { TestResultState } from 'vs/workbench/contrib/testing/common/testCollection'; export const testingViewIcon = registerIcon('test-view-icon', Codicon.beaker, localize('testViewIcon', 'View icon of the test view.')); export const testingRunIcon = registerIcon('testing-run-icon', Codicon.run, localize('testingRunIcon', 'Icon of the "run test" action.')); diff --git a/src/vs/workbench/contrib/testing/browser/testingDecorations.ts b/src/vs/workbench/contrib/testing/browser/testingDecorations.ts index 4e844b4539c..d8cf9648c70 100644 --- a/src/vs/workbench/contrib/testing/browser/testingDecorations.ts +++ b/src/vs/workbench/contrib/testing/browser/testingDecorations.ts @@ -23,14 +23,14 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IThemeService, themeColorFromId, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { TestMessageSeverity, TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { TestMessageSeverity } from 'vs/workbench/api/common/extHostTypes'; import { BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution } from 'vs/workbench/contrib/debug/common/debug'; import { testingRunAllIcon, testingRunIcon, testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons'; import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browser/testingOutputPeek'; 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, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; +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 { maxPriority } from 'vs/workbench/contrib/testing/common/testingStates'; import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri'; diff --git a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts index 0fb264b1f7f..ac81f5f7734 100644 --- a/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts +++ b/src/vs/workbench/contrib/testing/browser/testingExplorerView.ts @@ -43,7 +43,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { foreground } from 'vs/platform/theme/common/colorRegistry'; import { attachButtonStyler } from 'vs/platform/theme/common/styler'; import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { IResourceLabel, IResourceLabelOptions, IResourceLabelProps, ResourceLabels } from 'vs/workbench/browser/labels'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; @@ -57,7 +56,7 @@ 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, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; +import { identifyTest, ITestRunProfile, TestItemExpandState, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { TestId } from 'vs/workbench/contrib/testing/common/testId'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts index 5337fc08f7c..a2455fd1101 100644 --- a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts +++ b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts @@ -49,7 +49,6 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis import { WorkbenchCompressibleObjectTree } from 'vs/platform/list/browser/listService'; import { textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme, IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { IResourceLabel, ResourceLabels } from 'vs/workbench/browser/labels'; import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { flatTestItemDelimiter } from 'vs/workbench/contrib/testing/browser/explorerProjections/display'; @@ -59,7 +58,7 @@ import { ITestingOutputTerminalService } from 'vs/workbench/contrib/testing/brow 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, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; +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 { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener'; diff --git a/src/vs/workbench/contrib/testing/browser/theme.ts b/src/vs/workbench/contrib/testing/browser/theme.ts index a164b31b96a..d942dd4516a 100644 --- a/src/vs/workbench/contrib/testing/browser/theme.ts +++ b/src/vs/workbench/contrib/testing/browser/theme.ts @@ -7,8 +7,9 @@ import { Color, RGBA } from 'vs/base/common/color'; import { localize } from 'vs/nls'; import { editorErrorForeground, editorForeground, editorHintForeground, editorInfoForeground, editorWarningForeground, inputActiveOptionBackground, inputActiveOptionBorder, inputActiveOptionForeground, registerColor } from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; -import { TestMessageSeverity, TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { TestMessageSeverity } from 'vs/workbench/api/common/extHostTypes'; import { ACTIVITY_BAR_BADGE_BACKGROUND } from 'vs/workbench/common/theme'; +import { TestResultState } from 'vs/workbench/contrib/testing/common/testCollection'; export const testingColorIconFailed = registerColor('testing.iconFailed', { dark: '#f14c4c', diff --git a/src/vs/workbench/contrib/testing/common/constants.ts b/src/vs/workbench/contrib/testing/common/constants.ts index a3b12660609..8378f860fed 100644 --- a/src/vs/workbench/contrib/testing/common/constants.ts +++ b/src/vs/workbench/contrib/testing/common/constants.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; -import { TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; +import { TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; export const enum Testing { // marked as "extension" so that any existing test extensions are assigned to it. diff --git a/src/vs/workbench/contrib/testing/common/getComputedState.ts b/src/vs/workbench/contrib/testing/common/getComputedState.ts index c26b076d736..2599c32d270 100644 --- a/src/vs/workbench/contrib/testing/common/getComputedState.ts +++ b/src/vs/workbench/contrib/testing/common/getComputedState.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Iterable } from 'vs/base/common/iterator'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { TestResultState } from 'vs/workbench/contrib/testing/common/testCollection'; import { maxPriority, statePriority } from 'vs/workbench/contrib/testing/common/testingStates'; /** diff --git a/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts b/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts index b6c4494f239..f09e4163c94 100644 --- a/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts +++ b/src/vs/workbench/contrib/testing/common/ownedTestCollection.ts @@ -218,7 +218,7 @@ export class SingleUseTestCollection extends Disposable { parent: internal.parent && internal.parent.toString(), controllerId: this.controllerId, expand: internal.expand, - item: Convert.TestItem.from(actual, this.root.id), + item: Convert.TestItem.from(actual), }, ]); diff --git a/src/vs/workbench/contrib/testing/common/testCollection.ts b/src/vs/workbench/contrib/testing/common/testCollection.ts index 4df2dbaf31e..82da7da4fa0 100644 --- a/src/vs/workbench/contrib/testing/common/testCollection.ts +++ b/src/vs/workbench/contrib/testing/common/testCollection.ts @@ -8,15 +8,23 @@ import { MarshalledId } from 'vs/base/common/marshalling'; import { URI } from 'vs/base/common/uri'; import { IPosition } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; -import { TestMessageSeverity, TestResultState } from 'vs/workbench/api/common/extHostTypes'; - -export { TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { TestMessageSeverity } from 'vs/workbench/api/common/extHostTypes'; export interface ITestIdWithSrc { testId: string; controllerId: string; } +export const enum TestResultState { + Unset = 0, + Queued = 1, + Running = 2, + Passed = 3, + Failed = 4, + Skipped = 5, + Errored = 6 +} + export const identifyTest = (test: { controllerId: string, item: { extId: string } }): ITestIdWithSrc => ({ testId: test.item.extId, controllerId: test.controllerId }); @@ -98,6 +106,7 @@ export interface IRichLocation { export interface ITestMessage { message: string | IMarkdownString; + /** @deprecated */ severity: TestMessageSeverity; expectedOutput: string | undefined; actualOutput: string | undefined; diff --git a/src/vs/workbench/contrib/testing/common/testId.ts b/src/vs/workbench/contrib/testing/common/testId.ts index 1fe4d2f7b35..3540bdc80ae 100644 --- a/src/vs/workbench/contrib/testing/common/testId.ts +++ b/src/vs/workbench/contrib/testing/common/testId.ts @@ -92,6 +92,13 @@ export class TestId { return this.path[this.viewEnd - 1]; } + /** + * Gets whether this ID refers to the root. + */ + public get controllerId() { + return this.path[0]; + } + /** * Gets whether this ID refers to the root. */ diff --git a/src/vs/workbench/contrib/testing/common/testResult.ts b/src/vs/workbench/contrib/testing/common/testResult.ts index 0c050e17ce3..2dc4b7223d9 100644 --- a/src/vs/workbench/contrib/testing/common/testResult.ts +++ b/src/vs/workbench/contrib/testing/common/testResult.ts @@ -10,10 +10,9 @@ import { DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { Range } from 'vs/editor/common/core/range'; import { localize } from 'vs/nls'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { IComputedStateAccessor, refreshComputedState } from 'vs/workbench/contrib/testing/common/getComputedState'; import { IObservableValue, MutableObservableValue, staticObservableValue } from 'vs/workbench/contrib/testing/common/observableValue'; -import { ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, ITestTaskState, ResolvedTestRunRequest, TestItemExpandState, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, ITestTaskState, ResolvedTestRunRequest, TestItemExpandState, TestResultItem, TestResultState } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestCoverage } from 'vs/workbench/contrib/testing/common/testCoverage'; import { maxPriority, statesInOrder } from 'vs/workbench/contrib/testing/common/testingStates'; diff --git a/src/vs/workbench/contrib/testing/common/testResultService.ts b/src/vs/workbench/contrib/testing/common/testResultService.ts index 251037e39d8..30cee650e40 100644 --- a/src/vs/workbench/contrib/testing/common/testResultService.ts +++ b/src/vs/workbench/contrib/testing/common/testResultService.ts @@ -10,8 +10,7 @@ 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 { TestResultState } from 'vs/workbench/api/common/extHostTypes'; -import { ExtensionRunTestsRequest, ITestRunProfile, ResolvedTestRunRequest, TestResultItem, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ExtensionRunTestsRequest, ITestRunProfile, ResolvedTestRunRequest, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { ITestResult, LiveTestResult, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; diff --git a/src/vs/workbench/contrib/testing/common/testStubs.ts b/src/vs/workbench/contrib/testing/common/testStubs.ts index 8ef2b8768c8..efe93d92f67 100644 --- a/src/vs/workbench/contrib/testing/common/testStubs.ts +++ b/src/vs/workbench/contrib/testing/common/testStubs.ts @@ -28,14 +28,14 @@ export const testStubs = { collection.root.label = 'root'; collection.resolveHandler = item => { if (item === undefined) { - const a = new TestItemImpl(idPrefix + 'a', 'a', URI.file('/')); + const a = new TestItemImpl('ctrlId', idPrefix + 'a', 'a', URI.file('/')); a.canResolveChildren = true; - const b = new TestItemImpl(idPrefix + 'b', 'b', URI.file('/')); - collection.root.children.set([a, b]); + const b = new TestItemImpl('ctrlId', idPrefix + 'b', 'b', URI.file('/')); + collection.root.children.replace([a, b]); } else if (item.id === idPrefix + 'a') { - item.children.set([ - new TestItemImpl(idPrefix + 'aa', 'aa', URI.file('/')), - new TestItemImpl(idPrefix + 'ab', 'ab', URI.file('/')), + item.children.replace([ + new TestItemImpl('ctrlId', idPrefix + 'aa', 'aa', URI.file('/')), + new TestItemImpl('ctrlId', idPrefix + 'ab', 'ab', URI.file('/')), ]); } }; diff --git a/src/vs/workbench/contrib/testing/common/testingStates.ts b/src/vs/workbench/contrib/testing/common/testingStates.ts index 84c9cf019fe..d0ebaed215c 100644 --- a/src/vs/workbench/contrib/testing/common/testingStates.ts +++ b/src/vs/workbench/contrib/testing/common/testingStates.ts @@ -3,9 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; - -export { TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { TestResultState } from 'vs/workbench/contrib/testing/common/testCollection'; export type TreeStateNode = { statusNode: true; state: TestResultState; priority: number }; diff --git a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts index 0816fe168ba..b6158e5ee62 100644 --- a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts +++ b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByLocation.test.ts @@ -6,9 +6,8 @@ import * as assert from 'assert'; import { Emitter } from 'vs/base/common/event'; import { HierarchicalByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation'; -import { TestDiffOpType, TestItemExpandState, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection'; +import { TestDiffOpType, TestItemExpandState, TestResultItem, TestResultState } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestId } from 'vs/workbench/contrib/testing/common/testId'; -import { TestResultState } from 'vs/workbench/contrib/testing/common/testingStates'; import { TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; import { Convert, TestItemImpl } from 'vs/workbench/contrib/testing/common/testStubs'; import { TestTreeTestHarness } from 'vs/workbench/contrib/testing/test/browser/testObjectTree'; @@ -55,10 +54,10 @@ suite('Workbench - Testing Explorer Hierarchal by Location Projection', () => { harness.flush(); harness.pushDiff([ TestDiffOpType.Add, - { controllerId: 'ctrl2', parent: null, expand: TestItemExpandState.Expanded, item: Convert.TestItem.from(new TestItemImpl('c', 'c', undefined), 'ctrl2') }, + { controllerId: 'ctrl2', parent: null, expand: TestItemExpandState.Expanded, item: Convert.TestItem.from(new TestItemImpl('ctrl2', 'c', 'c', undefined)) }, ], [ TestDiffOpType.Add, - { controllerId: 'ctrl2', parent: new TestId(['ctrl2', 'c']).toString(), expand: TestItemExpandState.NotExpandable, item: Convert.TestItem.from(new TestItemImpl('c-a', 'ca', undefined), 'ctrl2') }, + { controllerId: 'ctrl2', parent: new TestId(['ctrl2', 'c']).toString(), expand: TestItemExpandState.NotExpandable, item: Convert.TestItem.from(new TestItemImpl('ctrl2', 'c-a', 'ca', undefined)) }, ]); assert.deepStrictEqual(harness.flush(), [ @@ -76,7 +75,7 @@ suite('Workbench - Testing Explorer Hierarchal by Location Projection', () => { { e: 'b' } ]); - harness.c.root.children.get('id-a')!.children.add(new TestItemImpl('ac', 'ac', undefined)); + harness.c.root.children.get('id-a')!.children.add(new TestItemImpl('ctrlId', 'ac', 'ac', undefined)); assert.deepStrictEqual(harness.flush(), [ { e: 'a', children: [{ e: 'aa' }, { e: 'ab' }, { e: 'ac' }] }, @@ -106,7 +105,7 @@ suite('Workbench - Testing Explorer Hierarchal by Location Projection', () => { resultsService.getStateById = () => [undefined, resultInState(TestResultState.Failed)]; const resultInState = (state: TestResultState): TestResultItem => ({ - item: Convert.TestItem.from(harness.c.tree.get(new TestId(['ctrlId', 'id-a']).toString())!.actual, 'ctrlId'), + item: Convert.TestItem.from(harness.c.tree.get(new TestId(['ctrlId', 'id-a']).toString())!.actual), parent: 'id-root', tasks: [], retired: false, diff --git a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts index 91578aeddc2..da9b5619182 100644 --- a/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts +++ b/src/vs/workbench/contrib/testing/test/browser/explorerProjections/hierarchalByName.test.ts @@ -43,10 +43,10 @@ suite('Workbench - Testing Explorer Hierarchal by Name Projection', () => { harness.flush(); harness.pushDiff([ TestDiffOpType.Add, - { controllerId: 'ctrl2', parent: null, expand: TestItemExpandState.Expanded, item: Convert.TestItem.from(new TestItemImpl('c', 'root2', undefined), 'ctrl2') }, + { controllerId: 'ctrl2', parent: null, expand: TestItemExpandState.Expanded, item: Convert.TestItem.from(new TestItemImpl('ctrl2', 'c', 'root2', undefined)) }, ], [ TestDiffOpType.Add, - { controllerId: 'ctrl2', parent: new TestId(['ctrl2', 'c']).toString(), expand: TestItemExpandState.NotExpandable, item: Convert.TestItem.from(new TestItemImpl('c-a', 'c', undefined), 'ctrl2') }, + { controllerId: 'ctrl2', parent: new TestId(['ctrl2', 'c']).toString(), expand: TestItemExpandState.NotExpandable, item: Convert.TestItem.from(new TestItemImpl('ctrl2', 'c-a', 'c', undefined)) }, ]); assert.deepStrictEqual(harness.flush(), [ @@ -58,7 +58,7 @@ suite('Workbench - Testing Explorer Hierarchal by Name Projection', () => { test('updates nodes if they add children', async () => { harness.flush(); - harness.c.root.children.get('id-a')!.children.add(new TestItemImpl('ac', 'ac', undefined)); + harness.c.root.children.get('id-a')!.children.add(new TestItemImpl('ctrl2', 'ac', 'ac', undefined)); assert.deepStrictEqual(harness.flush(), [ { e: 'aa' }, @@ -80,7 +80,7 @@ suite('Workbench - Testing Explorer Hierarchal by Name Projection', () => { test('swaps when node is no longer leaf', async () => { harness.flush(); - harness.c.root.children.get('id-b')!.children.add(new TestItemImpl('ba', 'ba', undefined)); + harness.c.root.children.get('id-b')!.children.add(new TestItemImpl('ctrl2', 'ba', 'ba', undefined)); assert.deepStrictEqual(harness.flush(), [ { e: 'aa' }, diff --git a/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts b/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts index 209ea14cbd3..a0f0d507c1c 100644 --- a/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts +++ b/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts @@ -10,14 +10,13 @@ import { Lazy } from 'vs/base/common/lazy'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; import { NullLogService } from 'vs/platform/log/common/log'; import { SingleUseTestCollection } from 'vs/workbench/contrib/testing/common/ownedTestCollection'; -import { ITestTaskState, ResolvedTestRunRequest, TestResultItem, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; +import { ITestTaskState, ResolvedTestRunRequest, TestResultItem, TestResultState, TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestProfileService } from 'vs/workbench/contrib/testing/common/testConfigurationService'; import { TestId } from 'vs/workbench/contrib/testing/common/testId'; -import { TestResultState } from 'vs/workbench/contrib/testing/common/testingStates'; import { HydratedTestResult, LiveOutputController, LiveTestResult, makeEmptyCounts, resultItemParents, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; import { TestResultService } from 'vs/workbench/contrib/testing/common/testResultService'; import { InMemoryResultStorage, ITestResultStorage } from 'vs/workbench/contrib/testing/common/testResultStorage'; -import { Convert, getInitializedMainTestCollection, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; +import { Convert, getInitializedMainTestCollection, TestItemImpl, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; export const emptyOutputController = () => new LiveOutputController( @@ -65,14 +64,14 @@ suite('Workbench - Test Results Service', () => { tests = testStubs.nested(); await tests.expand(tests.root.id, Infinity); r.addTestChainToRun('ctrlId', [ - Convert.TestItem.from(tests.root, 'ctrlId'), - Convert.TestItem.from(tests.root.children.get('id-a')!, 'ctrlId'), - Convert.TestItem.from(tests.root.children.get('id-a')!.children.get('id-aa')!, 'ctrlId'), + Convert.TestItem.from(tests.root), + Convert.TestItem.from(tests.root.children.get('id-a') as TestItemImpl), + Convert.TestItem.from(tests.root.children.get('id-a')!.children.get('id-aa') as TestItemImpl), ]); r.addTestChainToRun('ctrlId', [ - Convert.TestItem.from(tests.root.children.get('id-a')!, 'ctrlId'), - Convert.TestItem.from(tests.root.children.get('id-a')!.children.get('id-ab')!, 'ctrlId'), + Convert.TestItem.from(tests.root.children.get('id-a') as TestItemImpl), + Convert.TestItem.from(tests.root.children.get('id-a')!.children.get('id-ab') as TestItemImpl), ]); }); diff --git a/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts b/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts index 67d41de0bb6..218952e51ba 100644 --- a/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts +++ b/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts @@ -9,7 +9,7 @@ import { NullLogService } from 'vs/platform/log/common/log'; import { TestId } from 'vs/workbench/contrib/testing/common/testId'; import { ITestResult, LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult'; import { InMemoryResultStorage, RETAIN_MAX_RESULTS } from 'vs/workbench/contrib/testing/common/testResultStorage'; -import { Convert, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; +import { Convert, TestItemImpl, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; import { emptyOutputController } from 'vs/workbench/contrib/testing/test/common/testResultService.test'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; @@ -28,9 +28,9 @@ suite('Workbench - Test Result Storage', () => { const tests = testStubs.nested(); tests.expand(tests.root.id, Infinity); t.addTestChainToRun('ctrlId', [ - Convert.TestItem.from(tests.root, 'ctrlId'), - Convert.TestItem.from(tests.root.children.get('id-a')!, 'ctrlId'), - Convert.TestItem.from(tests.root.children.get('id-a')!.children.get('id-aa')!, 'ctrlId'), + Convert.TestItem.from(tests.root), + Convert.TestItem.from(tests.root.children.get('id-a') as TestItemImpl), + Convert.TestItem.from(tests.root.children.get('id-a')!.children.get('id-aa') as TestItemImpl), ]); if (addMessage) { diff --git a/src/vs/workbench/test/browser/api/extHostTesting.test.ts b/src/vs/workbench/test/browser/api/extHostTesting.test.ts index 3aa083acd84..222e5b31bc0 100644 --- a/src/vs/workbench/test/browser/api/extHostTesting.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTesting.test.ts @@ -11,7 +11,7 @@ import { mockObject, MockObject } from 'vs/base/test/common/mock'; import { MainThreadTestingShape } from 'vs/workbench/api/common/extHost.protocol'; import { TestRunProfileImpl, TestRunCoordinator, TestRunDto } from 'vs/workbench/api/common/extHostTesting'; import * as convert from 'vs/workbench/api/common/extHostTypeConverters'; -import { TestMessage, TestResultState, TestRunProfileGroup } from 'vs/workbench/api/common/extHostTypes'; +import { TestMessage, TestResultState, TestRunProfileKind } from 'vs/workbench/api/common/extHostTypes'; import { TestDiffOpType, TestItemExpandState } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestId } from 'vs/workbench/contrib/testing/common/testId'; import { TestItemImpl, testStubs } from 'vs/workbench/contrib/testing/common/testStubs'; @@ -74,24 +74,24 @@ suite('ExtHost Testing', () => { suite('OwnedTestCollection', () => { test('adds a root recursively', async () => { await single.expand(single.root.id, Infinity); - const a = single.root.children.get('id-a')!; - const b = single.root.children.get('id-b')!; + const a = single.root.children.get('id-a') as TestItemImpl; + const b = single.root.children.get('id-b') as TestItemImpl; assert.deepStrictEqual(single.collectDiff(), [ [ TestDiffOpType.Add, - { controllerId: 'ctrlId', parent: null, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(single.root, 'ctrlId') } } + { controllerId: 'ctrlId', parent: null, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(single.root) } } ], [ TestDiffOpType.Add, - { controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(a, 'ctrlId') } } + { controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(a) } } ], [ TestDiffOpType.Add, - { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-aa')!, 'ctrlId') } + { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-aa') as TestItemImpl) } ], [ TestDiffOpType.Add, - { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-ab')!, 'ctrlId') } + { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-ab') as TestItemImpl) } ], [ TestDiffOpType.Update, @@ -99,7 +99,7 @@ suite('ExtHost Testing', () => { ], [ TestDiffOpType.Add, - { controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b, 'ctrlId') } + { controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) } ], [ TestDiffOpType.Update, @@ -153,7 +153,7 @@ suite('ExtHost Testing', () => { test('adds new children', () => { single.expand(single.root.id, Infinity); single.collectDiff(); - const child = new TestItemImpl('id-ac', 'c', undefined); + const child = new TestItemImpl('ctrlId', 'id-ac', 'c', undefined); single.root.children.get('id-a')!.children.add(child); assert.deepStrictEqual(single.collectDiff(), [ @@ -161,7 +161,7 @@ suite('ExtHost Testing', () => { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, - item: convert.TestItem.from(child, 'ctrlId'), + item: convert.TestItem.from(child), }], ]); assert.deepStrictEqual( @@ -176,11 +176,11 @@ suite('ExtHost Testing', () => { single.collectDiff(); const oldA = single.root.children.get('id-a') as TestItemImpl; - const newA = new TestItemImpl('id-a', 'Hello world', undefined); - newA.children.set(oldA.children); - single.root.children.set([ + const newA = new TestItemImpl('ctrlId', 'id-a', 'Hello world', undefined); + newA.children.replace([...oldA.children]); + single.root.children.replace([ newA, - new TestItemImpl('id-b', single.root.children.get('id-b')!.label, undefined), + new TestItemImpl('ctrlId', 'id-b', single.root.children.get('id-b')!.label, undefined), ]); assert.deepStrictEqual(single.collectDiff(), [ @@ -207,12 +207,12 @@ suite('ExtHost Testing', () => { single.collectDiff(); const oldA = single.root.children.get('id-a')!; - const newA = new TestItemImpl('id-a', single.root.children.get('id-a')!.label, undefined); + const newA = new TestItemImpl('ctrlId', 'id-a', single.root.children.get('id-a')!.label, undefined); const oldAA = oldA.children.get('id-aa')!; const oldAB = oldA.children.get('id-ab')!; - const newAB = new TestItemImpl('id-ab', 'Hello world', undefined); - newA.children.set([oldAA, newAB]); - single.root.children.set([newA, single.root.children.get('id-b')!]); + const newAB = new TestItemImpl('ctrlId', 'id-ab', 'Hello world', undefined); + newA.children.replace([oldAA, newAB]); + single.root.children.replace([newA, single.root.children.get('id-b')!]); assert.deepStrictEqual(single.collectDiff(), [ [ @@ -247,8 +247,8 @@ suite('ExtHost Testing', () => { test('moves an item to be a new child', async () => { await single.expand(single.root.id, 0); single.collectDiff(); - const b = single.root.children.get('id-b')!; - const a = single.root.children.get('id-a')!; + const b = single.root.children.get('id-b') as TestItemImpl; + const a = single.root.children.get('id-a') as TestItemImpl; a.children.add(b); assert.deepStrictEqual(single.collectDiff(), [ [ @@ -257,7 +257,7 @@ suite('ExtHost Testing', () => { ], [ TestDiffOpType.Add, - { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b, 'ctrlId') } + { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) } ], ]); @@ -426,7 +426,7 @@ suite('ExtHost Testing', () => { cts = new CancellationTokenSource(); c = new TestRunCoordinator(proxy); - configuration = new TestRunProfileImpl(mockObject(), 'ctrlId', 42, 'Do Run', TestRunProfileGroup.Run, () => { }, false); + configuration = new TestRunProfileImpl(mockObject(), 'ctrlId', 42, 'Do Run', TestRunProfileKind.Run, () => { }, false); await single.expand(single.root.id, Infinity); single.collectDiff(); @@ -509,9 +509,9 @@ suite('ExtHost Testing', () => { 'ctrl', tracker.id, [ - convert.TestItem.from(single.root, 'ctrlId'), - convert.TestItem.from(single.root.children.get('id-a')!, 'ctrlId'), - convert.TestItem.from(single.root.children.get('id-a')!.children.get('id-aa')!, 'ctrlId'), + convert.TestItem.from(single.root), + convert.TestItem.from(single.root.children.get('id-a') as TestItemImpl), + convert.TestItem.from(single.root.children.get('id-a')!.children.get('id-aa') as TestItemImpl), ] ]); assert.deepStrictEqual(proxy.$addTestsToRun.args, expectedArgs); @@ -522,8 +522,8 @@ suite('ExtHost Testing', () => { 'ctrl', tracker.id, [ - convert.TestItem.from(single.root.children.get('id-a')!, 'ctrlId'), - convert.TestItem.from(single.root.children.get('id-a')!.children.get('id-ab')!, 'ctrlId'), + convert.TestItem.from(single.root.children.get('id-a') as TestItemImpl), + convert.TestItem.from(single.root.children.get('id-a')!.children.get('id-ab') as TestItemImpl), ], ]); assert.deepStrictEqual(proxy.$addTestsToRun.args, expectedArgs);