@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.
@@ -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 result.
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 runResults = await this.fetchAllResultDataTestReporter(testData, projectName, selectedFields);
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
- async fetchResultDataBasedOnWiBase(projectName, runId, resultId, isTestReporter = false, selectedFields) {
478
- var _a, _b, _c;
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 ((selectedFields === null || selectedFields === void 0 ? void 0 : selectedFields.length) && isTestReporter) {
498
- const filtered = (_a = selectedFields === null || selectedFields === void 0 ? void 0 : selectedFields.filter((field) => field.includes('@testCaseWorkItemField'))) === null || _a === void 0 ? void 0 : _a.map((field) => field.split('@')[0]);
499
- const selectedFieldSet = new Set(filtered);
500
- if (selectedFieldSet.size !== 0) {
501
- // Process related requirements if needed
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
- for (const relation of relations) {
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
- // Filter fields based on selected field set
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 result.
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
- var _a;
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: (_a = fetchedTestCase.iteration) === null || _a === void 0 ? void 0 : _a.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: actionResult.stepPosition, stepAction: filteredFields.has('includeSteps') ? actionResult.action : undefined, stepExpected: filteredFields.has('includeSteps') ? actionResult.expected : undefined, stepStatus: filteredFields.has('stepRunStatus')
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
- const filteredFields = (_a = selectedFields === null || selectedFields === void 0 ? void 0 : selectedFields.filter((field) => field.includes('@runResultField') || field.includes('@linked'))) === null || _a === void 0 ? void 0 : _a.map((field) => field.split('@')[0]);
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;