@elisra-devops/docgen-data-provider 1.102.0 → 1.103.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 +5 -0
- package/bin/modules/ResultDataProvider.d.ts +2 -0
- package/bin/modules/ResultDataProvider.js +65 -89
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/tests/modules/ResultDataProvider.test.js +39 -1
- package/bin/tests/modules/ResultDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/models/mewp-reporting.ts +5 -0
- package/src/modules/ResultDataProvider.ts +67 -114
- package/src/tests/modules/ResultDataProvider.test.ts +57 -1
|
@@ -24,6 +24,7 @@ export interface MewpL2RequirementWorkItem {
|
|
|
24
24
|
requirementId: string;
|
|
25
25
|
baseKey: string;
|
|
26
26
|
title: string;
|
|
27
|
+
owner: string;
|
|
27
28
|
subSystem: string;
|
|
28
29
|
responsibility: string;
|
|
29
30
|
linkedTestCaseIds: number[];
|
|
@@ -35,6 +36,7 @@ export interface MewpL2RequirementFamily {
|
|
|
35
36
|
requirementId: string;
|
|
36
37
|
baseKey: string;
|
|
37
38
|
title: string;
|
|
39
|
+
owner: string;
|
|
38
40
|
subSystem: string;
|
|
39
41
|
responsibility: string;
|
|
40
42
|
linkedTestCaseIds: number[];
|
|
@@ -71,7 +73,10 @@ export interface MewpCoverageBugCell {
|
|
|
71
73
|
export type MewpCoverageL3L4Cell = MewpL3L4Pair;
|
|
72
74
|
export interface MewpCoverageRow {
|
|
73
75
|
'L2 REQ ID': string;
|
|
76
|
+
'SR #': string;
|
|
74
77
|
'L2 REQ Title': string;
|
|
78
|
+
'L2 REQ Full Title'?: string;
|
|
79
|
+
'L2 Owner': string;
|
|
75
80
|
'L2 SubSystem': string;
|
|
76
81
|
'L2 Run Status': MewpRunStatus;
|
|
77
82
|
'Bug ID': number | '';
|
|
@@ -92,6 +92,7 @@ export default class ResultDataProvider {
|
|
|
92
92
|
private formatLogValue;
|
|
93
93
|
private buildTaggedLogMessage;
|
|
94
94
|
private createMewpCoverageRow;
|
|
95
|
+
private deriveMewpRequirementDisplayName;
|
|
95
96
|
private createEmptyMewpCoverageBugCell;
|
|
96
97
|
private createEmptyMewpCoverageL3L4Cell;
|
|
97
98
|
private buildMewpCoverageL3L4Rows;
|
|
@@ -170,6 +171,7 @@ export default class ResultDataProvider {
|
|
|
170
171
|
private extractLinkedWorkItemIdsFromRelations;
|
|
171
172
|
private extractMewpRequirementIdentifier;
|
|
172
173
|
private deriveMewpResponsibility;
|
|
174
|
+
private deriveMewpRequirementOwner;
|
|
173
175
|
private deriveMewpTestCaseResponsibility;
|
|
174
176
|
private deriveMewpSubSystem;
|
|
175
177
|
private resolveBugResponsibility;
|
|
@@ -608,19 +608,6 @@ class ResultDataProvider {
|
|
|
608
608
|
mentionedCodesByBase.set(baseKey, new Set());
|
|
609
609
|
mentionedCodesByBase.get(baseKey).add(code);
|
|
610
610
|
}
|
|
611
|
-
if (traceCurrentTestCase) {
|
|
612
|
-
logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_TRACE_TAG, {
|
|
613
|
-
event: 'test-case-start',
|
|
614
|
-
tc: testCaseId,
|
|
615
|
-
parsedSteps: executableSteps.length,
|
|
616
|
-
stepsWithMentions: mentionEntries.length,
|
|
617
|
-
mentionedCodes: [...mentionedL2Only].sort((a, b) => this.compareMewpRequirementCodes(a, b)).join('; ') ||
|
|
618
|
-
'<none>',
|
|
619
|
-
linkedCodesInTestCase: [...linkedFullCodes]
|
|
620
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
621
|
-
.join('; ') || '<none>',
|
|
622
|
-
}));
|
|
623
|
-
}
|
|
624
611
|
// Direction A logic:
|
|
625
612
|
// 1) Base mention ("SR0054") is parent-level and considered covered only when
|
|
626
613
|
// the whole family is covered across scoped test cases:
|
|
@@ -643,81 +630,30 @@ class ResultDataProvider {
|
|
|
643
630
|
const requiredFamilyMembers = specificFamilyMembers.length > 0 ? specificFamilyMembers : normalizedFamilyMembers;
|
|
644
631
|
// Base mention ("SR0054") requires full family coverage across selected test cases.
|
|
645
632
|
if (hasBaseMention) {
|
|
646
|
-
const missingRequiredFamilyMembers = requiredFamilyMembers.filter((memberCode) => !familyLinkedCodes.has(memberCode));
|
|
647
633
|
const isWholeFamilyCovered = requiredFamilyMembers.every((memberCode) => familyLinkedCodes.has(memberCode));
|
|
648
634
|
if (!isWholeFamilyCovered) {
|
|
649
635
|
missingBaseWhenFamilyUncovered.add(baseKey);
|
|
650
636
|
}
|
|
651
|
-
if (traceCurrentTestCase) {
|
|
652
|
-
logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_TRACE_TAG, {
|
|
653
|
-
event: 'base-family-coverage',
|
|
654
|
-
tc: testCaseId,
|
|
655
|
-
base: baseKey,
|
|
656
|
-
baseMention: true,
|
|
657
|
-
requiredFamily: requiredFamilyMembers
|
|
658
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
659
|
-
.join('; ') || '<none>',
|
|
660
|
-
linkedAcrossScope: [...familyLinkedCodes]
|
|
661
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
662
|
-
.join('; ') || '<none>',
|
|
663
|
-
missingRequired: missingRequiredFamilyMembers
|
|
664
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
665
|
-
.join('; ') || '<none>',
|
|
666
|
-
covered: isWholeFamilyCovered,
|
|
667
|
-
}));
|
|
668
|
-
}
|
|
669
637
|
}
|
|
670
638
|
// Specific mention ("SR0054-1") validates as exact-match only across scoped test cases.
|
|
671
639
|
const missingSpecificMembers = mentionedSpecificMembers.filter((code) => !familyLinkedCodes.has(code));
|
|
672
640
|
for (const code of missingSpecificMembers) {
|
|
673
641
|
missingSpecificMentionedNoFamily.add(code);
|
|
674
642
|
}
|
|
675
|
-
if (traceCurrentTestCase && mentionedSpecificMembers.length > 0) {
|
|
676
|
-
logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_TRACE_TAG, {
|
|
677
|
-
event: 'specific-members-check',
|
|
678
|
-
tc: testCaseId,
|
|
679
|
-
base: baseKey,
|
|
680
|
-
specificMentioned: mentionedSpecificMembers
|
|
681
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
682
|
-
.join('; ') || '<none>',
|
|
683
|
-
specificMissing: missingSpecificMembers
|
|
684
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
685
|
-
.join('; ') || '<none>',
|
|
686
|
-
}));
|
|
687
|
-
}
|
|
688
643
|
continue;
|
|
689
644
|
}
|
|
690
645
|
// Fallback path when family data is unavailable for this base key.
|
|
691
|
-
const fallbackMissingSpecific = [];
|
|
692
|
-
let fallbackMissingBase = false;
|
|
693
646
|
for (const code of mentionedCodes) {
|
|
694
647
|
const hasSpecificSuffix = /-\d+$/.test(code);
|
|
695
648
|
if (hasSpecificSuffix) {
|
|
696
649
|
if (!linkedFullCodesAcrossTestCases.has(code)) {
|
|
697
650
|
missingSpecificMentionedNoFamily.add(code);
|
|
698
|
-
fallbackMissingSpecific.push(code);
|
|
699
651
|
}
|
|
700
652
|
}
|
|
701
653
|
else if (!linkedBaseKeysAcrossTestCases.has(baseKey)) {
|
|
702
654
|
missingBaseWhenFamilyUncovered.add(baseKey);
|
|
703
|
-
fallbackMissingBase = true;
|
|
704
655
|
}
|
|
705
656
|
}
|
|
706
|
-
if (traceCurrentTestCase) {
|
|
707
|
-
logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_TRACE_TAG, {
|
|
708
|
-
event: 'fallback-path',
|
|
709
|
-
tc: testCaseId,
|
|
710
|
-
base: baseKey,
|
|
711
|
-
fallbackUsed: true,
|
|
712
|
-
mentioned: mentionedCodesList
|
|
713
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
714
|
-
.join('; ') || '<none>',
|
|
715
|
-
missingSpecific: fallbackMissingSpecific
|
|
716
|
-
.sort((a, b) => this.compareMewpRequirementCodes(a, b))
|
|
717
|
-
.join('; ') || '<none>',
|
|
718
|
-
missingBase: fallbackMissingBase,
|
|
719
|
-
}));
|
|
720
|
-
}
|
|
721
657
|
}
|
|
722
658
|
// Direction B is family-based: if any member of a family is mentioned in Expected Result,
|
|
723
659
|
// linked members of that same family are not considered "linked but not mentioned".
|
|
@@ -757,14 +693,6 @@ class ResultDataProvider {
|
|
|
757
693
|
const stepRef = mentionedBaseFirstStep.get(baseKey) || 'Step ?';
|
|
758
694
|
appendMentionedButNotLinked(baseKey, stepRef);
|
|
759
695
|
}
|
|
760
|
-
if (traceCurrentTestCase) {
|
|
761
|
-
logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_TRACE_TAG, {
|
|
762
|
-
event: 'direction-a-summary',
|
|
763
|
-
tc: testCaseId,
|
|
764
|
-
missingSpecific: sortedMissingSpecificMentionedNoFamily.join('; ') || '<none>',
|
|
765
|
-
missingBase: sortedMissingBaseWhenFamilyUncovered.join('; ') || '<none>',
|
|
766
|
-
}));
|
|
767
|
-
}
|
|
768
696
|
const sortedExtraLinked = [...new Set(extraLinked)]
|
|
769
697
|
.map((code) => this.normalizeMewpRequirementCodeWithSuffix(code))
|
|
770
698
|
.filter((code) => !!code)
|
|
@@ -799,18 +727,20 @@ class ResultDataProvider {
|
|
|
799
727
|
const validationStatus = mentionedButNotLinked || linkedButNotMentioned ? 'Fail' : 'Pass';
|
|
800
728
|
if (validationStatus === 'Fail')
|
|
801
729
|
diagnostics.failingRows += 1;
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
730
|
+
if (traceCurrentTestCase) {
|
|
731
|
+
logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_DIAGNOSTICS_TAG, {
|
|
732
|
+
testCaseId,
|
|
733
|
+
parsedSteps: executableSteps.length,
|
|
734
|
+
stepsWithMentions: mentionEntries.length,
|
|
735
|
+
customerIdsFound: mentionedL2Only.size,
|
|
736
|
+
linkedRequirements: linkedFullCodes.size,
|
|
737
|
+
mentionedButNotLinked: sortedMissingSpecificMentionedNoFamily.length +
|
|
738
|
+
sortedMissingBaseWhenFamilyUncovered.length,
|
|
739
|
+
linkedButNotMentioned: sortedExtraLinked.length,
|
|
740
|
+
status: validationStatus,
|
|
741
|
+
customerIdSample: [...mentionedL2Only].slice(0, 5).join(', '),
|
|
742
|
+
}));
|
|
743
|
+
}
|
|
814
744
|
rows.push({
|
|
815
745
|
'Test Case ID': testCaseId,
|
|
816
746
|
'Test Case Title': String(testCaseTitleMap.get(testCaseId) || '').trim(),
|
|
@@ -928,11 +858,17 @@ class ResultDataProvider {
|
|
|
928
858
|
createMewpCoverageRow(requirement, runStatus, bug, linkedL3L4) {
|
|
929
859
|
const l2ReqIdNumeric = Number((requirement === null || requirement === void 0 ? void 0 : requirement.workItemId) || 0);
|
|
930
860
|
const l2ReqId = l2ReqIdNumeric > 0 ? String(l2ReqIdNumeric) : '';
|
|
861
|
+
const srNumber = this.normalizeMewpRequirementCodeWithSuffix((requirement === null || requirement === void 0 ? void 0 : requirement.requirementId) || '');
|
|
931
862
|
const l2ReqTitle = this.toMewpComparableText(requirement.title);
|
|
863
|
+
const reqName = this.deriveMewpRequirementDisplayName(srNumber, l2ReqTitle);
|
|
864
|
+
const l2Owner = this.toMewpComparableText(requirement.owner);
|
|
932
865
|
const l2SubSystem = this.toMewpComparableText(requirement.subSystem);
|
|
933
866
|
return {
|
|
934
867
|
'L2 REQ ID': l2ReqId,
|
|
935
|
-
'
|
|
868
|
+
'SR #': srNumber,
|
|
869
|
+
'L2 REQ Title': reqName,
|
|
870
|
+
'L2 REQ Full Title': l2ReqTitle,
|
|
871
|
+
'L2 Owner': l2Owner,
|
|
936
872
|
'L2 SubSystem': l2SubSystem,
|
|
937
873
|
'L2 Run Status': runStatus,
|
|
938
874
|
'Bug ID': Number.isFinite(Number(bug === null || bug === void 0 ? void 0 : bug.id)) && Number(bug === null || bug === void 0 ? void 0 : bug.id) > 0 ? Number(bug === null || bug === void 0 ? void 0 : bug.id) : '',
|
|
@@ -944,6 +880,20 @@ class ResultDataProvider {
|
|
|
944
880
|
'L4 REQ Title': String((linkedL3L4 === null || linkedL3L4 === void 0 ? void 0 : linkedL3L4.l4Title) || '').trim(),
|
|
945
881
|
};
|
|
946
882
|
}
|
|
883
|
+
deriveMewpRequirementDisplayName(requirementCode, title) {
|
|
884
|
+
const normalizedTitle = this.toMewpComparableText(title);
|
|
885
|
+
if (!normalizedTitle)
|
|
886
|
+
return '';
|
|
887
|
+
const normalizedCode = this.normalizeMewpRequirementCodeWithSuffix(requirementCode || '');
|
|
888
|
+
if (!normalizedCode)
|
|
889
|
+
return normalizedTitle;
|
|
890
|
+
const escapedCode = normalizedCode.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
891
|
+
const codePrefixPattern = new RegExp(`^${escapedCode}(?:\\s*[:\\-–—]\\s*|\\s+)`, 'i');
|
|
892
|
+
const withoutCodePrefix = normalizedTitle.replace(codePrefixPattern, '').trim();
|
|
893
|
+
if (!withoutCodePrefix)
|
|
894
|
+
return normalizedTitle;
|
|
895
|
+
return withoutCodePrefix;
|
|
896
|
+
}
|
|
947
897
|
createEmptyMewpCoverageBugCell() {
|
|
948
898
|
return { id: '', title: '', responsibility: '' };
|
|
949
899
|
}
|
|
@@ -1199,7 +1149,9 @@ class ResultDataProvider {
|
|
|
1199
1149
|
const baseKey = String((requirement === null || requirement === void 0 ? void 0 : requirement.baseKey) || '').trim();
|
|
1200
1150
|
if (!baseKey)
|
|
1201
1151
|
continue;
|
|
1202
|
-
const
|
|
1152
|
+
const rawOwner = this.toMewpComparableText(requirement === null || requirement === void 0 ? void 0 : requirement.owner);
|
|
1153
|
+
const normalized = this.resolveMewpResponsibility(rawOwner) ||
|
|
1154
|
+
this.resolveMewpResponsibility(this.toMewpComparableText(requirement === null || requirement === void 0 ? void 0 : requirement.responsibility));
|
|
1203
1155
|
if (!normalized)
|
|
1204
1156
|
continue;
|
|
1205
1157
|
const existing = out.get(baseKey) || '';
|
|
@@ -1793,6 +1745,7 @@ class ResultDataProvider {
|
|
|
1793
1745
|
requirementId,
|
|
1794
1746
|
baseKey: this.toRequirementKey(requirementId),
|
|
1795
1747
|
title: this.toMewpComparableText((fields === null || fields === void 0 ? void 0 : fields['System.Title']) || (wi === null || wi === void 0 ? void 0 : wi.title)),
|
|
1748
|
+
owner: this.deriveMewpRequirementOwner(fields),
|
|
1796
1749
|
subSystem: this.deriveMewpSubSystem(fields),
|
|
1797
1750
|
responsibility: this.deriveMewpResponsibility(fields),
|
|
1798
1751
|
linkedTestCaseIds: this.extractLinkedTestCaseIdsFromRequirement((wi === null || wi === void 0 ? void 0 : wi.relations) || []),
|
|
@@ -1835,6 +1788,8 @@ class ResultDataProvider {
|
|
|
1835
1788
|
score += 2;
|
|
1836
1789
|
if (String((item === null || item === void 0 ? void 0 : item.title) || '').trim())
|
|
1837
1790
|
score += 1;
|
|
1791
|
+
if (String((item === null || item === void 0 ? void 0 : item.owner) || '').trim())
|
|
1792
|
+
score += 1;
|
|
1838
1793
|
if (String((item === null || item === void 0 ? void 0 : item.subSystem) || '').trim())
|
|
1839
1794
|
score += 1;
|
|
1840
1795
|
if (String((item === null || item === void 0 ? void 0 : item.responsibility) || '').trim())
|
|
@@ -1868,14 +1823,15 @@ class ResultDataProvider {
|
|
|
1868
1823
|
}
|
|
1869
1824
|
return [...families.entries()]
|
|
1870
1825
|
.map(([baseKey, family]) => {
|
|
1871
|
-
var _a, _b, _c, _d, _e;
|
|
1826
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1872
1827
|
return ({
|
|
1873
1828
|
workItemId: Number(((_a = family === null || family === void 0 ? void 0 : family.representative) === null || _a === void 0 ? void 0 : _a.workItemId) || 0),
|
|
1874
1829
|
requirementId: String(((_b = family === null || family === void 0 ? void 0 : family.representative) === null || _b === void 0 ? void 0 : _b.requirementId) || baseKey),
|
|
1875
1830
|
baseKey,
|
|
1876
1831
|
title: String(((_c = family === null || family === void 0 ? void 0 : family.representative) === null || _c === void 0 ? void 0 : _c.title) || ''),
|
|
1877
|
-
|
|
1878
|
-
|
|
1832
|
+
owner: String(((_d = family === null || family === void 0 ? void 0 : family.representative) === null || _d === void 0 ? void 0 : _d.owner) || ''),
|
|
1833
|
+
subSystem: String(((_e = family === null || family === void 0 ? void 0 : family.representative) === null || _e === void 0 ? void 0 : _e.subSystem) || ''),
|
|
1834
|
+
responsibility: String(((_f = family === null || family === void 0 ? void 0 : family.representative) === null || _f === void 0 ? void 0 : _f.responsibility) || ''),
|
|
1879
1835
|
linkedTestCaseIds: [...family.linkedTestCaseIds].sort((a, b) => a - b),
|
|
1880
1836
|
});
|
|
1881
1837
|
})
|
|
@@ -2304,6 +2260,24 @@ class ResultDataProvider {
|
|
|
2304
2260
|
}
|
|
2305
2261
|
return '';
|
|
2306
2262
|
}
|
|
2263
|
+
// L2 owner is sourced only from requirement SAPWBS fields.
|
|
2264
|
+
deriveMewpRequirementOwner(fields) {
|
|
2265
|
+
const directCandidates = [fields === null || fields === void 0 ? void 0 : fields['Custom.SAPWBS'], fields === null || fields === void 0 ? void 0 : fields['SAPWBS']];
|
|
2266
|
+
for (const candidate of directCandidates) {
|
|
2267
|
+
const normalized = this.toMewpComparableText(candidate);
|
|
2268
|
+
if (normalized)
|
|
2269
|
+
return normalized;
|
|
2270
|
+
}
|
|
2271
|
+
for (const [key, value] of Object.entries(fields || {})) {
|
|
2272
|
+
const normalizedKey = String(key || '').toLowerCase();
|
|
2273
|
+
if (!normalizedKey.includes('sapwbs'))
|
|
2274
|
+
continue;
|
|
2275
|
+
const normalizedValue = this.toMewpComparableText(value);
|
|
2276
|
+
if (normalizedValue)
|
|
2277
|
+
return normalizedValue;
|
|
2278
|
+
}
|
|
2279
|
+
return '';
|
|
2280
|
+
}
|
|
2307
2281
|
// Test-case responsibility must come from test-case path context (not SAPWBS).
|
|
2308
2282
|
deriveMewpTestCaseResponsibility(fields) {
|
|
2309
2283
|
const areaPathCandidates = [
|
|
@@ -4660,7 +4634,9 @@ ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_REF = 'Assumptions';
|
|
|
4660
4634
|
ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_HEADER_PATTERN = /assumptions/i;
|
|
4661
4635
|
ResultDataProvider.MEWP_L2_COVERAGE_COLUMNS = [
|
|
4662
4636
|
'L2 REQ ID',
|
|
4637
|
+
'SR #',
|
|
4663
4638
|
'L2 REQ Title',
|
|
4639
|
+
'L2 Owner',
|
|
4664
4640
|
'L2 SubSystem',
|
|
4665
4641
|
'L2 Run Status',
|
|
4666
4642
|
'Bug ID',
|