@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.
@@ -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} fromWorkItemFallback=${fallbackStepLoadStats.loadedFromFallback} ` +
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
- 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
- }));
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
- 'L2 REQ Title': l2ReqTitle,
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 normalized = this.resolveMewpResponsibility(this.toMewpComparableText(requirement === null || requirement === void 0 ? void 0 : requirement.responsibility));
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
- 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) || ''),
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',