@elisra-devops/docgen-data-provider 1.73.0 → 1.74.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 +11 -1
- package/bin/modules/ResultDataProvider.js +278 -37
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/tests/modules/ResultDataProvider.test.js +113 -9
- package/bin/tests/modules/ResultDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/ResultDataProvider.ts +390 -38
- package/src/tests/modules/ResultDataProvider.test.ts +140 -9
|
@@ -65,7 +65,7 @@ export default class ResultDataProvider {
|
|
|
65
65
|
* Builds MEWP L2 requirement coverage rows for audit reporting.
|
|
66
66
|
* Rows are one Requirement-TestCase pair; uncovered requirements are emitted with empty test-case columns.
|
|
67
67
|
*/
|
|
68
|
-
getMewpL2CoverageFlatResults(testPlanId: string, projectName: string, selectedSuiteIds: number[] | undefined): Promise<{
|
|
68
|
+
getMewpL2CoverageFlatResults(testPlanId: string, projectName: string, selectedSuiteIds: number[] | undefined, linkedQueryRequest?: any): Promise<{
|
|
69
69
|
sheetName: string;
|
|
70
70
|
columnOrder: string[];
|
|
71
71
|
rows: any[];
|
|
@@ -77,6 +77,9 @@ export default class ResultDataProvider {
|
|
|
77
77
|
mapAttachmentsUrl(runResults: any[], project: string): any[];
|
|
78
78
|
private buildMewpCoverageSheetName;
|
|
79
79
|
private createMewpCoverageRow;
|
|
80
|
+
private buildMewpCoverageRows;
|
|
81
|
+
private buildMewpTestCaseTitleMap;
|
|
82
|
+
private extractMewpTestCaseId;
|
|
80
83
|
private buildTestCaseStepsXmlMap;
|
|
81
84
|
private extractStepsXmlFromWorkItemFields;
|
|
82
85
|
private classifyRequirementStepOutcome;
|
|
@@ -85,6 +88,13 @@ export default class ResultDataProvider {
|
|
|
85
88
|
private normalizeRequirementStepText;
|
|
86
89
|
private toRequirementKey;
|
|
87
90
|
private fetchMewpL2Requirements;
|
|
91
|
+
private extractMewpQueryHref;
|
|
92
|
+
private fetchMewpL2RequirementsFromQuery;
|
|
93
|
+
private upsertMewpRequirement;
|
|
94
|
+
private hydrateMewpRequirementsFromWorkItems;
|
|
95
|
+
private getMewpWorkItemType;
|
|
96
|
+
private isMewpRequirementType;
|
|
97
|
+
private isMewpTestCaseType;
|
|
88
98
|
private fetchMewpRequirementTypeNames;
|
|
89
99
|
private fetchWorkItemsByIds;
|
|
90
100
|
private extractLinkedTestCaseIdsFromRequirement;
|
|
@@ -283,8 +283,8 @@ class ResultDataProvider {
|
|
|
283
283
|
* Builds MEWP L2 requirement coverage rows for audit reporting.
|
|
284
284
|
* Rows are one Requirement-TestCase pair; uncovered requirements are emitted with empty test-case columns.
|
|
285
285
|
*/
|
|
286
|
-
async getMewpL2CoverageFlatResults(testPlanId, projectName, selectedSuiteIds) {
|
|
287
|
-
var _a;
|
|
286
|
+
async getMewpL2CoverageFlatResults(testPlanId, projectName, selectedSuiteIds, linkedQueryRequest) {
|
|
287
|
+
var _a, _b;
|
|
288
288
|
const defaultPayload = {
|
|
289
289
|
sheetName: `MEWP L2 Coverage - Plan ${testPlanId}`,
|
|
290
290
|
columnOrder: [...ResultDataProvider.MEWP_L2_COVERAGE_COLUMNS],
|
|
@@ -294,27 +294,30 @@ class ResultDataProvider {
|
|
|
294
294
|
const planName = await this.fetchTestPlanName(testPlanId, projectName);
|
|
295
295
|
const suites = await this.fetchTestSuites(testPlanId, projectName, selectedSuiteIds, true);
|
|
296
296
|
const testData = await this.fetchTestData(suites, projectName, testPlanId, false);
|
|
297
|
-
const requirements = await this.fetchMewpL2Requirements(projectName);
|
|
297
|
+
const requirements = await this.fetchMewpL2Requirements(projectName, linkedQueryRequest);
|
|
298
298
|
if (requirements.length === 0) {
|
|
299
299
|
return Object.assign(Object.assign({}, defaultPayload), { sheetName: this.buildMewpCoverageSheetName(planName, testPlanId) });
|
|
300
300
|
}
|
|
301
301
|
const requirementIndex = new Map();
|
|
302
|
+
const observedTestCaseIdsByRequirement = new Map();
|
|
302
303
|
const requirementKeys = new Set();
|
|
303
304
|
requirements.forEach((requirement) => {
|
|
304
305
|
const key = this.toRequirementKey(requirement.requirementId);
|
|
305
306
|
if (!key)
|
|
306
307
|
return;
|
|
307
308
|
requirementKeys.add(key);
|
|
308
|
-
if (!requirementIndex.has(key)) {
|
|
309
|
-
requirementIndex.set(key, { passed: 0, failed: 0, notRun: 0 });
|
|
310
|
-
}
|
|
311
309
|
});
|
|
312
310
|
const parsedDefinitionStepsByTestCase = new Map();
|
|
313
311
|
const testCaseStepsXmlMap = this.buildTestCaseStepsXmlMap(testData);
|
|
312
|
+
const testCaseTitleMap = this.buildMewpTestCaseTitleMap(testData);
|
|
314
313
|
const runResults = await this.fetchAllResultDataTestReporter(testData, projectName, [], false, false);
|
|
315
314
|
for (const runResult of runResults) {
|
|
316
|
-
const testCaseId =
|
|
317
|
-
const
|
|
315
|
+
const testCaseId = this.extractMewpTestCaseId(runResult);
|
|
316
|
+
const runTestCaseTitle = this.toMewpComparableText(((_a = runResult === null || runResult === void 0 ? void 0 : runResult.testCase) === null || _a === void 0 ? void 0 : _a.name) || (runResult === null || runResult === void 0 ? void 0 : runResult.testCaseName) || (runResult === null || runResult === void 0 ? void 0 : runResult.testCaseTitle));
|
|
317
|
+
if (Number.isFinite(testCaseId) && testCaseId > 0 && runTestCaseTitle && !testCaseTitleMap.has(testCaseId)) {
|
|
318
|
+
testCaseTitleMap.set(testCaseId, runTestCaseTitle);
|
|
319
|
+
}
|
|
320
|
+
const actionResults = Array.isArray((_b = runResult === null || runResult === void 0 ? void 0 : runResult.iteration) === null || _b === void 0 ? void 0 : _b.actionResults)
|
|
318
321
|
? runResult.iteration.actionResults
|
|
319
322
|
: [];
|
|
320
323
|
const hasExecutedRun = Number((runResult === null || runResult === void 0 ? void 0 : runResult.lastRunId) || 0) > 0 && Number((runResult === null || runResult === void 0 ? void 0 : runResult.lastResultId) || 0) > 0;
|
|
@@ -323,7 +326,7 @@ class ResultDataProvider {
|
|
|
323
326
|
if (actionResult === null || actionResult === void 0 ? void 0 : actionResult.isSharedStepTitle)
|
|
324
327
|
continue;
|
|
325
328
|
const stepStatus = this.classifyRequirementStepOutcome(actionResult === null || actionResult === void 0 ? void 0 : actionResult.outcome);
|
|
326
|
-
this.accumulateRequirementCountsFromStepText(`${String((actionResult === null || actionResult === void 0 ? void 0 : actionResult.action) || '')} ${String((actionResult === null || actionResult === void 0 ? void 0 : actionResult.expected) || '')}`, stepStatus, requirementKeys, requirementIndex);
|
|
329
|
+
this.accumulateRequirementCountsFromStepText(`${String((actionResult === null || actionResult === void 0 ? void 0 : actionResult.action) || '')} ${String((actionResult === null || actionResult === void 0 ? void 0 : actionResult.expected) || '')}`, stepStatus, testCaseId, requirementKeys, requirementIndex, observedTestCaseIdsByRequirement);
|
|
327
330
|
}
|
|
328
331
|
continue;
|
|
329
332
|
}
|
|
@@ -345,16 +348,10 @@ class ResultDataProvider {
|
|
|
345
348
|
for (const step of definitionSteps) {
|
|
346
349
|
if (step === null || step === void 0 ? void 0 : step.isSharedStepTitle)
|
|
347
350
|
continue;
|
|
348
|
-
this.accumulateRequirementCountsFromStepText(`${String((step === null || step === void 0 ? void 0 : step.action) || '')} ${String((step === null || step === void 0 ? void 0 : step.expected) || '')}`, 'notRun', requirementKeys, requirementIndex);
|
|
351
|
+
this.accumulateRequirementCountsFromStepText(`${String((step === null || step === void 0 ? void 0 : step.action) || '')} ${String((step === null || step === void 0 ? void 0 : step.expected) || '')}`, 'notRun', testCaseId, requirementKeys, requirementIndex, observedTestCaseIdsByRequirement);
|
|
349
352
|
}
|
|
350
353
|
}
|
|
351
|
-
const rows =
|
|
352
|
-
const key = this.toRequirementKey(requirement.requirementId);
|
|
353
|
-
const summary = key && requirementIndex.has(key)
|
|
354
|
-
? requirementIndex.get(key)
|
|
355
|
-
: { passed: 0, failed: 0, notRun: 0 };
|
|
356
|
-
return this.createMewpCoverageRow(requirement, summary);
|
|
357
|
-
});
|
|
354
|
+
const rows = this.buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, testCaseTitleMap);
|
|
358
355
|
return {
|
|
359
356
|
sheetName: this.buildMewpCoverageSheetName(planName, testPlanId),
|
|
360
357
|
columnOrder: [...ResultDataProvider.MEWP_L2_COVERAGE_COLUMNS],
|
|
@@ -397,22 +394,100 @@ class ResultDataProvider {
|
|
|
397
394
|
const suffix = String(planName || '').trim() || `Plan ${testPlanId}`;
|
|
398
395
|
return `MEWP L2 Coverage - ${suffix}`;
|
|
399
396
|
}
|
|
400
|
-
createMewpCoverageRow(requirement, stepSummary) {
|
|
401
|
-
const
|
|
402
|
-
const
|
|
403
|
-
const customerRequirement = [requirementId, requirementTitle].filter(Boolean).join(' - ');
|
|
397
|
+
createMewpCoverageRow(requirement, testCaseId, testCaseTitle, stepSummary) {
|
|
398
|
+
const customerId = String(requirement.requirementId || '').trim();
|
|
399
|
+
const customerTitle = String(requirement.title || '').trim();
|
|
404
400
|
const responsibility = String(requirement.responsibility || '').trim();
|
|
401
|
+
const safeTestCaseId = Number.isFinite(testCaseId) && Number(testCaseId) > 0 ? Number(testCaseId) : '';
|
|
405
402
|
return {
|
|
406
|
-
'Customer
|
|
407
|
-
'
|
|
408
|
-
'
|
|
409
|
-
|
|
410
|
-
'
|
|
403
|
+
'Customer ID': customerId,
|
|
404
|
+
'Title (Customer name)': customerTitle,
|
|
405
|
+
'Responsibility - SAPWBS (ESUK/IL)': responsibility,
|
|
406
|
+
'Test case id': safeTestCaseId,
|
|
407
|
+
'Test case title': String(testCaseTitle || '').trim(),
|
|
411
408
|
'Number of passed steps': Number.isFinite(stepSummary === null || stepSummary === void 0 ? void 0 : stepSummary.passed) ? stepSummary.passed : 0,
|
|
412
409
|
'Number of failed steps': Number.isFinite(stepSummary === null || stepSummary === void 0 ? void 0 : stepSummary.failed) ? stepSummary.failed : 0,
|
|
413
|
-
'Number of
|
|
410
|
+
'Number of not run tests': Number.isFinite(stepSummary === null || stepSummary === void 0 ? void 0 : stepSummary.notRun) ? stepSummary.notRun : 0,
|
|
414
411
|
};
|
|
415
412
|
}
|
|
413
|
+
buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, testCaseTitleMap) {
|
|
414
|
+
var _a;
|
|
415
|
+
const rows = [];
|
|
416
|
+
for (const requirement of requirements) {
|
|
417
|
+
const key = this.toRequirementKey(requirement.requirementId);
|
|
418
|
+
const linkedTestCaseIds = ((requirement === null || requirement === void 0 ? void 0 : requirement.linkedTestCaseIds) || []).filter((id) => Number.isFinite(id) && Number(id) > 0);
|
|
419
|
+
const observedTestCaseIds = key
|
|
420
|
+
? Array.from(observedTestCaseIdsByRequirement.get(key) || [])
|
|
421
|
+
: [];
|
|
422
|
+
const testCaseIds = Array.from(new Set([...linkedTestCaseIds, ...observedTestCaseIds])).sort((a, b) => a - b);
|
|
423
|
+
if (testCaseIds.length === 0) {
|
|
424
|
+
rows.push(this.createMewpCoverageRow(requirement, undefined, '', {
|
|
425
|
+
passed: 0,
|
|
426
|
+
failed: 0,
|
|
427
|
+
notRun: 0,
|
|
428
|
+
}));
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
for (const testCaseId of testCaseIds) {
|
|
432
|
+
const summary = key
|
|
433
|
+
? ((_a = requirementIndex.get(key)) === null || _a === void 0 ? void 0 : _a.get(testCaseId)) || { passed: 0, failed: 0, notRun: 0 }
|
|
434
|
+
: { passed: 0, failed: 0, notRun: 0 };
|
|
435
|
+
rows.push(this.createMewpCoverageRow(requirement, testCaseId, String(testCaseTitleMap.get(testCaseId) || ''), summary));
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return rows;
|
|
439
|
+
}
|
|
440
|
+
buildMewpTestCaseTitleMap(testData) {
|
|
441
|
+
var _a, _b, _c, _d, _e;
|
|
442
|
+
const map = new Map();
|
|
443
|
+
const readTitleFromWorkItemFields = (workItemFields) => {
|
|
444
|
+
if (!Array.isArray(workItemFields))
|
|
445
|
+
return '';
|
|
446
|
+
for (const field of workItemFields) {
|
|
447
|
+
const keyCandidates = [field === null || field === void 0 ? void 0 : field.key, field === null || field === void 0 ? void 0 : field.name, field === null || field === void 0 ? void 0 : field.referenceName, field === null || field === void 0 ? void 0 : field.id]
|
|
448
|
+
.map((item) => String(item || '').toLowerCase().trim());
|
|
449
|
+
const isTitleField = keyCandidates.includes('system.title') || keyCandidates.includes('title');
|
|
450
|
+
if (!isTitleField)
|
|
451
|
+
continue;
|
|
452
|
+
const value = this.toMewpComparableText(field === null || field === void 0 ? void 0 : field.value);
|
|
453
|
+
if (value)
|
|
454
|
+
return value;
|
|
455
|
+
}
|
|
456
|
+
return '';
|
|
457
|
+
};
|
|
458
|
+
for (const suite of testData || []) {
|
|
459
|
+
const testPointsItems = Array.isArray(suite === null || suite === void 0 ? void 0 : suite.testPointsItems) ? suite.testPointsItems : [];
|
|
460
|
+
for (const point of testPointsItems) {
|
|
461
|
+
const pointTestCaseId = Number((point === null || point === void 0 ? void 0 : point.testCaseId) || ((_a = point === null || point === void 0 ? void 0 : point.testCase) === null || _a === void 0 ? void 0 : _a.id));
|
|
462
|
+
if (!Number.isFinite(pointTestCaseId) || pointTestCaseId <= 0 || map.has(pointTestCaseId))
|
|
463
|
+
continue;
|
|
464
|
+
const pointTitle = this.toMewpComparableText((point === null || point === void 0 ? void 0 : point.testCaseName) || ((_b = point === null || point === void 0 ? void 0 : point.testCase) === null || _b === void 0 ? void 0 : _b.name));
|
|
465
|
+
if (pointTitle)
|
|
466
|
+
map.set(pointTestCaseId, pointTitle);
|
|
467
|
+
}
|
|
468
|
+
const testCasesItems = Array.isArray(suite === null || suite === void 0 ? void 0 : suite.testCasesItems) ? suite.testCasesItems : [];
|
|
469
|
+
for (const testCase of testCasesItems) {
|
|
470
|
+
const id = Number(((_c = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _c === void 0 ? void 0 : _c.id) || (testCase === null || testCase === void 0 ? void 0 : testCase.testCaseId) || (testCase === null || testCase === void 0 ? void 0 : testCase.id));
|
|
471
|
+
if (!Number.isFinite(id) || id <= 0 || map.has(id))
|
|
472
|
+
continue;
|
|
473
|
+
const fromDirectFields = this.toMewpComparableText((testCase === null || testCase === void 0 ? void 0 : testCase.testCaseName) || (testCase === null || testCase === void 0 ? void 0 : testCase.name) || ((_d = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _d === void 0 ? void 0 : _d.name));
|
|
474
|
+
if (fromDirectFields) {
|
|
475
|
+
map.set(id, fromDirectFields);
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
const fromWorkItemField = readTitleFromWorkItemFields((_e = testCase === null || testCase === void 0 ? void 0 : testCase.workItem) === null || _e === void 0 ? void 0 : _e.workItemFields);
|
|
479
|
+
if (fromWorkItemField) {
|
|
480
|
+
map.set(id, fromWorkItemField);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
return map;
|
|
485
|
+
}
|
|
486
|
+
extractMewpTestCaseId(runResult) {
|
|
487
|
+
var _a;
|
|
488
|
+
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);
|
|
489
|
+
return Number.isFinite(testCaseId) ? testCaseId : 0;
|
|
490
|
+
}
|
|
416
491
|
buildTestCaseStepsXmlMap(testData) {
|
|
417
492
|
var _a, _b;
|
|
418
493
|
const map = new Map();
|
|
@@ -461,15 +536,25 @@ class ResultDataProvider {
|
|
|
461
536
|
return 'failed';
|
|
462
537
|
return 'notRun';
|
|
463
538
|
}
|
|
464
|
-
accumulateRequirementCountsFromStepText(stepText, status, requirementKeys, counters) {
|
|
539
|
+
accumulateRequirementCountsFromStepText(stepText, status, testCaseId, requirementKeys, counters, observedTestCaseIdsByRequirement) {
|
|
540
|
+
if (!Number.isFinite(testCaseId) || testCaseId <= 0)
|
|
541
|
+
return;
|
|
465
542
|
const codes = this.extractRequirementCodesFromText(stepText);
|
|
466
543
|
for (const code of codes) {
|
|
467
544
|
if (requirementKeys.size > 0 && !requirementKeys.has(code))
|
|
468
545
|
continue;
|
|
469
546
|
if (!counters.has(code)) {
|
|
470
|
-
counters.set(code,
|
|
547
|
+
counters.set(code, new Map());
|
|
548
|
+
}
|
|
549
|
+
const perTestCaseCounters = counters.get(code);
|
|
550
|
+
if (!perTestCaseCounters.has(testCaseId)) {
|
|
551
|
+
perTestCaseCounters.set(testCaseId, { passed: 0, failed: 0, notRun: 0 });
|
|
552
|
+
}
|
|
553
|
+
if (!observedTestCaseIdsByRequirement.has(code)) {
|
|
554
|
+
observedTestCaseIdsByRequirement.set(code, new Set());
|
|
471
555
|
}
|
|
472
|
-
|
|
556
|
+
observedTestCaseIdsByRequirement.get(code).add(testCaseId);
|
|
557
|
+
const counter = perTestCaseCounters.get(testCaseId);
|
|
473
558
|
if (status === 'passed')
|
|
474
559
|
counter.passed += 1;
|
|
475
560
|
else if (status === 'failed')
|
|
@@ -518,8 +603,12 @@ class ResultDataProvider {
|
|
|
518
603
|
return '';
|
|
519
604
|
return `SR${digits}`;
|
|
520
605
|
}
|
|
521
|
-
async fetchMewpL2Requirements(projectName) {
|
|
606
|
+
async fetchMewpL2Requirements(projectName, linkedQueryRequest) {
|
|
522
607
|
var _a;
|
|
608
|
+
const queryHref = this.extractMewpQueryHref(linkedQueryRequest);
|
|
609
|
+
if (queryHref) {
|
|
610
|
+
return this.fetchMewpL2RequirementsFromQuery(projectName, queryHref);
|
|
611
|
+
}
|
|
523
612
|
const workItemTypeNames = await this.fetchMewpRequirementTypeNames(projectName);
|
|
524
613
|
if (workItemTypeNames.length === 0) {
|
|
525
614
|
return [];
|
|
@@ -554,6 +643,158 @@ ORDER BY [System.Id]`;
|
|
|
554
643
|
});
|
|
555
644
|
return requirements.sort((a, b) => String(a.requirementId).localeCompare(String(b.requirementId)));
|
|
556
645
|
}
|
|
646
|
+
extractMewpQueryHref(linkedQueryRequest) {
|
|
647
|
+
var _a, _b;
|
|
648
|
+
const mode = String((linkedQueryRequest === null || linkedQueryRequest === void 0 ? void 0 : linkedQueryRequest.linkedQueryMode) || '')
|
|
649
|
+
.trim()
|
|
650
|
+
.toLowerCase();
|
|
651
|
+
if (mode !== 'query')
|
|
652
|
+
return '';
|
|
653
|
+
return String(((_b = (_a = linkedQueryRequest === null || linkedQueryRequest === void 0 ? void 0 : linkedQueryRequest.testAssociatedQuery) === null || _a === void 0 ? void 0 : _a.wiql) === null || _b === void 0 ? void 0 : _b.href) || '').trim();
|
|
654
|
+
}
|
|
655
|
+
async fetchMewpL2RequirementsFromQuery(projectName, queryHref) {
|
|
656
|
+
try {
|
|
657
|
+
const ticketsDataProvider = new TicketsDataProvider_1.default(this.orgUrl, this.token);
|
|
658
|
+
const queryResult = await ticketsDataProvider.GetQueryResultsFromWiql(queryHref, true, new Map());
|
|
659
|
+
const requirementTypeNames = await this.fetchMewpRequirementTypeNames(projectName);
|
|
660
|
+
const requirementTypeSet = new Set(requirementTypeNames.map((name) => String(name || '').trim().toLowerCase()));
|
|
661
|
+
const requirementsById = new Map();
|
|
662
|
+
const upsertRequirement = (workItem) => {
|
|
663
|
+
this.upsertMewpRequirement(requirementsById, workItem, requirementTypeSet);
|
|
664
|
+
};
|
|
665
|
+
const linkRequirementToTestCase = (requirementWorkItem, testCaseWorkItem) => {
|
|
666
|
+
const requirementId = Number((requirementWorkItem === null || requirementWorkItem === void 0 ? void 0 : requirementWorkItem.id) || 0);
|
|
667
|
+
const testCaseId = Number((testCaseWorkItem === null || testCaseWorkItem === void 0 ? void 0 : testCaseWorkItem.id) || 0);
|
|
668
|
+
if (!Number.isFinite(requirementId) || requirementId <= 0)
|
|
669
|
+
return;
|
|
670
|
+
if (!Number.isFinite(testCaseId) || testCaseId <= 0)
|
|
671
|
+
return;
|
|
672
|
+
upsertRequirement(requirementWorkItem);
|
|
673
|
+
const requirement = requirementsById.get(requirementId);
|
|
674
|
+
if (!requirement)
|
|
675
|
+
return;
|
|
676
|
+
requirement.linkedTestCaseIds.add(testCaseId);
|
|
677
|
+
};
|
|
678
|
+
if (Array.isArray(queryResult === null || queryResult === void 0 ? void 0 : queryResult.fetchedWorkItems)) {
|
|
679
|
+
for (const workItem of queryResult.fetchedWorkItems) {
|
|
680
|
+
upsertRequirement(workItem);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if ((queryResult === null || queryResult === void 0 ? void 0 : queryResult.sourceTargetsMap) && typeof queryResult.sourceTargetsMap.entries === 'function') {
|
|
684
|
+
for (const [sourceItem, targets] of queryResult.sourceTargetsMap.entries()) {
|
|
685
|
+
const sourceType = this.getMewpWorkItemType(sourceItem);
|
|
686
|
+
const sourceIsRequirement = this.isMewpRequirementType(sourceType, requirementTypeSet);
|
|
687
|
+
const sourceIsTestCase = this.isMewpTestCaseType(sourceType);
|
|
688
|
+
if (sourceIsRequirement) {
|
|
689
|
+
upsertRequirement(sourceItem);
|
|
690
|
+
}
|
|
691
|
+
const relatedItems = Array.isArray(targets) ? targets : [];
|
|
692
|
+
for (const targetItem of relatedItems) {
|
|
693
|
+
const targetType = this.getMewpWorkItemType(targetItem);
|
|
694
|
+
const targetIsRequirement = this.isMewpRequirementType(targetType, requirementTypeSet);
|
|
695
|
+
const targetIsTestCase = this.isMewpTestCaseType(targetType);
|
|
696
|
+
if (targetIsRequirement) {
|
|
697
|
+
upsertRequirement(targetItem);
|
|
698
|
+
}
|
|
699
|
+
if (sourceIsRequirement && targetIsTestCase) {
|
|
700
|
+
linkRequirementToTestCase(sourceItem, targetItem);
|
|
701
|
+
}
|
|
702
|
+
else if (sourceIsTestCase && targetIsRequirement) {
|
|
703
|
+
linkRequirementToTestCase(targetItem, sourceItem);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
await this.hydrateMewpRequirementsFromWorkItems(projectName, requirementsById);
|
|
709
|
+
return [...requirementsById.values()]
|
|
710
|
+
.map((requirement) => ({
|
|
711
|
+
workItemId: requirement.workItemId,
|
|
712
|
+
requirementId: requirement.requirementId,
|
|
713
|
+
title: requirement.title,
|
|
714
|
+
responsibility: requirement.responsibility,
|
|
715
|
+
linkedTestCaseIds: [...requirement.linkedTestCaseIds].sort((a, b) => a - b),
|
|
716
|
+
}))
|
|
717
|
+
.sort((a, b) => String(a.requirementId).localeCompare(String(b.requirementId)));
|
|
718
|
+
}
|
|
719
|
+
catch (error) {
|
|
720
|
+
logger_1.default.error(`Could not fetch MEWP requirements from query: ${(error === null || error === void 0 ? void 0 : error.message) || error}`);
|
|
721
|
+
return [];
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
upsertMewpRequirement(requirementsById, workItem, requirementTypeSet) {
|
|
725
|
+
const workItemId = Number((workItem === null || workItem === void 0 ? void 0 : workItem.id) || 0);
|
|
726
|
+
if (!Number.isFinite(workItemId) || workItemId <= 0)
|
|
727
|
+
return;
|
|
728
|
+
const fields = (workItem === null || workItem === void 0 ? void 0 : workItem.fields) || {};
|
|
729
|
+
const workItemType = this.getMewpWorkItemType(workItem);
|
|
730
|
+
if (!this.isMewpRequirementType(workItemType, requirementTypeSet))
|
|
731
|
+
return;
|
|
732
|
+
const existing = requirementsById.get(workItemId) || {
|
|
733
|
+
workItemId,
|
|
734
|
+
requirementId: String(workItemId),
|
|
735
|
+
title: '',
|
|
736
|
+
responsibility: '',
|
|
737
|
+
linkedTestCaseIds: new Set(),
|
|
738
|
+
};
|
|
739
|
+
const extractedRequirementId = this.extractMewpRequirementIdentifier(fields, workItemId);
|
|
740
|
+
const extractedTitle = this.toMewpComparableText(fields === null || fields === void 0 ? void 0 : fields['System.Title']);
|
|
741
|
+
const extractedResponsibility = this.deriveMewpResponsibility(fields);
|
|
742
|
+
existing.requirementId = extractedRequirementId || existing.requirementId || String(workItemId);
|
|
743
|
+
if (extractedTitle) {
|
|
744
|
+
existing.title = extractedTitle;
|
|
745
|
+
}
|
|
746
|
+
if (extractedResponsibility) {
|
|
747
|
+
existing.responsibility = extractedResponsibility;
|
|
748
|
+
}
|
|
749
|
+
requirementsById.set(workItemId, existing);
|
|
750
|
+
}
|
|
751
|
+
async hydrateMewpRequirementsFromWorkItems(projectName, requirementsById) {
|
|
752
|
+
const requirementIds = [...requirementsById.keys()];
|
|
753
|
+
if (requirementIds.length === 0)
|
|
754
|
+
return;
|
|
755
|
+
const fetchedRequirements = await this.fetchWorkItemsByIds(projectName, requirementIds, true);
|
|
756
|
+
for (const requirementWorkItem of fetchedRequirements) {
|
|
757
|
+
const workItemId = Number((requirementWorkItem === null || requirementWorkItem === void 0 ? void 0 : requirementWorkItem.id) || 0);
|
|
758
|
+
if (!Number.isFinite(workItemId) || workItemId <= 0)
|
|
759
|
+
continue;
|
|
760
|
+
const current = requirementsById.get(workItemId);
|
|
761
|
+
if (!current)
|
|
762
|
+
continue;
|
|
763
|
+
const fields = (requirementWorkItem === null || requirementWorkItem === void 0 ? void 0 : requirementWorkItem.fields) || {};
|
|
764
|
+
const requirementId = this.extractMewpRequirementIdentifier(fields, workItemId);
|
|
765
|
+
const title = this.toMewpComparableText(fields === null || fields === void 0 ? void 0 : fields['System.Title']);
|
|
766
|
+
const responsibility = this.deriveMewpResponsibility(fields);
|
|
767
|
+
const linkedTestCaseIds = this.extractLinkedTestCaseIdsFromRequirement((requirementWorkItem === null || requirementWorkItem === void 0 ? void 0 : requirementWorkItem.relations) || []);
|
|
768
|
+
current.requirementId = requirementId || current.requirementId || String(workItemId);
|
|
769
|
+
if (title) {
|
|
770
|
+
current.title = title;
|
|
771
|
+
}
|
|
772
|
+
if (responsibility) {
|
|
773
|
+
current.responsibility = responsibility;
|
|
774
|
+
}
|
|
775
|
+
linkedTestCaseIds.forEach((testCaseId) => current.linkedTestCaseIds.add(testCaseId));
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
getMewpWorkItemType(workItem) {
|
|
779
|
+
var _a;
|
|
780
|
+
return this.toMewpComparableText((_a = workItem === null || workItem === void 0 ? void 0 : workItem.fields) === null || _a === void 0 ? void 0 : _a['System.WorkItemType']);
|
|
781
|
+
}
|
|
782
|
+
isMewpRequirementType(workItemType, requirementTypeSet) {
|
|
783
|
+
const normalized = String(workItemType || '')
|
|
784
|
+
.trim()
|
|
785
|
+
.toLowerCase();
|
|
786
|
+
if (!normalized)
|
|
787
|
+
return false;
|
|
788
|
+
if (requirementTypeSet.has(normalized))
|
|
789
|
+
return true;
|
|
790
|
+
return normalized.includes('requirement') || normalized === 'epic';
|
|
791
|
+
}
|
|
792
|
+
isMewpTestCaseType(workItemType) {
|
|
793
|
+
const normalized = String(workItemType || '')
|
|
794
|
+
.trim()
|
|
795
|
+
.toLowerCase();
|
|
796
|
+
return normalized === 'test case' || normalized === 'testcase';
|
|
797
|
+
}
|
|
557
798
|
async fetchMewpRequirementTypeNames(projectName) {
|
|
558
799
|
try {
|
|
559
800
|
const url = `${this.orgUrl}${projectName}/_apis/wit/workitemtypes?api-version=7.1-preview.2`;
|
|
@@ -2541,14 +2782,14 @@ ORDER BY [System.Id]`;
|
|
|
2541
2782
|
}
|
|
2542
2783
|
}
|
|
2543
2784
|
ResultDataProvider.MEWP_L2_COVERAGE_COLUMNS = [
|
|
2544
|
-
'Customer
|
|
2545
|
-
'
|
|
2546
|
-
'
|
|
2547
|
-
'
|
|
2548
|
-
'
|
|
2785
|
+
'Customer ID',
|
|
2786
|
+
'Title (Customer name)',
|
|
2787
|
+
'Responsibility - SAPWBS (ESUK/IL)',
|
|
2788
|
+
'Test case id',
|
|
2789
|
+
'Test case title',
|
|
2549
2790
|
'Number of passed steps',
|
|
2550
2791
|
'Number of failed steps',
|
|
2551
|
-
'Number of
|
|
2792
|
+
'Number of not run tests',
|
|
2552
2793
|
];
|
|
2553
2794
|
exports.default = ResultDataProvider;
|
|
2554
2795
|
//# sourceMappingURL=ResultDataProvider.js.map
|