forked from microsoft/vscode-python
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtestDiscoveryHandler.ts
More file actions
104 lines (92 loc) · 4.05 KB
/
testDiscoveryHandler.ts
File metadata and controls
104 lines (92 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { CancellationToken, TestController, Uri, MarkdownString } from 'vscode';
import * as util from 'util';
import { DiscoveredTestPayload } from './types';
import { TestProvider } from '../../types';
import { traceError } from '../../../logging';
import { Testing } from '../../../common/utils/localize';
import { createErrorTestItem } from './testItemUtilities';
import { buildErrorNodeOptions, populateTestTree } from './utils';
import { TestItemIndex } from './testItemIndex';
/**
* Stateless handler for processing discovery payloads and building/updating the TestItem tree.
* This handler is shared across all workspaces and contains no instance state.
*/
export class TestDiscoveryHandler {
/**
* Process discovery payload and update test tree
* Pure function - no instance state used
*/
public processDiscovery(
payload: DiscoveredTestPayload,
testController: TestController,
testItemIndex: TestItemIndex,
workspaceUri: Uri,
testProvider: TestProvider,
token?: CancellationToken,
): void {
if (!payload) {
// No test data is available
return;
}
const workspacePath = workspaceUri.fsPath;
const rawTestData = payload as DiscoveredTestPayload;
// Check if there were any errors in the discovery process.
if (rawTestData.status === 'error') {
this.createErrorNode(testController, workspaceUri, rawTestData.error, testProvider);
} else {
// remove error node only if no errors exist.
testController.items.delete(`DiscoveryError:${workspacePath}`);
}
if (rawTestData.tests || rawTestData.tests === null) {
// if any tests exist, they should be populated in the test tree, regardless of whether there were errors or not.
// parse and insert test data.
// Clear existing mappings before rebuilding test tree
testItemIndex.clear();
// If the test root for this folder exists: Workspace refresh, update its children.
// Otherwise, it is a freshly discovered workspace, and we need to create a new test root and populate the test tree.
// Note: populateTestTree will call testItemIndex.registerTestItem() for each discovered test
populateTestTree(
testController,
rawTestData.tests,
undefined,
{
runIdToTestItem: testItemIndex.runIdToTestItemMap,
runIdToVSid: testItemIndex.runIdToVSidMap,
vsIdToRunId: testItemIndex.vsIdToRunIdMap,
} as any,
token,
);
}
}
/**
* Create an error node for discovery failures
*/
public createErrorNode(
testController: TestController,
workspaceUri: Uri,
error: string[] | undefined,
testProvider: TestProvider,
): void {
const workspacePath = workspaceUri.fsPath;
const testingErrorConst =
testProvider === 'pytest' ? Testing.errorPytestDiscovery : Testing.errorUnittestDiscovery;
traceError(testingErrorConst, 'for workspace: ', workspacePath, '\r\n', error?.join('\r\n\r\n') ?? '');
let errorNode = testController.items.get(`DiscoveryError:${workspacePath}`);
const message = util.format(
`${testingErrorConst} ${Testing.seePythonOutput}\r\n`,
error?.join('\r\n\r\n') ?? '',
);
if (errorNode === undefined) {
const options = buildErrorNodeOptions(workspaceUri, message, testProvider);
errorNode = createErrorTestItem(testController, options);
testController.items.add(errorNode);
}
const errorNodeLabel: MarkdownString = new MarkdownString(
`[Show output](command:python.viewOutput) to view error logs`,
);
errorNodeLabel.isTrusted = true;
errorNode.error = errorNodeLabel;
}
}