@elisra-devops/docgen-data-provider 1.94.0 → 1.95.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elisra-devops/docgen-data-provider",
3
- "version": "1.94.0",
3
+ "version": "1.95.0",
4
4
  "description": "A document generator data provider, aimed to retrive data from azure devops",
5
5
  "repository": {
6
6
  "type": "git",
@@ -410,7 +410,8 @@ export default class ResultDataProvider {
410
410
  projectName,
411
411
  selectedFields,
412
412
  false,
413
- includeAllHistory
413
+ includeAllHistory,
414
+ true
414
415
  );
415
416
 
416
417
  const rows = this.alignStepsWithIterationsFlatReport(
@@ -3086,40 +3087,108 @@ export default class ResultDataProvider {
3086
3087
  * Maps raw test point data to a simplified object.
3087
3088
  */
3088
3089
  private mapTestPoint(testPoint: any, projectName: string): any {
3089
- return {
3090
- testPointId: testPoint.id,
3091
- testCaseId: testPoint.testCaseReference.id,
3092
- testCaseName: testPoint.testCaseReference.name,
3093
- testCaseUrl: `${this.orgUrl}${projectName}/_workitems/edit/${testPoint.testCaseReference.id}`,
3094
- configurationName: testPoint.configuration?.name,
3095
- outcome: testPoint.results?.outcome || 'Not Run',
3096
- testSuite: testPoint.testSuite,
3097
- lastRunId: testPoint.results?.lastTestRunId,
3098
- lastResultId: testPoint.results?.lastResultId,
3099
- lastResultDetails: testPoint.results?.lastResultDetails,
3100
- };
3090
+ const pointAsOfTimestamp = this.resolvePointAsOfTimestamp(testPoint);
3091
+ return this.buildMappedTestPoint(
3092
+ {
3093
+ testPointId: testPoint.id,
3094
+ testCaseId: testPoint.testCaseReference.id,
3095
+ testCaseName: testPoint.testCaseReference.name,
3096
+ configurationName: testPoint.configuration?.name,
3097
+ outcome: testPoint.results?.outcome,
3098
+ testSuite: testPoint.testSuite,
3099
+ lastRunId: testPoint.results?.lastTestRunId,
3100
+ lastResultId: testPoint.results?.lastResultId,
3101
+ lastResultDetails: testPoint.results?.lastResultDetails,
3102
+ },
3103
+ projectName,
3104
+ pointAsOfTimestamp
3105
+ );
3101
3106
  }
3102
3107
 
3103
3108
  /**
3104
3109
  * Maps raw test point data to a simplified object.
3105
3110
  */
3106
3111
  private mapTestPointForCrossPlans(testPoint: any, projectName: string): any {
3107
- return {
3108
- testPointId: testPoint.id,
3109
- testCaseId: testPoint.testCase.id,
3110
- testCaseName: testPoint.testCase.name,
3111
- testCaseUrl: `${this.orgUrl}${projectName}/_workitems/edit/${testPoint.testCase.id}`,
3112
- testSuite: testPoint.testSuite,
3113
- configurationName: testPoint.configuration?.name,
3114
- outcome: testPoint.outcome || 'Not Run',
3115
- lastRunId: testPoint.lastTestRun?.id,
3116
- lastResultId: testPoint.lastResult?.id,
3117
- lastResultDetails: testPoint.lastResultDetails || {
3118
- duration: 0,
3119
- dateCompleted: '0000-00-00T00:00:00.000Z',
3120
- runBy: { displayName: 'No tester', id: '00000000-0000-0000-0000-000000000000' },
3112
+ const pointAsOfTimestamp = this.resolvePointAsOfTimestamp(testPoint);
3113
+ return this.buildMappedTestPoint(
3114
+ {
3115
+ testPointId: testPoint.id,
3116
+ testCaseId: testPoint.testCase.id,
3117
+ testCaseName: testPoint.testCase.name,
3118
+ configurationName: testPoint.configuration?.name,
3119
+ outcome: testPoint.outcome,
3120
+ testSuite: testPoint.testSuite,
3121
+ lastRunId: testPoint.lastTestRun?.id,
3122
+ lastResultId: testPoint.lastResult?.id,
3123
+ lastResultDetails: testPoint.lastResultDetails || {
3124
+ duration: 0,
3125
+ dateCompleted: '0000-00-00T00:00:00.000Z',
3126
+ runBy: { displayName: 'No tester', id: '00000000-0000-0000-0000-000000000000' },
3127
+ },
3121
3128
  },
3129
+ projectName,
3130
+ pointAsOfTimestamp
3131
+ );
3132
+ }
3133
+
3134
+ /**
3135
+ * Resolves a point timestamp that can be used as WIT `asOf` anchor.
3136
+ * Returns an ISO string when a valid date exists, otherwise an empty string.
3137
+ */
3138
+ private resolvePointAsOfTimestamp(testPoint: any): string {
3139
+ const candidates = [
3140
+ testPoint?.lastUpdatedDate,
3141
+ testPoint?.lastUpdatedOn,
3142
+ testPoint?.updatedDate,
3143
+ testPoint?.updatedOn,
3144
+ ];
3145
+
3146
+ for (const candidate of candidates) {
3147
+ const raw = String(candidate || '').trim();
3148
+ if (!raw) continue;
3149
+ const parsed = new Date(raw);
3150
+ if (!Number.isNaN(parsed.getTime())) {
3151
+ return parsed.toISOString();
3152
+ }
3153
+ }
3154
+
3155
+ return '';
3156
+ }
3157
+
3158
+ /**
3159
+ * Builds a normalized test point shape used by downstream result fetch flows.
3160
+ */
3161
+ private buildMappedTestPoint(
3162
+ pointData: {
3163
+ testPointId: any;
3164
+ testCaseId: any;
3165
+ testCaseName: any;
3166
+ configurationName?: any;
3167
+ outcome?: any;
3168
+ testSuite?: any;
3169
+ lastRunId?: any;
3170
+ lastResultId?: any;
3171
+ lastResultDetails?: any;
3172
+ },
3173
+ projectName: string,
3174
+ pointAsOfTimestamp: string
3175
+ ): any {
3176
+ const mappedPoint: any = {
3177
+ testPointId: pointData.testPointId,
3178
+ testCaseId: pointData.testCaseId,
3179
+ testCaseName: pointData.testCaseName,
3180
+ testCaseUrl: `${this.orgUrl}${projectName}/_workitems/edit/${pointData.testCaseId}`,
3181
+ configurationName: pointData.configurationName,
3182
+ outcome: pointData.outcome || 'Not Run',
3183
+ testSuite: pointData.testSuite,
3184
+ lastRunId: pointData.lastRunId,
3185
+ lastResultId: pointData.lastResultId,
3186
+ lastResultDetails: pointData.lastResultDetails,
3122
3187
  };
3188
+ if (pointAsOfTimestamp) {
3189
+ mappedPoint.pointAsOfTimestamp = pointAsOfTimestamp;
3190
+ }
3191
+ return mappedPoint;
3123
3192
  }
3124
3193
 
3125
3194
  // Helper method to get all test points for a test case
@@ -3186,6 +3255,9 @@ export default class ResultDataProvider {
3186
3255
  return fields;
3187
3256
  }
3188
3257
 
3258
+ /**
3259
+ * Reads a field value by reference name with case-insensitive key matching.
3260
+ */
3189
3261
  private getFieldValueByName(fields: Record<string, any>, fieldName: string): any {
3190
3262
  if (!fields || typeof fields !== 'object') return undefined;
3191
3263
  if (Object.prototype.hasOwnProperty.call(fields, fieldName)) {
@@ -3277,12 +3349,25 @@ export default class ResultDataProvider {
3277
3349
 
3278
3350
  const expandParam = expandAll ? '?$expand=all' : '';
3279
3351
  const url = `${this.orgUrl}${projectName}/_apis/wit/workItems/${id}/revisions/${rev}${expandParam}`;
3280
- try {
3281
- return await TFSServices.getItemContent(url, this.token);
3282
- } catch (error: any) {
3283
- logger.warn(`Failed to fetch work item ${id} by revision ${rev}: ${error?.message || error}`);
3284
- return null;
3352
+ return this.fetchWorkItemByUrl(url, `work item ${id} by revision ${rev}`);
3353
+ }
3354
+
3355
+ private async fetchWorkItemByAsOf(
3356
+ projectName: string,
3357
+ workItemId: number,
3358
+ asOfTimestamp: string,
3359
+ expandAll: boolean = false
3360
+ ): Promise<any | null> {
3361
+ const id = Number(workItemId || 0);
3362
+ const parsedAsOf = new Date(String(asOfTimestamp || '').trim());
3363
+ if (!Number.isFinite(id) || id <= 0 || Number.isNaN(parsedAsOf.getTime())) return null;
3364
+
3365
+ const query: string[] = [`asOf=${encodeURIComponent(parsedAsOf.toISOString())}`];
3366
+ if (expandAll) {
3367
+ query.push(`$expand=all`);
3285
3368
  }
3369
+ const url = `${this.orgUrl}${projectName}/_apis/wit/workItems/${id}?${query.join('&')}`;
3370
+ return this.fetchWorkItemByUrl(url, `work item ${id} by asOf ${parsedAsOf.toISOString()}`);
3286
3371
  }
3287
3372
 
3288
3373
  private async fetchWorkItemLatest(
@@ -3295,14 +3380,56 @@ export default class ResultDataProvider {
3295
3380
 
3296
3381
  const expandParam = expandAll ? '?$expand=all' : '';
3297
3382
  const url = `${this.orgUrl}${projectName}/_apis/wit/workItems/${id}${expandParam}`;
3383
+ return this.fetchWorkItemByUrl(url, `latest work item ${id}`);
3384
+ }
3385
+
3386
+ /**
3387
+ * Executes a work-item GET by URL and applies consistent warning/error handling.
3388
+ */
3389
+ private async fetchWorkItemByUrl(url: string, failureContext: string): Promise<any | null> {
3298
3390
  try {
3299
3391
  return await TFSServices.getItemContent(url, this.token);
3300
3392
  } catch (error: any) {
3301
- logger.warn(`Failed to fetch latest work item ${id}: ${error?.message || error}`);
3393
+ logger.warn(`Failed to fetch ${failureContext}: ${error?.message || error}`);
3302
3394
  return null;
3303
3395
  }
3304
3396
  }
3305
3397
 
3398
+ /**
3399
+ * Resolves runless test case data using ordered fallbacks:
3400
+ * 1) point-based `asOf` snapshot, 2) explicit revision, 3) suite payload snapshot, 4) latest WI.
3401
+ */
3402
+ private async resolveRunlessTestCaseData(
3403
+ projectName: string,
3404
+ testCaseId: number,
3405
+ suiteTestCaseRevision: number,
3406
+ pointAsOfTimestamp: string,
3407
+ fallbackSnapshot: any,
3408
+ expandAll: boolean
3409
+ ): Promise<any | null> {
3410
+ if (pointAsOfTimestamp) {
3411
+ const asOfSnapshot = await this.fetchWorkItemByAsOf(
3412
+ projectName,
3413
+ testCaseId,
3414
+ pointAsOfTimestamp,
3415
+ expandAll
3416
+ );
3417
+ if (asOfSnapshot) return asOfSnapshot;
3418
+ }
3419
+
3420
+ const revisionSnapshot = await this.fetchWorkItemByRevision(
3421
+ projectName,
3422
+ testCaseId,
3423
+ suiteTestCaseRevision,
3424
+ expandAll
3425
+ );
3426
+ if (revisionSnapshot) return revisionSnapshot;
3427
+
3428
+ if (fallbackSnapshot) return fallbackSnapshot;
3429
+
3430
+ return this.fetchWorkItemLatest(projectName, testCaseId, expandAll);
3431
+ }
3432
+
3306
3433
  /**
3307
3434
  * Fetches result data based on the Work Item Test Reporter.
3308
3435
  *
@@ -3325,7 +3452,8 @@ export default class ResultDataProvider {
3325
3452
  selectedFields?: string[],
3326
3453
  isQueryMode?: boolean,
3327
3454
  point?: any,
3328
- includeAllHistory: boolean = false
3455
+ includeAllHistory: boolean = false,
3456
+ useRunlessAsOf: boolean = false
3329
3457
  ): Promise<any> {
3330
3458
  try {
3331
3459
  let filteredFields: any = {};
@@ -3342,23 +3470,22 @@ export default class ResultDataProvider {
3342
3470
  point?.testCaseId || suiteTestCaseItem?.workItem?.id || suiteTestCaseItem?.testCaseId || 0
3343
3471
  );
3344
3472
  const suiteTestCaseRevision = this.resolveSuiteTestCaseRevision(suiteTestCaseItem);
3473
+ const pointAsOfTimestamp = useRunlessAsOf
3474
+ ? String(point?.pointAsOfTimestamp || '').trim()
3475
+ : '';
3345
3476
  const fallbackSnapshot = this.buildWorkItemSnapshotFromSuiteTestCase(
3346
3477
  suiteTestCaseItem,
3347
3478
  testCaseId,
3348
3479
  String(point?.testCaseName || '')
3349
3480
  );
3350
- let testCaseData = await this.fetchWorkItemByRevision(
3481
+ const testCaseData = await this.resolveRunlessTestCaseData(
3351
3482
  projectName,
3352
3483
  testCaseId,
3353
3484
  suiteTestCaseRevision,
3485
+ pointAsOfTimestamp,
3486
+ fallbackSnapshot,
3354
3487
  isTestReporter
3355
3488
  );
3356
- if (!testCaseData) {
3357
- testCaseData = fallbackSnapshot;
3358
- }
3359
- if (!testCaseData) {
3360
- testCaseData = await this.fetchWorkItemLatest(projectName, testCaseId, isTestReporter);
3361
- }
3362
3489
  if (!testCaseData) {
3363
3490
  logger.warn(`Could not resolve test case ${point.testCaseId} for runless point fallback.`);
3364
3491
  return null;
@@ -4992,7 +5119,8 @@ export default class ResultDataProvider {
4992
5119
  selectedFields?: string[],
4993
5120
  isQueryMode?: boolean,
4994
5121
  point?: any,
4995
- includeAllHistory: boolean = false
5122
+ includeAllHistory: boolean = false,
5123
+ useRunlessAsOf: boolean = false
4996
5124
  ): Promise<any> {
4997
5125
  return this.fetchResultDataBasedOnWiBase(
4998
5126
  projectName,
@@ -5002,7 +5130,8 @@ export default class ResultDataProvider {
5002
5130
  selectedFields,
5003
5131
  isQueryMode,
5004
5132
  point,
5005
- includeAllHistory
5133
+ includeAllHistory,
5134
+ useRunlessAsOf
5006
5135
  );
5007
5136
  }
5008
5137
 
@@ -5023,22 +5152,24 @@ export default class ResultDataProvider {
5023
5152
  projectName: string,
5024
5153
  selectedFields?: string[],
5025
5154
  isQueryMode?: boolean,
5026
- includeAllHistory: boolean = false
5155
+ includeAllHistory: boolean = false,
5156
+ useRunlessAsOf: boolean = false
5027
5157
  ): Promise<any[]> {
5028
5158
  return this.fetchAllResultDataBase(
5029
5159
  testData,
5030
5160
  projectName,
5031
5161
  true,
5032
- (projectName, testSuiteId, point, selectedFields, isQueryMode, includeAllHistory) =>
5162
+ (projectName, testSuiteId, point, selectedFields, isQueryMode, includeAllHistory, useRunlessAsOf) =>
5033
5163
  this.fetchResultDataForTestReporter(
5034
5164
  projectName,
5035
5165
  testSuiteId,
5036
5166
  point,
5037
5167
  selectedFields,
5038
5168
  isQueryMode,
5039
- includeAllHistory
5169
+ includeAllHistory,
5170
+ useRunlessAsOf
5040
5171
  ),
5041
- [selectedFields, isQueryMode, includeAllHistory]
5172
+ [selectedFields, isQueryMode, includeAllHistory, useRunlessAsOf]
5042
5173
  );
5043
5174
  }
5044
5175
 
@@ -5196,13 +5327,14 @@ export default class ResultDataProvider {
5196
5327
  point: any,
5197
5328
  selectedFields?: string[],
5198
5329
  isQueryMode?: boolean,
5199
- includeAllHistory: boolean = false
5330
+ includeAllHistory: boolean = false,
5331
+ useRunlessAsOf: boolean = false
5200
5332
  ) {
5201
5333
  return this.fetchResultDataBase(
5202
5334
  projectName,
5203
5335
  testSuiteId,
5204
5336
  point,
5205
- (project, runId, resultId, fields, isQueryMode, point, includeAllHistory) =>
5337
+ (project, runId, resultId, fields, isQueryMode, point, includeAllHistory, useRunlessAsOf) =>
5206
5338
  this.fetchResultDataBasedOnWiTestReporter(
5207
5339
  project,
5208
5340
  runId,
@@ -5210,7 +5342,8 @@ export default class ResultDataProvider {
5210
5342
  fields,
5211
5343
  isQueryMode,
5212
5344
  point,
5213
- includeAllHistory
5345
+ includeAllHistory,
5346
+ useRunlessAsOf
5214
5347
  ),
5215
5348
  (resultData, testSuiteId, point, selectedFields) => {
5216
5349
  const { lastRunId, lastResultId, configurationName, lastResultDetails } = point;
@@ -5330,7 +5463,7 @@ export default class ResultDataProvider {
5330
5463
  return null;
5331
5464
  }
5332
5465
  },
5333
- [selectedFields, isQueryMode, point, includeAllHistory]
5466
+ [selectedFields, isQueryMode, point, includeAllHistory, useRunlessAsOf]
5334
5467
  );
5335
5468
  }
5336
5469
 
@@ -333,6 +333,21 @@ describe('ResultDataProvider', () => {
333
333
  testCaseUrl: 'https://dev.azure.com/organization/test-project/_workitems/edit/1',
334
334
  });
335
335
  });
336
+
337
+ it('should include pointAsOfTimestamp when lastUpdatedDate is available', () => {
338
+ const testPoint = {
339
+ testCaseReference: { id: 1, name: 'Test Case 1' },
340
+ lastUpdatedDate: '2025-01-01T12:34:56Z',
341
+ };
342
+
343
+ const result = (resultDataProvider as any).mapTestPoint(testPoint, mockProjectName);
344
+
345
+ expect(result).toEqual(
346
+ expect.objectContaining({
347
+ pointAsOfTimestamp: '2025-01-01T12:34:56.000Z',
348
+ })
349
+ );
350
+ });
336
351
  });
337
352
 
338
353
  describe('calculateGroupResultSummary', () => {
@@ -3890,7 +3905,9 @@ describe('ResultDataProvider', () => {
3890
3905
  true,
3891
3906
  [],
3892
3907
  false,
3893
- point
3908
+ point,
3909
+ false,
3910
+ true
3894
3911
  );
3895
3912
 
3896
3913
  expect(TFSServices.getItemContent).toHaveBeenCalledWith(
@@ -3902,7 +3919,150 @@ describe('ResultDataProvider', () => {
3902
3919
  expect(res).toEqual(expect.objectContaining({ testCaseRevision: 9 }));
3903
3920
  });
3904
3921
 
3922
+ it('should ignore point asOf timestamp when runless asOf mode is disabled', async () => {
3923
+ const point = {
3924
+ testCaseId: '123',
3925
+ testCaseName: 'TC 123',
3926
+ outcome: 'passed',
3927
+ pointAsOfTimestamp: '2025-01-01T12:34:56Z',
3928
+ suiteTestCase: {
3929
+ workItem: {
3930
+ id: 123,
3931
+ rev: 9,
3932
+ workItemFields: [{ key: 'Microsoft.VSTS.TCM.Steps', value: '<steps></steps>' }],
3933
+ },
3934
+ },
3935
+ testSuite: { id: '1', name: 'Suite' },
3936
+ };
3937
+
3938
+ (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce({
3939
+ id: 123,
3940
+ rev: 9,
3941
+ fields: {
3942
+ 'System.State': 'Active',
3943
+ 'System.CreatedDate': '2024-01-01T00:00:00',
3944
+ 'Microsoft.VSTS.TCM.Priority': 1,
3945
+ 'System.Title': 'Title 123',
3946
+ 'Microsoft.VSTS.TCM.Steps': '<steps></steps>',
3947
+ },
3948
+ relations: null,
3949
+ });
3950
+
3951
+ const res = await (resultDataProvider as any).fetchResultDataBasedOnWiBase(
3952
+ mockProjectName,
3953
+ '0',
3954
+ '0',
3955
+ true,
3956
+ [],
3957
+ false,
3958
+ point
3959
+ );
3960
+
3961
+ const calledUrls = (TFSServices.getItemContent as jest.Mock).mock.calls.map((args: any[]) => String(args[0]));
3962
+ expect(calledUrls.some((url: string) => url.includes('/_apis/wit/workItems/123?asOf='))).toBe(false);
3963
+ expect(calledUrls.some((url: string) => url.includes('/_apis/wit/workItems/123/revisions/9'))).toBe(true);
3964
+ expect(res).toEqual(expect.objectContaining({ testCaseRevision: 9 }));
3965
+ });
3966
+
3967
+ it('should fetch no-run test case by asOf timestamp when pointAsOfTimestamp is available', async () => {
3968
+ (TFSServices.getItemContent as jest.Mock).mockReset();
3969
+ const point = {
3970
+ testCaseId: '123',
3971
+ testCaseName: 'TC 123',
3972
+ outcome: 'passed',
3973
+ pointAsOfTimestamp: '2025-01-01T12:34:56Z',
3974
+ suiteTestCase: {
3975
+ workItem: {
3976
+ id: 123,
3977
+ rev: 9,
3978
+ workItemFields: [{ key: 'Microsoft.VSTS.TCM.Steps', value: '<steps></steps>' }],
3979
+ },
3980
+ },
3981
+ testSuite: { id: '1', name: 'Suite' },
3982
+ };
3983
+
3984
+ (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce({
3985
+ id: 123,
3986
+ rev: 6,
3987
+ fields: {
3988
+ 'System.State': 'Active',
3989
+ 'System.CreatedDate': '2024-01-01T00:00:00',
3990
+ 'Microsoft.VSTS.TCM.Priority': 1,
3991
+ 'System.Title': 'Title 123',
3992
+ 'Microsoft.VSTS.TCM.Steps': '<steps></steps>',
3993
+ },
3994
+ relations: null,
3995
+ });
3996
+
3997
+ const res = await (resultDataProvider as any).fetchResultDataBasedOnWiBase(
3998
+ mockProjectName,
3999
+ '0',
4000
+ '0',
4001
+ true,
4002
+ [],
4003
+ false,
4004
+ point,
4005
+ false,
4006
+ true
4007
+ );
4008
+
4009
+ const calledUrls = (TFSServices.getItemContent as jest.Mock).mock.calls.map((args: any[]) => String(args[0]));
4010
+ expect(calledUrls.some((url: string) => url.includes('/_apis/wit/workItems/123?asOf='))).toBe(true);
4011
+ expect(calledUrls.some((url: string) => url.includes('/revisions/9'))).toBe(false);
4012
+ expect(res).toEqual(expect.objectContaining({ testCaseRevision: 6 }));
4013
+ });
4014
+
4015
+ it('should fallback to suite revision when asOf fetch fails', async () => {
4016
+ (TFSServices.getItemContent as jest.Mock).mockReset();
4017
+ const point = {
4018
+ testCaseId: '456',
4019
+ testCaseName: 'TC 456',
4020
+ outcome: 'Not Run',
4021
+ pointAsOfTimestamp: '2025-02-01T00:00:00Z',
4022
+ suiteTestCase: {
4023
+ workItem: {
4024
+ id: 456,
4025
+ workItemFields: [{ key: 'System.Rev', value: '11' }],
4026
+ },
4027
+ },
4028
+ testSuite: { id: '1', name: 'Suite' },
4029
+ };
4030
+
4031
+ (TFSServices.getItemContent as jest.Mock)
4032
+ .mockRejectedValueOnce(new Error('asOf failed'))
4033
+ .mockResolvedValueOnce({
4034
+ id: 456,
4035
+ rev: 11,
4036
+ fields: {
4037
+ 'System.State': 'Active',
4038
+ 'System.CreatedDate': '2024-01-01T00:00:00',
4039
+ 'Microsoft.VSTS.TCM.Priority': 1,
4040
+ 'System.Title': 'Title 456',
4041
+ 'Microsoft.VSTS.TCM.Steps': '<steps></steps>',
4042
+ },
4043
+ relations: [],
4044
+ });
4045
+
4046
+ const res = await (resultDataProvider as any).fetchResultDataBasedOnWiBase(
4047
+ mockProjectName,
4048
+ '0',
4049
+ '0',
4050
+ true,
4051
+ [],
4052
+ false,
4053
+ point,
4054
+ false,
4055
+ true
4056
+ );
4057
+
4058
+ const calledUrls = (TFSServices.getItemContent as jest.Mock).mock.calls.map((args: any[]) => String(args[0]));
4059
+ expect(calledUrls.some((url: string) => url.includes('/_apis/wit/workItems/456?asOf='))).toBe(true);
4060
+ expect(calledUrls.some((url: string) => url.includes('/_apis/wit/workItems/456/revisions/11'))).toBe(true);
4061
+ expect(res).toEqual(expect.objectContaining({ testCaseRevision: 11 }));
4062
+ });
4063
+
3905
4064
  it('should resolve no-run revision from System.Rev in suite test-case fields', async () => {
4065
+ (TFSServices.getItemContent as jest.Mock).mockReset();
3906
4066
  const point = {
3907
4067
  testCaseId: '321',
3908
4068
  testCaseName: 'TC 321',