@elisra-devops/docgen-data-provider 1.82.0 → 1.84.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/modules/ResultDataProvider.d.ts +3 -0
- package/bin/modules/ResultDataProvider.js +83 -5
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/tests/modules/ResultDataProvider.test.js +144 -0
- package/bin/tests/modules/ResultDataProvider.test.js.map +1 -1
- package/bin/utils/mewpExternalIngestionUtils.js +9 -0
- package/bin/utils/mewpExternalIngestionUtils.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/ResultDataProvider.ts +95 -4
- package/src/tests/modules/ResultDataProvider.test.ts +170 -0
- package/src/utils/mewpExternalIngestionUtils.ts +11 -0
|
@@ -101,7 +101,10 @@ export default class ResultDataProvider {
|
|
|
101
101
|
private buildMewpTestCaseTitleMap;
|
|
102
102
|
private extractMewpTestCaseId;
|
|
103
103
|
private buildTestCaseStepsXmlMap;
|
|
104
|
+
private extractStepsXmlFromTestCaseItem;
|
|
105
|
+
private extractStepsXmlFromFieldsMap;
|
|
104
106
|
private extractStepsXmlFromWorkItemFields;
|
|
107
|
+
private enrichMewpStepsXmlMapFromWorkItems;
|
|
105
108
|
private classifyRequirementStepOutcome;
|
|
106
109
|
private accumulateRequirementCountsFromActionResults;
|
|
107
110
|
private resolveRequirementStatusForWindow;
|
|
@@ -506,6 +506,11 @@ class ResultDataProvider {
|
|
|
506
506
|
allTestCaseIds.add(id);
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
|
+
const preloadedStepXmlCount = stepsXmlByTestCase.size;
|
|
510
|
+
const fallbackStepLoadStats = await this.enrichMewpStepsXmlMapFromWorkItems(projectName, [...allTestCaseIds], stepsXmlByTestCase);
|
|
511
|
+
logger_1.default.info(`MEWP internal validation steps source summary: testCases=${allTestCaseIds.size} ` +
|
|
512
|
+
`fromSuitePayload=${preloadedStepXmlCount} fromWorkItemFallback=${fallbackStepLoadStats.loadedFromFallback} ` +
|
|
513
|
+
`stepsXmlAvailable=${stepsXmlByTestCase.size} unresolved=${fallbackStepLoadStats.unresolvedCount}`);
|
|
509
514
|
const validL2BaseKeys = new Set([...requirementFamilies.keys()]);
|
|
510
515
|
const diagnostics = {
|
|
511
516
|
totalTestCases: 0,
|
|
@@ -580,7 +585,14 @@ class ResultDataProvider {
|
|
|
580
585
|
return !linkedBaseKeys.has(baseKey);
|
|
581
586
|
});
|
|
582
587
|
const missingFamily = [...expectedFamilyCodes].filter((code) => !linkedFullCodes.has(code));
|
|
583
|
-
|
|
588
|
+
// Direction B is family-based: if any member of a family is mentioned in Expected Result,
|
|
589
|
+
// linked members of that same family are not considered "linked but not mentioned".
|
|
590
|
+
const extraLinked = [...linkedFullCodes].filter((code) => {
|
|
591
|
+
const baseKey = this.toRequirementKey(code);
|
|
592
|
+
if (!baseKey)
|
|
593
|
+
return false;
|
|
594
|
+
return !mentionedBaseKeys.has(baseKey);
|
|
595
|
+
});
|
|
584
596
|
const mentionedButNotLinkedByStep = new Map();
|
|
585
597
|
const appendMentionedButNotLinked = (requirementId, stepRef) => {
|
|
586
598
|
const normalizedRequirementId = this.normalizeMewpRequirementCodeWithSuffix(requirementId);
|
|
@@ -1134,18 +1146,17 @@ class ResultDataProvider {
|
|
|
1134
1146
|
return Number.isFinite(testCaseId) ? testCaseId : 0;
|
|
1135
1147
|
}
|
|
1136
1148
|
buildTestCaseStepsXmlMap(testData) {
|
|
1137
|
-
var _a
|
|
1149
|
+
var _a;
|
|
1138
1150
|
const map = new Map();
|
|
1139
1151
|
for (const suite of testData || []) {
|
|
1140
1152
|
const testCasesItems = Array.isArray(suite === null || suite === void 0 ? void 0 : suite.testCasesItems) ? suite.testCasesItems : [];
|
|
1141
1153
|
for (const testCase of testCasesItems) {
|
|
1142
|
-
const id = Number((_a = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _a === void 0 ? void 0 : _a.id);
|
|
1154
|
+
const id = Number(((_a = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _a === void 0 ? void 0 : _a.id) || (testCase === null || testCase === void 0 ? void 0 : testCase.testCaseId) || (testCase === null || testCase === void 0 ? void 0 : testCase.id) || 0);
|
|
1143
1155
|
if (!Number.isFinite(id))
|
|
1144
1156
|
continue;
|
|
1145
1157
|
if (map.has(id))
|
|
1146
1158
|
continue;
|
|
1147
|
-
const
|
|
1148
|
-
const stepsXml = this.extractStepsXmlFromWorkItemFields(fields);
|
|
1159
|
+
const stepsXml = this.extractStepsXmlFromTestCaseItem(testCase);
|
|
1149
1160
|
if (stepsXml) {
|
|
1150
1161
|
map.set(id, stepsXml);
|
|
1151
1162
|
}
|
|
@@ -1153,6 +1164,43 @@ class ResultDataProvider {
|
|
|
1153
1164
|
}
|
|
1154
1165
|
return map;
|
|
1155
1166
|
}
|
|
1167
|
+
extractStepsXmlFromTestCaseItem(testCase) {
|
|
1168
|
+
var _a, _b, _c, _d, _e;
|
|
1169
|
+
const fieldsList = (_a = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _a === void 0 ? void 0 : _a.workItemFields;
|
|
1170
|
+
const fromFieldList = this.extractStepsXmlFromWorkItemFields(fieldsList);
|
|
1171
|
+
if (fromFieldList)
|
|
1172
|
+
return fromFieldList;
|
|
1173
|
+
const workItemFields = ((_b = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _b === void 0 ? void 0 : _b.fields) || {};
|
|
1174
|
+
const fromFieldsMap = this.extractStepsXmlFromFieldsMap(workItemFields);
|
|
1175
|
+
if (fromFieldsMap)
|
|
1176
|
+
return fromFieldsMap;
|
|
1177
|
+
const directCandidates = [
|
|
1178
|
+
testCase === null || testCase === void 0 ? void 0 : testCase.stepsResultXml,
|
|
1179
|
+
(_c = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _c === void 0 ? void 0 : _c.stepsResultXml,
|
|
1180
|
+
(_d = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _d === void 0 ? void 0 : _d['Microsoft.VSTS.TCM.Steps'],
|
|
1181
|
+
(_e = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _e === void 0 ? void 0 : _e.steps,
|
|
1182
|
+
];
|
|
1183
|
+
for (const candidate of directCandidates) {
|
|
1184
|
+
const value = String(candidate || '').trim();
|
|
1185
|
+
if (value)
|
|
1186
|
+
return value;
|
|
1187
|
+
}
|
|
1188
|
+
return '';
|
|
1189
|
+
}
|
|
1190
|
+
extractStepsXmlFromFieldsMap(fields) {
|
|
1191
|
+
const directCandidates = [
|
|
1192
|
+
fields === null || fields === void 0 ? void 0 : fields['Microsoft.VSTS.TCM.Steps'],
|
|
1193
|
+
fields === null || fields === void 0 ? void 0 : fields['microsoft.vsts.tcm.steps'],
|
|
1194
|
+
fields === null || fields === void 0 ? void 0 : fields['Steps'],
|
|
1195
|
+
fields === null || fields === void 0 ? void 0 : fields['steps'],
|
|
1196
|
+
];
|
|
1197
|
+
for (const candidate of directCandidates) {
|
|
1198
|
+
const value = String(candidate || '').trim();
|
|
1199
|
+
if (value)
|
|
1200
|
+
return value;
|
|
1201
|
+
}
|
|
1202
|
+
return '';
|
|
1203
|
+
}
|
|
1156
1204
|
extractStepsXmlFromWorkItemFields(workItemFields) {
|
|
1157
1205
|
if (!Array.isArray(workItemFields))
|
|
1158
1206
|
return '';
|
|
@@ -1171,6 +1219,36 @@ class ResultDataProvider {
|
|
|
1171
1219
|
}
|
|
1172
1220
|
return '';
|
|
1173
1221
|
}
|
|
1222
|
+
async enrichMewpStepsXmlMapFromWorkItems(projectName, testCaseIds, stepsXmlByTestCase) {
|
|
1223
|
+
const missingIds = [...new Set(testCaseIds)]
|
|
1224
|
+
.map((id) => Number(id))
|
|
1225
|
+
.filter((id) => Number.isFinite(id) && id > 0)
|
|
1226
|
+
.filter((id) => !stepsXmlByTestCase.has(id));
|
|
1227
|
+
if (missingIds.length === 0) {
|
|
1228
|
+
return { loadedFromFallback: 0, unresolvedCount: 0 };
|
|
1229
|
+
}
|
|
1230
|
+
let loadedFromFallback = 0;
|
|
1231
|
+
try {
|
|
1232
|
+
const workItems = await this.fetchWorkItemsByIds(projectName, missingIds, false);
|
|
1233
|
+
for (const workItem of workItems || []) {
|
|
1234
|
+
const id = Number((workItem === null || workItem === void 0 ? void 0 : workItem.id) || 0);
|
|
1235
|
+
if (!Number.isFinite(id) || id <= 0 || stepsXmlByTestCase.has(id))
|
|
1236
|
+
continue;
|
|
1237
|
+
const stepsXml = this.extractStepsXmlFromFieldsMap((workItem === null || workItem === void 0 ? void 0 : workItem.fields) || {});
|
|
1238
|
+
if (!stepsXml)
|
|
1239
|
+
continue;
|
|
1240
|
+
stepsXmlByTestCase.set(id, stepsXml);
|
|
1241
|
+
loadedFromFallback += 1;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
catch (error) {
|
|
1245
|
+
logger_1.default.warn(`MEWP internal validation: failed loading missing steps via work-item fallback: ${(error === null || error === void 0 ? void 0 : error.message) || error}`);
|
|
1246
|
+
}
|
|
1247
|
+
return {
|
|
1248
|
+
loadedFromFallback,
|
|
1249
|
+
unresolvedCount: Math.max(0, missingIds.length - loadedFromFallback),
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1174
1252
|
classifyRequirementStepOutcome(outcome) {
|
|
1175
1253
|
const normalized = String(outcome || '')
|
|
1176
1254
|
.trim()
|