@elisra-devops/docgen-data-provider 1.104.0 → 1.106.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.d.ts +2 -1
- package/bin/modules/TicketsDataProvider.js +71 -24
- 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 +194 -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 +156 -95
- 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 +284 -43
|
@@ -27,7 +27,7 @@ describe('TicketsDataProvider', () => {
|
|
|
27
27
|
wiql,
|
|
28
28
|
'Source',
|
|
29
29
|
[],
|
|
30
|
-
new Map()
|
|
30
|
+
new Map(),
|
|
31
31
|
);
|
|
32
32
|
expect(result).toBe(true);
|
|
33
33
|
});
|
|
@@ -39,7 +39,7 @@ describe('TicketsDataProvider', () => {
|
|
|
39
39
|
wiql,
|
|
40
40
|
'Source',
|
|
41
41
|
[],
|
|
42
|
-
new Map()
|
|
42
|
+
new Map(),
|
|
43
43
|
);
|
|
44
44
|
expect(result).toBe(false);
|
|
45
45
|
});
|
|
@@ -51,7 +51,7 @@ describe('TicketsDataProvider', () => {
|
|
|
51
51
|
wiql,
|
|
52
52
|
'Source',
|
|
53
53
|
['Epic', 'Feature'],
|
|
54
|
-
new Map()
|
|
54
|
+
new Map(),
|
|
55
55
|
);
|
|
56
56
|
expect(result).toBe(false);
|
|
57
57
|
});
|
|
@@ -63,7 +63,7 @@ describe('TicketsDataProvider', () => {
|
|
|
63
63
|
wiql,
|
|
64
64
|
'Target',
|
|
65
65
|
['Requirement', 'Bug'],
|
|
66
|
-
new Map()
|
|
66
|
+
new Map(),
|
|
67
67
|
);
|
|
68
68
|
expect(result).toBe(true);
|
|
69
69
|
});
|
|
@@ -75,7 +75,7 @@ describe('TicketsDataProvider', () => {
|
|
|
75
75
|
wiql,
|
|
76
76
|
'Target',
|
|
77
77
|
['Bug'],
|
|
78
|
-
new Map()
|
|
78
|
+
new Map(),
|
|
79
79
|
);
|
|
80
80
|
expect(result).toBe(false);
|
|
81
81
|
});
|
|
@@ -93,13 +93,98 @@ describe('TicketsDataProvider', () => {
|
|
|
93
93
|
});
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
+
describe('fetchSysRsQueries', () => {
|
|
97
|
+
it('should use sysrs root, exclude trace folders from system requirements and resolve both trace directions', async () => {
|
|
98
|
+
const rootQueries = { id: 'root' };
|
|
99
|
+
const sysRsRoot = { id: 'sysrs-root', name: 'SYSRS' };
|
|
100
|
+
const subsystemToSystemFolder = { id: 'fwd-folder', name: 'System To Customer' };
|
|
101
|
+
const systemToSubsystemFolder = { id: 'rev-folder', name: 'System To Subsystem' };
|
|
102
|
+
|
|
103
|
+
const getDocTypeRootSpy = jest
|
|
104
|
+
.spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
|
|
105
|
+
.mockResolvedValue({ root: sysRsRoot, found: true });
|
|
106
|
+
const fetchSystemRequirementQueriesSpy = jest
|
|
107
|
+
.spyOn(ticketsDataProvider as any, 'fetchSystemRequirementQueries')
|
|
108
|
+
.mockResolvedValue({ systemRequirementsQueryTree: { id: 'system-tree' } });
|
|
109
|
+
const findChildFolderByPossibleNamesSpy = jest
|
|
110
|
+
.spyOn(ticketsDataProvider as any, 'findChildFolderByPossibleNames')
|
|
111
|
+
.mockResolvedValueOnce(subsystemToSystemFolder)
|
|
112
|
+
.mockResolvedValueOnce(systemToSubsystemFolder);
|
|
113
|
+
const fetchRequirementsTraceQueriesForFolderSpy = jest
|
|
114
|
+
.spyOn(ticketsDataProvider as any, 'fetchRequirementsTraceQueriesForFolder')
|
|
115
|
+
.mockResolvedValueOnce({ id: 'fwd-trace-tree' })
|
|
116
|
+
.mockResolvedValueOnce({ id: 'rev-trace-tree' });
|
|
117
|
+
|
|
118
|
+
const result = await (ticketsDataProvider as any).fetchSysRsQueries(rootQueries);
|
|
119
|
+
|
|
120
|
+
expect(getDocTypeRootSpy).toHaveBeenCalledWith(rootQueries, 'sysrs');
|
|
121
|
+
expect(fetchSystemRequirementQueriesSpy).toHaveBeenCalledWith(sysRsRoot, [
|
|
122
|
+
'System To Customer',
|
|
123
|
+
'System To Subsystem',
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
expect(findChildFolderByPossibleNamesSpy).toHaveBeenNthCalledWith(
|
|
127
|
+
1,
|
|
128
|
+
sysRsRoot,
|
|
129
|
+
expect.arrayContaining(['system to customer', 'subsystem to system', 'customer to system']),
|
|
130
|
+
);
|
|
131
|
+
expect(findChildFolderByPossibleNamesSpy).toHaveBeenNthCalledWith(
|
|
132
|
+
2,
|
|
133
|
+
sysRsRoot,
|
|
134
|
+
expect.arrayContaining(['system to subsystem', 'system-to-subsystem']),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
expect(fetchRequirementsTraceQueriesForFolderSpy).toHaveBeenNthCalledWith(1, subsystemToSystemFolder);
|
|
138
|
+
expect(fetchRequirementsTraceQueriesForFolderSpy).toHaveBeenNthCalledWith(2, systemToSubsystemFolder);
|
|
139
|
+
|
|
140
|
+
expect(result).toEqual({
|
|
141
|
+
systemRequirementsQueries: { systemRequirementsQueryTree: { id: 'system-tree' } },
|
|
142
|
+
subsystemToSystemRequirementsQueries: { id: 'fwd-trace-tree' },
|
|
143
|
+
systemToSubsystemRequirementsQueries: { id: 'rev-trace-tree' },
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should fall back to root queries and return null trace trees when trace folders are missing', async () => {
|
|
148
|
+
const rootQueries = { id: 'root' };
|
|
149
|
+
|
|
150
|
+
jest
|
|
151
|
+
.spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
|
|
152
|
+
.mockResolvedValue({ root: rootQueries, found: false });
|
|
153
|
+
const fetchSystemRequirementQueriesSpy = jest
|
|
154
|
+
.spyOn(ticketsDataProvider as any, 'fetchSystemRequirementQueries')
|
|
155
|
+
.mockResolvedValue({ systemRequirementsQueryTree: { id: 'system-tree' } });
|
|
156
|
+
jest
|
|
157
|
+
.spyOn(ticketsDataProvider as any, 'findChildFolderByPossibleNames')
|
|
158
|
+
.mockResolvedValueOnce(null)
|
|
159
|
+
.mockResolvedValueOnce(null);
|
|
160
|
+
const fetchRequirementsTraceQueriesForFolderSpy = jest
|
|
161
|
+
.spyOn(ticketsDataProvider as any, 'fetchRequirementsTraceQueriesForFolder')
|
|
162
|
+
.mockResolvedValueOnce(null)
|
|
163
|
+
.mockResolvedValueOnce(null);
|
|
164
|
+
|
|
165
|
+
const result = await (ticketsDataProvider as any).fetchSysRsQueries(rootQueries);
|
|
166
|
+
|
|
167
|
+
expect(fetchSystemRequirementQueriesSpy).toHaveBeenCalledWith(rootQueries, [
|
|
168
|
+
'System To Customer',
|
|
169
|
+
'System To Subsystem',
|
|
170
|
+
]);
|
|
171
|
+
expect(fetchRequirementsTraceQueriesForFolderSpy).toHaveBeenNthCalledWith(1, null);
|
|
172
|
+
expect(fetchRequirementsTraceQueriesForFolderSpy).toHaveBeenNthCalledWith(2, null);
|
|
173
|
+
expect(result).toEqual({
|
|
174
|
+
systemRequirementsQueries: { systemRequirementsQueryTree: { id: 'system-tree' } },
|
|
175
|
+
subsystemToSystemRequirementsQueries: null,
|
|
176
|
+
systemToSubsystemRequirementsQueries: null,
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
96
181
|
describe('findChildFolderByPossibleNames', () => {
|
|
97
182
|
it('should return null when parent is missing or possibleNames is empty', async () => {
|
|
98
183
|
await expect(
|
|
99
|
-
(ticketsDataProvider as any).findChildFolderByPossibleNames(null, ['a'])
|
|
184
|
+
(ticketsDataProvider as any).findChildFolderByPossibleNames(null, ['a']),
|
|
100
185
|
).resolves.toBeNull();
|
|
101
186
|
await expect(
|
|
102
|
-
(ticketsDataProvider as any).findChildFolderByPossibleNames({ hasChildren: false }, [])
|
|
187
|
+
(ticketsDataProvider as any).findChildFolderByPossibleNames({ hasChildren: false }, []),
|
|
103
188
|
).resolves.toBeNull();
|
|
104
189
|
});
|
|
105
190
|
|
|
@@ -194,7 +279,7 @@ describe('TicketsDataProvider', () => {
|
|
|
194
279
|
starting,
|
|
195
280
|
fetcher,
|
|
196
281
|
'ctx',
|
|
197
|
-
validator
|
|
282
|
+
validator,
|
|
198
283
|
);
|
|
199
284
|
expect(res.usedFolder).toBe(starting);
|
|
200
285
|
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
@@ -221,7 +306,7 @@ describe('TicketsDataProvider', () => {
|
|
|
221
306
|
a,
|
|
222
307
|
fetcher,
|
|
223
308
|
'ctx',
|
|
224
|
-
validator
|
|
309
|
+
validator,
|
|
225
310
|
);
|
|
226
311
|
expect(res.usedFolder).toBe(root);
|
|
227
312
|
expect(res.result).toEqual({ last: true });
|
|
@@ -258,7 +343,7 @@ describe('TicketsDataProvider', () => {
|
|
|
258
343
|
// Assert
|
|
259
344
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
260
345
|
`${mockOrgUrl}${mockProject}/_apis/wit/workitems/${mockId}?$expand=All`,
|
|
261
|
-
mockToken
|
|
346
|
+
mockToken,
|
|
262
347
|
);
|
|
263
348
|
expect(result).toEqual(mockWorkItem);
|
|
264
349
|
});
|
|
@@ -325,7 +410,7 @@ describe('TicketsDataProvider', () => {
|
|
|
325
410
|
// Assert
|
|
326
411
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
327
412
|
`${mockOrgUrl}${mockProject}/_apis/wit/queries/Shared%20Queries?$depth=2&$expand=all`,
|
|
328
|
-
mockToken
|
|
413
|
+
mockToken,
|
|
329
414
|
);
|
|
330
415
|
expect(result).toEqual({
|
|
331
416
|
reqTestQueries: { reqTestTree: {}, testReqTree: {} },
|
|
@@ -358,7 +443,7 @@ describe('TicketsDataProvider', () => {
|
|
|
358
443
|
// Assert
|
|
359
444
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
360
445
|
`${mockOrgUrl}${mockProject}/_apis/wit/queries/${mockPath}?$depth=2&$expand=all`,
|
|
361
|
-
mockToken
|
|
446
|
+
mockToken,
|
|
362
447
|
);
|
|
363
448
|
expect(result).toEqual({
|
|
364
449
|
systemOverviewQueryTree: {},
|
|
@@ -564,8 +649,8 @@ describe('TicketsDataProvider', () => {
|
|
|
564
649
|
await expect(
|
|
565
650
|
(ticketsDataProvider as any).parseDirectLinkedQueryResultForTableFormat(
|
|
566
651
|
{ columns: [], workItemRelations: [], queryType: QueryType.OneHop } as any,
|
|
567
|
-
new Map()
|
|
568
|
-
)
|
|
652
|
+
new Map(),
|
|
653
|
+
),
|
|
569
654
|
).rejects.toThrow('No related work items were found');
|
|
570
655
|
});
|
|
571
656
|
|
|
@@ -600,7 +685,7 @@ describe('TicketsDataProvider', () => {
|
|
|
600
685
|
columns: [{ referenceName: 'CustomerRequirementId', name: 'CustomerRequirementId' }],
|
|
601
686
|
workItemRelations,
|
|
602
687
|
} as any,
|
|
603
|
-
testCaseToRelatedWiMap
|
|
688
|
+
testCaseToRelatedWiMap,
|
|
604
689
|
);
|
|
605
690
|
|
|
606
691
|
expect(fetchSpy).toHaveBeenCalled();
|
|
@@ -627,8 +712,8 @@ describe('TicketsDataProvider', () => {
|
|
|
627
712
|
columns: [],
|
|
628
713
|
workItemRelations: [{ source: { id: 1 }, target: null }],
|
|
629
714
|
} as any,
|
|
630
|
-
new Map()
|
|
631
|
-
)
|
|
715
|
+
new Map(),
|
|
716
|
+
),
|
|
632
717
|
).rejects.toThrow('Target relation is missing');
|
|
633
718
|
});
|
|
634
719
|
});
|
|
@@ -646,7 +731,7 @@ describe('TicketsDataProvider', () => {
|
|
|
646
731
|
{},
|
|
647
732
|
wiql,
|
|
648
733
|
['Bug'],
|
|
649
|
-
new Map()
|
|
734
|
+
new Map(),
|
|
650
735
|
);
|
|
651
736
|
expect(res).toBe(false);
|
|
652
737
|
});
|
|
@@ -657,7 +742,7 @@ describe('TicketsDataProvider', () => {
|
|
|
657
742
|
{},
|
|
658
743
|
wiql,
|
|
659
744
|
['Bug'],
|
|
660
|
-
new Map()
|
|
745
|
+
new Map(),
|
|
661
746
|
);
|
|
662
747
|
expect(res).toBe(false);
|
|
663
748
|
});
|
|
@@ -710,7 +795,7 @@ describe('TicketsDataProvider', () => {
|
|
|
710
795
|
const resultedRefNameMap = new Map<string, string>();
|
|
711
796
|
|
|
712
797
|
expect(() =>
|
|
713
|
-
(ticketsDataProvider as any).filterFieldsByColumns(item, columnsToFilterMap, resultedRefNameMap)
|
|
798
|
+
(ticketsDataProvider as any).filterFieldsByColumns(item, columnsToFilterMap, resultedRefNameMap),
|
|
714
799
|
).toThrow();
|
|
715
800
|
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining('Cannot filter columns'));
|
|
716
801
|
});
|
|
@@ -747,7 +832,7 @@ describe('TicketsDataProvider', () => {
|
|
|
747
832
|
expect.objectContaining({
|
|
748
833
|
name: 'Bug',
|
|
749
834
|
icon: expect.objectContaining({ dataUrl: 'data:image/png;base64,xxx' }),
|
|
750
|
-
})
|
|
835
|
+
}),
|
|
751
836
|
);
|
|
752
837
|
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('Failed to download icon'));
|
|
753
838
|
});
|
|
@@ -830,7 +915,7 @@ describe('TicketsDataProvider', () => {
|
|
|
830
915
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
831
916
|
`${mockOrgUrl}${mockProject}/${mockTeamName}/_apis/work/teamsettings/iterations`,
|
|
832
917
|
mockToken,
|
|
833
|
-
'get'
|
|
918
|
+
'get',
|
|
834
919
|
);
|
|
835
920
|
expect(result).toEqual(mockIterations);
|
|
836
921
|
});
|
|
@@ -849,7 +934,7 @@ describe('TicketsDataProvider', () => {
|
|
|
849
934
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
850
935
|
`${mockOrgUrl}${mockProject}/_apis/work/teamsettings/iterations`,
|
|
851
936
|
mockToken,
|
|
852
|
-
'get'
|
|
937
|
+
'get',
|
|
853
938
|
);
|
|
854
939
|
expect(result).toEqual(mockIterations);
|
|
855
940
|
});
|
|
@@ -870,7 +955,7 @@ describe('TicketsDataProvider', () => {
|
|
|
870
955
|
mockProject,
|
|
871
956
|
mockWiBody,
|
|
872
957
|
mockWiType,
|
|
873
|
-
mockByPass
|
|
958
|
+
mockByPass,
|
|
874
959
|
);
|
|
875
960
|
|
|
876
961
|
// Assert
|
|
@@ -881,7 +966,7 @@ describe('TicketsDataProvider', () => {
|
|
|
881
966
|
mockWiBody,
|
|
882
967
|
{
|
|
883
968
|
'Content-Type': 'application/json-patch+json',
|
|
884
|
-
}
|
|
969
|
+
},
|
|
885
970
|
);
|
|
886
971
|
expect(result).toEqual(mockResponse);
|
|
887
972
|
});
|
|
@@ -902,7 +987,7 @@ describe('TicketsDataProvider', () => {
|
|
|
902
987
|
mockProject,
|
|
903
988
|
mockWiBody,
|
|
904
989
|
mockWorkItemId,
|
|
905
|
-
mockByPass
|
|
990
|
+
mockByPass,
|
|
906
991
|
);
|
|
907
992
|
|
|
908
993
|
// Assert
|
|
@@ -913,7 +998,7 @@ describe('TicketsDataProvider', () => {
|
|
|
913
998
|
mockWiBody,
|
|
914
999
|
{
|
|
915
1000
|
'Content-Type': 'application/json-patch+json',
|
|
916
|
-
}
|
|
1001
|
+
},
|
|
917
1002
|
);
|
|
918
1003
|
expect(result).toEqual(mockResponse);
|
|
919
1004
|
});
|
|
@@ -943,7 +1028,7 @@ describe('TicketsDataProvider', () => {
|
|
|
943
1028
|
// Assert
|
|
944
1029
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
945
1030
|
`${mockOrgUrl}${mockProject}/_apis/wit/workitems/${mockId}?$expand=All`,
|
|
946
|
-
mockToken
|
|
1031
|
+
mockToken,
|
|
947
1032
|
);
|
|
948
1033
|
expect(result.length).toBe(1);
|
|
949
1034
|
|
|
@@ -1008,7 +1093,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1008
1093
|
// Assert
|
|
1009
1094
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
1010
1095
|
`${mockOrgUrl}${mockProject}/_apis/wit/workitems/${mockId}?$expand=All`,
|
|
1011
|
-
mockToken
|
|
1096
|
+
mockToken,
|
|
1012
1097
|
);
|
|
1013
1098
|
expect(result.length).toBe(1);
|
|
1014
1099
|
expect(result[0].rel).toBe('AttachedFile');
|
|
@@ -1156,7 +1241,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1156
1241
|
// Assert
|
|
1157
1242
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
1158
1243
|
`${mockOrgUrl}${mockProject}/_apis/wit/workitemtypes/${mockItemType}/fields`,
|
|
1159
|
-
mockToken
|
|
1244
|
+
mockToken,
|
|
1160
1245
|
);
|
|
1161
1246
|
// Should filter out ID and Title
|
|
1162
1247
|
expect(result).toHaveLength(2);
|
|
@@ -1254,7 +1339,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1254
1339
|
const res = await ticketsDataProvider.GetQueryResultsFromWiql(
|
|
1255
1340
|
'https://example.com/wiql',
|
|
1256
1341
|
false,
|
|
1257
|
-
new Map()
|
|
1342
|
+
new Map(),
|
|
1258
1343
|
);
|
|
1259
1344
|
expect(res).toBeUndefined();
|
|
1260
1345
|
});
|
|
@@ -1407,7 +1492,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1407
1492
|
undefined,
|
|
1408
1493
|
false,
|
|
1409
1494
|
['skipme'],
|
|
1410
|
-
false
|
|
1495
|
+
false,
|
|
1411
1496
|
);
|
|
1412
1497
|
expect(res).toEqual({ tree1: null, tree2: null });
|
|
1413
1498
|
});
|
|
@@ -1438,12 +1523,12 @@ describe('TicketsDataProvider', () => {
|
|
|
1438
1523
|
false,
|
|
1439
1524
|
null,
|
|
1440
1525
|
['Epic'],
|
|
1441
|
-
['Feature']
|
|
1526
|
+
['Feature'],
|
|
1442
1527
|
);
|
|
1443
1528
|
|
|
1444
1529
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
1445
1530
|
'https://example.com/q?$depth=2&$expand=all',
|
|
1446
|
-
mockToken
|
|
1531
|
+
mockToken,
|
|
1447
1532
|
);
|
|
1448
1533
|
expect(res.tree1).toEqual({ id: 'root', pId: 'root' });
|
|
1449
1534
|
expect(res.tree2).toBeNull();
|
|
@@ -1466,7 +1551,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1466
1551
|
'missing',
|
|
1467
1552
|
false,
|
|
1468
1553
|
[],
|
|
1469
|
-
true
|
|
1554
|
+
true,
|
|
1470
1555
|
);
|
|
1471
1556
|
|
|
1472
1557
|
expect(res.tree1).toEqual({ id: 'q', pId: null });
|
|
@@ -1489,7 +1574,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1489
1574
|
false,
|
|
1490
1575
|
null,
|
|
1491
1576
|
['Epic'],
|
|
1492
|
-
['Feature']
|
|
1577
|
+
['Feature'],
|
|
1493
1578
|
);
|
|
1494
1579
|
|
|
1495
1580
|
expect(res.tree1).toBeNull();
|
|
@@ -1534,7 +1619,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1534
1619
|
[],
|
|
1535
1620
|
undefined,
|
|
1536
1621
|
undefined,
|
|
1537
|
-
true
|
|
1622
|
+
true,
|
|
1538
1623
|
);
|
|
1539
1624
|
|
|
1540
1625
|
expect(res.tree1).not.toBeNull();
|
|
@@ -1564,7 +1649,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1564
1649
|
[],
|
|
1565
1650
|
undefined,
|
|
1566
1651
|
undefined,
|
|
1567
|
-
true
|
|
1652
|
+
true,
|
|
1568
1653
|
);
|
|
1569
1654
|
|
|
1570
1655
|
expect(res.tree1).toBeNull();
|
|
@@ -1591,7 +1676,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1591
1676
|
false,
|
|
1592
1677
|
null,
|
|
1593
1678
|
allowedTypes,
|
|
1594
|
-
allowedTypes
|
|
1679
|
+
allowedTypes,
|
|
1595
1680
|
);
|
|
1596
1681
|
|
|
1597
1682
|
expect(res.tree1).not.toBeNull();
|
|
@@ -1622,7 +1707,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1622
1707
|
undefined,
|
|
1623
1708
|
false,
|
|
1624
1709
|
[],
|
|
1625
|
-
true
|
|
1710
|
+
true,
|
|
1626
1711
|
);
|
|
1627
1712
|
|
|
1628
1713
|
expect(res.tree1).not.toBeNull();
|
|
@@ -1647,7 +1732,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1647
1732
|
[],
|
|
1648
1733
|
undefined,
|
|
1649
1734
|
undefined,
|
|
1650
|
-
true
|
|
1735
|
+
true,
|
|
1651
1736
|
);
|
|
1652
1737
|
|
|
1653
1738
|
expect(res.tree1).toBeNull();
|
|
@@ -1719,7 +1804,7 @@ describe('TicketsDataProvider', () => {
|
|
|
1719
1804
|
|
|
1720
1805
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
1721
1806
|
'https://example.com/q3?$depth=2&$expand=all',
|
|
1722
|
-
mockToken
|
|
1807
|
+
mockToken,
|
|
1723
1808
|
);
|
|
1724
1809
|
expect(res.tree1).toEqual(expect.objectContaining({ id: 'q3', pId: 'q3' }));
|
|
1725
1810
|
});
|
|
@@ -1809,6 +1894,70 @@ describe('TicketsDataProvider', () => {
|
|
|
1809
1894
|
});
|
|
1810
1895
|
});
|
|
1811
1896
|
|
|
1897
|
+
describe('init query result items', () => {
|
|
1898
|
+
it('should include fields and workItemType in tree query item mapping', async () => {
|
|
1899
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce({
|
|
1900
|
+
fields: {
|
|
1901
|
+
'System.Title': 'REQ-42',
|
|
1902
|
+
'Microsoft.VSTS.CMMI.Symptom': 'Symptom description',
|
|
1903
|
+
'System.Description': 'Fallback description',
|
|
1904
|
+
'System.WorkItemType': 'Requirement',
|
|
1905
|
+
},
|
|
1906
|
+
_links: { html: { href: 'https://example.com/wi/42' } },
|
|
1907
|
+
});
|
|
1908
|
+
|
|
1909
|
+
const allItems: Record<number, any> = {};
|
|
1910
|
+
await (ticketsDataProvider as any).initTreeQueryResultItem(
|
|
1911
|
+
{ id: 42, url: 'https://example.com/wi/42' },
|
|
1912
|
+
allItems,
|
|
1913
|
+
);
|
|
1914
|
+
|
|
1915
|
+
expect(allItems[42]).toEqual(
|
|
1916
|
+
expect.objectContaining({
|
|
1917
|
+
id: 42,
|
|
1918
|
+
title: 'REQ-42',
|
|
1919
|
+
description: 'Symptom description',
|
|
1920
|
+
htmlUrl: 'https://example.com/wi/42',
|
|
1921
|
+
fields: expect.objectContaining({
|
|
1922
|
+
'System.WorkItemType': 'Requirement',
|
|
1923
|
+
}),
|
|
1924
|
+
workItemType: 'Requirement',
|
|
1925
|
+
children: [],
|
|
1926
|
+
}),
|
|
1927
|
+
);
|
|
1928
|
+
});
|
|
1929
|
+
|
|
1930
|
+
it('should include fields and fallback description in flat query item mapping', async () => {
|
|
1931
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValueOnce({
|
|
1932
|
+
fields: {
|
|
1933
|
+
'System.Title': 'REQ-84',
|
|
1934
|
+
'System.Description': 'System description',
|
|
1935
|
+
'System.WorkItemType': 'Feature',
|
|
1936
|
+
},
|
|
1937
|
+
_links: { html: { href: 'https://example.com/wi/84' } },
|
|
1938
|
+
});
|
|
1939
|
+
|
|
1940
|
+
const workItemMap = new Map<number, any>();
|
|
1941
|
+
await (ticketsDataProvider as any).initFlatQueryResultItem(
|
|
1942
|
+
{ id: 84, url: 'https://example.com/wi/84' },
|
|
1943
|
+
workItemMap,
|
|
1944
|
+
);
|
|
1945
|
+
|
|
1946
|
+
expect(workItemMap.get(84)).toEqual(
|
|
1947
|
+
expect.objectContaining({
|
|
1948
|
+
id: 84,
|
|
1949
|
+
title: 'REQ-84',
|
|
1950
|
+
description: 'System description',
|
|
1951
|
+
htmlUrl: 'https://example.com/wi/84',
|
|
1952
|
+
fields: expect.objectContaining({
|
|
1953
|
+
'System.WorkItemType': 'Feature',
|
|
1954
|
+
}),
|
|
1955
|
+
workItemType: 'Feature',
|
|
1956
|
+
}),
|
|
1957
|
+
);
|
|
1958
|
+
});
|
|
1959
|
+
});
|
|
1960
|
+
|
|
1812
1961
|
describe('GetQueryResultsByWiqlHref', () => {
|
|
1813
1962
|
it('should fetch and model query results', async () => {
|
|
1814
1963
|
// Arrange
|
|
@@ -1848,6 +1997,81 @@ describe('TicketsDataProvider', () => {
|
|
|
1848
1997
|
});
|
|
1849
1998
|
|
|
1850
1999
|
describe('GetSharedQueries - docType branches', () => {
|
|
2000
|
+
it('should handle STP docType', async () => {
|
|
2001
|
+
// Arrange
|
|
2002
|
+
const mockQueries = {
|
|
2003
|
+
children: [{ name: 'STP', isFolder: true, children: [] }],
|
|
2004
|
+
};
|
|
2005
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValue(mockQueries);
|
|
2006
|
+
|
|
2007
|
+
// Act
|
|
2008
|
+
const result = await ticketsDataProvider.GetSharedQueries(mockProject, '', 'stp');
|
|
2009
|
+
|
|
2010
|
+
// Assert
|
|
2011
|
+
expect(result).toBeDefined();
|
|
2012
|
+
});
|
|
2013
|
+
|
|
2014
|
+
it('should fallback to STD root when STP root is missing', async () => {
|
|
2015
|
+
const rootQueries = { id: 'root', children: [] };
|
|
2016
|
+
const stdRoot = { id: 'std-root', children: [] };
|
|
2017
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValue(rootQueries);
|
|
2018
|
+
|
|
2019
|
+
const getDocTypeRootSpy = jest
|
|
2020
|
+
.spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
|
|
2021
|
+
.mockImplementation(async (...args: any[]) => {
|
|
2022
|
+
const docTypeName = String(args[1] || '');
|
|
2023
|
+
if (docTypeName === 'stp') return { root: rootQueries, found: false };
|
|
2024
|
+
if (docTypeName === 'std') return { root: stdRoot, found: true };
|
|
2025
|
+
return { root: rootQueries, found: false };
|
|
2026
|
+
});
|
|
2027
|
+
|
|
2028
|
+
const fetchDocTypeBranchesSpy = jest
|
|
2029
|
+
.spyOn(ticketsDataProvider as any, 'fetchDocTypeBranches')
|
|
2030
|
+
.mockResolvedValue({
|
|
2031
|
+
reqToTest: { result: { reqTestTree: { id: 'req-tree' }, testReqTree: { id: 'fallback-tree' } } },
|
|
2032
|
+
testToReq: { result: { testReqTree: { id: 'test-tree' } } },
|
|
2033
|
+
mom: { result: { linkedMomTree: { id: 'mom-tree' } } },
|
|
2034
|
+
});
|
|
2035
|
+
|
|
2036
|
+
const result = await ticketsDataProvider.GetSharedQueries(mockProject, '', 'stp');
|
|
2037
|
+
|
|
2038
|
+
expect(getDocTypeRootSpy).toHaveBeenNthCalledWith(1, rootQueries, 'stp');
|
|
2039
|
+
expect(getDocTypeRootSpy).toHaveBeenNthCalledWith(2, rootQueries, 'std');
|
|
2040
|
+
expect(fetchDocTypeBranchesSpy).toHaveBeenCalledWith(rootQueries, stdRoot, expect.any(Array));
|
|
2041
|
+
expect(result.reqTestQueries.reqTestTree).toEqual({ id: 'req-tree' });
|
|
2042
|
+
expect(result.reqTestQueries.testReqTree).toEqual({ id: 'test-tree' });
|
|
2043
|
+
expect(result.linkedMomQueries.linkedMomTree).toEqual({ id: 'mom-tree' });
|
|
2044
|
+
});
|
|
2045
|
+
|
|
2046
|
+
it('should prefer STP root over STD when both exist', async () => {
|
|
2047
|
+
const rootQueries = { id: 'root', children: [] };
|
|
2048
|
+
const stpRoot = { id: 'stp-root', children: [] };
|
|
2049
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValue(rootQueries);
|
|
2050
|
+
|
|
2051
|
+
const getDocTypeRootSpy = jest
|
|
2052
|
+
.spyOn(ticketsDataProvider as any, 'getDocTypeRoot')
|
|
2053
|
+
.mockImplementation(async (...args: any[]) => {
|
|
2054
|
+
const docTypeName = String(args[1] || '');
|
|
2055
|
+
if (docTypeName === 'stp') return { root: stpRoot, found: true };
|
|
2056
|
+
if (docTypeName === 'std') return { root: { id: 'std-root', children: [] }, found: true };
|
|
2057
|
+
return { root: rootQueries, found: false };
|
|
2058
|
+
});
|
|
2059
|
+
|
|
2060
|
+
const fetchDocTypeBranchesSpy = jest
|
|
2061
|
+
.spyOn(ticketsDataProvider as any, 'fetchDocTypeBranches')
|
|
2062
|
+
.mockResolvedValue({
|
|
2063
|
+
reqToTest: { result: { reqTestTree: { id: 'req-tree' }, testReqTree: null } },
|
|
2064
|
+
testToReq: { result: { testReqTree: { id: 'test-tree' } } },
|
|
2065
|
+
mom: { result: { linkedMomTree: null } },
|
|
2066
|
+
});
|
|
2067
|
+
|
|
2068
|
+
await ticketsDataProvider.GetSharedQueries(mockProject, '', 'stp');
|
|
2069
|
+
|
|
2070
|
+
expect(getDocTypeRootSpy).toHaveBeenCalledTimes(1);
|
|
2071
|
+
expect(getDocTypeRootSpy).toHaveBeenCalledWith(rootQueries, 'stp');
|
|
2072
|
+
expect(fetchDocTypeBranchesSpy).toHaveBeenCalledWith(rootQueries, stpRoot, expect.any(Array));
|
|
2073
|
+
});
|
|
2074
|
+
|
|
1851
2075
|
it('should handle STR docType', async () => {
|
|
1852
2076
|
// Arrange
|
|
1853
2077
|
const mockQueries = {
|
|
@@ -1890,6 +2114,23 @@ describe('TicketsDataProvider', () => {
|
|
|
1890
2114
|
expect(result).toBeDefined();
|
|
1891
2115
|
});
|
|
1892
2116
|
|
|
2117
|
+
it('should handle SYSRS docType', async () => {
|
|
2118
|
+
// Arrange
|
|
2119
|
+
const mockQueries = {
|
|
2120
|
+
children: [{ name: 'SYSRS', isFolder: true, children: [] }],
|
|
2121
|
+
};
|
|
2122
|
+
(TFSServices.getItemContent as jest.Mock).mockResolvedValue(mockQueries);
|
|
2123
|
+
|
|
2124
|
+
// Act
|
|
2125
|
+
const result = await ticketsDataProvider.GetSharedQueries(mockProject, '', 'sysrs');
|
|
2126
|
+
|
|
2127
|
+
// Assert
|
|
2128
|
+
expect(result).toBeDefined();
|
|
2129
|
+
expect(result).toHaveProperty('systemRequirementsQueries');
|
|
2130
|
+
expect(result).toHaveProperty('subsystemToSystemRequirementsQueries');
|
|
2131
|
+
expect(result).toHaveProperty('systemToSubsystemRequirementsQueries');
|
|
2132
|
+
});
|
|
2133
|
+
|
|
1893
2134
|
it('should handle unknown docType', async () => {
|
|
1894
2135
|
// Arrange
|
|
1895
2136
|
const mockQueries = { children: [] };
|
|
@@ -2195,7 +2436,7 @@ describe('TicketsDataProvider', () => {
|
|
|
2195
2436
|
const res = await ticketsDataProvider.GetCategorizedRequirementsByType(wiqlHref);
|
|
2196
2437
|
expect(res).toEqual({ categories: {}, totalCount: 0 });
|
|
2197
2438
|
expect(logger.warn).toHaveBeenCalledWith(
|
|
2198
|
-
expect.stringContaining('No work items found in query result')
|
|
2439
|
+
expect.stringContaining('No work items found in query result'),
|
|
2199
2440
|
);
|
|
2200
2441
|
});
|
|
2201
2442
|
});
|