@elisra-devops/docgen-data-provider 1.77.0 → 1.79.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/models/mewp-reporting.d.ts +1 -0
- package/bin/modules/ResultDataProvider.d.ts +0 -1
- package/bin/modules/ResultDataProvider.js +72 -50
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/tests/modules/ResultDataProvider.test.js +6 -6
- package/bin/tests/modules/ResultDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/models/mewp-reporting.ts +1 -0
- package/src/modules/ResultDataProvider.ts +89 -44
- package/src/tests/modules/ResultDataProvider.test.ts +6 -7
|
@@ -86,7 +86,6 @@ export default class ResultDataProvider {
|
|
|
86
86
|
private createEmptyMewpCoverageBugCell;
|
|
87
87
|
private createEmptyMewpCoverageL3L4Cell;
|
|
88
88
|
private buildMewpCoverageL3L4Rows;
|
|
89
|
-
private formatMewpCustomerId;
|
|
90
89
|
private buildMewpCoverageRows;
|
|
91
90
|
private resolveCoverageBugResponsibility;
|
|
92
91
|
private resolveMewpL2RunStatus;
|
|
@@ -381,6 +381,53 @@ class ResultDataProvider {
|
|
|
381
381
|
}));
|
|
382
382
|
this.accumulateRequirementCountsFromActionResults(fallbackActionResults, testCaseId, requirementKeys, requirementIndex, observedTestCaseIdsByRequirement);
|
|
383
383
|
}
|
|
384
|
+
const requirementBaseKeys = new Set(requirements.map((item) => String((item === null || item === void 0 ? void 0 : item.baseKey) || '').trim()).filter((item) => !!item));
|
|
385
|
+
const externalL3L4BaseKeys = new Set([...externalL3L4ByBaseKey.keys()]);
|
|
386
|
+
const externalL3L4OverlapKeys = [...externalL3L4BaseKeys].filter((key) => requirementBaseKeys.has(key));
|
|
387
|
+
const failedRequirementBaseKeys = new Set();
|
|
388
|
+
const failedTestCaseIds = new Set();
|
|
389
|
+
for (const [requirementBaseKey, byTestCase] of requirementIndex.entries()) {
|
|
390
|
+
for (const [testCaseId, counts] of byTestCase.entries()) {
|
|
391
|
+
if (Number((counts === null || counts === void 0 ? void 0 : counts.failed) || 0) > 0) {
|
|
392
|
+
failedRequirementBaseKeys.add(requirementBaseKey);
|
|
393
|
+
failedTestCaseIds.add(testCaseId);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
const externalBugTestCaseIds = new Set([...externalBugsByTestCase.keys()]);
|
|
398
|
+
const externalBugFailedTestCaseOverlap = [...externalBugTestCaseIds].filter((id) => failedTestCaseIds.has(id));
|
|
399
|
+
const externalBugBaseKeys = new Set();
|
|
400
|
+
for (const bugs of externalBugsByTestCase.values()) {
|
|
401
|
+
for (const bug of bugs || []) {
|
|
402
|
+
const key = String((bug === null || bug === void 0 ? void 0 : bug.requirementBaseKey) || '').trim();
|
|
403
|
+
if (key)
|
|
404
|
+
externalBugBaseKeys.add(key);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const externalBugRequirementOverlap = [...externalBugBaseKeys].filter((key) => requirementBaseKeys.has(key));
|
|
408
|
+
const externalBugFailedRequirementOverlap = [...externalBugBaseKeys].filter((key) => failedRequirementBaseKeys.has(key));
|
|
409
|
+
logger_1.default.info(`MEWP coverage join diagnostics: requirementBaseKeys=${requirementBaseKeys.size} ` +
|
|
410
|
+
`failedRequirementBaseKeys=${failedRequirementBaseKeys.size} failedTestCases=${failedTestCaseIds.size}; ` +
|
|
411
|
+
`externalL3L4BaseKeys=${externalL3L4BaseKeys.size} externalL3L4Overlap=${externalL3L4OverlapKeys.length}; ` +
|
|
412
|
+
`externalBugTestCases=${externalBugTestCaseIds.size} externalBugFailedTestCaseOverlap=${externalBugFailedTestCaseOverlap.length}; ` +
|
|
413
|
+
`externalBugBaseKeys=${externalBugBaseKeys.size} externalBugRequirementOverlap=${externalBugRequirementOverlap.length} ` +
|
|
414
|
+
`externalBugFailedRequirementOverlap=${externalBugFailedRequirementOverlap.length}`);
|
|
415
|
+
if (externalL3L4BaseKeys.size > 0 && externalL3L4OverlapKeys.length === 0) {
|
|
416
|
+
const sampleReq = [...requirementBaseKeys].slice(0, 5);
|
|
417
|
+
const sampleExt = [...externalL3L4BaseKeys].slice(0, 5);
|
|
418
|
+
logger_1.default.warn(`MEWP coverage join diagnostics: no L3/L4 key overlap found. ` +
|
|
419
|
+
`sampleRequirementKeys=${sampleReq.join(', ')} sampleExternalL3L4Keys=${sampleExt.join(', ')}`);
|
|
420
|
+
}
|
|
421
|
+
if (externalBugBaseKeys.size > 0 && externalBugRequirementOverlap.length === 0) {
|
|
422
|
+
const sampleReq = [...requirementBaseKeys].slice(0, 5);
|
|
423
|
+
const sampleExt = [...externalBugBaseKeys].slice(0, 5);
|
|
424
|
+
logger_1.default.warn(`MEWP coverage join diagnostics: no bug requirement-key overlap found. ` +
|
|
425
|
+
`sampleRequirementKeys=${sampleReq.join(', ')} sampleExternalBugKeys=${sampleExt.join(', ')}`);
|
|
426
|
+
}
|
|
427
|
+
if (externalBugTestCaseIds.size > 0 && externalBugFailedTestCaseOverlap.length === 0) {
|
|
428
|
+
logger_1.default.warn(`MEWP coverage join diagnostics: no overlap between external bug test cases and failed test cases. ` +
|
|
429
|
+
`Bug rows remain empty because bugs are shown only for failed L2s.`);
|
|
430
|
+
}
|
|
384
431
|
const rows = this.buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, linkedRequirementsByTestCase, externalL3L4ByBaseKey, externalBugsByTestCase);
|
|
385
432
|
const coverageRowStats = rows.reduce((acc, row) => {
|
|
386
433
|
const hasBug = Number((row === null || row === void 0 ? void 0 : row['Bug ID']) || 0) > 0;
|
|
@@ -647,7 +694,8 @@ class ResultDataProvider {
|
|
|
647
694
|
return `MEWP Internal Validation - ${suffix}`;
|
|
648
695
|
}
|
|
649
696
|
createMewpCoverageRow(requirement, runStatus, bug, linkedL3L4) {
|
|
650
|
-
const
|
|
697
|
+
const l2ReqIdNumeric = Number((requirement === null || requirement === void 0 ? void 0 : requirement.workItemId) || 0);
|
|
698
|
+
const l2ReqId = l2ReqIdNumeric > 0 ? String(l2ReqIdNumeric) : '';
|
|
651
699
|
const l2ReqTitle = this.toMewpComparableText(requirement.title);
|
|
652
700
|
const l2SubSystem = this.toMewpComparableText(requirement.subSystem);
|
|
653
701
|
return {
|
|
@@ -688,15 +736,6 @@ class ResultDataProvider {
|
|
|
688
736
|
}
|
|
689
737
|
return rows;
|
|
690
738
|
}
|
|
691
|
-
formatMewpCustomerId(rawValue) {
|
|
692
|
-
const normalized = this.normalizeMewpRequirementCode(this.toMewpComparableText(rawValue));
|
|
693
|
-
if (normalized)
|
|
694
|
-
return normalized;
|
|
695
|
-
const onlyDigits = String(rawValue || '').replace(/\D/g, '');
|
|
696
|
-
if (onlyDigits)
|
|
697
|
-
return `SR${onlyDigits}`;
|
|
698
|
-
return '';
|
|
699
|
-
}
|
|
700
739
|
buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, linkedRequirementsByTestCase, l3l4ByBaseKey, externalBugsByTestCase) {
|
|
701
740
|
var _a;
|
|
702
741
|
const rows = [];
|
|
@@ -1322,7 +1361,7 @@ class ResultDataProvider {
|
|
|
1322
1361
|
const workItems = await this.fetchWorkItemsByIds(projectName, requirementIds, true);
|
|
1323
1362
|
const requirements = workItems.map((wi) => {
|
|
1324
1363
|
const fields = (wi === null || wi === void 0 ? void 0 : wi.fields) || {};
|
|
1325
|
-
const requirementId = this.extractMewpRequirementIdentifier(fields
|
|
1364
|
+
const requirementId = this.extractMewpRequirementIdentifier(fields);
|
|
1326
1365
|
const areaPath = this.toMewpComparableText(fields === null || fields === void 0 ? void 0 : fields['System.AreaPath']);
|
|
1327
1366
|
return {
|
|
1328
1367
|
workItemId: Number((wi === null || wi === void 0 ? void 0 : wi.id) || 0),
|
|
@@ -1404,13 +1443,14 @@ class ResultDataProvider {
|
|
|
1404
1443
|
}
|
|
1405
1444
|
return [...families.entries()]
|
|
1406
1445
|
.map(([baseKey, family]) => {
|
|
1407
|
-
var _a, _b, _c, _d;
|
|
1446
|
+
var _a, _b, _c, _d, _e;
|
|
1408
1447
|
return ({
|
|
1409
|
-
|
|
1448
|
+
workItemId: Number(((_a = family === null || family === void 0 ? void 0 : family.representative) === null || _a === void 0 ? void 0 : _a.workItemId) || 0),
|
|
1449
|
+
requirementId: String(((_b = family === null || family === void 0 ? void 0 : family.representative) === null || _b === void 0 ? void 0 : _b.requirementId) || baseKey),
|
|
1410
1450
|
baseKey,
|
|
1411
|
-
title: String(((
|
|
1412
|
-
subSystem: String(((
|
|
1413
|
-
responsibility: String(((
|
|
1451
|
+
title: String(((_c = family === null || family === void 0 ? void 0 : family.representative) === null || _c === void 0 ? void 0 : _c.title) || ''),
|
|
1452
|
+
subSystem: String(((_d = family === null || family === void 0 ? void 0 : family.representative) === null || _d === void 0 ? void 0 : _d.subSystem) || ''),
|
|
1453
|
+
responsibility: String(((_e = family === null || family === void 0 ? void 0 : family.representative) === null || _e === void 0 ? void 0 : _e.responsibility) || ''),
|
|
1414
1454
|
linkedTestCaseIds: [...family.linkedTestCaseIds].sort((a, b) => a - b),
|
|
1415
1455
|
});
|
|
1416
1456
|
})
|
|
@@ -1666,48 +1706,30 @@ class ResultDataProvider {
|
|
|
1666
1706
|
}
|
|
1667
1707
|
return [...out].sort((a, b) => a - b);
|
|
1668
1708
|
}
|
|
1669
|
-
extractMewpRequirementIdentifier(fields
|
|
1709
|
+
extractMewpRequirementIdentifier(fields) {
|
|
1670
1710
|
const entries = Object.entries(fields || {});
|
|
1671
|
-
|
|
1672
|
-
|
|
1711
|
+
const normalizeFieldKey = (value) => String(value || '')
|
|
1712
|
+
.toLowerCase()
|
|
1713
|
+
.replace(/[^a-z0-9]/g, '');
|
|
1714
|
+
// Strict MEWP mode: only explicit MEWP customer-id fields are accepted.
|
|
1715
|
+
// API display name: "Customer ID"
|
|
1716
|
+
// API reference name: "Custom.CustomerID"
|
|
1717
|
+
const customerIdFieldKeys = new Set([
|
|
1673
1718
|
'customerid',
|
|
1674
|
-
'
|
|
1675
|
-
|
|
1676
|
-
'requirementid',
|
|
1677
|
-
'externalid',
|
|
1678
|
-
'srid',
|
|
1679
|
-
'sapwbsid',
|
|
1680
|
-
];
|
|
1719
|
+
'customcustomerid',
|
|
1720
|
+
]);
|
|
1681
1721
|
for (const [key, value] of entries) {
|
|
1682
|
-
const normalizedKey =
|
|
1683
|
-
if (!
|
|
1722
|
+
const normalizedKey = normalizeFieldKey(key);
|
|
1723
|
+
if (!customerIdFieldKeys.has(normalizedKey))
|
|
1684
1724
|
continue;
|
|
1685
1725
|
const valueAsString = this.toMewpComparableText(value);
|
|
1686
1726
|
if (!valueAsString)
|
|
1687
1727
|
continue;
|
|
1688
|
-
const
|
|
1689
|
-
if (
|
|
1690
|
-
return
|
|
1728
|
+
const normalizedRequirementId = this.normalizeMewpRequirementCodeWithSuffix(valueAsString);
|
|
1729
|
+
if (normalizedRequirementId)
|
|
1730
|
+
return normalizedRequirementId;
|
|
1691
1731
|
}
|
|
1692
|
-
|
|
1693
|
-
const looseHints = ['customer', 'requirement', 'external', 'sapwbs', 'sr'];
|
|
1694
|
-
for (const [key, value] of entries) {
|
|
1695
|
-
const normalizedKey = String(key || '').toLowerCase();
|
|
1696
|
-
if (!looseHints.some((hint) => normalizedKey.includes(hint)))
|
|
1697
|
-
continue;
|
|
1698
|
-
const valueAsString = this.toMewpComparableText(value);
|
|
1699
|
-
if (!valueAsString)
|
|
1700
|
-
continue;
|
|
1701
|
-
const normalized = this.normalizeMewpRequirementCodeWithSuffix(valueAsString);
|
|
1702
|
-
if (normalized)
|
|
1703
|
-
return normalized;
|
|
1704
|
-
}
|
|
1705
|
-
// Optional fallback from title only (avoid scanning all fields and accidental SR matches).
|
|
1706
|
-
const title = this.toMewpComparableText(fields === null || fields === void 0 ? void 0 : fields['System.Title']);
|
|
1707
|
-
const titleCode = this.normalizeMewpRequirementCodeWithSuffix(title);
|
|
1708
|
-
if (titleCode)
|
|
1709
|
-
return titleCode;
|
|
1710
|
-
return fallbackWorkItemId ? `SR${fallbackWorkItemId}` : '';
|
|
1732
|
+
return '';
|
|
1711
1733
|
}
|
|
1712
1734
|
deriveMewpResponsibility(fields) {
|
|
1713
1735
|
const explicitSapWbs = this.toMewpComparableText(fields === null || fields === void 0 ? void 0 : fields['Custom.SAPWBS']);
|