@elisra-devops/docgen-data-provider 1.102.0 → 1.104.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 +3 -0
- package/bin/modules/ResultDataProvider.js +128 -90
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/tests/modules/ResultDataProvider.test.js +114 -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 +154 -115
- package/src/tests/modules/ResultDataProvider.test.ts +151 -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;
|
|
@@ -115,6 +116,7 @@ export default class ResultDataProvider {
|
|
|
115
116
|
* 3) `System.Description` / `Description` from work-item field list (`workItemFields`)
|
|
116
117
|
*/
|
|
117
118
|
private buildMewpTestCaseDescriptionMap;
|
|
119
|
+
private enrichMewpTestCaseMapsFromLatestWorkItems;
|
|
118
120
|
private extractMewpTestCaseId;
|
|
119
121
|
private buildTestCaseStepsXmlMap;
|
|
120
122
|
private extractStepsXmlFromTestCaseItem;
|
|
@@ -170,6 +172,7 @@ export default class ResultDataProvider {
|
|
|
170
172
|
private extractLinkedWorkItemIdsFromRelations;
|
|
171
173
|
private extractMewpRequirementIdentifier;
|
|
172
174
|
private deriveMewpResponsibility;
|
|
175
|
+
private deriveMewpRequirementOwner;
|
|
173
176
|
private deriveMewpTestCaseResponsibility;
|
|
174
177
|
private deriveMewpSubSystem;
|
|
175
178
|
private resolveBugResponsibility;
|
|
@@ -534,9 +534,14 @@ class ResultDataProvider {
|
|
|
534
534
|
}
|
|
535
535
|
}
|
|
536
536
|
const preloadedStepXmlCount = stepsXmlByTestCase.size;
|
|
537
|
+
const latestWorkItemMapStats = await this.enrichMewpTestCaseMapsFromLatestWorkItems(projectName, [...allTestCaseIds], stepsXmlByTestCase, testCaseTitleMap, testCaseDescriptionMap);
|
|
537
538
|
const fallbackStepLoadStats = await this.enrichMewpStepsXmlMapFromWorkItems(projectName, [...allTestCaseIds], stepsXmlByTestCase);
|
|
538
539
|
logger_1.default.info(`MEWP internal validation steps source summary: testCases=${allTestCaseIds.size} ` +
|
|
539
|
-
`fromSuitePayload=${preloadedStepXmlCount}
|
|
540
|
+
`fromSuitePayload=${preloadedStepXmlCount} ` +
|
|
541
|
+
`fromLatestWorkItem=${latestWorkItemMapStats.stepsLoadedFromLatest} ` +
|
|
542
|
+
`titleFromLatest=${latestWorkItemMapStats.titleLoadedFromLatest} ` +
|
|
543
|
+
`descriptionFromLatest=${latestWorkItemMapStats.descriptionLoadedFromLatest} ` +
|
|
544
|
+
`fromWorkItemFallback=${fallbackStepLoadStats.loadedFromFallback} ` +
|
|
540
545
|
`stepsXmlAvailable=${stepsXmlByTestCase.size} unresolved=${fallbackStepLoadStats.unresolvedCount}`);
|
|
541
546
|
const validL2BaseKeys = new Set([...requirementFamilies.keys()]);
|
|
542
547
|
const diagnostics = {
|
|
@@ -608,19 +613,6 @@ class ResultDataProvider {
|
|
|
608
613
|
mentionedCodesByBase.set(baseKey, new Set());
|
|
609
614
|
mentionedCodesByBase.get(baseKey).add(code);
|
|
610
615
|
}
|
|
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
616
|
// Direction A logic:
|
|
625
617
|
// 1) Base mention ("SR0054") is parent-level and considered covered only when
|
|
626
618
|
// the whole family is covered across scoped test cases:
|
|
@@ -643,81 +635,30 @@ class ResultDataProvider {
|
|
|
643
635
|
const requiredFamilyMembers = specificFamilyMembers.length > 0 ? specificFamilyMembers : normalizedFamilyMembers;
|
|
644
636
|
// Base mention ("SR0054") requires full family coverage across selected test cases.
|
|
645
637
|
if (hasBaseMention) {
|
|
646
|
-
const missingRequiredFamilyMembers = requiredFamilyMembers.filter((memberCode) => !familyLinkedCodes.has(memberCode));
|
|
647
638
|
const isWholeFamilyCovered = requiredFamilyMembers.every((memberCode) => familyLinkedCodes.has(memberCode));
|
|
648
639
|
if (!isWholeFamilyCovered) {
|
|
649
640
|
missingBaseWhenFamilyUncovered.add(baseKey);
|
|
650
641
|
}
|
|
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
642
|
}
|
|
670
643
|
// Specific mention ("SR0054-1") validates as exact-match only across scoped test cases.
|
|
671
644
|
const missingSpecificMembers = mentionedSpecificMembers.filter((code) => !familyLinkedCodes.has(code));
|
|
672
645
|
for (const code of missingSpecificMembers) {
|
|
673
646
|
missingSpecificMentionedNoFamily.add(code);
|
|
674
647
|
}
|
|
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
648
|
continue;
|
|
689
649
|
}
|
|
690
650
|
// Fallback path when family data is unavailable for this base key.
|
|
691
|
-
const fallbackMissingSpecific = [];
|
|
692
|
-
let fallbackMissingBase = false;
|
|
693
651
|
for (const code of mentionedCodes) {
|
|
694
652
|
const hasSpecificSuffix = /-\d+$/.test(code);
|
|
695
653
|
if (hasSpecificSuffix) {
|
|
696
654
|
if (!linkedFullCodesAcrossTestCases.has(code)) {
|
|
697
655
|
missingSpecificMentionedNoFamily.add(code);
|
|
698
|
-
fallbackMissingSpecific.push(code);
|
|
699
656
|
}
|
|
700
657
|
}
|
|
701
658
|
else if (!linkedBaseKeysAcrossTestCases.has(baseKey)) {
|
|
702
659
|
missingBaseWhenFamilyUncovered.add(baseKey);
|
|
703
|
-
fallbackMissingBase = true;
|
|
704
660
|
}
|
|
705
661
|
}
|
|
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
662
|
}
|
|
722
663
|
// Direction B is family-based: if any member of a family is mentioned in Expected Result,
|
|
723
664
|
// linked members of that same family are not considered "linked but not mentioned".
|
|
@@ -757,14 +698,6 @@ class ResultDataProvider {
|
|
|
757
698
|
const stepRef = mentionedBaseFirstStep.get(baseKey) || 'Step ?';
|
|
758
699
|
appendMentionedButNotLinked(baseKey, stepRef);
|
|
759
700
|
}
|
|
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
701
|
const sortedExtraLinked = [...new Set(extraLinked)]
|
|
769
702
|
.map((code) => this.normalizeMewpRequirementCodeWithSuffix(code))
|
|
770
703
|
.filter((code) => !!code)
|
|
@@ -799,18 +732,20 @@ class ResultDataProvider {
|
|
|
799
732
|
const validationStatus = mentionedButNotLinked || linkedButNotMentioned ? 'Fail' : 'Pass';
|
|
800
733
|
if (validationStatus === 'Fail')
|
|
801
734
|
diagnostics.failingRows += 1;
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
735
|
+
if (traceCurrentTestCase) {
|
|
736
|
+
logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_DIAGNOSTICS_TAG, {
|
|
737
|
+
testCaseId,
|
|
738
|
+
parsedSteps: executableSteps.length,
|
|
739
|
+
stepsWithMentions: mentionEntries.length,
|
|
740
|
+
customerIdsFound: mentionedL2Only.size,
|
|
741
|
+
linkedRequirements: linkedFullCodes.size,
|
|
742
|
+
mentionedButNotLinked: sortedMissingSpecificMentionedNoFamily.length +
|
|
743
|
+
sortedMissingBaseWhenFamilyUncovered.length,
|
|
744
|
+
linkedButNotMentioned: sortedExtraLinked.length,
|
|
745
|
+
status: validationStatus,
|
|
746
|
+
customerIdSample: [...mentionedL2Only].slice(0, 5).join(', '),
|
|
747
|
+
}));
|
|
748
|
+
}
|
|
814
749
|
rows.push({
|
|
815
750
|
'Test Case ID': testCaseId,
|
|
816
751
|
'Test Case Title': String(testCaseTitleMap.get(testCaseId) || '').trim(),
|
|
@@ -928,11 +863,17 @@ class ResultDataProvider {
|
|
|
928
863
|
createMewpCoverageRow(requirement, runStatus, bug, linkedL3L4) {
|
|
929
864
|
const l2ReqIdNumeric = Number((requirement === null || requirement === void 0 ? void 0 : requirement.workItemId) || 0);
|
|
930
865
|
const l2ReqId = l2ReqIdNumeric > 0 ? String(l2ReqIdNumeric) : '';
|
|
866
|
+
const srNumber = this.normalizeMewpRequirementCodeWithSuffix((requirement === null || requirement === void 0 ? void 0 : requirement.requirementId) || '');
|
|
931
867
|
const l2ReqTitle = this.toMewpComparableText(requirement.title);
|
|
868
|
+
const reqName = this.deriveMewpRequirementDisplayName(srNumber, l2ReqTitle);
|
|
869
|
+
const l2Owner = this.toMewpComparableText(requirement.owner);
|
|
932
870
|
const l2SubSystem = this.toMewpComparableText(requirement.subSystem);
|
|
933
871
|
return {
|
|
934
872
|
'L2 REQ ID': l2ReqId,
|
|
935
|
-
'
|
|
873
|
+
'SR #': srNumber,
|
|
874
|
+
'L2 REQ Title': reqName,
|
|
875
|
+
'L2 REQ Full Title': l2ReqTitle,
|
|
876
|
+
'L2 Owner': l2Owner,
|
|
936
877
|
'L2 SubSystem': l2SubSystem,
|
|
937
878
|
'L2 Run Status': runStatus,
|
|
938
879
|
'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 +885,20 @@ class ResultDataProvider {
|
|
|
944
885
|
'L4 REQ Title': String((linkedL3L4 === null || linkedL3L4 === void 0 ? void 0 : linkedL3L4.l4Title) || '').trim(),
|
|
945
886
|
};
|
|
946
887
|
}
|
|
888
|
+
deriveMewpRequirementDisplayName(requirementCode, title) {
|
|
889
|
+
const normalizedTitle = this.toMewpComparableText(title);
|
|
890
|
+
if (!normalizedTitle)
|
|
891
|
+
return '';
|
|
892
|
+
const normalizedCode = this.normalizeMewpRequirementCodeWithSuffix(requirementCode || '');
|
|
893
|
+
if (!normalizedCode)
|
|
894
|
+
return normalizedTitle;
|
|
895
|
+
const escapedCode = normalizedCode.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
896
|
+
const codePrefixPattern = new RegExp(`^${escapedCode}(?:\\s*[:\\-–—]\\s*|\\s+)`, 'i');
|
|
897
|
+
const withoutCodePrefix = normalizedTitle.replace(codePrefixPattern, '').trim();
|
|
898
|
+
if (!withoutCodePrefix)
|
|
899
|
+
return normalizedTitle;
|
|
900
|
+
return withoutCodePrefix;
|
|
901
|
+
}
|
|
947
902
|
createEmptyMewpCoverageBugCell() {
|
|
948
903
|
return { id: '', title: '', responsibility: '' };
|
|
949
904
|
}
|
|
@@ -1199,7 +1154,9 @@ class ResultDataProvider {
|
|
|
1199
1154
|
const baseKey = String((requirement === null || requirement === void 0 ? void 0 : requirement.baseKey) || '').trim();
|
|
1200
1155
|
if (!baseKey)
|
|
1201
1156
|
continue;
|
|
1202
|
-
const
|
|
1157
|
+
const rawOwner = this.toMewpComparableText(requirement === null || requirement === void 0 ? void 0 : requirement.owner);
|
|
1158
|
+
const normalized = this.resolveMewpResponsibility(rawOwner) ||
|
|
1159
|
+
this.resolveMewpResponsibility(this.toMewpComparableText(requirement === null || requirement === void 0 ? void 0 : requirement.responsibility));
|
|
1203
1160
|
if (!normalized)
|
|
1204
1161
|
continue;
|
|
1205
1162
|
const existing = out.get(baseKey) || '';
|
|
@@ -1338,6 +1295,63 @@ class ResultDataProvider {
|
|
|
1338
1295
|
}
|
|
1339
1296
|
return map;
|
|
1340
1297
|
}
|
|
1298
|
+
async enrichMewpTestCaseMapsFromLatestWorkItems(projectName, testCaseIds, stepsXmlByTestCase, testCaseTitleMap, testCaseDescriptionMap) {
|
|
1299
|
+
var _a, _b;
|
|
1300
|
+
const uniqueIds = [...new Set(testCaseIds)]
|
|
1301
|
+
.map((id) => Number(id))
|
|
1302
|
+
.filter((id) => Number.isFinite(id) && id > 0);
|
|
1303
|
+
if (uniqueIds.length === 0) {
|
|
1304
|
+
return {
|
|
1305
|
+
stepsLoadedFromLatest: 0,
|
|
1306
|
+
titleLoadedFromLatest: 0,
|
|
1307
|
+
descriptionLoadedFromLatest: 0,
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
let stepsLoadedFromLatest = 0;
|
|
1311
|
+
let titleLoadedFromLatest = 0;
|
|
1312
|
+
let descriptionLoadedFromLatest = 0;
|
|
1313
|
+
try {
|
|
1314
|
+
const latestWorkItems = await this.fetchWorkItemsByIds(projectName, uniqueIds, false);
|
|
1315
|
+
for (const workItem of latestWorkItems || []) {
|
|
1316
|
+
const id = Number((workItem === null || workItem === void 0 ? void 0 : workItem.id) || 0);
|
|
1317
|
+
if (!Number.isFinite(id) || id <= 0)
|
|
1318
|
+
continue;
|
|
1319
|
+
const fields = (workItem === null || workItem === void 0 ? void 0 : workItem.fields) || {};
|
|
1320
|
+
const latestStepsXml = this.extractStepsXmlFromFieldsMap(fields);
|
|
1321
|
+
if (latestStepsXml) {
|
|
1322
|
+
const previous = String(stepsXmlByTestCase.get(id) || '');
|
|
1323
|
+
if (previous !== latestStepsXml) {
|
|
1324
|
+
stepsLoadedFromLatest += 1;
|
|
1325
|
+
}
|
|
1326
|
+
stepsXmlByTestCase.set(id, latestStepsXml);
|
|
1327
|
+
}
|
|
1328
|
+
const latestTitle = this.toMewpComparableText((_a = this.getFieldValueByName(fields, 'System.Title')) !== null && _a !== void 0 ? _a : this.getFieldValueByName(fields, 'Title'));
|
|
1329
|
+
if (latestTitle) {
|
|
1330
|
+
const previous = String(testCaseTitleMap.get(id) || '');
|
|
1331
|
+
if (previous !== latestTitle) {
|
|
1332
|
+
titleLoadedFromLatest += 1;
|
|
1333
|
+
}
|
|
1334
|
+
testCaseTitleMap.set(id, latestTitle);
|
|
1335
|
+
}
|
|
1336
|
+
const latestDescription = this.toMewpComparableText((_b = this.getFieldValueByName(fields, 'System.Description')) !== null && _b !== void 0 ? _b : this.getFieldValueByName(fields, 'Description'));
|
|
1337
|
+
if (latestDescription) {
|
|
1338
|
+
const previous = String(testCaseDescriptionMap.get(id) || '');
|
|
1339
|
+
if (previous !== latestDescription) {
|
|
1340
|
+
descriptionLoadedFromLatest += 1;
|
|
1341
|
+
}
|
|
1342
|
+
testCaseDescriptionMap.set(id, latestDescription);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
catch (error) {
|
|
1347
|
+
logger_1.default.warn(`MEWP internal validation: failed to load latest test-case fields: ${(error === null || error === void 0 ? void 0 : error.message) || error}`);
|
|
1348
|
+
}
|
|
1349
|
+
return {
|
|
1350
|
+
stepsLoadedFromLatest,
|
|
1351
|
+
titleLoadedFromLatest,
|
|
1352
|
+
descriptionLoadedFromLatest,
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1341
1355
|
extractMewpTestCaseId(runResult) {
|
|
1342
1356
|
var _a;
|
|
1343
1357
|
const testCaseId = Number((runResult === null || runResult === void 0 ? void 0 : runResult.testCaseId) || ((_a = runResult === null || runResult === void 0 ? void 0 : runResult.testCase) === null || _a === void 0 ? void 0 : _a.id) || 0);
|
|
@@ -1793,6 +1807,7 @@ class ResultDataProvider {
|
|
|
1793
1807
|
requirementId,
|
|
1794
1808
|
baseKey: this.toRequirementKey(requirementId),
|
|
1795
1809
|
title: this.toMewpComparableText((fields === null || fields === void 0 ? void 0 : fields['System.Title']) || (wi === null || wi === void 0 ? void 0 : wi.title)),
|
|
1810
|
+
owner: this.deriveMewpRequirementOwner(fields),
|
|
1796
1811
|
subSystem: this.deriveMewpSubSystem(fields),
|
|
1797
1812
|
responsibility: this.deriveMewpResponsibility(fields),
|
|
1798
1813
|
linkedTestCaseIds: this.extractLinkedTestCaseIdsFromRequirement((wi === null || wi === void 0 ? void 0 : wi.relations) || []),
|
|
@@ -1835,6 +1850,8 @@ class ResultDataProvider {
|
|
|
1835
1850
|
score += 2;
|
|
1836
1851
|
if (String((item === null || item === void 0 ? void 0 : item.title) || '').trim())
|
|
1837
1852
|
score += 1;
|
|
1853
|
+
if (String((item === null || item === void 0 ? void 0 : item.owner) || '').trim())
|
|
1854
|
+
score += 1;
|
|
1838
1855
|
if (String((item === null || item === void 0 ? void 0 : item.subSystem) || '').trim())
|
|
1839
1856
|
score += 1;
|
|
1840
1857
|
if (String((item === null || item === void 0 ? void 0 : item.responsibility) || '').trim())
|
|
@@ -1868,14 +1885,15 @@ class ResultDataProvider {
|
|
|
1868
1885
|
}
|
|
1869
1886
|
return [...families.entries()]
|
|
1870
1887
|
.map(([baseKey, family]) => {
|
|
1871
|
-
var _a, _b, _c, _d, _e;
|
|
1888
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1872
1889
|
return ({
|
|
1873
1890
|
workItemId: Number(((_a = family === null || family === void 0 ? void 0 : family.representative) === null || _a === void 0 ? void 0 : _a.workItemId) || 0),
|
|
1874
1891
|
requirementId: String(((_b = family === null || family === void 0 ? void 0 : family.representative) === null || _b === void 0 ? void 0 : _b.requirementId) || baseKey),
|
|
1875
1892
|
baseKey,
|
|
1876
1893
|
title: String(((_c = family === null || family === void 0 ? void 0 : family.representative) === null || _c === void 0 ? void 0 : _c.title) || ''),
|
|
1877
|
-
|
|
1878
|
-
|
|
1894
|
+
owner: String(((_d = family === null || family === void 0 ? void 0 : family.representative) === null || _d === void 0 ? void 0 : _d.owner) || ''),
|
|
1895
|
+
subSystem: String(((_e = family === null || family === void 0 ? void 0 : family.representative) === null || _e === void 0 ? void 0 : _e.subSystem) || ''),
|
|
1896
|
+
responsibility: String(((_f = family === null || family === void 0 ? void 0 : family.representative) === null || _f === void 0 ? void 0 : _f.responsibility) || ''),
|
|
1879
1897
|
linkedTestCaseIds: [...family.linkedTestCaseIds].sort((a, b) => a - b),
|
|
1880
1898
|
});
|
|
1881
1899
|
})
|
|
@@ -2304,6 +2322,24 @@ class ResultDataProvider {
|
|
|
2304
2322
|
}
|
|
2305
2323
|
return '';
|
|
2306
2324
|
}
|
|
2325
|
+
// L2 owner is sourced only from requirement SAPWBS fields.
|
|
2326
|
+
deriveMewpRequirementOwner(fields) {
|
|
2327
|
+
const directCandidates = [fields === null || fields === void 0 ? void 0 : fields['Custom.SAPWBS'], fields === null || fields === void 0 ? void 0 : fields['SAPWBS']];
|
|
2328
|
+
for (const candidate of directCandidates) {
|
|
2329
|
+
const normalized = this.toMewpComparableText(candidate);
|
|
2330
|
+
if (normalized)
|
|
2331
|
+
return normalized;
|
|
2332
|
+
}
|
|
2333
|
+
for (const [key, value] of Object.entries(fields || {})) {
|
|
2334
|
+
const normalizedKey = String(key || '').toLowerCase();
|
|
2335
|
+
if (!normalizedKey.includes('sapwbs'))
|
|
2336
|
+
continue;
|
|
2337
|
+
const normalizedValue = this.toMewpComparableText(value);
|
|
2338
|
+
if (normalizedValue)
|
|
2339
|
+
return normalizedValue;
|
|
2340
|
+
}
|
|
2341
|
+
return '';
|
|
2342
|
+
}
|
|
2307
2343
|
// Test-case responsibility must come from test-case path context (not SAPWBS).
|
|
2308
2344
|
deriveMewpTestCaseResponsibility(fields) {
|
|
2309
2345
|
const areaPathCandidates = [
|
|
@@ -4660,7 +4696,9 @@ ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_REF = 'Assumptions';
|
|
|
4660
4696
|
ResultDataProvider.MEWP_INTERNAL_VALIDATION_ASSUMPTIONS_HEADER_PATTERN = /assumptions/i;
|
|
4661
4697
|
ResultDataProvider.MEWP_L2_COVERAGE_COLUMNS = [
|
|
4662
4698
|
'L2 REQ ID',
|
|
4699
|
+
'SR #',
|
|
4663
4700
|
'L2 REQ Title',
|
|
4701
|
+
'L2 Owner',
|
|
4664
4702
|
'L2 SubSystem',
|
|
4665
4703
|
'L2 Run Status',
|
|
4666
4704
|
'Bug ID',
|