@elisra-devops/docgen-data-provider 1.63.13 → 1.67.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.
Files changed (91) hide show
  1. package/.github/workflows/ci.yml +26 -9
  2. package/.github/workflows/release.yml +9 -10
  3. package/bin/helpers/tfs.d.ts +3 -0
  4. package/bin/helpers/tfs.js +44 -7
  5. package/bin/helpers/tfs.js.map +1 -1
  6. package/bin/modules/GitDataProvider.d.ts +10 -0
  7. package/bin/modules/GitDataProvider.js +10 -0
  8. package/bin/modules/GitDataProvider.js.map +1 -1
  9. package/bin/modules/TestDataProvider.js +0 -1
  10. package/bin/modules/TestDataProvider.js.map +1 -1
  11. package/bin/modules/TicketsDataProvider.d.ts +63 -24
  12. package/bin/modules/TicketsDataProvider.js +216 -114
  13. package/bin/modules/TicketsDataProvider.js.map +1 -1
  14. package/bin/tests/helpers/helper.test.js +279 -0
  15. package/bin/tests/helpers/helper.test.js.map +1 -0
  16. package/bin/{helpers/test → tests/helpers}/tfs.test.js +312 -49
  17. package/bin/tests/helpers/tfs.test.js.map +1 -0
  18. package/bin/tests/index.test.js +25 -0
  19. package/bin/tests/index.test.js.map +1 -0
  20. package/bin/tests/models/tfs-data.test.js +160 -0
  21. package/bin/tests/models/tfs-data.test.js.map +1 -0
  22. package/bin/{modules/test → tests/modules}/JfrogDataProvider.test.js +9 -9
  23. package/bin/tests/modules/JfrogDataProvider.test.js.map +1 -0
  24. package/bin/tests/modules/ResultDataProvider.test.js +1942 -0
  25. package/bin/tests/modules/ResultDataProvider.test.js.map +1 -0
  26. package/bin/tests/modules/gitDataProvider.test.js +1888 -0
  27. package/bin/tests/modules/gitDataProvider.test.js.map +1 -0
  28. package/bin/{modules/test → tests/modules}/managmentDataProvider.test.js +13 -1
  29. package/bin/tests/modules/managmentDataProvider.test.js.map +1 -0
  30. package/bin/tests/modules/pipelineDataProvider.test.d.ts +1 -0
  31. package/bin/tests/modules/pipelineDataProvider.test.js +783 -0
  32. package/bin/tests/modules/pipelineDataProvider.test.js.map +1 -0
  33. package/bin/tests/modules/testDataProvider.test.d.ts +1 -0
  34. package/bin/tests/modules/testDataProvider.test.js +717 -0
  35. package/bin/tests/modules/testDataProvider.test.js.map +1 -0
  36. package/bin/tests/modules/ticketsDataProvider.test.d.ts +1 -0
  37. package/bin/tests/modules/ticketsDataProvider.test.js +1681 -0
  38. package/bin/tests/modules/ticketsDataProvider.test.js.map +1 -0
  39. package/bin/tests/utils/DataProviderUtils.test.d.ts +1 -0
  40. package/bin/tests/utils/DataProviderUtils.test.js +61 -0
  41. package/bin/tests/utils/DataProviderUtils.test.js.map +1 -0
  42. package/bin/tests/utils/testStepParserHelper.test.d.ts +1 -0
  43. package/bin/tests/utils/testStepParserHelper.test.js +359 -0
  44. package/bin/tests/utils/testStepParserHelper.test.js.map +1 -0
  45. package/package.json +9 -1
  46. package/src/helpers/tfs.ts +51 -7
  47. package/src/modules/GitDataProvider.ts +10 -0
  48. package/src/modules/TestDataProvider.ts +0 -1
  49. package/src/modules/TicketsDataProvider.ts +298 -141
  50. package/src/tests/helpers/helper.test.ts +337 -0
  51. package/src/tests/helpers/tfs.test.ts +1092 -0
  52. package/src/tests/index.test.ts +28 -0
  53. package/src/tests/models/tfs-data.test.ts +203 -0
  54. package/src/tests/modules/JfrogDataProvider.test.ts +167 -0
  55. package/src/tests/modules/ResultDataProvider.test.ts +2571 -0
  56. package/src/tests/modules/gitDataProvider.test.ts +2628 -0
  57. package/src/{modules/test → tests/modules}/managmentDataProvider.test.ts +33 -1
  58. package/src/tests/modules/pipelineDataProvider.test.ts +1038 -0
  59. package/src/tests/modules/testDataProvider.test.ts +1046 -0
  60. package/src/tests/modules/ticketsDataProvider.test.ts +2204 -0
  61. package/src/tests/utils/DataProviderUtils.test.ts +76 -0
  62. package/src/tests/utils/testStepParserHelper.test.ts +437 -0
  63. package/tsconfig.json +1 -0
  64. package/bin/helpers/test/tfs.test.js.map +0 -1
  65. package/bin/modules/test/JfrogDataProvider.test.js.map +0 -1
  66. package/bin/modules/test/ResultDataProvider.test.js +0 -444
  67. package/bin/modules/test/ResultDataProvider.test.js.map +0 -1
  68. package/bin/modules/test/gitDataProvider.test.js +0 -428
  69. package/bin/modules/test/gitDataProvider.test.js.map +0 -1
  70. package/bin/modules/test/managmentDataProvider.test.js.map +0 -1
  71. package/bin/modules/test/pipelineDataProvider.test.js +0 -237
  72. package/bin/modules/test/pipelineDataProvider.test.js.map +0 -1
  73. package/bin/modules/test/testDataProvider.test.js +0 -234
  74. package/bin/modules/test/testDataProvider.test.js.map +0 -1
  75. package/bin/modules/test/ticketsDataProvider.test.js +0 -348
  76. package/bin/modules/test/ticketsDataProvider.test.js.map +0 -1
  77. package/src/helpers/test/tfs.test.ts +0 -748
  78. package/src/modules/test/JfrogDataProvider.test.ts +0 -171
  79. package/src/modules/test/ResultDataProvider.test.ts +0 -542
  80. package/src/modules/test/gitDataProvider.test.ts +0 -645
  81. package/src/modules/test/pipelineDataProvider.test.ts +0 -292
  82. package/src/modules/test/testDataProvider.test.ts +0 -318
  83. package/src/modules/test/ticketsDataProvider.test.ts +0 -462
  84. /package/bin/{helpers/test/tfs.test.d.ts → tests/helpers/helper.test.d.ts} +0 -0
  85. /package/bin/{modules/test/JfrogDataProvider.test.d.ts → tests/helpers/tfs.test.d.ts} +0 -0
  86. /package/bin/{modules/test/ResultDataProvider.test.d.ts → tests/index.test.d.ts} +0 -0
  87. /package/bin/{modules/test/gitDataProvider.test.d.ts → tests/models/tfs-data.test.d.ts} +0 -0
  88. /package/bin/{modules/test/managmentDataProvider.test.d.ts → tests/modules/JfrogDataProvider.test.d.ts} +0 -0
  89. /package/bin/{modules/test/pipelineDataProvider.test.d.ts → tests/modules/ResultDataProvider.test.d.ts} +0 -0
  90. /package/bin/{modules/test/testDataProvider.test.d.ts → tests/modules/gitDataProvider.test.d.ts} +0 -0
  91. /package/bin/{modules/test/ticketsDataProvider.test.d.ts → tests/modules/managmentDataProvider.test.d.ts} +0 -0
@@ -1,462 +0,0 @@
1
- import { TFSServices } from '../../helpers/tfs';
2
- import TicketsDataProvider from '../TicketsDataProvider';
3
- import logger from '../../utils/logger';
4
- import { Helper } from '../../helpers/helper';
5
- import { QueryType } from '../../models/tfs-data';
6
-
7
- jest.mock('../../helpers/tfs');
8
- jest.mock('../../utils/logger');
9
- jest.mock('../../helpers/helper');
10
-
11
- describe('TicketsDataProvider', () => {
12
- let ticketsDataProvider: TicketsDataProvider;
13
- const mockOrgUrl = 'https://dev.azure.com/organization/';
14
- const mockToken = 'mock-token';
15
- const mockProject = 'test-project';
16
-
17
- beforeEach(() => {
18
- jest.clearAllMocks();
19
- ticketsDataProvider = new TicketsDataProvider(mockOrgUrl, mockToken);
20
- });
21
-
22
- describe('FetchImageAsBase64', () => {
23
- it('should fetch image as base64', async () => {
24
- // Arrange
25
- const mockUrl = 'https://example.com/image.jpg';
26
- const mockBase64 = 'base64-encoded-image';
27
- (TFSServices.fetchAzureDevOpsImageAsBase64 as jest.Mock).mockResolvedValueOnce(mockBase64);
28
-
29
- // Act
30
- const result = await ticketsDataProvider.FetchImageAsBase64(mockUrl);
31
-
32
- // Assert
33
- expect(TFSServices.fetchAzureDevOpsImageAsBase64).toHaveBeenCalledWith(mockUrl, mockToken, 'get', null);
34
- expect(result).toBe(mockBase64);
35
- });
36
- });
37
-
38
- describe('GetWorkItem', () => {
39
- it('should fetch work item with correct URL', async () => {
40
- // Arrange
41
- const mockId = '123';
42
- const mockWorkItem = { id: 123, fields: { 'System.Title': 'Test Work Item' } };
43
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockWorkItem);
44
-
45
- // Act
46
- const result = await ticketsDataProvider.GetWorkItem(mockProject, mockId);
47
-
48
- // Assert
49
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
50
- `${mockOrgUrl}${mockProject}/_apis/wit/workitems/${mockId}?$expand=All`,
51
- mockToken
52
- );
53
- expect(result).toEqual(mockWorkItem);
54
- });
55
- });
56
-
57
- describe('GetLinksByIds', () => {
58
- it('should retrieve links by ids', async () => {
59
- // Arrange
60
- const mockIds = [1, 2];
61
- const mockWorkItems = [
62
- { id: 1, fields: { 'System.Title': 'Item 1' } },
63
- { id: 2, fields: { 'System.Title': 'Item 2' } },
64
- ];
65
- const mockLinksMap = new Map();
66
- mockLinksMap.set('1', { id: '1', rels: ['3'] });
67
- mockLinksMap.set('2', { id: '2', rels: [] });
68
-
69
- const mockRelatedItems = [{ id: 3, fields: { 'System.Title': 'Related Item' } }];
70
- const mockTraceItem = { id: '1', title: 'Item 1', url: 'url', customerId: 'customer', links: [] };
71
-
72
- jest.spyOn(ticketsDataProvider, 'PopulateWorkItemsByIds').mockResolvedValueOnce(mockWorkItems);
73
- jest.spyOn(ticketsDataProvider, 'GetRelationsIds').mockResolvedValueOnce(mockLinksMap);
74
- jest
75
- .spyOn(ticketsDataProvider, 'GetParentLink')
76
- .mockResolvedValueOnce(mockTraceItem)
77
- .mockResolvedValueOnce({ id: '2', title: 'Item 2', url: 'url', customerId: 'customer', links: [] });
78
- jest.spyOn(ticketsDataProvider, 'PopulateWorkItemsByIds').mockResolvedValueOnce(mockRelatedItems);
79
- jest.spyOn(ticketsDataProvider, 'GetLinks').mockResolvedValueOnce([]);
80
-
81
- // Act
82
- const result = await ticketsDataProvider.GetLinksByIds(mockProject, mockIds);
83
-
84
- // Assert
85
- expect(result.length).toBe(2);
86
- expect(ticketsDataProvider.PopulateWorkItemsByIds).toHaveBeenCalledWith(mockIds, mockProject);
87
- expect(ticketsDataProvider.GetRelationsIds).toHaveBeenCalledWith(mockWorkItems);
88
- });
89
- });
90
-
91
- describe('GetSharedQueries', () => {
92
- it('should fetch STD shared queries with correct URL', async () => {
93
- // Arrange
94
- const mockPath = '';
95
- const mockDocType = 'STD';
96
- const mockQueries = { name: 'Query 1' } as any;
97
- const mockBranchesResponse = {
98
- reqToTest: { result: { reqTestTree: {} }, usedFolder: {} },
99
- testToReq: { result: { testReqTree: {} }, usedFolder: {} },
100
- mom: { result: { linkedMomTree: {} }, usedFolder: {} },
101
- } as any;
102
-
103
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockQueries);
104
- jest.spyOn(ticketsDataProvider as any, 'ensureQueryChildren').mockResolvedValueOnce(mockQueries);
105
- jest
106
- .spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
107
- .mockResolvedValueOnce({ root: mockQueries, found: true });
108
- jest
109
- .spyOn(ticketsDataProvider as any, 'fetchDocTypeBranches')
110
- .mockResolvedValueOnce(mockBranchesResponse);
111
-
112
- // Act
113
- const result = await ticketsDataProvider.GetSharedQueries(mockProject, mockPath, mockDocType);
114
-
115
- // Assert
116
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
117
- `${mockOrgUrl}${mockProject}/_apis/wit/queries/Shared%20Queries?$depth=2&$expand=all`,
118
- mockToken
119
- );
120
- expect(result).toEqual({
121
- reqTestQueries: { reqTestTree: {}, testReqTree: {} },
122
- linkedMomQueries: { linkedMomTree: {} },
123
- });
124
- });
125
-
126
- it('should fetch SVD shared queries and call fetchAnyQueries', async () => {
127
- // Arrange
128
- const mockPath = 'Custom Path';
129
- const mockDocType = 'SVD';
130
- const mockQueries = { name: 'Query 1' } as any;
131
- const mockBranchesResponse = {
132
- systemOverview: { result: {}, usedFolder: {} },
133
- knownBugs: { result: {}, usedFolder: {} },
134
- } as any;
135
-
136
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockQueries);
137
- jest.spyOn(ticketsDataProvider as any, 'ensureQueryChildren').mockResolvedValueOnce(mockQueries);
138
- jest
139
- .spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
140
- .mockResolvedValueOnce({ root: mockQueries, found: true });
141
- jest
142
- .spyOn(ticketsDataProvider as any, 'fetchDocTypeBranches')
143
- .mockResolvedValueOnce(mockBranchesResponse);
144
-
145
- // Act
146
- const result = await ticketsDataProvider.GetSharedQueries(mockProject, mockPath, mockDocType);
147
-
148
- // Assert
149
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
150
- `${mockOrgUrl}${mockProject}/_apis/wit/queries/${mockPath}?$depth=2&$expand=all`,
151
- mockToken
152
- );
153
- expect(result).toEqual({
154
- systemOverviewQueryTree: {},
155
- knownBugsQueryTree: {},
156
- });
157
- });
158
-
159
- it('should handle errors', async () => {
160
- // Arrange
161
- const mockPath = '';
162
- const mockError = new Error('API error');
163
-
164
- (TFSServices.getItemContent as jest.Mock).mockImplementationOnce(() => {
165
- return Promise.reject(mockError);
166
- });
167
-
168
- // Act & Assert
169
- await expect(ticketsDataProvider.GetSharedQueries(mockProject, mockPath)).rejects.toThrow('API error');
170
- expect(logger.error).toHaveBeenCalled();
171
- });
172
- });
173
-
174
- describe('GetQueryResultsFromWiql', () => {
175
- it('should handle OneHop query with table format', async () => {
176
- // Arrange
177
- const mockWiqlHref = 'https://example.com/wiql';
178
- const mockTestCaseMap = new Map<number, Set<any>>();
179
- const mockQueryResult = {
180
- queryType: QueryType.OneHop,
181
- columns: [],
182
- workItemRelations: [{ source: null, target: { id: 1, url: 'url' } }],
183
- };
184
- const mockTableResult = {
185
- sourceTargetsMap: new Map(),
186
- sortingSourceColumnsMap: new Map(),
187
- sortingTargetsColumnsMap: new Map(),
188
- };
189
-
190
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockQueryResult);
191
- jest
192
- .spyOn(ticketsDataProvider as any, 'parseDirectLinkedQueryResultForTableFormat')
193
- .mockResolvedValueOnce(mockTableResult);
194
-
195
- // Act
196
- const result = await ticketsDataProvider.GetQueryResultsFromWiql(mockWiqlHref, true, mockTestCaseMap);
197
-
198
- // Assert
199
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(mockWiqlHref, mockToken);
200
- expect(result).toEqual(mockTableResult);
201
- });
202
-
203
- it('should throw error when wiqlHref is empty', async () => {
204
- // Arrange
205
- const mockTestCaseMap = new Map<number, Set<any>>();
206
-
207
- // Act & Assert
208
- const result = await ticketsDataProvider.GetQueryResultsFromWiql('', false, mockTestCaseMap);
209
- expect(logger.error).toHaveBeenCalled();
210
- expect(result).toBeUndefined();
211
- });
212
- });
213
-
214
- describe('GetModeledQuery', () => {
215
- it('should structure query list correctly', () => {
216
- // Arrange
217
- const mockQueryList = [
218
- {
219
- name: 'Query 1',
220
- _links: { wiql: 'http://example.com/wiql1' },
221
- id: 'q1',
222
- },
223
- {
224
- name: 'Query 2',
225
- _links: { wiql: null },
226
- id: 'q2',
227
- },
228
- ];
229
-
230
- // Act
231
- const result = ticketsDataProvider.GetModeledQuery(mockQueryList);
232
-
233
- // Assert
234
- expect(result).toEqual([
235
- { queryName: 'Query 1', wiql: 'http://example.com/wiql1', id: 'q1' },
236
- { queryName: 'Query 2', wiql: null, id: 'q2' },
237
- ]);
238
- });
239
- });
240
-
241
- describe('PopulateWorkItemsByIds', () => {
242
- it('should fetch work items in batches of 200', async () => {
243
- // Arrange
244
- const mockIds = Array.from({ length: 250 }, (_, i) => i + 1);
245
- const mockResponse1 = { value: mockIds.slice(0, 200).map((id) => ({ id })) };
246
- const mockResponse2 = { value: mockIds.slice(200).map((id) => ({ id })) };
247
-
248
- (TFSServices.getItemContent as jest.Mock)
249
- .mockResolvedValueOnce(mockResponse1)
250
- .mockResolvedValueOnce(mockResponse2);
251
-
252
- // Act
253
- const result = await ticketsDataProvider.PopulateWorkItemsByIds(mockIds, mockProject);
254
-
255
- // Assert
256
- expect(TFSServices.getItemContent).toHaveBeenCalledTimes(2);
257
- expect(result.length).toBe(250);
258
- });
259
-
260
- it('should handle errors and return empty array', async () => {
261
- // Arrange
262
- const mockIds = [1, 2, 3];
263
- const mockError = new Error('API error');
264
-
265
- (TFSServices.getItemContent as jest.Mock).mockRejectedValueOnce(mockError);
266
-
267
- // Act
268
- const result = await ticketsDataProvider.PopulateWorkItemsByIds(mockIds, mockProject);
269
-
270
- // Assert
271
- expect(result).toEqual([]);
272
- expect(logger.error).toHaveBeenCalled();
273
- });
274
- });
275
-
276
- describe('GetIterationsByTeamName', () => {
277
- it('should fetch iterations with team name specified', async () => {
278
- // Arrange
279
- const mockTeamName = 'test-team';
280
- const mockIterations = ['iteration1', 'iteration2'];
281
-
282
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockIterations);
283
-
284
- // Act
285
- const result = await ticketsDataProvider.GetIterationsByTeamName(mockProject, mockTeamName);
286
-
287
- // Assert
288
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
289
- `${mockOrgUrl}${mockProject}/${mockTeamName}/_apis/work/teamsettings/iterations`,
290
- mockToken,
291
- 'get'
292
- );
293
- expect(result).toEqual(mockIterations);
294
- });
295
-
296
- it('should fetch iterations without team name', async () => {
297
- // Arrange
298
- const mockTeamName = '';
299
- const mockIterations = ['iteration1', 'iteration2'];
300
-
301
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockIterations);
302
-
303
- // Act
304
- const result = await ticketsDataProvider.GetIterationsByTeamName(mockProject, mockTeamName);
305
-
306
- // Assert
307
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
308
- `${mockOrgUrl}${mockProject}/_apis/work/teamsettings/iterations`,
309
- mockToken,
310
- 'get'
311
- );
312
- expect(result).toEqual(mockIterations);
313
- });
314
- });
315
-
316
- describe('CreateNewWorkItem', () => {
317
- it('should create work item with correct parameters', async () => {
318
- // Arrange
319
- const mockWiBody = [{ op: 'add', path: '/fields/System.Title', value: 'New Item' }];
320
- const mockWiType = 'Bug';
321
- const mockByPass = true;
322
- const mockResponse = { id: 123, fields: { 'System.Title': 'New Item' } };
323
-
324
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockResponse);
325
-
326
- // Act
327
- const result = await ticketsDataProvider.CreateNewWorkItem(
328
- mockProject,
329
- mockWiBody,
330
- mockWiType,
331
- mockByPass
332
- );
333
-
334
- // Assert
335
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
336
- `${mockOrgUrl}${mockProject}/_apis/wit/workitems/$${mockWiType}?bypassRules=true`,
337
- mockToken,
338
- 'POST',
339
- mockWiBody,
340
- {
341
- 'Content-Type': 'application/json-patch+json',
342
- }
343
- );
344
- expect(result).toEqual(mockResponse);
345
- });
346
- });
347
-
348
- describe('UpdateWorkItem', () => {
349
- it('should update work item with correct parameters', async () => {
350
- // Arrange
351
- const mockWiBody = [{ op: 'add', path: '/fields/System.Title', value: 'Updated Item' }];
352
- const mockWorkItemId = 123;
353
- const mockByPass = true;
354
- const mockResponse = { id: 123, fields: { 'System.Title': 'Updated Item' } };
355
-
356
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockResponse);
357
-
358
- // Act
359
- const result = await ticketsDataProvider.UpdateWorkItem(
360
- mockProject,
361
- mockWiBody,
362
- mockWorkItemId,
363
- mockByPass
364
- );
365
-
366
- // Assert
367
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
368
- `${mockOrgUrl}${mockProject}/_apis/wit/workitems/${mockWorkItemId}?bypassRules=true`,
369
- mockToken,
370
- 'patch',
371
- mockWiBody,
372
- {
373
- 'Content-Type': 'application/json-patch+json',
374
- }
375
- );
376
- expect(result).toEqual(mockResponse);
377
- });
378
- });
379
-
380
- describe('GetWorkitemAttachments', () => {
381
- it('should return attachments for work item', async () => {
382
- // Arrange
383
- const mockId = '123';
384
- const mockWorkItem = {
385
- relations: [
386
- {
387
- rel: 'AttachedFile',
388
- url: 'https://example.com/attachment/1',
389
- attributes: { name: 'file.txt' },
390
- },
391
- ],
392
- };
393
-
394
- // Mock the TFSServices.getItemContent directly to return our mock data
395
- // This is what will be called by the new TicketsDataProvider instance
396
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockWorkItem);
397
-
398
- // Act
399
- const result = await ticketsDataProvider.GetWorkitemAttachments(mockProject, mockId);
400
-
401
- // Assert
402
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
403
- `${mockOrgUrl}${mockProject}/_apis/wit/workitems/${mockId}?$expand=All`,
404
- mockToken
405
- );
406
- expect(result.length).toBe(1);
407
-
408
- // Check that the downloadUrl was added correctly
409
- expect(result[0]).toHaveProperty('downloadUrl', 'https://example.com/attachment/1/file.txt');
410
- expect(result[0].rel).toBe('AttachedFile');
411
- });
412
-
413
- it('should handle work item with no relations', async () => {
414
- // Arrange
415
- const mockId = '123';
416
- const mockWorkItem = { relations: null };
417
-
418
- jest.spyOn(ticketsDataProvider, 'GetWorkItem').mockResolvedValueOnce(mockWorkItem);
419
-
420
- // Act
421
- const result = await ticketsDataProvider.GetWorkitemAttachments(mockProject, mockId);
422
-
423
- // Assert
424
- expect(result).toEqual([]);
425
- });
426
-
427
- it('should filter out non-attachment relations', async () => {
428
- // Arrange
429
- const mockId = '123';
430
- const mockWorkItem = {
431
- relations: [
432
- {
433
- rel: 'Parent',
434
- url: 'https://example.com/parent/1',
435
- attributes: { name: 'parent' },
436
- },
437
- {
438
- rel: 'AttachedFile',
439
- url: 'https://example.com/attachment/1',
440
- attributes: { name: 'file.txt' },
441
- },
442
- ],
443
- };
444
-
445
- // Mock TFSServices.getItemContent directly instead of GetWorkItem
446
- (TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockWorkItem);
447
-
448
- // Act
449
- const result = await ticketsDataProvider.GetWorkitemAttachments(mockProject, mockId);
450
-
451
- // Assert
452
- expect(TFSServices.getItemContent).toHaveBeenCalledWith(
453
- `${mockOrgUrl}${mockProject}/_apis/wit/workitems/${mockId}?$expand=All`,
454
- mockToken
455
- );
456
- expect(result.length).toBe(1);
457
- expect(result[0].rel).toBe('AttachedFile');
458
- // Only the AttachedFile relation should be in the result
459
- expect(result.some((item) => item.rel === 'Parent')).toBe(false);
460
- });
461
- });
462
- });