@elisra-devops/docgen-data-provider 1.83.0 → 1.85.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 +5 -0
- package/bin/modules/ResultDataProvider.js +221 -23
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/tests/modules/ResultDataProvider.test.js +209 -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 +250 -19
- package/src/tests/modules/ResultDataProvider.test.ts +254 -0
- package/src/utils/mewpExternalIngestionUtils.ts +11 -0
|
@@ -1341,6 +1341,81 @@ describe('ResultDataProvider', () => {
|
|
|
1341
1341
|
expect(il).toBe('IL');
|
|
1342
1342
|
});
|
|
1343
1343
|
|
|
1344
|
+
it('should derive responsibility from Area Path alias when System.AreaPath is missing', () => {
|
|
1345
|
+
const esuk = (resultDataProvider as any).deriveMewpResponsibility({
|
|
1346
|
+
'Custom.SAPWBS': '',
|
|
1347
|
+
'Area Path': 'MEWP\\Customer Requirements\\Level 2\\ATP\\ESUK',
|
|
1348
|
+
});
|
|
1349
|
+
const il = (resultDataProvider as any).deriveMewpResponsibility({
|
|
1350
|
+
'Custom.SAPWBS': '',
|
|
1351
|
+
'Area Path': 'MEWP\\Customer Requirements\\Level 2\\ATP',
|
|
1352
|
+
});
|
|
1353
|
+
|
|
1354
|
+
expect(esuk).toBe('ESUK');
|
|
1355
|
+
expect(il).toBe('IL');
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1358
|
+
it('should derive test-case responsibility from testCasesItems area-path fields', async () => {
|
|
1359
|
+
const fetchByIdsSpy = jest
|
|
1360
|
+
.spyOn(resultDataProvider as any, 'fetchWorkItemsByIds')
|
|
1361
|
+
.mockResolvedValue([]);
|
|
1362
|
+
|
|
1363
|
+
const map = await (resultDataProvider as any).buildMewpTestCaseResponsibilityMap(
|
|
1364
|
+
[
|
|
1365
|
+
{
|
|
1366
|
+
testCasesItems: [
|
|
1367
|
+
{
|
|
1368
|
+
workItem: {
|
|
1369
|
+
id: 101,
|
|
1370
|
+
workItemFields: [{ name: 'Area Path', value: 'MEWP\\Customer Requirements\\Level 2\\ATP' }],
|
|
1371
|
+
},
|
|
1372
|
+
},
|
|
1373
|
+
{
|
|
1374
|
+
workItem: {
|
|
1375
|
+
id: 102,
|
|
1376
|
+
workItemFields: [
|
|
1377
|
+
{ referenceName: 'System.AreaPath', value: 'MEWP\\Customer Requirements\\Level 2\\ATP\\ESUK' },
|
|
1378
|
+
],
|
|
1379
|
+
},
|
|
1380
|
+
},
|
|
1381
|
+
],
|
|
1382
|
+
testPointsItems: [],
|
|
1383
|
+
},
|
|
1384
|
+
],
|
|
1385
|
+
mockProjectName
|
|
1386
|
+
);
|
|
1387
|
+
|
|
1388
|
+
expect(map.get(101)).toBe('IL');
|
|
1389
|
+
expect(map.get(102)).toBe('ESUK');
|
|
1390
|
+
expect(fetchByIdsSpy).not.toHaveBeenCalled();
|
|
1391
|
+
});
|
|
1392
|
+
|
|
1393
|
+
it('should derive test-case responsibility from AreaPath even when SAPWBS exists on test-case payload', async () => {
|
|
1394
|
+
jest.spyOn(resultDataProvider as any, 'fetchWorkItemsByIds').mockResolvedValue([]);
|
|
1395
|
+
|
|
1396
|
+
const map = await (resultDataProvider as any).buildMewpTestCaseResponsibilityMap(
|
|
1397
|
+
[
|
|
1398
|
+
{
|
|
1399
|
+
testCasesItems: [
|
|
1400
|
+
{
|
|
1401
|
+
workItem: {
|
|
1402
|
+
id: 201,
|
|
1403
|
+
workItemFields: [
|
|
1404
|
+
{ referenceName: 'Custom.SAPWBS', value: 'ESUK' },
|
|
1405
|
+
{ referenceName: 'System.AreaPath', value: 'MEWP\\Customer Requirements\\Level 2\\ATP' },
|
|
1406
|
+
],
|
|
1407
|
+
},
|
|
1408
|
+
},
|
|
1409
|
+
],
|
|
1410
|
+
testPointsItems: [],
|
|
1411
|
+
},
|
|
1412
|
+
],
|
|
1413
|
+
mockProjectName
|
|
1414
|
+
);
|
|
1415
|
+
|
|
1416
|
+
expect(map.get(201)).toBe('IL');
|
|
1417
|
+
});
|
|
1418
|
+
|
|
1344
1419
|
it('should zip bug rows with L3/L4 pairs and avoid cross-product duplication', () => {
|
|
1345
1420
|
const requirements = [
|
|
1346
1421
|
{
|
|
@@ -1628,6 +1703,78 @@ describe('ResultDataProvider', () => {
|
|
|
1628
1703
|
expect(rows[0]['Bug ID']).toBe(99001);
|
|
1629
1704
|
expect(rows[0]['Bug Responsibility']).toBe('Elisra');
|
|
1630
1705
|
});
|
|
1706
|
+
|
|
1707
|
+
it('should fallback bug responsibility from test case mapping when external bug row is unknown', () => {
|
|
1708
|
+
const requirements = [
|
|
1709
|
+
{
|
|
1710
|
+
requirementId: 'SR5310',
|
|
1711
|
+
baseKey: 'SR5310',
|
|
1712
|
+
title: 'Req 5310',
|
|
1713
|
+
subSystem: 'Power',
|
|
1714
|
+
responsibility: '',
|
|
1715
|
+
linkedTestCaseIds: [101],
|
|
1716
|
+
},
|
|
1717
|
+
];
|
|
1718
|
+
|
|
1719
|
+
const requirementIndex = new Map([
|
|
1720
|
+
[
|
|
1721
|
+
'SR5310',
|
|
1722
|
+
new Map([
|
|
1723
|
+
[
|
|
1724
|
+
101,
|
|
1725
|
+
{
|
|
1726
|
+
passed: 0,
|
|
1727
|
+
failed: 1,
|
|
1728
|
+
notRun: 0,
|
|
1729
|
+
},
|
|
1730
|
+
],
|
|
1731
|
+
]),
|
|
1732
|
+
],
|
|
1733
|
+
]);
|
|
1734
|
+
|
|
1735
|
+
const observedTestCaseIdsByRequirement = new Map<string, Set<number>>([
|
|
1736
|
+
['SR5310', new Set([101])],
|
|
1737
|
+
]);
|
|
1738
|
+
|
|
1739
|
+
const linkedRequirementsByTestCase = new Map([
|
|
1740
|
+
[
|
|
1741
|
+
101,
|
|
1742
|
+
{
|
|
1743
|
+
baseKeys: new Set(['SR5310']),
|
|
1744
|
+
fullCodes: new Set(['SR5310']),
|
|
1745
|
+
bugIds: new Set([10003]),
|
|
1746
|
+
},
|
|
1747
|
+
],
|
|
1748
|
+
]);
|
|
1749
|
+
|
|
1750
|
+
const externalBugsByTestCase = new Map([
|
|
1751
|
+
[
|
|
1752
|
+
101,
|
|
1753
|
+
[
|
|
1754
|
+
{
|
|
1755
|
+
id: 10003,
|
|
1756
|
+
title: 'Bug 10003',
|
|
1757
|
+
responsibility: 'Unknown',
|
|
1758
|
+
requirementBaseKey: 'SR5310',
|
|
1759
|
+
},
|
|
1760
|
+
],
|
|
1761
|
+
],
|
|
1762
|
+
]);
|
|
1763
|
+
|
|
1764
|
+
const rows = (resultDataProvider as any).buildMewpCoverageRows(
|
|
1765
|
+
requirements,
|
|
1766
|
+
requirementIndex,
|
|
1767
|
+
observedTestCaseIdsByRequirement,
|
|
1768
|
+
linkedRequirementsByTestCase,
|
|
1769
|
+
new Map(),
|
|
1770
|
+
externalBugsByTestCase,
|
|
1771
|
+
new Map(),
|
|
1772
|
+
new Map([[101, 'IL']])
|
|
1773
|
+
);
|
|
1774
|
+
|
|
1775
|
+
expect(rows).toHaveLength(1);
|
|
1776
|
+
expect(rows[0]['Bug Responsibility']).toBe('Elisra');
|
|
1777
|
+
});
|
|
1631
1778
|
});
|
|
1632
1779
|
|
|
1633
1780
|
describe('getMewpInternalValidationFlatResults', () => {
|
|
@@ -2439,6 +2586,80 @@ describe('ResultDataProvider', () => {
|
|
|
2439
2586
|
expect(String(result.rows[0]['Mentioned but Not Linked'] || '')).not.toContain('VVRM');
|
|
2440
2587
|
expect(String(result.rows[0]['Linked but Not Mentioned'] || '')).not.toContain('VVRM');
|
|
2441
2588
|
});
|
|
2589
|
+
|
|
2590
|
+
it('should fallback to work-item fields for steps XML when suite payload has no workItemFields', async () => {
|
|
2591
|
+
jest.spyOn(resultDataProvider as any, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
|
|
2592
|
+
jest.spyOn(resultDataProvider as any, 'fetchMewpScopedTestData').mockResolvedValueOnce([
|
|
2593
|
+
{
|
|
2594
|
+
testPointsItems: [{ testCaseId: 501, testCaseName: 'TC 501' }],
|
|
2595
|
+
testCasesItems: [
|
|
2596
|
+
{
|
|
2597
|
+
workItem: {
|
|
2598
|
+
id: 501,
|
|
2599
|
+
workItemFields: [],
|
|
2600
|
+
},
|
|
2601
|
+
},
|
|
2602
|
+
],
|
|
2603
|
+
},
|
|
2604
|
+
]);
|
|
2605
|
+
jest.spyOn(resultDataProvider as any, 'fetchMewpL2Requirements').mockResolvedValueOnce([
|
|
2606
|
+
{
|
|
2607
|
+
workItemId: 9001,
|
|
2608
|
+
requirementId: 'SR0501',
|
|
2609
|
+
baseKey: 'SR0501',
|
|
2610
|
+
title: 'Req 501',
|
|
2611
|
+
responsibility: 'ESUK',
|
|
2612
|
+
linkedTestCaseIds: [501],
|
|
2613
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
2614
|
+
},
|
|
2615
|
+
]);
|
|
2616
|
+
jest.spyOn(resultDataProvider as any, 'buildLinkedRequirementsByTestCase').mockResolvedValueOnce(
|
|
2617
|
+
new Map([
|
|
2618
|
+
[
|
|
2619
|
+
501,
|
|
2620
|
+
{
|
|
2621
|
+
baseKeys: new Set(['SR0501']),
|
|
2622
|
+
fullCodes: new Set(['SR0501']),
|
|
2623
|
+
},
|
|
2624
|
+
],
|
|
2625
|
+
])
|
|
2626
|
+
);
|
|
2627
|
+
jest.spyOn(resultDataProvider as any, 'fetchWorkItemsByIds').mockResolvedValueOnce([
|
|
2628
|
+
{
|
|
2629
|
+
id: 501,
|
|
2630
|
+
fields: {
|
|
2631
|
+
'Microsoft.VSTS.TCM.Steps':
|
|
2632
|
+
'<steps><step id="2" type="ActionStep"><parameterizedString isformatted="true">Action</parameterizedString><parameterizedString isformatted="true">SR0501</parameterizedString></step></steps>',
|
|
2633
|
+
},
|
|
2634
|
+
},
|
|
2635
|
+
]);
|
|
2636
|
+
jest.spyOn((resultDataProvider as any).testStepParserHelper, 'parseTestSteps').mockResolvedValueOnce([
|
|
2637
|
+
{
|
|
2638
|
+
stepId: '1',
|
|
2639
|
+
stepPosition: '1',
|
|
2640
|
+
action: 'Action',
|
|
2641
|
+
expected: 'SR0501',
|
|
2642
|
+
isSharedStepTitle: false,
|
|
2643
|
+
},
|
|
2644
|
+
]);
|
|
2645
|
+
|
|
2646
|
+
const result = await (resultDataProvider as any).getMewpInternalValidationFlatResults(
|
|
2647
|
+
'123',
|
|
2648
|
+
mockProjectName,
|
|
2649
|
+
[1]
|
|
2650
|
+
);
|
|
2651
|
+
|
|
2652
|
+
expect((resultDataProvider as any).fetchWorkItemsByIds).toHaveBeenCalled();
|
|
2653
|
+
expect(result.rows).toHaveLength(1);
|
|
2654
|
+
expect(result.rows[0]).toEqual(
|
|
2655
|
+
expect.objectContaining({
|
|
2656
|
+
'Test Case ID': 501,
|
|
2657
|
+
'Mentioned but Not Linked': '',
|
|
2658
|
+
'Linked but Not Mentioned': '',
|
|
2659
|
+
'Validation Status': 'Pass',
|
|
2660
|
+
})
|
|
2661
|
+
);
|
|
2662
|
+
});
|
|
2442
2663
|
});
|
|
2443
2664
|
|
|
2444
2665
|
describe('MEWP rel fallback scoping', () => {
|
|
@@ -2661,6 +2882,39 @@ describe('ResultDataProvider', () => {
|
|
|
2661
2882
|
);
|
|
2662
2883
|
});
|
|
2663
2884
|
|
|
2885
|
+
it('should resolve external bug responsibility from AreaPath columns when SAPWBS is empty', async () => {
|
|
2886
|
+
const mewpExternalTableUtils = (resultDataProvider as any).mewpExternalTableUtils;
|
|
2887
|
+
jest.spyOn(mewpExternalTableUtils, 'loadExternalTableRows').mockResolvedValueOnce([
|
|
2888
|
+
{
|
|
2889
|
+
Elisra_SortIndex: '101',
|
|
2890
|
+
SR: 'SR0001',
|
|
2891
|
+
TargetWorkItemId: '9011',
|
|
2892
|
+
Title: 'Bug from ATP\\ESUK path',
|
|
2893
|
+
TargetState: 'Active',
|
|
2894
|
+
SAPWBS: '',
|
|
2895
|
+
AreaPath: 'MEWP\\Customer Requirements\\Level 2\\ATP\\ESUK',
|
|
2896
|
+
},
|
|
2897
|
+
{
|
|
2898
|
+
Elisra_SortIndex: '102',
|
|
2899
|
+
SR: 'SR0002',
|
|
2900
|
+
TargetWorkItemId: '9012',
|
|
2901
|
+
Title: 'Bug from ATP path',
|
|
2902
|
+
TargetState: 'Active',
|
|
2903
|
+
SAPWBS: '',
|
|
2904
|
+
'System.AreaPath': 'MEWP\\Customer Requirements\\Level 2\\ATP',
|
|
2905
|
+
},
|
|
2906
|
+
]);
|
|
2907
|
+
|
|
2908
|
+
const map = await (resultDataProvider as any).loadExternalBugsByTestCase(validBugsSource);
|
|
2909
|
+
const bugs101 = map.get(101) || [];
|
|
2910
|
+
const bugs102 = map.get(102) || [];
|
|
2911
|
+
|
|
2912
|
+
expect(bugs101).toHaveLength(1);
|
|
2913
|
+
expect(bugs102).toHaveLength(1);
|
|
2914
|
+
expect(bugs101[0].responsibility).toBe('ESUK');
|
|
2915
|
+
expect(bugs102[0].responsibility).toBe('Elisra');
|
|
2916
|
+
});
|
|
2917
|
+
|
|
2664
2918
|
it('should require Elisra_SortIndex and ignore rows that only provide WorkItemId', async () => {
|
|
2665
2919
|
const mewpExternalTableUtils = (resultDataProvider as any).mewpExternalTableUtils;
|
|
2666
2920
|
jest.spyOn(mewpExternalTableUtils, 'loadExternalTableRows').mockResolvedValueOnce([
|
|
@@ -99,12 +99,23 @@ export default class MewpExternalIngestionUtils {
|
|
|
99
99
|
'TargetSapWbs',
|
|
100
100
|
])
|
|
101
101
|
);
|
|
102
|
+
const bugAreaPathRaw = adapters.toComparableText(
|
|
103
|
+
this.externalTableUtils.readExternalCell(row, [
|
|
104
|
+
'System.AreaPath',
|
|
105
|
+
'AreaPath',
|
|
106
|
+
'Area Path',
|
|
107
|
+
'TargetAreaPath',
|
|
108
|
+
'Target Area Path',
|
|
109
|
+
'Links.TargetWorkItem.AreaPath',
|
|
110
|
+
])
|
|
111
|
+
);
|
|
102
112
|
|
|
103
113
|
const bug: MewpBugLink = {
|
|
104
114
|
id: bugId,
|
|
105
115
|
title: bugTitle,
|
|
106
116
|
responsibility: adapters.resolveBugResponsibility({
|
|
107
117
|
'Custom.SAPWBS': bugResponsibilityRaw,
|
|
118
|
+
'System.AreaPath': bugAreaPathRaw,
|
|
108
119
|
}),
|
|
109
120
|
requirementBaseKey,
|
|
110
121
|
};
|