@elisra-devops/docgen-data-provider 1.136.6 → 1.137.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 +9 -7
- package/bin/helpers/helper.js +50 -57
- package/bin/helpers/helper.js.map +1 -1
- package/bin/modules/MangementDataProvider.d.ts +1 -0
- package/bin/modules/MangementDataProvider.js +9 -0
- package/bin/modules/MangementDataProvider.js.map +1 -1
- package/bin/modules/TestDataProvider.d.ts +1 -0
- package/bin/modules/TestDataProvider.js +45 -4
- package/bin/modules/TestDataProvider.js.map +1 -1
- package/bin/tests/helpers/helper.test.js +58 -3
- package/bin/tests/helpers/helper.test.js.map +1 -1
- package/bin/tests/modules/managmentDataProvider.test.js +22 -0
- package/bin/tests/modules/managmentDataProvider.test.js.map +1 -1
- package/bin/tests/modules/testDataProvider.test.js +92 -3
- package/bin/tests/modules/testDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/helper.ts +59 -85
- package/src/modules/MangementDataProvider.ts +12 -0
- package/src/modules/TestDataProvider.ts +36 -3
- package/src/tests/helpers/helper.test.ts +69 -3
- package/src/tests/modules/managmentDataProvider.test.ts +44 -0
- package/src/tests/modules/testDataProvider.test.ts +105 -3
|
@@ -115,20 +115,45 @@ export default class TestDataProvider {
|
|
|
115
115
|
return descriptions;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
// DFS pre-order flatten of a suite payload that may be a nested tree (asTreeView=true),
|
|
119
|
+
// a flat list whose elements also carry populated `children[]`, or a plain flat list.
|
|
120
|
+
// The `seen` guard means a suite is only emitted once even if it appears both in the
|
|
121
|
+
// top-level array and nested under a `children` array, so tree order always wins when
|
|
122
|
+
// available, with no duplicates and no change in behavior when `children` is absent.
|
|
123
|
+
private flattenSuitesTreeOrder(suites: any[]): any[] {
|
|
124
|
+
const flat: any[] = [];
|
|
125
|
+
const seen = new Set<any>();
|
|
126
|
+
|
|
127
|
+
const visit = (suite: any) => {
|
|
128
|
+
if (!suite || seen.has(suite.id)) return;
|
|
129
|
+
seen.add(suite.id);
|
|
130
|
+
const { children, ...rest } = suite;
|
|
131
|
+
flat.push(rest);
|
|
132
|
+
if (Array.isArray(children)) {
|
|
133
|
+
children.forEach(visit);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
suites.forEach(visit);
|
|
138
|
+
return flat;
|
|
139
|
+
}
|
|
140
|
+
|
|
118
141
|
private async normalizeAndEnrichSuitesResponse(project: string, data: any): Promise<any> {
|
|
119
|
-
const
|
|
142
|
+
const rawSuites = Array.isArray(data?.testSuites)
|
|
120
143
|
? data.testSuites
|
|
121
144
|
: Array.isArray(data?.value)
|
|
122
145
|
? data.value
|
|
123
146
|
: Array.isArray(data)
|
|
124
147
|
? data
|
|
125
148
|
: [];
|
|
149
|
+
const suites = this.flattenSuitesTreeOrder(rawSuites);
|
|
126
150
|
|
|
127
|
-
const mapped = suites.map((suite: any) => ({
|
|
151
|
+
const mapped = suites.map((suite: any, index: number) => ({
|
|
128
152
|
...suite,
|
|
129
153
|
title: suite?.title || suite?.name || '',
|
|
130
154
|
parentSuiteId: suite?.parentSuiteId ?? suite?.parentSuite?.id ?? 0,
|
|
131
155
|
description: this.getSuiteDescription(suite),
|
|
156
|
+
treeOrder: index,
|
|
132
157
|
}));
|
|
133
158
|
|
|
134
159
|
const missingDescriptionIds = mapped
|
|
@@ -190,7 +215,7 @@ export default class TestDataProvider {
|
|
|
190
215
|
|
|
191
216
|
// Bearer branch — follow x-ms-continuationtoken until the server stops returning it.
|
|
192
217
|
// Doc: https://learn.microsoft.com/en-us/rest/api/azure/devops/testplan/test-suites/get-test-suites-for-plan?view=azure-devops-rest-7.0
|
|
193
|
-
const base = `${this.joinOrgProject(project)}/_apis/testplan/Plans/${planid}/suites?expand=children&api-version=7.0`;
|
|
218
|
+
const base = `${this.joinOrgProject(project)}/_apis/testplan/Plans/${planid}/suites?expand=children&asTreeView=true&api-version=7.0`;
|
|
194
219
|
const cacheKey = `${base}__all_pages`;
|
|
195
220
|
|
|
196
221
|
if (this.cache.has(cacheKey)) {
|
|
@@ -277,6 +302,14 @@ export default class TestDataProvider {
|
|
|
277
302
|
}
|
|
278
303
|
}
|
|
279
304
|
|
|
305
|
+
// Multiple hierarchies must be emitted in tree order, not in the order the
|
|
306
|
+
// caller happened to list suiteIdsFilter.
|
|
307
|
+
topLevelSuites.sort((a, b) => {
|
|
308
|
+
const orderA = suiteMap.get(a)?.treeOrder ?? suiteMap.get(parseInt(a))?.treeOrder ?? 0;
|
|
309
|
+
const orderB = suiteMap.get(b)?.treeOrder ?? suiteMap.get(parseInt(b))?.treeOrder ?? 0;
|
|
310
|
+
return orderA - orderB;
|
|
311
|
+
});
|
|
312
|
+
|
|
280
313
|
if (topLevelSuites.length === 0) {
|
|
281
314
|
// Fallback: use first suite if no clear top-level suites found
|
|
282
315
|
const selectedSuiteId = suiteIdsFilter[0].toString();
|
|
@@ -4,9 +4,6 @@ import { Query, Workitem } from '../../models/tfs-data';
|
|
|
4
4
|
describe('Helper', () => {
|
|
5
5
|
beforeEach(() => {
|
|
6
6
|
// Reset static state before each test
|
|
7
|
-
Helper.suitList = [];
|
|
8
|
-
Helper.level = 1;
|
|
9
|
-
Helper.first = true;
|
|
10
7
|
Helper.levelList = [];
|
|
11
8
|
});
|
|
12
9
|
|
|
@@ -241,6 +238,75 @@ describe('Helper', () => {
|
|
|
241
238
|
// Assert
|
|
242
239
|
expect(result.length).toBe(5);
|
|
243
240
|
});
|
|
241
|
+
|
|
242
|
+
it('should emit siblings in array (tree) order even when their ids are not ascending', () => {
|
|
243
|
+
// Arrange - array order mirrors a manually reordered ADO tree: D, B, A, C
|
|
244
|
+
const suits = [
|
|
245
|
+
{ id: '1', title: 'Root', parentSuiteId: 0 },
|
|
246
|
+
{ id: '40', title: 'Suite D', parentSuiteId: '1' },
|
|
247
|
+
{ id: '20', title: 'Suite B', parentSuiteId: '1' },
|
|
248
|
+
{ id: '10', title: 'Suite A', parentSuiteId: '1' },
|
|
249
|
+
{ id: '30', title: 'Suite C', parentSuiteId: '1' },
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
// Act
|
|
253
|
+
const result = Helper.findSuitesRecursive(mockPlanId, mockUrl, mockProject, suits, '1', true);
|
|
254
|
+
|
|
255
|
+
// Assert
|
|
256
|
+
expect(result.map((s) => s.name)).toEqual(['Suite D', 'Suite B', 'Suite A', 'Suite C']);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should emit the selected nested suite first even when it appears last in the source array', () => {
|
|
260
|
+
// Arrange
|
|
261
|
+
const suits = [
|
|
262
|
+
{ id: '3', title: 'Grandchild Suite', parentSuiteId: '2' },
|
|
263
|
+
{ id: '1', title: 'Root Suite', parentSuiteId: 0 },
|
|
264
|
+
{ id: '2', title: 'Child Suite 1', parentSuiteId: '1' },
|
|
265
|
+
];
|
|
266
|
+
|
|
267
|
+
// Act
|
|
268
|
+
const result = Helper.findSuitesRecursive(mockPlanId, mockUrl, mockProject, suits, '2', true);
|
|
269
|
+
|
|
270
|
+
// Assert
|
|
271
|
+
expect(result.map((s) => s.name)).toEqual(['Child Suite 1', 'Grandchild Suite']);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should compute levels correctly regardless of source array position', () => {
|
|
275
|
+
// Arrange - grandchild appears before its parent in the array
|
|
276
|
+
const suits = [
|
|
277
|
+
{ id: '3', title: 'Level 2', parentSuiteId: '2' },
|
|
278
|
+
{ id: '1', title: 'Root', parentSuiteId: 0 },
|
|
279
|
+
{ id: '2', title: 'Level 1', parentSuiteId: '1' },
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
// Act
|
|
283
|
+
const result = Helper.findSuitesRecursive(mockPlanId, mockUrl, mockProject, suits, '1', true);
|
|
284
|
+
|
|
285
|
+
// Assert
|
|
286
|
+
expect(result.find((s) => s.name === 'Level 1')?.level).toBe(1);
|
|
287
|
+
expect(result.find((s) => s.name === 'Level 2')?.level).toBe(2);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('should not leak state between sequential calls', () => {
|
|
291
|
+
// Arrange
|
|
292
|
+
const suitsA = [
|
|
293
|
+
{ id: '1', title: 'Root A', parentSuiteId: 0 },
|
|
294
|
+
{ id: '2', title: 'Child A', parentSuiteId: '1' },
|
|
295
|
+
];
|
|
296
|
+
const suitsB = [
|
|
297
|
+
{ id: '10', title: 'Root B', parentSuiteId: 0 },
|
|
298
|
+
{ id: '20', title: 'Child B1', parentSuiteId: '10' },
|
|
299
|
+
{ id: '30', title: 'Child B2', parentSuiteId: '10' },
|
|
300
|
+
];
|
|
301
|
+
|
|
302
|
+
// Act
|
|
303
|
+
const resultA = Helper.findSuitesRecursive(mockPlanId, mockUrl, mockProject, suitsA, '1', true);
|
|
304
|
+
const resultB = Helper.findSuitesRecursive(mockPlanId, mockUrl, mockProject, suitsB, '10', true);
|
|
305
|
+
|
|
306
|
+
// Assert - resultB is unaffected by resultA's traversal
|
|
307
|
+
expect(resultA.map((s) => s.name)).toEqual(['Child A']);
|
|
308
|
+
expect(resultB.map((s) => s.name)).toEqual(['Child B1', 'Child B2']);
|
|
309
|
+
});
|
|
244
310
|
});
|
|
245
311
|
|
|
246
312
|
describe('LevelBuilder', () => {
|
|
@@ -276,6 +276,50 @@ describe('MangementDataProvider', () => {
|
|
|
276
276
|
);
|
|
277
277
|
});
|
|
278
278
|
});
|
|
279
|
+
|
|
280
|
+
describe('GetIdentityById', () => {
|
|
281
|
+
it('should call getItemContent with the exact documented URL shape', async () => {
|
|
282
|
+
const mockResponse = {
|
|
283
|
+
count: 1,
|
|
284
|
+
value: [{ id: 'id-1', properties: { Domain: { $value: 'GALAXY' }, Account: { $value: 'EdenS' } } }],
|
|
285
|
+
};
|
|
286
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce(mockResponse);
|
|
287
|
+
|
|
288
|
+
const result = await managementDataProvider.GetIdentityById('69c3a88a-e668-4ed9-b9e8-9c2eb96fc30e');
|
|
289
|
+
|
|
290
|
+
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
291
|
+
`${mockOrgUrl}_apis/identities?identityIds=69c3a88a-e668-4ed9-b9e8-9c2eb96fc30e&queryMembership=None&api-version=6.0`,
|
|
292
|
+
mockToken,
|
|
293
|
+
'get',
|
|
294
|
+
null,
|
|
295
|
+
null,
|
|
296
|
+
false
|
|
297
|
+
);
|
|
298
|
+
expect(result).toEqual(mockResponse);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should URL-encode an identity id that needs escaping', async () => {
|
|
302
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce({ count: 0, value: [] });
|
|
303
|
+
|
|
304
|
+
await managementDataProvider.GetIdentityById('id with spaces');
|
|
305
|
+
|
|
306
|
+
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
307
|
+
`${mockOrgUrl}_apis/identities?identityIds=id%20with%20spaces&queryMembership=None&api-version=6.0`,
|
|
308
|
+
mockToken,
|
|
309
|
+
'get',
|
|
310
|
+
null,
|
|
311
|
+
null,
|
|
312
|
+
false
|
|
313
|
+
);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('should propagate an error from the API call', async () => {
|
|
317
|
+
const expectedError = new Error('Identities API call failed');
|
|
318
|
+
(TFSServices.getItemContent as jest.Mock).mockRejectedValueOnce(expectedError);
|
|
319
|
+
|
|
320
|
+
await expect(managementDataProvider.GetIdentityById('id-1')).rejects.toThrow('Identities API call failed');
|
|
321
|
+
});
|
|
322
|
+
});
|
|
279
323
|
});
|
|
280
324
|
|
|
281
325
|
describe('MangementDataProvider - Additional Tests', () => {
|
|
@@ -326,7 +326,7 @@ describe('TestDataProvider', () => {
|
|
|
326
326
|
const result = await bearerProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
327
327
|
|
|
328
328
|
expect(TFSServices.getItemContentWithHeaders).toHaveBeenCalledWith(
|
|
329
|
-
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/testplan/Plans/${mockPlanId}/suites?expand=children&api-version=7.0`,
|
|
329
|
+
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/testplan/Plans/${mockPlanId}/suites?expand=children&asTreeView=true&api-version=7.0`,
|
|
330
330
|
mockBearerToken,
|
|
331
331
|
'get',
|
|
332
332
|
{},
|
|
@@ -368,7 +368,7 @@ describe('TestDataProvider', () => {
|
|
|
368
368
|
const result = await bearerProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
369
369
|
|
|
370
370
|
expect(TFSServices.getItemContentWithHeaders).toHaveBeenCalledWith(
|
|
371
|
-
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/testplan/Plans/${mockPlanId}/suites?expand=children&api-version=7.0`,
|
|
371
|
+
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/testplan/Plans/${mockPlanId}/suites?expand=children&asTreeView=true&api-version=7.0`,
|
|
372
372
|
mockBearerToken,
|
|
373
373
|
'get',
|
|
374
374
|
{},
|
|
@@ -407,6 +407,7 @@ describe('TestDataProvider', () => {
|
|
|
407
407
|
const calledUrl = (TFSServices.getItemContentWithHeaders as jest.Mock).mock.calls[0][0] as string;
|
|
408
408
|
expect(calledUrl).toContain(`/_apis/testplan/Plans/${mockPlanId}/suites`);
|
|
409
409
|
expect(calledUrl).toContain('expand=children');
|
|
410
|
+
expect(calledUrl).toContain('asTreeView=true');
|
|
410
411
|
expect(calledUrl).toContain('api-version=7.0');
|
|
411
412
|
expect(calledUrl).not.toContain('includeChildren');
|
|
412
413
|
});
|
|
@@ -480,6 +481,82 @@ describe('TestDataProvider', () => {
|
|
|
480
481
|
expect(callCount).toBeGreaterThan(0);
|
|
481
482
|
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('reached MAX_PAGES'));
|
|
482
483
|
});
|
|
484
|
+
|
|
485
|
+
it('should flatten a nested asTreeView=true payload into DFS pre-order', async () => {
|
|
486
|
+
const bearerProvider = new TestDataProvider(mockOrgUrl, mockBearerToken);
|
|
487
|
+
const treePayload = {
|
|
488
|
+
value: [
|
|
489
|
+
{
|
|
490
|
+
id: 1,
|
|
491
|
+
name: 'Root',
|
|
492
|
+
children: [
|
|
493
|
+
{ id: 20, name: 'Suite B', parentSuite: { id: 1 } },
|
|
494
|
+
{
|
|
495
|
+
id: 10,
|
|
496
|
+
name: 'Suite A',
|
|
497
|
+
parentSuite: { id: 1 },
|
|
498
|
+
children: [{ id: 11, name: 'Suite A.1', parentSuite: { id: 10 } }],
|
|
499
|
+
},
|
|
500
|
+
],
|
|
501
|
+
},
|
|
502
|
+
],
|
|
503
|
+
count: 1,
|
|
504
|
+
};
|
|
505
|
+
(TFSServices.getItemContentWithHeaders as jest.Mock).mockResolvedValueOnce({
|
|
506
|
+
data: treePayload,
|
|
507
|
+
headers: {},
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
const result = await bearerProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
511
|
+
|
|
512
|
+
expect(result.testSuites.map((s: any) => s.id)).toEqual([1, 20, 10, 11]);
|
|
513
|
+
expect(result.testSuites.map((s: any) => s.treeOrder)).toEqual([0, 1, 2, 3]);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
it('should derive tree order from a flat list whose elements carry populated children[], without duplicating suites', async () => {
|
|
517
|
+
const bearerProvider = new TestDataProvider(mockOrgUrl, mockBearerToken);
|
|
518
|
+
// Server ignored/does-not-support asTreeView and returned a flat, id-ordered list,
|
|
519
|
+
// but each suite still carries its own children[] in display order.
|
|
520
|
+
const flatWithChildren = {
|
|
521
|
+
value: [
|
|
522
|
+
{ id: 10, name: 'Suite A', parentSuite: { id: 1 }, children: [{ id: 11, name: 'Suite A.1' }] },
|
|
523
|
+
{ id: 11, name: 'Suite A.1', parentSuite: { id: 10 } },
|
|
524
|
+
{ id: 1, name: 'Root', children: [{ id: 10, name: 'Suite A' }, { id: 20, name: 'Suite B' }] },
|
|
525
|
+
{ id: 20, name: 'Suite B', parentSuite: { id: 1 } },
|
|
526
|
+
],
|
|
527
|
+
count: 4,
|
|
528
|
+
};
|
|
529
|
+
(TFSServices.getItemContentWithHeaders as jest.Mock).mockResolvedValueOnce({
|
|
530
|
+
data: flatWithChildren,
|
|
531
|
+
headers: {},
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
const result = await bearerProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
535
|
+
|
|
536
|
+
expect(result.testSuites.map((s: any) => s.id)).toEqual([10, 11, 1, 20]);
|
|
537
|
+
expect(result.testSuites).toHaveLength(4);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
it('should leave order unchanged for a flat list with no children field (regression guard)', async () => {
|
|
541
|
+
const bearerProvider = new TestDataProvider(mockOrgUrl, mockBearerToken);
|
|
542
|
+
const flatPayload = {
|
|
543
|
+
value: [
|
|
544
|
+
{ id: 40, name: 'Suite D' },
|
|
545
|
+
{ id: 20, name: 'Suite B' },
|
|
546
|
+
{ id: 10, name: 'Suite A' },
|
|
547
|
+
],
|
|
548
|
+
count: 3,
|
|
549
|
+
};
|
|
550
|
+
(TFSServices.getItemContentWithHeaders as jest.Mock).mockResolvedValueOnce({
|
|
551
|
+
data: flatPayload,
|
|
552
|
+
headers: {},
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
const result = await bearerProvider.GetTestSuitesForPlan(mockProject, mockPlanId);
|
|
556
|
+
|
|
557
|
+
expect(result.testSuites.map((s: any) => s.id)).toEqual([40, 20, 10]);
|
|
558
|
+
expect(result.testSuites.map((s: any) => s.treeOrder)).toEqual([0, 1, 2]);
|
|
559
|
+
});
|
|
483
560
|
});
|
|
484
561
|
|
|
485
562
|
describe('PAT-token branch — regression guard', () => {
|
|
@@ -548,7 +625,7 @@ describe('TestDataProvider', () => {
|
|
|
548
625
|
const result = await bearerProvider.GetTestSuiteById(mockProject, mockPlanId, mockSuiteId, true);
|
|
549
626
|
|
|
550
627
|
expect(TFSServices.getItemContentWithHeaders).toHaveBeenCalledWith(
|
|
551
|
-
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/testplan/Plans/${mockPlanId}/suites?expand=children&api-version=7.0`,
|
|
628
|
+
`${mockOrgUrl.replace(/\/+$/, '')}/${mockProject}/_apis/testplan/Plans/${mockPlanId}/suites?expand=children&asTreeView=true&api-version=7.0`,
|
|
552
629
|
mockBearerToken,
|
|
553
630
|
'get',
|
|
554
631
|
{},
|
|
@@ -672,6 +749,31 @@ describe('TestDataProvider', () => {
|
|
|
672
749
|
expect(res).toEqual([{ id: '10' }, { id: '11' }]);
|
|
673
750
|
});
|
|
674
751
|
|
|
752
|
+
it('should emit multiple hierarchies in tree order, not in suiteIdsFilter order', async () => {
|
|
753
|
+
jest.spyOn(testDataProvider, 'GetTestSuitesForPlan').mockResolvedValueOnce({
|
|
754
|
+
testSuites: [
|
|
755
|
+
{ id: 1, parentSuiteId: 0, treeOrder: 0 },
|
|
756
|
+
{ id: 2, parentSuiteId: 0, treeOrder: 1 },
|
|
757
|
+
{ id: 10, parentSuiteId: 1, treeOrder: 2 },
|
|
758
|
+
{ id: 11, parentSuiteId: 2, treeOrder: 3 },
|
|
759
|
+
],
|
|
760
|
+
} as any);
|
|
761
|
+
|
|
762
|
+
// Caller lists the second hierarchy's suite (11) before the first (10),
|
|
763
|
+
// but suite 10 (treeOrder 2) precedes suite 11 (treeOrder 3) in the tree.
|
|
764
|
+
const suiteIdsFilter = [11, 10];
|
|
765
|
+
const getByIdSpy = jest
|
|
766
|
+
.spyOn(testDataProvider, 'GetTestSuiteById')
|
|
767
|
+
.mockResolvedValueOnce([{ id: '10' }])
|
|
768
|
+
.mockResolvedValueOnce([{ id: '11' }]);
|
|
769
|
+
|
|
770
|
+
const res = await testDataProvider.GetTestSuitesByPlan(mockProject, mockPlanId, true, suiteIdsFilter);
|
|
771
|
+
|
|
772
|
+
expect(getByIdSpy).toHaveBeenNthCalledWith(1, mockProject, mockPlanId, '10', true, suiteIdsFilter);
|
|
773
|
+
expect(getByIdSpy).toHaveBeenNthCalledWith(2, mockProject, mockPlanId, '11', true, suiteIdsFilter);
|
|
774
|
+
expect(res).toEqual([{ id: '10' }, { id: '11' }]);
|
|
775
|
+
});
|
|
776
|
+
|
|
675
777
|
it('should fallback to first suite when no top-level suites can be determined', async () => {
|
|
676
778
|
jest.spyOn(testDataProvider, 'GetTestSuitesForPlan').mockResolvedValueOnce({
|
|
677
779
|
testSuites: [{ id: 1, parentSuiteId: 0 }],
|