@elisra-devops/docgen-data-provider 1.29.3 → 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,29 +1349,13 @@ class ResultDataProvider {
1258
1349
  fetchedTestCase.iteration.actionResults != null &&
1259
1350
  filteredFields.size > 0,
1260
1351
  createResultObject: ({ testItem, point, fetchedTestCase, actionResult, filteredFields = new Set(), }) => {
1261
- const baseObj = {
1262
- suiteName: testItem.testGroupName,
1263
- testCase: {
1352
+ const baseObj = Object.assign({ suiteName: testItem.testGroupName, testCase: {
1264
1353
  id: point.testCaseId,
1265
1354
  title: point.testCaseName,
1266
1355
  url: point.testCaseUrl,
1267
1356
  result: fetchedTestCase.testCaseResult,
1268
1357
  comment: fetchedTestCase.comment,
1269
- },
1270
- priority: fetchedTestCase.priority,
1271
- runBy: fetchedTestCase.runBy,
1272
- activatedBy: fetchedTestCase.activatedBy,
1273
- assignedTo: fetchedTestCase.assignedTo,
1274
- subSystem: fetchedTestCase.subSystem,
1275
- failureType: fetchedTestCase.failureType,
1276
- automationStatus: fetchedTestCase.automationStatus,
1277
- executionDate: fetchedTestCase.executionDate,
1278
- configurationName: fetchedTestCase.configurationName,
1279
- errorMessage: fetchedTestCase.errorMessage,
1280
- relatedRequirements: fetchedTestCase.relatedRequirements,
1281
- relatedBugs: fetchedTestCase.relatedBugs,
1282
- relatedCRs: fetchedTestCase.relatedCRs,
1283
- };
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);
1284
1359
  // If we have action results, add step-specific properties
1285
1360
  if (actionResult) {
1286
1361
  return Object.assign(Object.assign({}, baseObj), { stepNo: filteredFields.has('includeSteps') ||
@@ -1307,8 +1382,8 @@ class ResultDataProvider {
1307
1382
  * @returns A promise that resolves to the formatted result data object containing details about the test case,
1308
1383
  * test suite, last run, iteration, and other selected fields.
1309
1384
  */
1310
- async fetchResultDataForTestReporter(projectName, testSuiteId, point, selectedFields) {
1311
- 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) => {
1312
1387
  var _a, _b;
1313
1388
  const { lastRunId, lastResultId, configurationName, lastResultDetails } = point;
1314
1389
  try {
@@ -1325,24 +1400,36 @@ class ResultDataProvider {
1325
1400
  iteration,
1326
1401
  testCaseRevision: resultData.testCaseRevision,
1327
1402
  resolution: resultData.resolutionState,
1328
- automationStatus: resultData.filteredFields['Microsoft.VSTS.TCM.AutomationStatus'] || undefined,
1329
- analysisAttachments: resultData.analysisAttachments,
1330
1403
  failureType: undefined,
1331
1404
  priority: undefined,
1332
- assignedTo: resultData.filteredFields['System.AssignedTo'],
1333
- subSystem: resultData.filteredFields['Custom.SubSystem'],
1334
1405
  runBy: undefined,
1335
1406
  executionDate: undefined,
1336
1407
  testCaseResult: undefined,
1337
1408
  comment: undefined,
1338
1409
  errorMessage: undefined,
1339
1410
  configurationName: undefined,
1340
- relatedRequirements: undefined,
1341
- relatedBugs: undefined,
1342
- relatedCRs: undefined,
1411
+ relatedRequirements: resultData.relatedRequirements || undefined,
1412
+ relatedBugs: resultData.relatedBugs || undefined,
1413
+ relatedCRs: resultData.relatedCRs || undefined,
1343
1414
  lastRunResult: undefined,
1415
+ customFields: {}, // Create an object to store custom fields
1344
1416
  };
1345
- 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]);
1346
1433
  if (filteredFields && filteredFields.length > 0) {
1347
1434
  for (const field of filteredFields) {
1348
1435
  switch (field) {
@@ -1381,15 +1468,6 @@ class ResultDataProvider {
1381
1468
  case 'configurationName':
1382
1469
  resultDataResponse.configurationName = configurationName;
1383
1470
  break;
1384
- case 'associatedRequirement':
1385
- resultDataResponse.relatedRequirements = resultData.relatedRequirements;
1386
- break;
1387
- case 'associatedBug':
1388
- resultDataResponse.relatedBugs = resultData.relatedBugs;
1389
- break;
1390
- case 'associatedCR':
1391
- resultDataResponse.relatedCRs = resultData.relatedCRs;
1392
- break;
1393
1471
  default:
1394
1472
  logger_1.default.debug(`Field ${field} not handled`);
1395
1473
  break;
@@ -1403,7 +1481,7 @@ class ResultDataProvider {
1403
1481
  logger_1.default.error(`Error stack: ${err.stack}`);
1404
1482
  return null;
1405
1483
  }
1406
- }, [selectedFields]);
1484
+ }, [selectedFields, isQueryMode]);
1407
1485
  }
1408
1486
  }
1409
1487
  exports.default = ResultDataProvider;