Skip to content

Commit d801d41

Browse files
authored
Test tags from suites should be inherited (#1015)
Tags defined on swift-testing suites are meant to be inherited by child suites/tests. VS Code doesn't apply this inheritance automatically, so we must set a suite's tags on its children ourselves. Issue: #1014
1 parent d131215 commit d801d41

File tree

2 files changed

+95
-6
lines changed

2 files changed

+95
-6
lines changed

src/TestExplorer/TestDiscovery.ts

+27
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,27 @@ function deepMergeTestItemChildren(existingItem: vscode.TestItem, newItem: vscod
158158
);
159159
}
160160

161+
/**
162+
* Given a `TestClass` adds the TestClasses tags to each of its children.
163+
* Does not apply recursively.
164+
* @param testClass A test class whose tags should be propagated to its children.
165+
* @returns A `TestClass` whose children include the parent's tags.
166+
*/
167+
function applyTagsToChildren(testClass: TestClass): TestClass {
168+
return {
169+
...testClass,
170+
children: testClass.children.reduce((children, child) => {
171+
return [
172+
...children,
173+
{
174+
...child,
175+
tags: [...child.tags, ...testClass.tags],
176+
},
177+
];
178+
}, [] as TestClass[]),
179+
};
180+
}
181+
161182
/**
162183
* Updates the existing `vscode.TestItem` if it exists with the same ID as the `TestClass`,
163184
* otherwise creates an add a new one. The location on the returned vscode.TestItem is always updated.
@@ -203,6 +224,12 @@ export function upsertTestItem(
203224
deepMergeTestItemChildren(existingItem, newItem);
204225
}
205226

227+
// In VS Code tags are not inherited automatically, so if we're recieving a suite we need
228+
// to set a suites tag on all of its children. Because test items are added top down the children
229+
// aren't updated recursively all at once, but rather one level at a time which then propagages
230+
// parent tags down the tree as children are upserted.
231+
testItem = applyTagsToChildren(testItem);
232+
206233
// Manually add the test style as a tag so we can filter by test type.
207234
newItem.tags = [{ id: testItem.style }, ...testItem.tags];
208235

test/suite/testexplorer/TestDiscovery.test.ts

+68-6
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,19 @@ suite("TestDiscovery Suite", () => {
3131
interface SimplifiedTestItem {
3232
id: string;
3333
children: SimplifiedTestItem[];
34+
tags: readonly { id: string }[];
3435
}
3536

3637
function testControllerChildren(collection: vscode.TestItemCollection): SimplifiedTestItem[] {
3738
return reduceTestItemChildren(
3839
collection,
3940
(acc, item) => [
4041
...acc,
41-
{ id: item.id, children: testControllerChildren(item.children) },
42+
{
43+
id: item.id,
44+
tags: [...item.tags.map(tag => ({ id: tag.id }))],
45+
children: testControllerChildren(item.children),
46+
},
4247
],
4348
[] as SimplifiedTestItem[]
4449
);
@@ -77,7 +82,7 @@ suite("TestDiscovery Suite", () => {
7782
updateTests(testController, [testItem("bar")]);
7883

7984
assert.deepStrictEqual(testControllerChildren(testController.items), [
80-
{ id: "bar", children: [] },
85+
{ id: "bar", tags: [{ id: "XCTest" }, { id: "runnable" }], children: [] },
8186
]);
8287
});
8388

@@ -109,9 +114,10 @@ suite("TestDiscovery Suite", () => {
109114
assert.deepStrictEqual(testControllerChildren(testController.items), [
110115
{
111116
id: "foo",
117+
tags: [{ id: "XCTest" }, { id: "runnable" }],
112118
children: [
113-
{ id: "baz", children: [] },
114-
{ id: "bar", children: [] },
119+
{ id: "baz", tags: [{ id: "XCTest" }, { id: "runnable" }], children: [] },
120+
{ id: "bar", tags: [{ id: "XCTest" }, { id: "runnable" }], children: [] },
115121
],
116122
},
117123
]);
@@ -140,7 +146,13 @@ suite("TestDiscovery Suite", () => {
140146
updateTests(testController, [newFoo]);
141147

142148
assert.deepStrictEqual(testControllerChildren(testController.items), [
143-
{ id: "foo", children: [{ id: "bar", children: [] }] },
149+
{
150+
id: "foo",
151+
tags: [{ id: "XCTest" }, { id: "runnable" }],
152+
children: [
153+
{ id: "bar", tags: [{ id: "XCTest" }, { id: "runnable" }], children: [] },
154+
],
155+
},
144156
]);
145157
assert.deepStrictEqual(testController.items.get("foo")?.uri, newLocation.uri);
146158
assert.deepStrictEqual(testController.items.get("foo")?.label, "New Label");
@@ -168,7 +180,57 @@ suite("TestDiscovery Suite", () => {
168180
updateTestsFromClasses(testController, swiftPackage, [item]);
169181

170182
assert.deepStrictEqual(testControllerChildren(testController.items), [
171-
{ id: "TestTarget", children: [{ id: "bar", children: [] }] },
183+
{
184+
id: "TestTarget",
185+
tags: [{ id: "test-target" }, { id: "runnable" }],
186+
children: [
187+
{ id: "bar", tags: [{ id: "XCTest" }, { id: "runnable" }], children: [] },
188+
],
189+
},
190+
]);
191+
});
192+
193+
test("Children in suites with tags inherit the suite's tags", async () => {
194+
const testSuite = testItem("suite");
195+
testSuite.tags = [{ id: "rootTag" }];
196+
const childSuite = testItem("childSuite");
197+
childSuite.tags = [{ id: "childSuiteTag" }];
198+
const childTest = testItem("childTest");
199+
childTest.tags = [{ id: "childTestTag" }];
200+
childSuite.children = [childTest];
201+
testSuite.children = [childSuite];
202+
203+
updateTests(testController, [testSuite]);
204+
205+
assert.deepEqual(testControllerChildren(testController.items), [
206+
{
207+
id: "suite",
208+
tags: [{ id: "XCTest" }, { id: "rootTag" }, { id: "runnable" }],
209+
children: [
210+
{
211+
id: "childSuite",
212+
tags: [
213+
{ id: "XCTest" },
214+
{ id: "childSuiteTag" },
215+
{ id: "rootTag" },
216+
{ id: "runnable" },
217+
],
218+
children: [
219+
{
220+
id: "childTest",
221+
children: [],
222+
tags: [
223+
{ id: "XCTest" },
224+
{ id: "childTestTag" },
225+
{ id: "childSuiteTag" },
226+
{ id: "rootTag" },
227+
{ id: "runnable" },
228+
],
229+
},
230+
],
231+
},
232+
],
233+
},
172234
]);
173235
});
174236
});

0 commit comments

Comments
 (0)