@elisra-devops/docgen-data-provider 1.104.0 → 1.105.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/helpers/helper.d.ts +2 -1
- package/bin/helpers/helper.js +5 -4
- package/bin/helpers/helper.js.map +1 -1
- package/bin/models/tfs-data.d.ts +1 -0
- package/bin/models/tfs-data.js.map +1 -1
- package/bin/modules/TestDataProvider.d.ts +4 -0
- package/bin/modules/TestDataProvider.js +99 -14
- package/bin/modules/TestDataProvider.js.map +1 -1
- package/bin/modules/TicketsDataProvider.js +14 -3
- package/bin/modules/TicketsDataProvider.js.map +1 -1
- package/bin/tests/helpers/helper.test.js +2 -1
- package/bin/tests/helpers/helper.test.js.map +1 -1
- package/bin/tests/modules/testDataProvider.test.js +162 -9
- package/bin/tests/modules/testDataProvider.test.js.map +1 -1
- package/bin/tests/modules/ticketsDataProvider.test.js +66 -0
- package/bin/tests/modules/ticketsDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/helper.ts +19 -4
- package/src/models/tfs-data.ts +1 -0
- package/src/modules/TestDataProvider.ts +130 -22
- package/src/modules/TicketsDataProvider.ts +18 -5
- package/src/tests/helpers/helper.test.ts +2 -1
- package/src/tests/modules/testDataProvider.test.ts +225 -9
- package/src/tests/modules/ticketsDataProvider.test.ts +75 -0
|
@@ -199,12 +199,25 @@ export default class TicketsDataProvider {
|
|
|
199
199
|
const queriesWithChildren = await this.ensureQueryChildren(queries);
|
|
200
200
|
|
|
201
201
|
switch (normalizedDocType) {
|
|
202
|
-
case 'std':
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
'std'
|
|
202
|
+
case 'std':
|
|
203
|
+
case 'stp': {
|
|
204
|
+
const rootCandidates =
|
|
205
|
+
normalizedDocType === 'stp' ? (['stp', 'std'] as const) : (['std'] as const);
|
|
206
|
+
let stdRoot = queriesWithChildren;
|
|
207
|
+
let stdRootFound = false;
|
|
208
|
+
for (const candidate of rootCandidates) {
|
|
209
|
+
const lookup = await this.getDocTypeRoot(queriesWithChildren, candidate);
|
|
210
|
+
if (lookup.found) {
|
|
211
|
+
stdRoot = lookup.root;
|
|
212
|
+
stdRootFound = true;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
logger.debug(
|
|
217
|
+
`[GetSharedQueries][${normalizedDocType}] using ${
|
|
218
|
+
stdRootFound ? 'dedicated folder' : 'root queries'
|
|
219
|
+
}`
|
|
206
220
|
);
|
|
207
|
-
logger.debug(`[GetSharedQueries][std] using ${stdRootFound ? 'dedicated folder' : 'root queries'}`);
|
|
208
221
|
// Each branch describes the dedicated folder names, the fetch routine, and how to validate results.
|
|
209
222
|
const stdBranches = await this.fetchDocTypeBranches(queriesWithChildren, stdRoot, [
|
|
210
223
|
{
|
|
@@ -13,13 +13,14 @@ describe('Helper', () => {
|
|
|
13
13
|
describe('suiteData class', () => {
|
|
14
14
|
it('should create suiteData with correct properties', () => {
|
|
15
15
|
// Act
|
|
16
|
-
const suite = new suiteData('Test Suite', '123', '456', 2);
|
|
16
|
+
const suite = new suiteData('Test Suite', '123', '456', 2, 'Suite description');
|
|
17
17
|
|
|
18
18
|
// Assert
|
|
19
19
|
expect(suite.name).toBe('Test Suite');
|
|
20
20
|
expect(suite.id).toBe('123');
|
|
21
21
|
expect(suite.parent).toBe('456');
|
|
22
22
|
expect(suite.level).toBe(2);
|
|
23
|
+
expect(suite.description).toBe('Suite description');
|
|
23
24
|
expect(suite.url).toBeUndefined();
|
|
24
25
|
});
|
|
25
26
|
});
|
|
@@ -204,8 +204,8 @@ describe('TestDataProvider', () => {
|
|
|
204
204
|
// Arrange
|
|
205
205
|
const mockData = {
|
|
206
206
|
testSuites: [
|
|
207
|
-
{ id: '123', name: 'Test Suite 1' },
|
|
208
|
-
{ id: '456', name: 'Test Suite 2' },
|
|
207
|
+
{ id: '123', name: 'Test Suite 1', suiteDescription: 'Legacy Desc 1' },
|
|
208
|
+
{ id: '456', name: 'Test Suite 2', description: 'Legacy Desc 2' },
|
|
209
209
|
],
|
|
210
210
|
};
|
|
211
211
|
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockData);
|
|
@@ -214,19 +214,110 @@ describe('TestDataProvider', () => {
|
|
|
214
214
|
const result = await testDataProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
215
215
|
|
|
216
216
|
// Assert
|
|
217
|
-
expect(result).toEqual(
|
|
217
|
+
expect(result.testSuites).toEqual(
|
|
218
|
+
expect.arrayContaining([
|
|
219
|
+
expect.objectContaining({
|
|
220
|
+
id: '123',
|
|
221
|
+
title: 'Test Suite 1',
|
|
222
|
+
parentSuiteId: 0,
|
|
223
|
+
description: 'Legacy Desc 1',
|
|
224
|
+
}),
|
|
225
|
+
expect.objectContaining({
|
|
226
|
+
id: '456',
|
|
227
|
+
title: 'Test Suite 2',
|
|
228
|
+
parentSuiteId: 0,
|
|
229
|
+
description: 'Legacy Desc 2',
|
|
230
|
+
}),
|
|
231
|
+
])
|
|
232
|
+
);
|
|
218
233
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
219
234
|
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_api/_testManagement/GetTestSuitesForPlan?__v=5&planId=${mockPlanId}`,
|
|
220
235
|
mockToken
|
|
221
236
|
);
|
|
222
237
|
});
|
|
223
238
|
|
|
239
|
+
it('should enrich missing suite descriptions via work items batch for PAT token', async () => {
|
|
240
|
+
const suitesPayload = {
|
|
241
|
+
testSuites: [
|
|
242
|
+
{ id: 11, name: 'Suite A' },
|
|
243
|
+
{ id: 22, name: 'Suite B', suiteDescription: 'From legacy payload' },
|
|
244
|
+
],
|
|
245
|
+
};
|
|
246
|
+
const workItemsPayload = {
|
|
247
|
+
value: [{ id: 11, fields: { 'System.Description': '<div>WI Desc A</div>' } }],
|
|
248
|
+
};
|
|
249
|
+
(TFSServices.getItemContent as jest.Mock).mockImplementation((url: string) => {
|
|
250
|
+
if (url.includes('/_apis/wit/workitemsbatch')) {
|
|
251
|
+
return Promise.resolve(workItemsPayload);
|
|
252
|
+
}
|
|
253
|
+
return Promise.resolve(suitesPayload);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const result = await testDataProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
257
|
+
|
|
258
|
+
expect(TFSServices.getItemContent).toHaveBeenNthCalledWith(
|
|
259
|
+
1,
|
|
260
|
+
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_api/_testManagement/GetTestSuitesForPlan?__v=5&planId=${mockPlanId}`,
|
|
261
|
+
mockToken
|
|
262
|
+
);
|
|
263
|
+
expect(TFSServices.getItemContent).toHaveBeenNthCalledWith(
|
|
264
|
+
2,
|
|
265
|
+
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/wit/workitemsbatch?api-version=7.1`,
|
|
266
|
+
mockToken,
|
|
267
|
+
'post',
|
|
268
|
+
{
|
|
269
|
+
ids: [11],
|
|
270
|
+
fields: ['System.Description'],
|
|
271
|
+
errorPolicy: 'Omit',
|
|
272
|
+
},
|
|
273
|
+
{ 'Content-Type': 'application/json' }
|
|
274
|
+
);
|
|
275
|
+
expect(result.testSuites).toEqual(
|
|
276
|
+
expect.arrayContaining([
|
|
277
|
+
expect.objectContaining({ id: 11, description: '<div>WI Desc A</div>' }),
|
|
278
|
+
expect.objectContaining({ id: 22, description: 'From legacy payload' }),
|
|
279
|
+
])
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should chunk work items batch requests when suite IDs exceed batch limit', async () => {
|
|
284
|
+
const suitesPayload = {
|
|
285
|
+
testSuites: Array.from({ length: 205 }, (_, i) => ({
|
|
286
|
+
id: i + 1,
|
|
287
|
+
name: `Suite ${i + 1}`,
|
|
288
|
+
})),
|
|
289
|
+
};
|
|
290
|
+
(TFSServices.getItemContent as jest.Mock).mockImplementation((url: string, _token: string, method?: string, data?: any) => {
|
|
291
|
+
if (url.includes('/_apis/wit/workitemsbatch') && method === 'post') {
|
|
292
|
+
const ids = Array.isArray(data?.ids) ? data.ids : [];
|
|
293
|
+
return Promise.resolve({
|
|
294
|
+
value: ids.map((id: number) => ({
|
|
295
|
+
id,
|
|
296
|
+
fields: { 'System.Description': `Desc ${id}` },
|
|
297
|
+
})),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return Promise.resolve(suitesPayload);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const result = await testDataProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
304
|
+
|
|
305
|
+
expect((TFSServices.getItemContent as jest.Mock).mock.calls).toHaveLength(3);
|
|
306
|
+
expect((TFSServices.getItemContent as jest.Mock).mock.calls[1][2]).toBe('post');
|
|
307
|
+
expect((TFSServices.getItemContent as jest.Mock).mock.calls[1][3].ids).toHaveLength(200);
|
|
308
|
+
expect((TFSServices.getItemContent as jest.Mock).mock.calls[2][2]).toBe('post');
|
|
309
|
+
expect((TFSServices.getItemContent as jest.Mock).mock.calls[2][3].ids).toHaveLength(5);
|
|
310
|
+
|
|
311
|
+
expect(result.testSuites.find((s: any) => s.id === 1)?.description).toBe('Desc 1');
|
|
312
|
+
expect(result.testSuites.find((s: any) => s.id === 205)?.description).toBe('Desc 205');
|
|
313
|
+
});
|
|
314
|
+
|
|
224
315
|
it('should use testplan suites endpoint for bearer token and normalize response', async () => {
|
|
225
316
|
const bearerProvider = new TestDataProvider(mockOrgUrl, mockBearerToken);
|
|
226
317
|
const mockData = {
|
|
227
318
|
value: [
|
|
228
|
-
{ id: '123', name: 'Suite 1' },
|
|
229
|
-
{ id: '456', name: 'Suite 2', parentSuite: { id: '123' } },
|
|
319
|
+
{ id: '123', name: 'Suite 1', description: 'Desc 1' },
|
|
320
|
+
{ id: '456', name: 'Suite 2', parentSuite: { id: '123' }, suiteDescription: 'Desc 2' },
|
|
230
321
|
],
|
|
231
322
|
count: 2,
|
|
232
323
|
};
|
|
@@ -240,8 +331,58 @@ describe('TestDataProvider', () => {
|
|
|
240
331
|
);
|
|
241
332
|
expect(result.testSuites).toEqual(
|
|
242
333
|
expect.arrayContaining([
|
|
243
|
-
expect.objectContaining({ id: '123', title: 'Suite 1', parentSuiteId: 0 }),
|
|
244
|
-
expect.objectContaining({
|
|
334
|
+
expect.objectContaining({ id: '123', title: 'Suite 1', parentSuiteId: 0, description: 'Desc 1' }),
|
|
335
|
+
expect.objectContaining({
|
|
336
|
+
id: '456',
|
|
337
|
+
title: 'Suite 2',
|
|
338
|
+
parentSuiteId: '123',
|
|
339
|
+
description: 'Desc 2',
|
|
340
|
+
}),
|
|
341
|
+
])
|
|
342
|
+
);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('should enrich missing suite descriptions via work items batch for bearer token', async () => {
|
|
346
|
+
const bearerProvider = new TestDataProvider(mockOrgUrl, mockBearerToken);
|
|
347
|
+
const suitesPayload = {
|
|
348
|
+
value: [
|
|
349
|
+
{ id: 101, name: 'Suite A' },
|
|
350
|
+
{ id: 202, name: 'Suite B', description: 'Native Desc B' },
|
|
351
|
+
],
|
|
352
|
+
};
|
|
353
|
+
const workItemsPayload = {
|
|
354
|
+
value: [{ id: 101, fields: { 'System.Description': 'Enriched Desc A' } }],
|
|
355
|
+
};
|
|
356
|
+
(TFSServices.getItemContent as jest.Mock).mockImplementation((url: string) => {
|
|
357
|
+
if (url.includes('/_apis/wit/workitemsbatch')) {
|
|
358
|
+
return Promise.resolve(workItemsPayload);
|
|
359
|
+
}
|
|
360
|
+
return Promise.resolve(suitesPayload);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
const result = await bearerProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
364
|
+
|
|
365
|
+
expect(TFSServices.getItemContent).toHaveBeenNthCalledWith(
|
|
366
|
+
1,
|
|
367
|
+
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/testplan/Plans/${mockPlanId}/suites?includeChildren=true&api-version=7.0`,
|
|
368
|
+
mockBearerToken
|
|
369
|
+
);
|
|
370
|
+
expect(TFSServices.getItemContent).toHaveBeenNthCalledWith(
|
|
371
|
+
2,
|
|
372
|
+
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/wit/workitemsbatch?api-version=7.1`,
|
|
373
|
+
mockBearerToken,
|
|
374
|
+
'post',
|
|
375
|
+
{
|
|
376
|
+
ids: [101],
|
|
377
|
+
fields: ['System.Description'],
|
|
378
|
+
errorPolicy: 'Omit',
|
|
379
|
+
},
|
|
380
|
+
{ 'Content-Type': 'application/json' }
|
|
381
|
+
);
|
|
382
|
+
expect(result.testSuites).toEqual(
|
|
383
|
+
expect.arrayContaining([
|
|
384
|
+
expect.objectContaining({ id: 101, description: 'Enriched Desc A' }),
|
|
385
|
+
expect.objectContaining({ id: 202, description: 'Native Desc B' }),
|
|
245
386
|
])
|
|
246
387
|
);
|
|
247
388
|
});
|
|
@@ -268,7 +409,14 @@ describe('TestDataProvider', () => {
|
|
|
268
409
|
mockPlanId,
|
|
269
410
|
mockOrgUrl,
|
|
270
411
|
mockProject,
|
|
271
|
-
|
|
412
|
+
expect.arrayContaining([
|
|
413
|
+
expect.objectContaining({
|
|
414
|
+
id: '123',
|
|
415
|
+
title: 'Test Suite 1',
|
|
416
|
+
parentSuiteId: 0,
|
|
417
|
+
description: '',
|
|
418
|
+
}),
|
|
419
|
+
]),
|
|
272
420
|
mockSuiteId,
|
|
273
421
|
true
|
|
274
422
|
);
|
|
@@ -278,7 +426,7 @@ describe('TestDataProvider', () => {
|
|
|
278
426
|
it('should use bearer suites payload when token is bearer', async () => {
|
|
279
427
|
const bearerProvider = new TestDataProvider(mockOrgUrl, mockBearerToken);
|
|
280
428
|
const mockTestSuites = {
|
|
281
|
-
value: [{ id: '123', name: 'Suite 1', parentSuite: { id: 0 } }],
|
|
429
|
+
value: [{ id: '123', name: 'Suite 1', parentSuite: { id: 0 }, description: 'Suite Desc' }],
|
|
282
430
|
};
|
|
283
431
|
const mockSuiteData = [new suiteData('Suite 1', '123', '456', 1)];
|
|
284
432
|
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockTestSuites);
|
|
@@ -1046,6 +1194,74 @@ describe('TestDataProvider', () => {
|
|
|
1046
1194
|
);
|
|
1047
1195
|
});
|
|
1048
1196
|
|
|
1197
|
+
it('should populate testPhase from Custom.TestPhase', async () => {
|
|
1198
|
+
const suite = { id: '1', name: 'Suite 1' } as any;
|
|
1199
|
+
const testCases = {
|
|
1200
|
+
count: 1,
|
|
1201
|
+
value: [{ testCase: { id: 123, url: 'https://example.com/testcase/123' } }],
|
|
1202
|
+
};
|
|
1203
|
+
|
|
1204
|
+
jest.spyOn(testDataProvider as any, 'fetchWithCache').mockResolvedValueOnce({
|
|
1205
|
+
id: 123,
|
|
1206
|
+
fields: {
|
|
1207
|
+
'System.Title': 'TC 123',
|
|
1208
|
+
'System.AreaPath': 'A',
|
|
1209
|
+
'System.Description': 'D',
|
|
1210
|
+
'Custom.TestPhase': 'SIT',
|
|
1211
|
+
'Microsoft.VSTS.TCM.Steps': null,
|
|
1212
|
+
},
|
|
1213
|
+
relations: [],
|
|
1214
|
+
});
|
|
1215
|
+
|
|
1216
|
+
const res = await testDataProvider.StructureTestCase(
|
|
1217
|
+
mockProject,
|
|
1218
|
+
testCases as any,
|
|
1219
|
+
suite,
|
|
1220
|
+
false,
|
|
1221
|
+
false,
|
|
1222
|
+
false,
|
|
1223
|
+
new Map<string, string[]>(),
|
|
1224
|
+
new Map<string, string[]>()
|
|
1225
|
+
);
|
|
1226
|
+
|
|
1227
|
+
expect(res).toHaveLength(1);
|
|
1228
|
+
expect(res[0].testPhase).toBe('SIT');
|
|
1229
|
+
});
|
|
1230
|
+
|
|
1231
|
+
it('should extract testPhase from fallback key containing testphase', async () => {
|
|
1232
|
+
const suite = { id: '1', name: 'Suite 1' } as any;
|
|
1233
|
+
const testCases = {
|
|
1234
|
+
count: 1,
|
|
1235
|
+
value: [{ testCase: { id: 123, url: 'https://example.com/testcase/123' } }],
|
|
1236
|
+
};
|
|
1237
|
+
|
|
1238
|
+
jest.spyOn(testDataProvider as any, 'fetchWithCache').mockResolvedValueOnce({
|
|
1239
|
+
id: 123,
|
|
1240
|
+
fields: {
|
|
1241
|
+
'System.Title': 'TC 123',
|
|
1242
|
+
'System.AreaPath': 'A',
|
|
1243
|
+
'System.Description': 'D',
|
|
1244
|
+
'Custom.MyTestPhaseField': { displayName: 'Regression' },
|
|
1245
|
+
'Microsoft.VSTS.TCM.Steps': null,
|
|
1246
|
+
},
|
|
1247
|
+
relations: [],
|
|
1248
|
+
});
|
|
1249
|
+
|
|
1250
|
+
const res = await testDataProvider.StructureTestCase(
|
|
1251
|
+
mockProject,
|
|
1252
|
+
testCases as any,
|
|
1253
|
+
suite,
|
|
1254
|
+
false,
|
|
1255
|
+
false,
|
|
1256
|
+
false,
|
|
1257
|
+
new Map<string, string[]>(),
|
|
1258
|
+
new Map<string, string[]>()
|
|
1259
|
+
);
|
|
1260
|
+
|
|
1261
|
+
expect(res).toHaveLength(1);
|
|
1262
|
+
expect(res[0].testPhase).toBe('Regression');
|
|
1263
|
+
});
|
|
1264
|
+
|
|
1049
1265
|
it('should return empty list when test case fetch fails', async () => {
|
|
1050
1266
|
const suite = { id: '1', name: 'Suite 1' } as any;
|
|
1051
1267
|
const testCases = {
|
|
@@ -1848,6 +1848,81 @@ describe('TicketsDataProvider', () => {
|
|
|
1848
1848
|
});
|
|
1849
1849
|
|
|
1850
1850
|
describe('GetSharedQueries - docType branches', () => {
|
|
1851
|
+
it('should handle STP docType', async () => {
|
|
1852
|
+
// Arrange
|
|
1853
|
+
const mockQueries = {
|
|
1854
|
+
children: [{ name: 'STP', isFolder: true, children: [] }],
|
|
1855
|
+
};
|
|
1856
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValue(mockQueries);
|
|
1857
|
+
|
|
1858
|
+
// Act
|
|
1859
|
+
const result = await ticketsDataProvider.GetSharedQueries(mockProject, '', 'stp');
|
|
1860
|
+
|
|
1861
|
+
// Assert
|
|
1862
|
+
expect(result).toBeDefined();
|
|
1863
|
+
});
|
|
1864
|
+
|
|
1865
|
+
it('should fallback to STD root when STP root is missing', async () => {
|
|
1866
|
+
const rootQueries = { id: 'root', children: [] };
|
|
1867
|
+
const stdRoot = { id: 'std-root', children: [] };
|
|
1868
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValue(rootQueries);
|
|
1869
|
+
|
|
1870
|
+
const getDocTypeRootSpy = jest
|
|
1871
|
+
.spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
|
|
1872
|
+
.mockImplementation(async (...args: any[]) => {
|
|
1873
|
+
const docTypeName = String(args[1] || '');
|
|
1874
|
+
if (docTypeName === 'stp') return { root: rootQueries, found: false };
|
|
1875
|
+
if (docTypeName === 'std') return { root: stdRoot, found: true };
|
|
1876
|
+
return { root: rootQueries, found: false };
|
|
1877
|
+
});
|
|
1878
|
+
|
|
1879
|
+
const fetchDocTypeBranchesSpy = jest
|
|
1880
|
+
.spyOn(ticketsDataProvider as any, 'fetchDocTypeBranches')
|
|
1881
|
+
.mockResolvedValue({
|
|
1882
|
+
reqToTest: { result: { reqTestTree: { id: 'req-tree' }, testReqTree: { id: 'fallback-tree' } } },
|
|
1883
|
+
testToReq: { result: { testReqTree: { id: 'test-tree' } } },
|
|
1884
|
+
mom: { result: { linkedMomTree: { id: 'mom-tree' } } },
|
|
1885
|
+
});
|
|
1886
|
+
|
|
1887
|
+
const result = await ticketsDataProvider.GetSharedQueries(mockProject, '', 'stp');
|
|
1888
|
+
|
|
1889
|
+
expect(getDocTypeRootSpy).toHaveBeenNthCalledWith(1, rootQueries, 'stp');
|
|
1890
|
+
expect(getDocTypeRootSpy).toHaveBeenNthCalledWith(2, rootQueries, 'std');
|
|
1891
|
+
expect(fetchDocTypeBranchesSpy).toHaveBeenCalledWith(rootQueries, stdRoot, expect.any(Array));
|
|
1892
|
+
expect(result.reqTestQueries.reqTestTree).toEqual({ id: 'req-tree' });
|
|
1893
|
+
expect(result.reqTestQueries.testReqTree).toEqual({ id: 'test-tree' });
|
|
1894
|
+
expect(result.linkedMomQueries.linkedMomTree).toEqual({ id: 'mom-tree' });
|
|
1895
|
+
});
|
|
1896
|
+
|
|
1897
|
+
it('should prefer STP root over STD when both exist', async () => {
|
|
1898
|
+
const rootQueries = { id: 'root', children: [] };
|
|
1899
|
+
const stpRoot = { id: 'stp-root', children: [] };
|
|
1900
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValue(rootQueries);
|
|
1901
|
+
|
|
1902
|
+
const getDocTypeRootSpy = jest
|
|
1903
|
+
.spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
|
|
1904
|
+
.mockImplementation(async (...args: any[]) => {
|
|
1905
|
+
const docTypeName = String(args[1] || '');
|
|
1906
|
+
if (docTypeName === 'stp') return { root: stpRoot, found: true };
|
|
1907
|
+
if (docTypeName === 'std') return { root: { id: 'std-root', children: [] }, found: true };
|
|
1908
|
+
return { root: rootQueries, found: false };
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1911
|
+
const fetchDocTypeBranchesSpy = jest
|
|
1912
|
+
.spyOn(ticketsDataProvider as any, 'fetchDocTypeBranches')
|
|
1913
|
+
.mockResolvedValue({
|
|
1914
|
+
reqToTest: { result: { reqTestTree: { id: 'req-tree' }, testReqTree: null } },
|
|
1915
|
+
testToReq: { result: { testReqTree: { id: 'test-tree' } } },
|
|
1916
|
+
mom: { result: { linkedMomTree: null } },
|
|
1917
|
+
});
|
|
1918
|
+
|
|
1919
|
+
await ticketsDataProvider.GetSharedQueries(mockProject, '', 'stp');
|
|
1920
|
+
|
|
1921
|
+
expect(getDocTypeRootSpy).toHaveBeenCalledTimes(1);
|
|
1922
|
+
expect(getDocTypeRootSpy).toHaveBeenCalledWith(rootQueries, 'stp');
|
|
1923
|
+
expect(fetchDocTypeBranchesSpy).toHaveBeenCalledWith(rootQueries, stpRoot, expect.any(Array));
|
|
1924
|
+
});
|
|
1925
|
+
|
|
1851
1926
|
it('should handle STR docType', async () => {
|
|
1852
1927
|
// Arrange
|
|
1853
1928
|
const mockQueries = {
|