@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.
@@ -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
- logger_1.default.debug(this.buildTaggedLogMessage(ResultDataProvider.MEWP_INTERNAL_VALIDATION_DIAGNOSTICS_TAG, {
803
- testCaseId,
804
- parsedSteps: executableSteps.length,
805
- stepsWithMentions: mentionEntries.length,
806
- customerIdsFound: mentionedL2Only.size,
807
- linkedRequirements: linkedFullCodes.size,
808
- mentionedButNotLinked: sortedMissingSpecificMentionedNoFamily.length +
809
- sortedMissingBaseWhenFamilyUncovered.length,
810
- linkedButNotMentioned: sortedExtraLinked.length,
811
- status: validationStatus,
812
- customerIdSample: [...mentionedL2Only].slice(0, 5).join(', '),
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
- 'L2 REQ Title': l2ReqTitle,
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 normalized = this.resolveMewpResponsibility(this.toMewpComparableText(requirement === null || requirement === void 0 ? void 0 : requirement.responsibility));
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
- subSystem: String(((_d = family === null || family === void 0 ? void 0 : family.representative) === null || _d === void 0 ? void 0 : _d.subSystem) || ''),
1878
- responsibility: String(((_e = family === null || family === void 0 ? void 0 : family.representative) === null || _e === void 0 ? void 0 : _e.responsibility) || ''),
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',