From 06be9f4029eaa33d4d4867f85dd9dadc63423c68 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Fri, 20 Nov 2020 15:14:17 -0800 Subject: [PATCH] testing: tests and speed improvements --- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/common/extHostTesting.ts | 72 ++++++++++++------- src/vs/workbench/api/common/extHostTypes.ts | 11 +++ .../test/browser/api/extHostTesting.test.ts | 30 +++++++- 4 files changed, 86 insertions(+), 29 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 5a2f6c75413..c595e1876e8 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2359,7 +2359,7 @@ declare module 'vscode' { runnable?: boolean; /** - * Whether this test item can be debugged. + * Whether this test item can be debugged. Defaults to `false` if not provided. */ debuggable?: boolean; diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts index dd4af111c9a..02fc32cbffb 100644 --- a/src/vs/workbench/api/common/extHostTesting.ts +++ b/src/vs/workbench/api/common/extHostTesting.ts @@ -17,7 +17,7 @@ import { ExtHostTestingResource, ExtHostTestingShape, MainContext, MainThreadTes import { IExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { TestItem } from 'vs/workbench/api/common/extHostTypeConverters'; -import { Disposable } from 'vs/workbench/api/common/extHostTypes'; +import { Disposable, RequiredTestItem } from 'vs/workbench/api/common/extHostTypes'; import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { AbstractIncrementalTestCollection, EMPTY_TEST_RESULT, IncrementalChangeCollector, IncrementalTestCollectionItem, InternalTestItem, RunTestForProviderRequest, RunTestsResult, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection'; import type * as vscode from 'vscode'; @@ -178,7 +178,7 @@ export class ExtHostTesting implements ExtHostTestingShape { } } -const keyMap: { [K in keyof Omit, 'children'>]: null } = { +const keyMap: { [K in keyof Omit]: null } = { label: null, location: null, state: null, @@ -215,6 +215,9 @@ export interface OwnedCollectionTestItem extends InternalTestItem { previousEquals: (v: vscode.TestItem) => boolean; } +/** + * @private + */ export class OwnedTestCollection { protected readonly testIdToInternal = new Map(); @@ -542,11 +545,16 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection): vscode.TestItem[] { - return itemIds.map(itemId => { + public getAllAsTestItem(itemIds: Iterable): vscode.TestItem[] { + let output: vscode.TestItem[] = []; + for (const itemId of itemIds) { const item = this.items.get(itemId); - return item && this.getPublicTestItem(item); - }).filter(isDefined); + if (item) { + output.push(this.getPublicTestItem(item)); + } + } + + return output; } /** @@ -584,7 +592,7 @@ export class MirroredTestCollection extends AbstractIncrementalTestCollection { const MirroredItemId = Symbol('MirroredItemId'); -const createMirroredTestItem = (internal: MirroredCollectionTestItem, collection: MirroredTestCollection): vscode.TestItem => { - const obj = {}; +class ExtHostTestItem implements vscode.TestItem, RequiredTestItem { + readonly #internal: MirroredCollectionTestItem; + readonly #collection: MirroredTestCollection; - Object.defineProperty(obj, MirroredItemId, { - enumerable: false, - configurable: false, - value: internal.id, - }); + public get label() { return this.#internal.revived.label; } + public get description() { return this.#internal.revived.description; } + public get state() { return this.#internal.revived.state; } + public get location() { return this.#internal.revived.location; } + public get runnable() { return this.#internal.revived.runnable ?? true; } + public get debuggable() { return this.#internal.revived.debuggable ?? false; } + public get children() { + return this.#collection.getAllAsTestItem(this.#internal.children); + } - Object.defineProperty(obj, 'children', { - enumerable: true, - configurable: false, - get: () => collection.getAllAsTestItem([...internal.children]) - }); + get [MirroredItemId]() { return this.#internal.id; } - simpleProps.forEach(prop => Object.defineProperty(obj, prop, { - enumerable: true, - configurable: false, - get: () => internal.revived[prop], - })); + constructor(internal: MirroredCollectionTestItem, collection: MirroredTestCollection) { + this.#internal = internal; + this.#collection = collection; + } - return obj as any; -}; + public toJSON() { + const serialized: RequiredTestItem = { + label: this.label, + description: this.description, + state: this.state, + location: this.location, + runnable: this.runnable, + debuggable: this.debuggable, + children: this.children.map(c => (c as ExtHostTestItem).toJSON()), + }; + + return serialized; + } +} interface IObserverData { observers: number; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 1013635962d..8788574ca1b 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -2940,4 +2940,15 @@ export class TestState { } } +type AllowedUndefined = 'description' | 'location'; + +/** + * Test item without any optional properties. Only some properties are + * permitted to be undefined, but they must still exist. + */ +export type RequiredTestItem = { + [K in keyof Required]: K extends AllowedUndefined ? vscode.TestItem[K] : Required[K] +}; + + //#endregion diff --git a/src/vs/workbench/test/browser/api/extHostTesting.test.ts b/src/vs/workbench/test/browser/api/extHostTesting.test.ts index 3e9732a0fcd..9ed0f4b2557 100644 --- a/src/vs/workbench/test/browser/api/extHostTesting.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTesting.test.ts @@ -19,8 +19,16 @@ const stubTest = (label: string): TestItem => ({ description: '' }); +const simplify = (item: TestItem) => { + if ('toJSON' in item) { + item = (item as any).toJSON(); + } + + return { ...item, children: undefined }; +}; + const assertTreesEqual = (a: Readonly, b: Readonly) => { - assert.deepStrictEqual({ ...a, children: undefined }, { ...b, children: undefined }); + assert.deepStrictEqual(simplify(a), simplify(b)); const aChildren = (a.children ?? []).sort(); const bChildren = (b.children ?? []).sort(); @@ -274,11 +282,29 @@ suite('ExtHost Testing', () => { single.onItemChange(tests, 'pid'); m.apply(single.collectDiff()); - assert.deepStrictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); + assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); assertTreeListEqual(m.changeEvent.added, [child]); assertTreeListEqual(m.changeEvent.removed, []); assertTreeListEqual(m.changeEvent.updated, []); }); + + test('gets the common ancestor (1)', () => { + tests.children![0].children![0].label = 'za'; + tests.children![0].children![1].label = 'zb'; + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'a'); + }); + + test('gets the common ancestor (2)', () => { + tests.children![0].children![0].label = 'za'; + tests.children![1].label = 'ab'; + single.onItemChange(tests, 'pid'); + m.apply(single.collectDiff()); + + assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root'); + }); }); }); }); -- GitLab