@elisra-devops/docgen-data-provider 1.85.0 → 1.87.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 +1 -0
- package/bin/modules/ResultDataProvider.js +98 -29
- package/bin/modules/ResultDataProvider.js.map +1 -1
- package/bin/tests/modules/ResultDataProvider.test.js +285 -1
- package/bin/tests/modules/ResultDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/ResultDataProvider.ts +105 -27
- package/src/tests/modules/ResultDataProvider.test.ts +330 -1
|
@@ -1603,6 +1603,195 @@ describe('ResultDataProvider', () => {
|
|
|
1603
1603
|
}),
|
|
1604
1604
|
]));
|
|
1605
1605
|
});
|
|
1606
|
+
it('should pass when a base SR mention is fully covered by its only linked child', async () => {
|
|
1607
|
+
jest.spyOn(resultDataProvider, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
|
|
1608
|
+
jest.spyOn(resultDataProvider, 'fetchTestSuites').mockResolvedValueOnce([{ testSuiteId: 1 }]);
|
|
1609
|
+
jest.spyOn(resultDataProvider, 'fetchTestData').mockResolvedValueOnce([
|
|
1610
|
+
{
|
|
1611
|
+
testPointsItems: [{ testCaseId: 402, testCaseName: 'TC 402 - Single child covered' }],
|
|
1612
|
+
testCasesItems: [
|
|
1613
|
+
{
|
|
1614
|
+
workItem: {
|
|
1615
|
+
id: 402,
|
|
1616
|
+
workItemFields: [{ key: 'Steps', value: '<steps id=\"mock-steps-tc-402\"></steps>' }],
|
|
1617
|
+
},
|
|
1618
|
+
},
|
|
1619
|
+
],
|
|
1620
|
+
},
|
|
1621
|
+
]);
|
|
1622
|
+
jest.spyOn(resultDataProvider, 'fetchMewpL2Requirements').mockResolvedValueOnce([
|
|
1623
|
+
{
|
|
1624
|
+
workItemId: 9101,
|
|
1625
|
+
requirementId: 'SR0054',
|
|
1626
|
+
baseKey: 'SR0054',
|
|
1627
|
+
title: 'SR0054 parent',
|
|
1628
|
+
responsibility: 'ESUK',
|
|
1629
|
+
linkedTestCaseIds: [],
|
|
1630
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
1631
|
+
},
|
|
1632
|
+
{
|
|
1633
|
+
workItemId: 9102,
|
|
1634
|
+
requirementId: 'SR0054-1',
|
|
1635
|
+
baseKey: 'SR0054',
|
|
1636
|
+
title: 'SR0054 child 1',
|
|
1637
|
+
responsibility: 'ESUK',
|
|
1638
|
+
linkedTestCaseIds: [],
|
|
1639
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
1640
|
+
},
|
|
1641
|
+
]);
|
|
1642
|
+
jest.spyOn(resultDataProvider, 'buildLinkedRequirementsByTestCase').mockResolvedValueOnce(new Map([
|
|
1643
|
+
[
|
|
1644
|
+
402,
|
|
1645
|
+
{
|
|
1646
|
+
baseKeys: new Set(['SR0054']),
|
|
1647
|
+
fullCodes: new Set(['SR0054-1']),
|
|
1648
|
+
},
|
|
1649
|
+
],
|
|
1650
|
+
]));
|
|
1651
|
+
jest.spyOn(resultDataProvider.testStepParserHelper, 'parseTestSteps').mockResolvedValueOnce([
|
|
1652
|
+
{
|
|
1653
|
+
stepId: '3',
|
|
1654
|
+
stepPosition: '3',
|
|
1655
|
+
action: 'Validate family root',
|
|
1656
|
+
expected: 'SR0054',
|
|
1657
|
+
isSharedStepTitle: false,
|
|
1658
|
+
},
|
|
1659
|
+
]);
|
|
1660
|
+
const result = await resultDataProvider.getMewpInternalValidationFlatResults('123', mockProjectName, [1]);
|
|
1661
|
+
expect(result.rows).toHaveLength(1);
|
|
1662
|
+
expect(result.rows[0]).toEqual(expect.objectContaining({
|
|
1663
|
+
'Test Case ID': 402,
|
|
1664
|
+
'Mentioned but Not Linked': '',
|
|
1665
|
+
'Linked but Not Mentioned': '',
|
|
1666
|
+
'Validation Status': 'Pass',
|
|
1667
|
+
}));
|
|
1668
|
+
});
|
|
1669
|
+
it('should group linked-but-not-mentioned requirements by SR family', async () => {
|
|
1670
|
+
jest.spyOn(resultDataProvider, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
|
|
1671
|
+
jest.spyOn(resultDataProvider, 'fetchTestSuites').mockResolvedValueOnce([{ testSuiteId: 1 }]);
|
|
1672
|
+
jest.spyOn(resultDataProvider, 'fetchTestData').mockResolvedValueOnce([
|
|
1673
|
+
{
|
|
1674
|
+
testPointsItems: [{ testCaseId: 403, testCaseName: 'TC 403 - Linked only' }],
|
|
1675
|
+
testCasesItems: [
|
|
1676
|
+
{
|
|
1677
|
+
workItem: {
|
|
1678
|
+
id: 403,
|
|
1679
|
+
workItemFields: [{ key: 'Steps', value: '<steps id=\"mock-steps-tc-403\"></steps>' }],
|
|
1680
|
+
},
|
|
1681
|
+
},
|
|
1682
|
+
],
|
|
1683
|
+
},
|
|
1684
|
+
]);
|
|
1685
|
+
jest.spyOn(resultDataProvider, 'fetchMewpL2Requirements').mockResolvedValueOnce([
|
|
1686
|
+
{
|
|
1687
|
+
workItemId: 9201,
|
|
1688
|
+
requirementId: 'SR0054-1',
|
|
1689
|
+
baseKey: 'SR0054',
|
|
1690
|
+
title: 'SR0054 child 1',
|
|
1691
|
+
responsibility: 'ESUK',
|
|
1692
|
+
linkedTestCaseIds: [],
|
|
1693
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
1694
|
+
},
|
|
1695
|
+
{
|
|
1696
|
+
workItemId: 9202,
|
|
1697
|
+
requirementId: 'SR0054-2',
|
|
1698
|
+
baseKey: 'SR0054',
|
|
1699
|
+
title: 'SR0054 child 2',
|
|
1700
|
+
responsibility: 'ESUK',
|
|
1701
|
+
linkedTestCaseIds: [],
|
|
1702
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
workItemId: 9203,
|
|
1706
|
+
requirementId: 'SR0100-1',
|
|
1707
|
+
baseKey: 'SR0100',
|
|
1708
|
+
title: 'SR0100 child 1',
|
|
1709
|
+
responsibility: 'ESUK',
|
|
1710
|
+
linkedTestCaseIds: [],
|
|
1711
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
1712
|
+
},
|
|
1713
|
+
]);
|
|
1714
|
+
jest.spyOn(resultDataProvider, 'buildLinkedRequirementsByTestCase').mockResolvedValueOnce(new Map([
|
|
1715
|
+
[
|
|
1716
|
+
403,
|
|
1717
|
+
{
|
|
1718
|
+
baseKeys: new Set(['SR0054', 'SR0100']),
|
|
1719
|
+
fullCodes: new Set(['SR0054-1', 'SR0054-2', 'SR0100-1']),
|
|
1720
|
+
},
|
|
1721
|
+
],
|
|
1722
|
+
]));
|
|
1723
|
+
jest.spyOn(resultDataProvider.testStepParserHelper, 'parseTestSteps').mockResolvedValueOnce([
|
|
1724
|
+
{
|
|
1725
|
+
stepId: '1',
|
|
1726
|
+
stepPosition: '1',
|
|
1727
|
+
action: 'Action only',
|
|
1728
|
+
expected: '',
|
|
1729
|
+
isSharedStepTitle: false,
|
|
1730
|
+
},
|
|
1731
|
+
]);
|
|
1732
|
+
const result = await resultDataProvider.getMewpInternalValidationFlatResults('123', mockProjectName, [1]);
|
|
1733
|
+
expect(result.rows).toHaveLength(1);
|
|
1734
|
+
expect(String(result.rows[0]['Mentioned but Not Linked'] || '')).toBe('');
|
|
1735
|
+
expect(String(result.rows[0]['Linked but Not Mentioned'] || '')).toContain('SR0054: SR0054-1, SR0054-2');
|
|
1736
|
+
expect(String(result.rows[0]['Linked but Not Mentioned'] || '')).toContain('SR0100-1');
|
|
1737
|
+
});
|
|
1738
|
+
it('should report only base SR when an entire mentioned family is uncovered', async () => {
|
|
1739
|
+
jest.spyOn(resultDataProvider, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
|
|
1740
|
+
jest.spyOn(resultDataProvider, 'fetchTestSuites').mockResolvedValueOnce([{ testSuiteId: 1 }]);
|
|
1741
|
+
jest.spyOn(resultDataProvider, 'fetchTestData').mockResolvedValueOnce([
|
|
1742
|
+
{
|
|
1743
|
+
testPointsItems: [{ testCaseId: 401, testCaseName: 'TC 401 - Family uncovered' }],
|
|
1744
|
+
testCasesItems: [
|
|
1745
|
+
{
|
|
1746
|
+
workItem: {
|
|
1747
|
+
id: 401,
|
|
1748
|
+
workItemFields: [{ key: 'Steps', value: '<steps id=\"mock-steps-tc-401\"></steps>' }],
|
|
1749
|
+
},
|
|
1750
|
+
},
|
|
1751
|
+
],
|
|
1752
|
+
},
|
|
1753
|
+
]);
|
|
1754
|
+
jest.spyOn(resultDataProvider, 'fetchMewpL2Requirements').mockResolvedValueOnce([
|
|
1755
|
+
{
|
|
1756
|
+
workItemId: 9001,
|
|
1757
|
+
requirementId: 'SR0054-1',
|
|
1758
|
+
baseKey: 'SR0054',
|
|
1759
|
+
title: 'SR0054 child 1',
|
|
1760
|
+
responsibility: 'ESUK',
|
|
1761
|
+
linkedTestCaseIds: [],
|
|
1762
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
1763
|
+
},
|
|
1764
|
+
{
|
|
1765
|
+
workItemId: 9002,
|
|
1766
|
+
requirementId: 'SR0054-2',
|
|
1767
|
+
baseKey: 'SR0054',
|
|
1768
|
+
title: 'SR0054 child 2',
|
|
1769
|
+
responsibility: 'ESUK',
|
|
1770
|
+
linkedTestCaseIds: [],
|
|
1771
|
+
areaPath: 'MEWP\\Customer Requirements\\Level 2',
|
|
1772
|
+
},
|
|
1773
|
+
]);
|
|
1774
|
+
jest.spyOn(resultDataProvider, 'buildLinkedRequirementsByTestCase').mockResolvedValueOnce(new Map([[401, { baseKeys: new Set(), fullCodes: new Set() }]]));
|
|
1775
|
+
jest.spyOn(resultDataProvider.testStepParserHelper, 'parseTestSteps').mockResolvedValueOnce([
|
|
1776
|
+
{
|
|
1777
|
+
stepId: '3',
|
|
1778
|
+
stepPosition: '3',
|
|
1779
|
+
action: 'Validate family root',
|
|
1780
|
+
expected: 'SR0054',
|
|
1781
|
+
isSharedStepTitle: false,
|
|
1782
|
+
},
|
|
1783
|
+
]);
|
|
1784
|
+
const result = await resultDataProvider.getMewpInternalValidationFlatResults('123', mockProjectName, [1]);
|
|
1785
|
+
expect(result.rows).toHaveLength(1);
|
|
1786
|
+
expect(result.rows[0]).toEqual(expect.objectContaining({
|
|
1787
|
+
'Test Case ID': 401,
|
|
1788
|
+
'Mentioned but Not Linked': 'Step 3: SR0054',
|
|
1789
|
+
'Linked but Not Mentioned': '',
|
|
1790
|
+
'Validation Status': 'Fail',
|
|
1791
|
+
}));
|
|
1792
|
+
expect(String(result.rows[0]['Mentioned but Not Linked'] || '')).not.toContain('SR0054-1');
|
|
1793
|
+
expect(String(result.rows[0]['Mentioned but Not Linked'] || '')).not.toContain('SR0054-2');
|
|
1794
|
+
});
|
|
1606
1795
|
it('should not duplicate Direction A discrepancy when same requirement is repeated in multiple steps', async () => {
|
|
1607
1796
|
jest.spyOn(resultDataProvider, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
|
|
1608
1797
|
jest.spyOn(resultDataProvider, 'fetchTestSuites').mockResolvedValueOnce([{ testSuiteId: 1 }]);
|
|
@@ -1913,7 +2102,7 @@ describe('ResultDataProvider', () => {
|
|
|
1913
2102
|
expect(new Set(result.rows.map((row) => row['Test Case ID']))).toEqual(new Set([201, 202, 203]));
|
|
1914
2103
|
expect(byTestCase.get(201)).toEqual(expect.objectContaining({
|
|
1915
2104
|
'Test Case Title': 'TC 201 - Mixed discrepancies',
|
|
1916
|
-
'Mentioned but Not Linked': 'Step 1: SR0095-3
|
|
2105
|
+
'Mentioned but Not Linked': 'Step 1: SR0095-3; SR0511: SR0511-1, SR0511-2',
|
|
1917
2106
|
'Linked but Not Mentioned': 'SR8888',
|
|
1918
2107
|
'Validation Status': 'Fail',
|
|
1919
2108
|
}));
|
|
@@ -2208,6 +2397,101 @@ describe('ResultDataProvider', () => {
|
|
|
2208
2397
|
}));
|
|
2209
2398
|
});
|
|
2210
2399
|
});
|
|
2400
|
+
describe('buildLinkedRequirementsByTestCase', () => {
|
|
2401
|
+
it('should map linked requirements only for supported test-case requirement relation types', async () => {
|
|
2402
|
+
var _a, _b, _c, _d;
|
|
2403
|
+
const requirements = [
|
|
2404
|
+
{
|
|
2405
|
+
workItemId: 7001,
|
|
2406
|
+
requirementId: 'SR0054-1',
|
|
2407
|
+
baseKey: 'SR0054',
|
|
2408
|
+
linkedTestCaseIds: [],
|
|
2409
|
+
},
|
|
2410
|
+
];
|
|
2411
|
+
const testData = [
|
|
2412
|
+
{
|
|
2413
|
+
testCasesItems: [{ workItem: { id: 1001 } }],
|
|
2414
|
+
testPointsItems: [],
|
|
2415
|
+
},
|
|
2416
|
+
];
|
|
2417
|
+
const fetchByIdsSpy = jest
|
|
2418
|
+
.spyOn(resultDataProvider, 'fetchWorkItemsByIds')
|
|
2419
|
+
.mockImplementation(async (...args) => {
|
|
2420
|
+
const ids = Array.isArray(args === null || args === void 0 ? void 0 : args[1]) ? args[1] : [];
|
|
2421
|
+
const includeRelations = !!(args === null || args === void 0 ? void 0 : args[2]);
|
|
2422
|
+
if (includeRelations) {
|
|
2423
|
+
return [
|
|
2424
|
+
{
|
|
2425
|
+
id: 1001,
|
|
2426
|
+
relations: [
|
|
2427
|
+
{
|
|
2428
|
+
rel: 'Microsoft.VSTS.Common.TestedBy-Reverse',
|
|
2429
|
+
url: 'https://dev.azure.com/org/project/_apis/wit/workItems/7001',
|
|
2430
|
+
},
|
|
2431
|
+
{
|
|
2432
|
+
rel: 'System.LinkTypes.Related',
|
|
2433
|
+
url: 'https://dev.azure.com/org/project/_apis/wit/workItems/7001',
|
|
2434
|
+
},
|
|
2435
|
+
],
|
|
2436
|
+
},
|
|
2437
|
+
];
|
|
2438
|
+
}
|
|
2439
|
+
return ids.map((id) => ({
|
|
2440
|
+
id,
|
|
2441
|
+
fields: {
|
|
2442
|
+
'System.WorkItemType': id === 7001 ? 'Requirement' : 'Test Case',
|
|
2443
|
+
},
|
|
2444
|
+
}));
|
|
2445
|
+
});
|
|
2446
|
+
const linked = await resultDataProvider.buildLinkedRequirementsByTestCase(requirements, testData, mockProjectName);
|
|
2447
|
+
expect(fetchByIdsSpy).toHaveBeenCalled();
|
|
2448
|
+
expect((_b = (_a = linked.get(1001)) === null || _a === void 0 ? void 0 : _a.baseKeys) === null || _b === void 0 ? void 0 : _b.has('SR0054')).toBe(true);
|
|
2449
|
+
expect((_d = (_c = linked.get(1001)) === null || _c === void 0 ? void 0 : _c.fullCodes) === null || _d === void 0 ? void 0 : _d.has('SR0054-1')).toBe(true);
|
|
2450
|
+
});
|
|
2451
|
+
it('should ignore unsupported relation types when linking test case to requirements', async () => {
|
|
2452
|
+
var _a, _b, _c, _d;
|
|
2453
|
+
const requirements = [
|
|
2454
|
+
{
|
|
2455
|
+
workItemId: 7002,
|
|
2456
|
+
requirementId: 'SR0099-1',
|
|
2457
|
+
baseKey: 'SR0099',
|
|
2458
|
+
linkedTestCaseIds: [],
|
|
2459
|
+
},
|
|
2460
|
+
];
|
|
2461
|
+
const testData = [
|
|
2462
|
+
{
|
|
2463
|
+
testCasesItems: [{ workItem: { id: 1002 } }],
|
|
2464
|
+
testPointsItems: [],
|
|
2465
|
+
},
|
|
2466
|
+
];
|
|
2467
|
+
jest.spyOn(resultDataProvider, 'fetchWorkItemsByIds').mockImplementation(async (...args) => {
|
|
2468
|
+
const ids = Array.isArray(args === null || args === void 0 ? void 0 : args[1]) ? args[1] : [];
|
|
2469
|
+
const includeRelations = !!(args === null || args === void 0 ? void 0 : args[2]);
|
|
2470
|
+
if (includeRelations) {
|
|
2471
|
+
return [
|
|
2472
|
+
{
|
|
2473
|
+
id: 1002,
|
|
2474
|
+
relations: [
|
|
2475
|
+
{
|
|
2476
|
+
rel: 'System.LinkTypes.Related',
|
|
2477
|
+
url: 'https://dev.azure.com/org/project/_apis/wit/workItems/7002',
|
|
2478
|
+
},
|
|
2479
|
+
],
|
|
2480
|
+
},
|
|
2481
|
+
];
|
|
2482
|
+
}
|
|
2483
|
+
return ids.map((id) => ({
|
|
2484
|
+
id,
|
|
2485
|
+
fields: {
|
|
2486
|
+
'System.WorkItemType': id === 7002 ? 'Requirement' : 'Test Case',
|
|
2487
|
+
},
|
|
2488
|
+
}));
|
|
2489
|
+
});
|
|
2490
|
+
const linked = await resultDataProvider.buildLinkedRequirementsByTestCase(requirements, testData, mockProjectName);
|
|
2491
|
+
expect((_b = (_a = linked.get(1002)) === null || _a === void 0 ? void 0 : _a.baseKeys) === null || _b === void 0 ? void 0 : _b.has('SR0099')).toBe(false);
|
|
2492
|
+
expect((_d = (_c = linked.get(1002)) === null || _c === void 0 ? void 0 : _c.fullCodes) === null || _d === void 0 ? void 0 : _d.has('SR0099-1')).toBe(false);
|
|
2493
|
+
});
|
|
2494
|
+
});
|
|
2211
2495
|
describe('MEWP rel fallback scoping', () => {
|
|
2212
2496
|
it('should fallback to previous Rel run when latest selected Rel has no run for a test case', async () => {
|
|
2213
2497
|
const suites = [
|