@elisra-devops/docgen-data-provider 1.134.0 → 1.136.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/modules/TicketsDataProvider.d.ts +14 -2
- package/bin/modules/TicketsDataProvider.js +82 -70
- package/bin/modules/TicketsDataProvider.js.map +1 -1
- package/bin/tests/modules/ticketsDataProvider.traceColumns.test.js +29 -17
- package/bin/tests/modules/ticketsDataProvider.traceColumns.test.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/TicketsDataProvider.ts +101 -76
- package/src/tests/modules/ticketsDataProvider.traceColumns.test.ts +29 -17
|
@@ -191,6 +191,12 @@ export default class TicketsDataProvider {
|
|
|
191
191
|
GetQueryResultsByWiqlHref(wiqlHref: string, project: string): Promise<any>;
|
|
192
192
|
GetQueryResultsByWiqlString(wiql: string, projectName: string): Promise<any>;
|
|
193
193
|
GetQueryResultById(query: string, project: string): Promise<any>;
|
|
194
|
+
GetQueryDefinitionById(queryId: string, project: string): Promise<{
|
|
195
|
+
id: string;
|
|
196
|
+
name: string;
|
|
197
|
+
columns: any[];
|
|
198
|
+
wiql: any;
|
|
199
|
+
}>;
|
|
194
200
|
private normalizeHistoricalAsOf;
|
|
195
201
|
private normalizeHistoricalCompareValue;
|
|
196
202
|
private normalizeTestPhaseValue;
|
|
@@ -371,8 +377,14 @@ export default class TicketsDataProvider {
|
|
|
371
377
|
* source + first target work item). Trace queries are single-type per side in practice.
|
|
372
378
|
*/
|
|
373
379
|
GetTraceColumnsByType(reqTestWiqlHref: string | undefined, testReqWiqlHref: string | undefined, project: string): Promise<{
|
|
374
|
-
|
|
375
|
-
|
|
380
|
+
'req-test'?: {
|
|
381
|
+
Requirement: any[];
|
|
382
|
+
'Test Case': any[];
|
|
383
|
+
};
|
|
384
|
+
'test-req'?: {
|
|
385
|
+
Requirement: any[];
|
|
386
|
+
'Test Case': any[];
|
|
387
|
+
};
|
|
376
388
|
}>;
|
|
377
389
|
}
|
|
378
390
|
export {};
|
|
@@ -1302,6 +1302,17 @@ class TicketsDataProvider {
|
|
|
1302
1302
|
var wiql = querie._links.wiql;
|
|
1303
1303
|
return await this.GetQueryResultsByWiqlHref(wiql.href, project);
|
|
1304
1304
|
}
|
|
1305
|
+
async GetQueryDefinitionById(queryId, project) {
|
|
1306
|
+
var _a, _b, _c, _d, _e;
|
|
1307
|
+
const url = `${this.orgUrl}${project}/_apis/wit/queries/${encodeURIComponent(queryId)}?$expand=all`;
|
|
1308
|
+
const def = await tfs_1.TFSServices.getItemContent(url, this.token);
|
|
1309
|
+
return {
|
|
1310
|
+
id: (_a = def === null || def === void 0 ? void 0 : def.id) !== null && _a !== void 0 ? _a : queryId,
|
|
1311
|
+
name: (_b = def === null || def === void 0 ? void 0 : def.name) !== null && _b !== void 0 ? _b : '',
|
|
1312
|
+
columns: (_c = def === null || def === void 0 ? void 0 : def.columns) !== null && _c !== void 0 ? _c : [],
|
|
1313
|
+
wiql: (_e = (_d = def === null || def === void 0 ? void 0 : def._links) === null || _d === void 0 ? void 0 : _d.wiql) !== null && _e !== void 0 ? _e : null,
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1305
1316
|
normalizeHistoricalAsOf(value) {
|
|
1306
1317
|
const raw = String(value || '').trim();
|
|
1307
1318
|
if (!raw) {
|
|
@@ -1663,29 +1674,40 @@ class TicketsDataProvider {
|
|
|
1663
1674
|
skippedWorkItemIds,
|
|
1664
1675
|
};
|
|
1665
1676
|
}
|
|
1666
|
-
collectHistoricalQueries(root, parentPath = '') {
|
|
1667
|
-
const items = [];
|
|
1677
|
+
async collectHistoricalQueries(root, parentPath = '', acc = [], visited = new Set()) {
|
|
1668
1678
|
if (!root) {
|
|
1669
|
-
return
|
|
1679
|
+
return acc;
|
|
1670
1680
|
}
|
|
1671
1681
|
const name = String((root === null || root === void 0 ? void 0 : root.name) || '').trim();
|
|
1672
1682
|
const currentPath = parentPath && name ? `${parentPath}/${name}` : name || parentPath;
|
|
1673
1683
|
if (!(root === null || root === void 0 ? void 0 : root.isFolder)) {
|
|
1674
1684
|
const id = String((root === null || root === void 0 ? void 0 : root.id) || '').trim();
|
|
1675
1685
|
if (id) {
|
|
1676
|
-
|
|
1686
|
+
acc.push({
|
|
1677
1687
|
id,
|
|
1678
1688
|
queryName: name || id,
|
|
1679
1689
|
path: parentPath || 'Shared Queries',
|
|
1680
1690
|
});
|
|
1681
1691
|
}
|
|
1682
|
-
return
|
|
1692
|
+
return acc;
|
|
1683
1693
|
}
|
|
1684
|
-
const
|
|
1685
|
-
|
|
1686
|
-
|
|
1694
|
+
const folderId = String((root === null || root === void 0 ? void 0 : root.id) || '').trim();
|
|
1695
|
+
if (folderId && visited.has(folderId)) {
|
|
1696
|
+
return acc;
|
|
1687
1697
|
}
|
|
1688
|
-
|
|
1698
|
+
if (folderId) {
|
|
1699
|
+
visited.add(folderId);
|
|
1700
|
+
}
|
|
1701
|
+
try {
|
|
1702
|
+
await this.ensureQueryChildren(root);
|
|
1703
|
+
}
|
|
1704
|
+
catch (err) {
|
|
1705
|
+
logger_1.default.warn(`collectHistoricalQueries: failed to expand folder "${name}" (id=${folderId}): ${err.message}`);
|
|
1706
|
+
return acc;
|
|
1707
|
+
}
|
|
1708
|
+
const children = Array.isArray(root === null || root === void 0 ? void 0 : root.children) ? root.children : [];
|
|
1709
|
+
await Promise.all(children.map((child) => this.collectHistoricalQueries(child, currentPath || 'Shared Queries', acc, visited)));
|
|
1710
|
+
return acc;
|
|
1689
1711
|
}
|
|
1690
1712
|
/**
|
|
1691
1713
|
* Returns a flat list of shared queries for historical/as-of execution.
|
|
@@ -1699,7 +1721,7 @@ class TicketsDataProvider {
|
|
|
1699
1721
|
return tfs_1.TFSServices.getItemContent(url, this.token);
|
|
1700
1722
|
});
|
|
1701
1723
|
const normalizedRoot = this.normalizeHistoricalQueryRoot(root);
|
|
1702
|
-
const items = this.collectHistoricalQueries(normalizedRoot).filter((query) => query.id !== '');
|
|
1724
|
+
const items = (await this.collectHistoricalQueries(normalizedRoot)).filter((query) => query.id !== '');
|
|
1703
1725
|
items.sort((a, b) => {
|
|
1704
1726
|
const byPath = a.path.localeCompare(b.path);
|
|
1705
1727
|
if (byPath !== 0)
|
|
@@ -2780,17 +2802,6 @@ class TicketsDataProvider {
|
|
|
2780
2802
|
referenceName: c.referenceName,
|
|
2781
2803
|
name: c.name,
|
|
2782
2804
|
}));
|
|
2783
|
-
const mergeCols = (a, b) => {
|
|
2784
|
-
const seen = new Set();
|
|
2785
|
-
const result = [];
|
|
2786
|
-
for (const col of [...a, ...b]) {
|
|
2787
|
-
if (!seen.has(col.referenceName)) {
|
|
2788
|
-
seen.add(col.referenceName);
|
|
2789
|
-
result.push(col);
|
|
2790
|
-
}
|
|
2791
|
-
}
|
|
2792
|
-
return result;
|
|
2793
|
-
};
|
|
2794
2805
|
// Sample one work item to read its System.WorkItemType.
|
|
2795
2806
|
// In OneHop query relations: !relation.source means root (target = source WI);
|
|
2796
2807
|
// relation.source present means link (target = target WI).
|
|
@@ -2823,64 +2834,65 @@ class TicketsDataProvider {
|
|
|
2823
2834
|
const fields = (_a = res === null || res === void 0 ? void 0 : res.value) !== null && _a !== void 0 ? _a : [];
|
|
2824
2835
|
return new Set(fields.map((f) => f.referenceName));
|
|
2825
2836
|
};
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
let reqTestRelations = [];
|
|
2831
|
-
let testReqRelations = [];
|
|
2832
|
-
if (reqTestWiqlHref) {
|
|
2833
|
-
const qr = await tfs_1.TFSServices.getItemContent(reqTestWiqlHref, this.token);
|
|
2834
|
-
reqTestCols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
|
|
2835
|
-
reqTestRelations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
|
|
2836
|
-
}
|
|
2837
|
-
if (testReqWiqlHref) {
|
|
2838
|
-
const qr = await tfs_1.TFSServices.getItemContent(testReqWiqlHref, this.token);
|
|
2839
|
-
testReqCols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
|
|
2840
|
-
testReqRelations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
|
|
2841
|
-
}
|
|
2842
|
-
const declaredCols = mergeCols(reqTestCols, testReqCols);
|
|
2843
|
-
if (declaredCols.length === 0) {
|
|
2837
|
+
// Resolve per-side columns for one query independently.
|
|
2838
|
+
// srcIsReq: true = source WI is Requirement (req-test query), false = source WI is Test Case (test-req query).
|
|
2839
|
+
const resolveQuerySides = async (cols, relations, srcIsReq) => {
|
|
2840
|
+
if (cols.length === 0)
|
|
2844
2841
|
return { Requirement: [], 'Test Case': [] };
|
|
2842
|
+
if (relations.length === 0) {
|
|
2843
|
+
// No items to sample — degrade to declared columns on both sides
|
|
2844
|
+
return { Requirement: cols, 'Test Case': cols };
|
|
2845
|
+
}
|
|
2846
|
+
const [srcType, tgtType] = await Promise.all([
|
|
2847
|
+
sampleWitType(relations, true),
|
|
2848
|
+
sampleWitType(relations, false),
|
|
2849
|
+
]);
|
|
2850
|
+
const reqType = srcIsReq ? srcType : tgtType;
|
|
2851
|
+
const tcType = srcIsReq ? tgtType : srcType;
|
|
2852
|
+
if (!reqType || !tcType) {
|
|
2853
|
+
logger_1.default.warn('GetTraceColumnsByType: could not determine WIT type names — returning declared columns for both sides');
|
|
2854
|
+
return { Requirement: cols, 'Test Case': cols };
|
|
2845
2855
|
}
|
|
2846
|
-
// Step 2: sample WIT type names
|
|
2847
|
-
// reqTest: source = Requirement, target = Test Case
|
|
2848
|
-
// testReq: source = Test Case, target = Requirement
|
|
2849
|
-
let reqTypeName;
|
|
2850
|
-
let tcTypeName;
|
|
2851
|
-
if (reqTestRelations.length > 0) {
|
|
2852
|
-
[reqTypeName, tcTypeName] = await Promise.all([
|
|
2853
|
-
sampleWitType(reqTestRelations, true),
|
|
2854
|
-
sampleWitType(reqTestRelations, false),
|
|
2855
|
-
]);
|
|
2856
|
-
}
|
|
2857
|
-
if ((!reqTypeName || !tcTypeName) && testReqRelations.length > 0) {
|
|
2858
|
-
const [tSrc, tTgt] = await Promise.all([
|
|
2859
|
-
sampleWitType(testReqRelations, true),
|
|
2860
|
-
sampleWitType(testReqRelations, false),
|
|
2861
|
-
]);
|
|
2862
|
-
if (!tcTypeName)
|
|
2863
|
-
tcTypeName = tSrc;
|
|
2864
|
-
if (!reqTypeName)
|
|
2865
|
-
reqTypeName = tTgt;
|
|
2866
|
-
}
|
|
2867
|
-
if (!reqTypeName || !tcTypeName) {
|
|
2868
|
-
logger_1.default.warn('GetTraceColumnsByType: could not determine WIT type names — returning merged columns');
|
|
2869
|
-
return { Requirement: declaredCols, 'Test Case': declaredCols };
|
|
2870
|
-
}
|
|
2871
|
-
// Step 3: fetch WIT field schemas and intersect with declared columns
|
|
2872
2856
|
const [reqFieldSet, tcFieldSet] = await Promise.all([
|
|
2873
|
-
fetchTypeFieldSet(
|
|
2874
|
-
fetchTypeFieldSet(
|
|
2857
|
+
fetchTypeFieldSet(reqType),
|
|
2858
|
+
fetchTypeFieldSet(tcType),
|
|
2875
2859
|
]);
|
|
2876
2860
|
return {
|
|
2877
|
-
Requirement:
|
|
2878
|
-
'Test Case':
|
|
2861
|
+
Requirement: cols.filter((c) => reqFieldSet.has(c.referenceName)),
|
|
2862
|
+
'Test Case': cols.filter((c) => tcFieldSet.has(c.referenceName)),
|
|
2879
2863
|
};
|
|
2864
|
+
};
|
|
2865
|
+
try {
|
|
2866
|
+
const result = {};
|
|
2867
|
+
if (reqTestWiqlHref) {
|
|
2868
|
+
try {
|
|
2869
|
+
const qr = await tfs_1.TFSServices.getItemContent(reqTestWiqlHref, this.token);
|
|
2870
|
+
const cols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
|
|
2871
|
+
const relations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
|
|
2872
|
+
result['req-test'] = await resolveQuerySides(cols, relations, true);
|
|
2873
|
+
}
|
|
2874
|
+
catch (err) {
|
|
2875
|
+
logger_1.default.error(`GetTraceColumnsByType[req-test] failed: ${err.message}`);
|
|
2876
|
+
result['req-test'] = { Requirement: [], 'Test Case': [] };
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
if (testReqWiqlHref) {
|
|
2880
|
+
try {
|
|
2881
|
+
const qr = await tfs_1.TFSServices.getItemContent(testReqWiqlHref, this.token);
|
|
2882
|
+
const cols = normalizeCols((qr === null || qr === void 0 ? void 0 : qr.columns) || []);
|
|
2883
|
+
const relations = (qr === null || qr === void 0 ? void 0 : qr.workItemRelations) || [];
|
|
2884
|
+
result['test-req'] = await resolveQuerySides(cols, relations, false);
|
|
2885
|
+
}
|
|
2886
|
+
catch (err) {
|
|
2887
|
+
logger_1.default.error(`GetTraceColumnsByType[test-req] failed: ${err.message}`);
|
|
2888
|
+
result['test-req'] = { Requirement: [], 'Test Case': [] };
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
return result;
|
|
2880
2892
|
}
|
|
2881
2893
|
catch (err) {
|
|
2882
2894
|
logger_1.default.error(`GetTraceColumnsByType failed: ${err.message}`);
|
|
2883
|
-
return {
|
|
2895
|
+
return {};
|
|
2884
2896
|
}
|
|
2885
2897
|
}
|
|
2886
2898
|
}
|