testing: update more nits

This commit is contained in:
Connor Peet 2021-07-16 13:17:53 -07:00
parent 74fcf10908
commit 92f692d4a3
No known key found for this signature in database
GPG key ID: CF8FD2EA0DBC61BD
5 changed files with 53 additions and 39 deletions

View file

@ -2159,27 +2159,37 @@ declare module 'vscode' {
* Collection of test items, found in {@link TestItem.children} and
* {@link TestController.items}.
*/
export interface TestItemCollection {
export interface TestItemCollection extends Iterable<TestItem> {
/**
* A read-only array of all the test items children. Can be retrieved, or
* set in order to replace children in the collection.
* Updates the items stored by the collection.
* @param items Items to store, can be an array or other iterable.
*/
// todo@API unsure if this should readonly and have a separate replaceAll-like function
all: readonly TestItem[];
set(items: Iterable<TestItem>): void;
/**
* Iterate over each entry in this collection.
*
* @param callback Function to execute for each entry.
* @param thisArg The `this` context used when invoking the handler function.
*/
forEach(callback: (item: TestItem, collection: TestItemCollection) => unknown, thisArg?: unknown): void;
/**
* Adds the test item to the children. If an item with the same ID already
* exists, it'll be replaced.
* @param items Item to add.
*/
add(item: TestItem): void;
/**
* Removes the a single test item from the collection.
* @param itemId Item ID to delete.
*/
delete(itemId: string): void;
/**
* Efficiently gets a test item by ID, if it exists, in the children.
* @param itemId Item ID to get.
*/
get(itemId: string): TestItem | undefined;
}

View file

@ -145,24 +145,22 @@ export class InvalidTestItemError extends Error {
}
}
export const createTestItemCollection = (owningItem: TestItemImpl):
vscode.TestItemCollection & { toJSON(): readonly vscode.TestItem[] } => {
export type TestItemCollectionImpl = vscode.TestItemCollection & { toJSON(): readonly TestItemImpl[] };
export const createTestItemCollection = (owningItem: TestItemImpl): TestItemCollectionImpl => {
const api = getPrivateApiFor(owningItem);
let all: readonly TestItemImpl[] | undefined;
let mapped = new Map<string, TestItemImpl>();
return {
/** @inheritdoc */
get all() {
if (!all) {
all = Object.freeze([...mapped.values()]);
forEach(callback: (item: vscode.TestItem, collection: vscode.TestItemCollection) => unknown, thisArg?: unknown) {
for (const item of mapped.values()) {
callback.call(thisArg, item, this);
}
return all;
},
/** @inheritdoc */
set all(items: readonly vscode.TestItem[]) {
set(items: Iterable<vscode.TestItem>) {
const newMapped = new Map<string, TestItemImpl>();
const toDelete = new Set(mapped.keys());
const bulk: ITestItemBulkReplace = { op: ExtHostTestItemEventOp.Bulk, ops: [] };
@ -190,7 +188,6 @@ export const createTestItemCollection = (owningItem: TestItemImpl):
// important mutations come after firing, so if an error happens no
// changes will be "saved":
mapped = newMapped;
all = undefined;
},
@ -201,14 +198,12 @@ export const createTestItemCollection = (owningItem: TestItemImpl):
}
mapped.set(item.id, item);
all = undefined;
api.listener?.({ op: ExtHostTestItemEventOp.Upsert, item });
},
/** @inheritdoc */
delete(id: string) {
if (mapped.delete(id)) {
all = undefined;
api.listener?.({ op: ExtHostTestItemEventOp.RemoveChild, id });
}
},
@ -220,7 +215,12 @@ export const createTestItemCollection = (owningItem: TestItemImpl):
/** JSON serialization function. */
toJSON() {
return this.all;
return Array.from(mapped.values());
},
/** @inheritdoc */
[Symbol.iterator]() {
return mapped.values();
},
};
};
@ -228,7 +228,7 @@ export const createTestItemCollection = (owningItem: TestItemImpl):
export class TestItemImpl implements vscode.TestItem {
public readonly id!: string;
public readonly uri!: vscode.Uri | undefined;
public readonly children!: vscode.TestItemCollection;
public readonly children!: TestItemCollectionImpl;
public readonly parent!: TestItemImpl | undefined;
public range!: vscode.Range | undefined;

View file

@ -234,7 +234,7 @@ export class SingleUseTestCollection extends Disposable {
}
// Case 3: upsert of an existing item by ID, with a new instance
const oldChildren = internal.actual.children.all;
const oldChildren = internal.actual.children;
const oldActual = internal.actual;
const changedProps = diffTestItems(oldActual, actual);
getPrivateApiFor(oldActual).listener = undefined;
@ -271,7 +271,7 @@ export class SingleUseTestCollection extends Disposable {
this.connectItem(actual, internal, parent);
// Discover any existing children that might have already been added
for (const child of actual.children.all) {
for (const child of actual.children) {
this.upsertItem(child, internal);
}
}
@ -317,12 +317,16 @@ export class SingleUseTestCollection extends Disposable {
return;
}
const asyncChildren = internal.actual.children.all
.map(c => this.expand(TestId.joinToString(internal.fullId, c.id), levels))
.filter(isThenable);
const expandRequests: Promise<void>[] = [];
for (const child of internal.actual.children) {
const promise = this.expand(TestId.joinToString(internal.fullId, child.id), levels);
if (isThenable(promise)) {
expandRequests.push(promise);
}
}
if (asyncChildren.length) {
return Promise.all(asyncChildren).then(() => { });
if (expandRequests.length) {
return Promise.all(expandRequests).then(() => { });
}
}
@ -386,7 +390,7 @@ export class SingleUseTestCollection extends Disposable {
getPrivateApiFor(item.actual).listener = undefined;
this.tree.delete(item.fullId.toString());
for (const child of item.actual.children.all) {
for (const child of item.actual.children) {
queue.push(this.tree.get(TestId.joinToString(item.fullId, child.id)));
}
}

View file

@ -32,12 +32,12 @@ export const testStubs = {
const a = new TestItemImpl(idPrefix + 'a', 'a', URI.file('/'));
a.canResolveChildren = true;
const b = new TestItemImpl(idPrefix + 'b', 'b', URI.file('/'));
item.children.all = [a, b];
item.children.set([a, b]);
} else if (item.id === idPrefix + 'a') {
item.children.all = [
item.children.set([
new TestItemImpl(idPrefix + 'aa', 'aa', URI.file('/')),
new TestItemImpl(idPrefix + 'ab', 'ab', URI.file('/')),
];
]);
}
};

View file

@ -36,8 +36,8 @@ const assertTreesEqual = (a: TestItem | undefined, b: TestItem | undefined) => {
assert.deepStrictEqual(simplify(a), simplify(b));
const aChildren = a.children.all.map(c => c.id).sort();
const bChildren = b.children.all.map(c => c.id).sort();
const aChildren = [...a.children].map(c => c.id).sort();
const bChildren = [...b.children].map(c => c.id).sort();
assert.strictEqual(aChildren.length, bChildren.length, `expected ${a.label}.children.length == ${b.label}.children.length`);
aChildren.forEach(key => assertTreesEqual(a.children.get(key), b.children.get(key)));
};
@ -179,13 +179,13 @@ suite('ExtHost Testing', () => {
single.expand(single.root.id, Infinity);
single.collectDiff();
const oldA = single.root.children.get('id-a')!;
const oldA = single.root.children.get('id-a') as TestItemImpl;
const newA = new TestItemImpl('id-a', 'Hello world', undefined);
newA.children.all = oldA.children.all;
single.root.children.all = [
newA.children.set(oldA.children);
single.root.children.set([
newA,
new TestItemImpl('id-b', single.root.children.get('id-b')!.label, undefined),
];
]);
assert.deepStrictEqual(single.collectDiff(), [
[
@ -215,8 +215,8 @@ suite('ExtHost Testing', () => {
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.all = [oldAA, newAB];
single.root.children.all = [newA, single.root.children.get('id-b')!];
newA.children.set([oldAA, newAB]);
single.root.children.set([newA, single.root.children.get('id-b')!]);
assert.deepStrictEqual(single.collectDiff(), [
[
@ -272,7 +272,7 @@ suite('ExtHost Testing', () => {
],
]);
assert.deepStrictEqual(single.root.children.all, [single.root.children.get('id-a')]);
assert.deepStrictEqual([...single.root.children], [single.root.children.get('id-a')]);
assert.deepStrictEqual(b.parent, a);
});
});