@elisra-devops/docgen-data-provider 1.29.2 → 1.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/modules/ResultDataProvider.d.ts +19 -2
- package/bin/modules/ResultDataProvider.js +172 -92
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/modules/TicketsDataProvider.d.ts +14 -0
- package/bin/modules/TicketsDataProvider.js +46 -4
- package/bin/modules/TicketsDataProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/ResultDataProvider.ts +229 -89
- package/src/modules/TicketsDataProvider.ts +59 -4
|
@@ -26,6 +26,7 @@ export default class ResultDataProvider {
|
|
|
26
26
|
token: string;
|
|
27
27
|
private limit;
|
|
28
28
|
private testStepParserHelper;
|
|
29
|
+
private testToAssociatedItemMap;
|
|
29
30
|
constructor(orgUrl: string, token: string);
|
|
30
31
|
/**
|
|
31
32
|
* Combines the results of test group result summary, test results summary, and detailed results summary into a single key-value pair array.
|
|
@@ -47,7 +48,7 @@ export default class ResultDataProvider {
|
|
|
47
48
|
*
|
|
48
49
|
* @throws Will log an error if any step in the process fails.
|
|
49
50
|
*/
|
|
50
|
-
getTestReporterResults(testPlanId: string, projectName: string, selectedSuiteIds: number[], selectedFields: string[], allowCrossTestPlan: boolean, enableRunTestCaseFilter: boolean, enableRunStepStatusFilter: boolean): Promise<any[] | undefined>;
|
|
51
|
+
getTestReporterResults(testPlanId: string, projectName: string, selectedSuiteIds: number[], selectedFields: string[], allowCrossTestPlan: boolean, enableRunTestCaseFilter: boolean, enableRunStepStatusFilter: boolean, linkedQueryRequest: any, errorFilterMode?: string): Promise<any[] | undefined>;
|
|
51
52
|
/**
|
|
52
53
|
* Mapping each attachment to a proper URL for downloading it
|
|
53
54
|
* @param runResults Array of run results
|
|
@@ -100,8 +101,24 @@ export default class ResultDataProvider {
|
|
|
100
101
|
* Fetches test cases by suite ID.
|
|
101
102
|
*/
|
|
102
103
|
private fetchTestCasesBySuiteId;
|
|
104
|
+
/**
|
|
105
|
+
* Fetches result data based on the Work Item Test Reporter.
|
|
106
|
+
*
|
|
107
|
+
* This method retrieves detailed result data for a specific test run and result ID,
|
|
108
|
+
* including related work items, selected fields, and additional processing options.
|
|
109
|
+
*
|
|
110
|
+
* @param projectName - The name of the project containing the test run.
|
|
111
|
+
* @param runId - The unique identifier of the test run.
|
|
112
|
+
* @param resultId - The unique identifier of the test result.
|
|
113
|
+
* @param isTestReporter - (Optional) A flag indicating whether the result data is being fetched for the Test Reporter.
|
|
114
|
+
* @param selectedFields - (Optional) An array of field names to include in the result data.
|
|
115
|
+
* @param isQueryMode - (Optional) A flag indicating whether the result data is being fetched in query mode.
|
|
116
|
+
* @returns A promise that resolves to the fetched result data.
|
|
117
|
+
*/
|
|
103
118
|
private fetchResultDataBasedOnWiBase;
|
|
104
119
|
private isNotRunStep;
|
|
120
|
+
private appendQueryRelations;
|
|
121
|
+
private appendLinkedRelations;
|
|
105
122
|
/**
|
|
106
123
|
* Fetches result data based on the specified work item (WI) details.
|
|
107
124
|
*
|
|
@@ -281,7 +298,7 @@ export default class ResultDataProvider {
|
|
|
281
298
|
*
|
|
282
299
|
* @param testData - An array of test data objects to be processed.
|
|
283
300
|
* @param iterations - An array of iteration objects to align with the test data.
|
|
284
|
-
* @param selectedFields - An array of selected fields to determine which properties to include in the
|
|
301
|
+
* @param selectedFields - An array of selected fields to determine which properties to include in the response.
|
|
285
302
|
* @returns An array of structured result objects containing aligned test steps and iterations.
|
|
286
303
|
*
|
|
287
304
|
* The method uses a base alignment function and provides custom logic for:
|
|
@@ -15,6 +15,7 @@ const DataProviderUtils_1 = require("../utils/DataProviderUtils");
|
|
|
15
15
|
const tfs_1 = require("../helpers/tfs");
|
|
16
16
|
const logger_1 = require("../utils/logger");
|
|
17
17
|
const testStepParserHelper_1 = require("../utils/testStepParserHelper");
|
|
18
|
+
const TicketsDataProvider_1 = require("./TicketsDataProvider");
|
|
18
19
|
const pLimit = require('p-limit');
|
|
19
20
|
/**
|
|
20
21
|
* Provides methods to fetch, process, and summarize test data from Azure DevOps.
|
|
@@ -65,6 +66,7 @@ class ResultDataProvider {
|
|
|
65
66
|
this.orgUrl = orgUrl;
|
|
66
67
|
this.token = token;
|
|
67
68
|
this.testStepParserHelper = new testStepParserHelper_1.default(orgUrl, token);
|
|
69
|
+
this.testToAssociatedItemMap = new Map();
|
|
68
70
|
}
|
|
69
71
|
/**
|
|
70
72
|
* Combines the results of test group result summary, test results summary, and detailed results summary into a single key-value pair array.
|
|
@@ -184,11 +186,13 @@ class ResultDataProvider {
|
|
|
184
186
|
*
|
|
185
187
|
* @throws Will log an error if any step in the process fails.
|
|
186
188
|
*/
|
|
187
|
-
async getTestReporterResults(testPlanId, projectName, selectedSuiteIds, selectedFields, allowCrossTestPlan, enableRunTestCaseFilter, enableRunStepStatusFilter) {
|
|
189
|
+
async getTestReporterResults(testPlanId, projectName, selectedSuiteIds, selectedFields, allowCrossTestPlan, enableRunTestCaseFilter, enableRunStepStatusFilter, linkedQueryRequest, errorFilterMode = 'none') {
|
|
190
|
+
var _a;
|
|
188
191
|
const fetchedTestResults = [];
|
|
189
192
|
logger_1.default.debug(`Fetching test reporter results for test plan ID: ${testPlanId}, project name: ${projectName}`);
|
|
190
193
|
logger_1.default.debug(`Selected suite IDs: ${selectedSuiteIds}`);
|
|
191
194
|
try {
|
|
195
|
+
const ticketsDataProvider = new TicketsDataProvider_1.default(this.orgUrl, this.token);
|
|
192
196
|
logger_1.default.debug(`Fetching Plan info for test plan ID: ${testPlanId}, project name: ${projectName}`);
|
|
193
197
|
const plan = await this.fetchTestPlanName(testPlanId, projectName);
|
|
194
198
|
logger_1.default.debug(`Fetching Test suites for test plan ID: ${testPlanId}, project name: ${projectName}`);
|
|
@@ -196,11 +200,37 @@ class ResultDataProvider {
|
|
|
196
200
|
logger_1.default.debug(`Fetching test data for test plan ID: ${testPlanId}, project name: ${projectName}`);
|
|
197
201
|
const testData = await this.fetchTestData(suites, projectName, testPlanId, allowCrossTestPlan);
|
|
198
202
|
logger_1.default.debug(`Fetching Run results for test data, project name: ${projectName}`);
|
|
199
|
-
const
|
|
203
|
+
const isQueryMode = linkedQueryRequest.linkedQueryMode === 'query';
|
|
204
|
+
if (isQueryMode) {
|
|
205
|
+
// Fetch associated items
|
|
206
|
+
await ticketsDataProvider.GetQueryResultsFromWiql(linkedQueryRequest.testAssociatedQuery.wiql.href, true, this.testToAssociatedItemMap);
|
|
207
|
+
}
|
|
208
|
+
const runResults = await this.fetchAllResultDataTestReporter(testData, projectName, selectedFields, isQueryMode);
|
|
200
209
|
logger_1.default.debug(`Aligning steps with iterations for test reporter results`);
|
|
201
210
|
const testReporterData = this.alignStepsWithIterationsTestReporter(testData, runResults, selectedFields, !enableRunTestCaseFilter);
|
|
202
211
|
// Apply filters sequentially based on enabled flags
|
|
203
212
|
let filteredResults = testReporterData;
|
|
213
|
+
//TODO: think of a way to filter out the fields that are not selected from this part of the code and not from the fetchAllResultDataTestReporter function
|
|
214
|
+
if (errorFilterMode !== 'none') {
|
|
215
|
+
const onlyFailedTestCaseCondition = (result) => { var _a, _b, _c; return result && ((_c = (_b = (_a = result.testCase) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.resultMessage) === null || _c === void 0 ? void 0 : _c.includes('Failed')); };
|
|
216
|
+
const onlyFailedTestStepsCondition = (result) => result && result.stepStatus === 'Failed';
|
|
217
|
+
switch (errorFilterMode) {
|
|
218
|
+
case 'onlyTestCaseResult':
|
|
219
|
+
logger_1.default.debug(`Filtering test reporter results for only test case result`);
|
|
220
|
+
filteredResults = filteredResults.filter(onlyFailedTestCaseCondition);
|
|
221
|
+
break;
|
|
222
|
+
case 'onlyTestStepsResult':
|
|
223
|
+
logger_1.default.debug(`Filtering test reporter results for only test steps result`);
|
|
224
|
+
filteredResults = filteredResults.filter(onlyFailedTestStepsCondition);
|
|
225
|
+
break;
|
|
226
|
+
case 'both':
|
|
227
|
+
logger_1.default.debug(`Filtering test reporter results for both test case and test steps result`);
|
|
228
|
+
filteredResults = (_a = filteredResults === null || filteredResults === void 0 ? void 0 : filteredResults.filter(onlyFailedTestCaseCondition)) === null || _a === void 0 ? void 0 : _a.filter(onlyFailedTestStepsCondition);
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
204
234
|
// filter: Test step run status
|
|
205
235
|
if (enableRunStepStatusFilter) {
|
|
206
236
|
filteredResults = filteredResults.filter((result) => !this.isNotRunStep(result));
|
|
@@ -474,8 +504,22 @@ class ResultDataProvider {
|
|
|
474
504
|
const { value: testCases } = await tfs_1.TFSServices.getItemContent(url, this.token);
|
|
475
505
|
return testCases;
|
|
476
506
|
}
|
|
477
|
-
|
|
478
|
-
|
|
507
|
+
/**
|
|
508
|
+
* Fetches result data based on the Work Item Test Reporter.
|
|
509
|
+
*
|
|
510
|
+
* This method retrieves detailed result data for a specific test run and result ID,
|
|
511
|
+
* including related work items, selected fields, and additional processing options.
|
|
512
|
+
*
|
|
513
|
+
* @param projectName - The name of the project containing the test run.
|
|
514
|
+
* @param runId - The unique identifier of the test run.
|
|
515
|
+
* @param resultId - The unique identifier of the test result.
|
|
516
|
+
* @param isTestReporter - (Optional) A flag indicating whether the result data is being fetched for the Test Reporter.
|
|
517
|
+
* @param selectedFields - (Optional) An array of field names to include in the result data.
|
|
518
|
+
* @param isQueryMode - (Optional) A flag indicating whether the result data is being fetched in query mode.
|
|
519
|
+
* @returns A promise that resolves to the fetched result data.
|
|
520
|
+
*/
|
|
521
|
+
async fetchResultDataBasedOnWiBase(projectName, runId, resultId, isTestReporter = false, selectedFields, isQueryMode) {
|
|
522
|
+
var _a, _b;
|
|
479
523
|
try {
|
|
480
524
|
if (runId === '0' || resultId === '0') {
|
|
481
525
|
logger_1.default.warn(`Invalid runId or resultId: ${runId}, ${resultId}`);
|
|
@@ -494,47 +538,24 @@ class ResultDataProvider {
|
|
|
494
538
|
let relatedBugs = [];
|
|
495
539
|
let relatedCRs = [];
|
|
496
540
|
// Process selected fields if provided
|
|
497
|
-
if (
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
541
|
+
if (isTestReporter) {
|
|
542
|
+
// Process related requirements if needed
|
|
543
|
+
if (isQueryMode) {
|
|
544
|
+
this.appendQueryRelations(resultData, relatedRequirements, relatedBugs, relatedCRs);
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
const filteredLinkedFields = (_a = selectedFields === null || selectedFields === void 0 ? void 0 : selectedFields.filter((field) => field.includes('@linked'))) === null || _a === void 0 ? void 0 : _a.map((field) => field.split('@')[0]);
|
|
548
|
+
const selectedLinkedFieldSet = new Set(filteredLinkedFields);
|
|
502
549
|
const { relations } = wiByRevision;
|
|
503
550
|
if (relations) {
|
|
504
|
-
|
|
505
|
-
if (((_b = relation.rel) === null || _b === void 0 ? void 0 : _b.includes('System.LinkTypes')) ||
|
|
506
|
-
((_c = relation.rel) === null || _c === void 0 ? void 0 : _c.includes('Microsoft.VSTS.Common.TestedBy'))) {
|
|
507
|
-
const relatedUrl = relation.url;
|
|
508
|
-
try {
|
|
509
|
-
const wi = await tfs_1.TFSServices.getItemContent(relatedUrl, this.token);
|
|
510
|
-
if (wi.fields['System.WorkItemType'] === 'Requirement') {
|
|
511
|
-
const { id, fields, _links } = wi;
|
|
512
|
-
const requirementTitle = fields['System.Title'];
|
|
513
|
-
const customerFieldKey = Object.keys(fields).find((key) => key.toLowerCase().includes('customer'));
|
|
514
|
-
const customerId = customerFieldKey ? fields[customerFieldKey] : undefined;
|
|
515
|
-
const url = _links.html.href;
|
|
516
|
-
relatedRequirements.push({ id, requirementTitle, customerId, url });
|
|
517
|
-
}
|
|
518
|
-
else if (wi.fields['System.WorkItemType'] === 'Bug') {
|
|
519
|
-
const { id, fields, _links } = wi;
|
|
520
|
-
const bugTitle = fields['System.Title'];
|
|
521
|
-
const url = _links.html.href;
|
|
522
|
-
relatedBugs.push({ id, bugTitle, url });
|
|
523
|
-
}
|
|
524
|
-
else if (wi.fields['System.WorkItemType'] === 'Change Request') {
|
|
525
|
-
const { id, fields, _links } = wi;
|
|
526
|
-
const crTitle = fields['System.Title'];
|
|
527
|
-
const url = _links.html.href;
|
|
528
|
-
relatedCRs.push({ id, crTitle, url });
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
catch (err) {
|
|
532
|
-
logger_1.default.error(`Could not append related work item to test case ${wiByRevision.id}: ${err.message}`);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
551
|
+
await this.appendLinkedRelations(relations, relatedRequirements, relatedBugs, relatedCRs, wiByRevision, selectedLinkedFieldSet);
|
|
536
552
|
}
|
|
537
|
-
|
|
553
|
+
selectedLinkedFieldSet.clear();
|
|
554
|
+
}
|
|
555
|
+
const filteredTestCaseFields = (_b = selectedFields === null || selectedFields === void 0 ? void 0 : selectedFields.filter((field) => field.includes('@testCaseWorkItemField'))) === null || _b === void 0 ? void 0 : _b.map((field) => field.split('@')[0]);
|
|
556
|
+
const selectedFieldSet = new Set(filteredTestCaseFields);
|
|
557
|
+
// Filter fields based on selected field set
|
|
558
|
+
if (selectedFieldSet.size !== 0) {
|
|
538
559
|
filteredFields = Object.keys(wiByRevision.fields)
|
|
539
560
|
.filter((key) => selectedFieldSet.has(key))
|
|
540
561
|
.reduce((obj, key) => {
|
|
@@ -543,6 +564,7 @@ class ResultDataProvider {
|
|
|
543
564
|
return obj;
|
|
544
565
|
}, {});
|
|
545
566
|
}
|
|
567
|
+
selectedFieldSet.clear();
|
|
546
568
|
}
|
|
547
569
|
return Object.assign(Object.assign({}, resultData), { stepsResultXml: wiByRevision.fields['Microsoft.VSTS.TCM.Steps'] || undefined, analysisAttachments, testCaseRevision: resultData.testCaseRevision, filteredFields,
|
|
548
570
|
relatedRequirements,
|
|
@@ -557,6 +579,75 @@ class ResultDataProvider {
|
|
|
557
579
|
return null;
|
|
558
580
|
}
|
|
559
581
|
}
|
|
582
|
+
appendQueryRelations(resultData, relatedRequirements, relatedBugs, relatedCRs) {
|
|
583
|
+
if (this.testToAssociatedItemMap.size !== 0) {
|
|
584
|
+
const relatedItemSet = this.testToAssociatedItemMap.get(Number(resultData.testCase.id));
|
|
585
|
+
if (relatedItemSet) {
|
|
586
|
+
for (const relatedItem of relatedItemSet) {
|
|
587
|
+
const { id, fields, _links } = relatedItem;
|
|
588
|
+
let url = '';
|
|
589
|
+
switch (fields['System.WorkItemType']) {
|
|
590
|
+
case 'Requirement':
|
|
591
|
+
const requirementTitle = fields['System.Title'];
|
|
592
|
+
url = _links.html.href;
|
|
593
|
+
relatedRequirements.push({ id, requirementTitle, url });
|
|
594
|
+
break;
|
|
595
|
+
case 'Bug':
|
|
596
|
+
const bugTitle = fields['System.Title'];
|
|
597
|
+
url = _links.html.href;
|
|
598
|
+
relatedBugs.push({ id, bugTitle, url });
|
|
599
|
+
break;
|
|
600
|
+
case 'Change Request':
|
|
601
|
+
const crTitle = fields['System.Title'];
|
|
602
|
+
url = _links.html.href;
|
|
603
|
+
relatedCRs.push({ id, crTitle, url });
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
async appendLinkedRelations(relations, relatedRequirements, relatedBugs, relatedCRs, wiByRevision, selectedLinkedFieldSet) {
|
|
611
|
+
var _a, _b;
|
|
612
|
+
for (const relation of relations) {
|
|
613
|
+
if (((_a = relation.rel) === null || _a === void 0 ? void 0 : _a.includes('System.LinkTypes')) ||
|
|
614
|
+
((_b = relation.rel) === null || _b === void 0 ? void 0 : _b.includes('Microsoft.VSTS.Common.TestedBy'))) {
|
|
615
|
+
const relatedUrl = relation.url;
|
|
616
|
+
try {
|
|
617
|
+
const wi = await tfs_1.TFSServices.getItemContent(relatedUrl, this.token);
|
|
618
|
+
if (wi.fields['System.State'] === 'Closed') {
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
if (selectedLinkedFieldSet.has('associatedRequirement') &&
|
|
622
|
+
wi.fields['System.WorkItemType'] === 'Requirement') {
|
|
623
|
+
const { id, fields, _links } = wi;
|
|
624
|
+
const requirementTitle = fields['System.Title'];
|
|
625
|
+
const customerFieldKey = Object.keys(fields).find((key) => key.toLowerCase().includes('customer'));
|
|
626
|
+
const customerId = customerFieldKey ? fields[customerFieldKey] : undefined;
|
|
627
|
+
const url = _links.html.href;
|
|
628
|
+
relatedRequirements.push({ id, requirementTitle, customerId, url });
|
|
629
|
+
}
|
|
630
|
+
else if (selectedLinkedFieldSet.has('associatedBug') &&
|
|
631
|
+
wi.fields['System.WorkItemType'] === 'Bug') {
|
|
632
|
+
const { id, fields, _links } = wi;
|
|
633
|
+
const bugTitle = fields['System.Title'];
|
|
634
|
+
const url = _links.html.href;
|
|
635
|
+
relatedBugs.push({ id, bugTitle, url });
|
|
636
|
+
}
|
|
637
|
+
else if (selectedLinkedFieldSet.has('associatedCR') &&
|
|
638
|
+
wi.fields['System.WorkItemType'] === 'Change Request') {
|
|
639
|
+
const { id, fields, _links } = wi;
|
|
640
|
+
const crTitle = fields['System.Title'];
|
|
641
|
+
const url = _links.html.href;
|
|
642
|
+
relatedCRs.push({ id, crTitle, url });
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
catch (err) {
|
|
646
|
+
logger_1.default.error(`Could not append related work item to test case ${wiByRevision.id}: ${err.message}`);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
560
651
|
/**
|
|
561
652
|
* Fetches result data based on the specified work item (WI) details.
|
|
562
653
|
*
|
|
@@ -1216,8 +1307,8 @@ class ResultDataProvider {
|
|
|
1216
1307
|
* @param selectedFields - (Optional) An array of field names to include in the result data.
|
|
1217
1308
|
* @returns A promise that resolves to the fetched result data.
|
|
1218
1309
|
*/
|
|
1219
|
-
async fetchResultDataBasedOnWiTestReporter(projectName, runId, resultId, selectedFields) {
|
|
1220
|
-
return this.fetchResultDataBasedOnWiBase(projectName, runId, resultId, true, selectedFields);
|
|
1310
|
+
async fetchResultDataBasedOnWiTestReporter(projectName, runId, resultId, selectedFields, isQueryMode) {
|
|
1311
|
+
return this.fetchResultDataBasedOnWiBase(projectName, runId, resultId, true, selectedFields, isQueryMode);
|
|
1221
1312
|
}
|
|
1222
1313
|
/**
|
|
1223
1314
|
* Fetches all result data for the test reporter by processing the provided test data.
|
|
@@ -1231,8 +1322,8 @@ class ResultDataProvider {
|
|
|
1231
1322
|
* @param selectedFields - An optional array of field names to include in the result data.
|
|
1232
1323
|
* @returns A promise that resolves to an array of processed result data.
|
|
1233
1324
|
*/
|
|
1234
|
-
async fetchAllResultDataTestReporter(testData, projectName, selectedFields) {
|
|
1235
|
-
return this.fetchAllResultDataBase(testData, projectName, (projectName, testSuiteId, point, selectedFields) => this.fetchResultDataForTestReporter(projectName, testSuiteId, point, selectedFields), [selectedFields]);
|
|
1325
|
+
async fetchAllResultDataTestReporter(testData, projectName, selectedFields, isQueryMode) {
|
|
1326
|
+
return this.fetchAllResultDataBase(testData, projectName, (projectName, testSuiteId, point, selectedFields, isQueryMode) => this.fetchResultDataForTestReporter(projectName, testSuiteId, point, selectedFields, isQueryMode), [selectedFields, isQueryMode]);
|
|
1236
1327
|
}
|
|
1237
1328
|
/**
|
|
1238
1329
|
* Aligns test steps with iterations for the test reporter by processing test data and iterations
|
|
@@ -1240,7 +1331,7 @@ class ResultDataProvider {
|
|
|
1240
1331
|
*
|
|
1241
1332
|
* @param testData - An array of test data objects to be processed.
|
|
1242
1333
|
* @param iterations - An array of iteration objects to align with the test data.
|
|
1243
|
-
* @param selectedFields - An array of selected fields to determine which properties to include in the
|
|
1334
|
+
* @param selectedFields - An array of selected fields to determine which properties to include in the response.
|
|
1244
1335
|
* @returns An array of structured result objects containing aligned test steps and iterations.
|
|
1245
1336
|
*
|
|
1246
1337
|
* The method uses a base alignment function and provides custom logic for:
|
|
@@ -1258,33 +1349,20 @@ class ResultDataProvider {
|
|
|
1258
1349
|
fetchedTestCase.iteration.actionResults != null &&
|
|
1259
1350
|
filteredFields.size > 0,
|
|
1260
1351
|
createResultObject: ({ testItem, point, fetchedTestCase, actionResult, filteredFields = new Set(), }) => {
|
|
1261
|
-
|
|
1262
|
-
const baseObj = {
|
|
1263
|
-
suiteName: testItem.testGroupName,
|
|
1264
|
-
testCase: {
|
|
1352
|
+
const baseObj = Object.assign({ suiteName: testItem.testGroupName, testCase: {
|
|
1265
1353
|
id: point.testCaseId,
|
|
1266
1354
|
title: point.testCaseName,
|
|
1267
1355
|
url: point.testCaseUrl,
|
|
1268
1356
|
result: fetchedTestCase.testCaseResult,
|
|
1269
|
-
comment:
|
|
1270
|
-
},
|
|
1271
|
-
priority: fetchedTestCase.priority,
|
|
1272
|
-
runBy: fetchedTestCase.runBy,
|
|
1273
|
-
activatedBy: fetchedTestCase.activatedBy,
|
|
1274
|
-
assignedTo: fetchedTestCase.assignedTo,
|
|
1275
|
-
subSystem: fetchedTestCase.subSystem,
|
|
1276
|
-
failureType: fetchedTestCase.failureType,
|
|
1277
|
-
automationStatus: fetchedTestCase.automationStatus,
|
|
1278
|
-
executionDate: fetchedTestCase.executionDate,
|
|
1279
|
-
configurationName: fetchedTestCase.configurationName,
|
|
1280
|
-
errorMessage: fetchedTestCase.errorMessage,
|
|
1281
|
-
relatedRequirements: fetchedTestCase.relatedRequirements,
|
|
1282
|
-
relatedBugs: fetchedTestCase.relatedBugs,
|
|
1283
|
-
relatedCRs: fetchedTestCase.relatedCRs,
|
|
1284
|
-
};
|
|
1357
|
+
comment: fetchedTestCase.comment,
|
|
1358
|
+
}, priority: fetchedTestCase.priority, runBy: fetchedTestCase.runBy, activatedBy: fetchedTestCase.activatedBy, failureType: fetchedTestCase.failureType, executionDate: fetchedTestCase.executionDate, configurationName: fetchedTestCase.configurationName, errorMessage: fetchedTestCase.errorMessage, relatedRequirements: fetchedTestCase.relatedRequirements, relatedBugs: fetchedTestCase.relatedBugs, relatedCRs: fetchedTestCase.relatedCRs }, fetchedTestCase.customFields);
|
|
1285
1359
|
// If we have action results, add step-specific properties
|
|
1286
1360
|
if (actionResult) {
|
|
1287
|
-
return Object.assign(Object.assign({}, baseObj), { stepNo:
|
|
1361
|
+
return Object.assign(Object.assign({}, baseObj), { stepNo: filteredFields.has('includeSteps') ||
|
|
1362
|
+
filteredFields.has('stepRunStatus') ||
|
|
1363
|
+
filteredFields.has('testStepComment')
|
|
1364
|
+
? actionResult.stepPosition
|
|
1365
|
+
: undefined, stepAction: filteredFields.has('includeSteps') ? actionResult.action : undefined, stepExpected: filteredFields.has('includeSteps') ? actionResult.expected : undefined, stepStatus: filteredFields.has('stepRunStatus')
|
|
1288
1366
|
? this.convertUnspecifiedRunStatus(actionResult)
|
|
1289
1367
|
: undefined, stepComments: filteredFields.has('testStepComment') ? actionResult.errorMessage : undefined });
|
|
1290
1368
|
}
|
|
@@ -1304,8 +1382,8 @@ class ResultDataProvider {
|
|
|
1304
1382
|
* @returns A promise that resolves to the formatted result data object containing details about the test case,
|
|
1305
1383
|
* test suite, last run, iteration, and other selected fields.
|
|
1306
1384
|
*/
|
|
1307
|
-
async fetchResultDataForTestReporter(projectName, testSuiteId, point, selectedFields) {
|
|
1308
|
-
return this.fetchResultDataBase(projectName, testSuiteId, point, (project, runId, resultId, fields) => this.fetchResultDataBasedOnWiTestReporter(project, runId, resultId, fields), (resultData, testSuiteId, point, selectedFields) => {
|
|
1385
|
+
async fetchResultDataForTestReporter(projectName, testSuiteId, point, selectedFields, isQueryMode) {
|
|
1386
|
+
return this.fetchResultDataBase(projectName, testSuiteId, point, (project, runId, resultId, fields, isQueryMode) => this.fetchResultDataBasedOnWiTestReporter(project, runId, resultId, fields, isQueryMode), (resultData, testSuiteId, point, selectedFields) => {
|
|
1309
1387
|
var _a, _b;
|
|
1310
1388
|
const { lastRunId, lastResultId, configurationName, lastResultDetails } = point;
|
|
1311
1389
|
try {
|
|
@@ -1322,24 +1400,36 @@ class ResultDataProvider {
|
|
|
1322
1400
|
iteration,
|
|
1323
1401
|
testCaseRevision: resultData.testCaseRevision,
|
|
1324
1402
|
resolution: resultData.resolutionState,
|
|
1325
|
-
automationStatus: resultData.filteredFields['Microsoft.VSTS.TCM.AutomationStatus'] || undefined,
|
|
1326
|
-
analysisAttachments: resultData.analysisAttachments,
|
|
1327
1403
|
failureType: undefined,
|
|
1328
|
-
comment: undefined,
|
|
1329
1404
|
priority: undefined,
|
|
1330
|
-
assignedTo: resultData.filteredFields['System.AssignedTo'],
|
|
1331
|
-
subSystem: resultData.filteredFields['Custom.SubSystem'],
|
|
1332
1405
|
runBy: undefined,
|
|
1333
1406
|
executionDate: undefined,
|
|
1334
1407
|
testCaseResult: undefined,
|
|
1408
|
+
comment: undefined,
|
|
1335
1409
|
errorMessage: undefined,
|
|
1336
1410
|
configurationName: undefined,
|
|
1337
|
-
relatedRequirements: undefined,
|
|
1338
|
-
relatedBugs: undefined,
|
|
1339
|
-
relatedCRs: undefined,
|
|
1411
|
+
relatedRequirements: resultData.relatedRequirements || undefined,
|
|
1412
|
+
relatedBugs: resultData.relatedBugs || undefined,
|
|
1413
|
+
relatedCRs: resultData.relatedCRs || undefined,
|
|
1340
1414
|
lastRunResult: undefined,
|
|
1415
|
+
customFields: {}, // Create an object to store custom fields
|
|
1341
1416
|
};
|
|
1342
|
-
|
|
1417
|
+
// Process all custom fields from resultData.filteredFields
|
|
1418
|
+
if (resultData.filteredFields) {
|
|
1419
|
+
for (const [fieldName, fieldValue] of Object.entries(resultData.filteredFields)) {
|
|
1420
|
+
if (fieldValue !== undefined && fieldValue !== null) {
|
|
1421
|
+
// Convert Microsoft.VSTS.TCM.AutomationStatus to automationStatus
|
|
1422
|
+
// or System.AssignedTo to assignedTo
|
|
1423
|
+
const nameParts = fieldName.split('.');
|
|
1424
|
+
let propertyName = nameParts[nameParts.length - 1];
|
|
1425
|
+
// Convert to camelCase (first letter lowercase)
|
|
1426
|
+
propertyName = propertyName.charAt(0).toLowerCase() + propertyName.slice(1);
|
|
1427
|
+
// Add to customFields object
|
|
1428
|
+
resultDataResponse.customFields[propertyName] = fieldValue;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
const filteredFields = (_a = selectedFields === null || selectedFields === void 0 ? void 0 : selectedFields.filter((field) => field.includes('@runResultField'))) === null || _a === void 0 ? void 0 : _a.map((field) => field.split('@')[0]);
|
|
1343
1433
|
if (filteredFields && filteredFields.length > 0) {
|
|
1344
1434
|
for (const field of filteredFields) {
|
|
1345
1435
|
switch (field) {
|
|
@@ -1362,13 +1452,12 @@ class ResultDataProvider {
|
|
|
1362
1452
|
url: `${this.orgUrl}${projectName}/_testManagement/runs?runId=${lastRunId}&_a=resultSummary&resultId=${lastResultId}`,
|
|
1363
1453
|
};
|
|
1364
1454
|
}
|
|
1455
|
+
case 'testCaseComment':
|
|
1456
|
+
resultDataResponse.comment = iteration === null || iteration === void 0 ? void 0 : iteration.comment;
|
|
1365
1457
|
break;
|
|
1366
1458
|
case 'failureType':
|
|
1367
1459
|
resultDataResponse.failureType = resultData.failureType;
|
|
1368
1460
|
break;
|
|
1369
|
-
case 'testCaseComment':
|
|
1370
|
-
resultDataResponse.comment = resultData.comment || undefined;
|
|
1371
|
-
break;
|
|
1372
1461
|
case 'runBy':
|
|
1373
1462
|
const runBy = lastResultDetails.runBy.displayName;
|
|
1374
1463
|
resultDataResponse.runBy = runBy;
|
|
@@ -1379,15 +1468,6 @@ class ResultDataProvider {
|
|
|
1379
1468
|
case 'configurationName':
|
|
1380
1469
|
resultDataResponse.configurationName = configurationName;
|
|
1381
1470
|
break;
|
|
1382
|
-
case 'associatedRequirement':
|
|
1383
|
-
resultDataResponse.relatedRequirements = resultData.relatedRequirements;
|
|
1384
|
-
break;
|
|
1385
|
-
case 'associatedBug':
|
|
1386
|
-
resultDataResponse.relatedBugs = resultData.relatedBugs;
|
|
1387
|
-
break;
|
|
1388
|
-
case 'associatedCR':
|
|
1389
|
-
resultDataResponse.relatedCRs = resultData.relatedCRs;
|
|
1390
|
-
break;
|
|
1391
1471
|
default:
|
|
1392
1472
|
logger_1.default.debug(`Field ${field} not handled`);
|
|
1393
1473
|
break;
|
|
@@ -1401,7 +1481,7 @@ class ResultDataProvider {
|
|
|
1401
1481
|
logger_1.default.error(`Error stack: ${err.stack}`);
|
|
1402
1482
|
return null;
|
|
1403
1483
|
}
|
|
1404
|
-
}, [selectedFields]);
|
|
1484
|
+
}, [selectedFields, isQueryMode]);
|
|
1405
1485
|
}
|
|
1406
1486
|
}
|
|
1407
1487
|
exports.default = ResultDataProvider;
|