@elisra-devops/docgen-data-provider 1.72.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.
@@ -1074,6 +1074,323 @@ describe('ResultDataProvider', () => {
1074
1074
  });
1075
1075
  });
1076
1076
 
1077
+ describe('getMewpL2CoverageFlatResults', () => {
1078
+ it('should support query-mode requirement scope for MEWP coverage', async () => {
1079
+ jest.spyOn(resultDataProvider as any, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
1080
+ jest.spyOn(resultDataProvider as any, 'fetchTestSuites').mockResolvedValueOnce([{ testSuiteId: 1 }]);
1081
+ jest.spyOn(resultDataProvider as any, 'fetchTestData').mockResolvedValueOnce([
1082
+ {
1083
+ testPointsItems: [{ testCaseId: 101, lastRunId: 10, lastResultId: 20, testCaseName: 'TC 101' }],
1084
+ testCasesItems: [
1085
+ {
1086
+ workItem: {
1087
+ id: 101,
1088
+ workItemFields: [{ key: 'System.Title', value: 'TC 101' }],
1089
+ },
1090
+ },
1091
+ ],
1092
+ },
1093
+ ]);
1094
+ jest.spyOn(resultDataProvider as any, 'fetchMewpRequirementTypeNames').mockResolvedValueOnce([
1095
+ 'Requirement',
1096
+ ]);
1097
+ jest.spyOn(resultDataProvider as any, 'fetchWorkItemsByIds').mockResolvedValueOnce([
1098
+ {
1099
+ id: 9001,
1100
+ fields: {
1101
+ 'System.WorkItemType': 'Requirement',
1102
+ 'System.Title': 'Requirement from query',
1103
+ 'Custom.CustomerId': 'SR3001',
1104
+ 'System.AreaPath': 'MEWP\\IL',
1105
+ },
1106
+ relations: [
1107
+ {
1108
+ rel: 'Microsoft.VSTS.Common.TestedBy-Forward',
1109
+ url: 'https://dev.azure.com/org/_apis/wit/workItems/101',
1110
+ },
1111
+ ],
1112
+ },
1113
+ ]);
1114
+ jest.spyOn(resultDataProvider as any, 'fetchAllResultDataTestReporter').mockResolvedValueOnce([
1115
+ {
1116
+ testCaseId: 101,
1117
+ testCase: { id: 101, name: 'TC 101' },
1118
+ iteration: {
1119
+ actionResults: [{ action: 'Validate SR3001', expected: '', outcome: 'Passed' }],
1120
+ },
1121
+ },
1122
+ ]);
1123
+
1124
+ const TicketsProviderMock: any = require('../../modules/TicketsDataProvider').default;
1125
+ TicketsProviderMock.mockImplementationOnce(() => ({
1126
+ GetQueryResultsFromWiql: jest.fn().mockResolvedValue({
1127
+ fetchedWorkItems: [
1128
+ {
1129
+ id: 9001,
1130
+ fields: {
1131
+ 'System.WorkItemType': 'Requirement',
1132
+ 'System.Title': 'Requirement from query',
1133
+ 'Custom.CustomerId': 'SR3001',
1134
+ 'System.AreaPath': 'MEWP\\IL',
1135
+ },
1136
+ },
1137
+ ],
1138
+ }),
1139
+ }));
1140
+
1141
+ const result = await (resultDataProvider as any).getMewpL2CoverageFlatResults(
1142
+ '123',
1143
+ mockProjectName,
1144
+ [1],
1145
+ {
1146
+ linkedQueryMode: 'query',
1147
+ testAssociatedQuery: { wiql: { href: 'https://example.com/wiql' } },
1148
+ }
1149
+ );
1150
+
1151
+ const row = result.rows.find((item: any) => item['Customer ID'] === 'SR3001');
1152
+ expect(row).toEqual(
1153
+ expect.objectContaining({
1154
+ 'Title (Customer name)': 'Requirement from query',
1155
+ 'Responsibility - SAPWBS (ESUK/IL)': 'IL',
1156
+ 'Test case id': 101,
1157
+ 'Test case title': 'TC 101',
1158
+ 'Number of passed steps': 1,
1159
+ 'Number of failed steps': 0,
1160
+ 'Number of not run tests': 0,
1161
+ })
1162
+ );
1163
+
1164
+ expect(TicketsProviderMock).toHaveBeenCalled();
1165
+ const instance = TicketsProviderMock.mock.results[0].value;
1166
+ expect(instance.GetQueryResultsFromWiql).toHaveBeenCalledWith(
1167
+ 'https://example.com/wiql',
1168
+ true,
1169
+ expect.any(Map)
1170
+ );
1171
+ });
1172
+
1173
+ it('should map SR ids from steps and output requirement-test-case coverage rows', async () => {
1174
+ jest.spyOn(resultDataProvider as any, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
1175
+ jest.spyOn(resultDataProvider as any, 'fetchTestSuites').mockResolvedValueOnce([{ testSuiteId: 1 }]);
1176
+ jest.spyOn(resultDataProvider as any, 'fetchTestData').mockResolvedValueOnce([
1177
+ {
1178
+ testPointsItems: [
1179
+ { testCaseId: 101, lastRunId: 11, lastResultId: 22, testCaseName: 'TC 101' },
1180
+ { testCaseId: 102, lastRunId: 0, lastResultId: 0, testCaseName: 'TC 102' },
1181
+ ],
1182
+ testCasesItems: [
1183
+ {
1184
+ workItem: {
1185
+ id: 102,
1186
+ workItemFields: [{ key: 'Steps', value: '<steps></steps>' }],
1187
+ },
1188
+ },
1189
+ ],
1190
+ },
1191
+ ]);
1192
+ jest.spyOn(resultDataProvider as any, 'fetchMewpL2Requirements').mockResolvedValueOnce([
1193
+ {
1194
+ workItemId: 5001,
1195
+ requirementId: 'SR1001',
1196
+ title: 'Covered requirement',
1197
+ responsibility: 'ESUK',
1198
+ linkedTestCaseIds: [101],
1199
+ },
1200
+ {
1201
+ workItemId: 5002,
1202
+ requirementId: 'SR1002',
1203
+ title: 'Referenced from non-linked step text',
1204
+ responsibility: 'IL',
1205
+ linkedTestCaseIds: [],
1206
+ },
1207
+ {
1208
+ workItemId: 5003,
1209
+ requirementId: 'SR1003',
1210
+ title: 'Not covered by any test case',
1211
+ responsibility: 'IL',
1212
+ linkedTestCaseIds: [],
1213
+ },
1214
+ ]);
1215
+ jest.spyOn(resultDataProvider as any, 'fetchAllResultDataTestReporter').mockResolvedValueOnce([
1216
+ {
1217
+ testCaseId: 101,
1218
+ testCase: { id: 101, name: 'TC 101' },
1219
+ iteration: {
1220
+ actionResults: [
1221
+ {
1222
+ action: 'Validate <b>S</b><b>R</b> 1 0 0 1 happy path',
1223
+ expected: '',
1224
+ outcome: 'Passed',
1225
+ },
1226
+ { action: 'Validate SR1001 failed flow', expected: '&nbsp;', outcome: 'Failed' },
1227
+ { action: '', expected: 'Pending S R 1 0 0 1 scenario', outcome: 'Unspecified' },
1228
+ ],
1229
+ },
1230
+ },
1231
+ {
1232
+ testCaseId: 102,
1233
+ testCase: { id: 102, name: 'TC 102' },
1234
+ iteration: undefined,
1235
+ },
1236
+ ]);
1237
+ jest
1238
+ .spyOn((resultDataProvider as any).testStepParserHelper, 'parseTestSteps')
1239
+ .mockResolvedValueOnce([
1240
+ {
1241
+ stepId: '1',
1242
+ stepPosition: '1',
1243
+ action: 'Definition contains SR1002',
1244
+ expected: '',
1245
+ isSharedStepTitle: false,
1246
+ },
1247
+ ]);
1248
+
1249
+ const result = await (resultDataProvider as any).getMewpL2CoverageFlatResults(
1250
+ '123',
1251
+ mockProjectName,
1252
+ [1]
1253
+ );
1254
+
1255
+ expect(result).toEqual(
1256
+ expect.objectContaining({
1257
+ sheetName: expect.stringContaining('MEWP L2 Coverage'),
1258
+ columnOrder: expect.arrayContaining(['Customer ID', 'Test case id', 'Number of not run tests']),
1259
+ })
1260
+ );
1261
+
1262
+ const covered = result.rows.find(
1263
+ (row: any) => row['Customer ID'] === 'SR1001' && row['Test case id'] === 101
1264
+ );
1265
+ const inferredByStepText = result.rows.find(
1266
+ (row: any) => row['Customer ID'] === 'SR1002' && row['Test case id'] === 102
1267
+ );
1268
+ const uncovered = result.rows.find(
1269
+ (row: any) =>
1270
+ row['Customer ID'] === 'SR1003' &&
1271
+ (row['Test case id'] === '' || row['Test case id'] === undefined || row['Test case id'] === null)
1272
+ );
1273
+
1274
+ expect(covered).toEqual(
1275
+ expect.objectContaining({
1276
+ 'Title (Customer name)': 'Covered requirement',
1277
+ 'Responsibility - SAPWBS (ESUK/IL)': 'ESUK',
1278
+ 'Test case title': 'TC 101',
1279
+ 'Number of passed steps': 1,
1280
+ 'Number of failed steps': 1,
1281
+ 'Number of not run tests': 1,
1282
+ })
1283
+ );
1284
+ expect(inferredByStepText).toEqual(
1285
+ expect.objectContaining({
1286
+ 'Title (Customer name)': 'Referenced from non-linked step text',
1287
+ 'Responsibility - SAPWBS (ESUK/IL)': 'IL',
1288
+ 'Test case title': 'TC 102',
1289
+ 'Number of passed steps': 0,
1290
+ 'Number of failed steps': 0,
1291
+ 'Number of not run tests': 1,
1292
+ })
1293
+ );
1294
+ expect(uncovered).toEqual(
1295
+ expect.objectContaining({
1296
+ 'Title (Customer name)': 'Not covered by any test case',
1297
+ 'Responsibility - SAPWBS (ESUK/IL)': 'IL',
1298
+ 'Test case title': '',
1299
+ 'Number of passed steps': 0,
1300
+ 'Number of failed steps': 0,
1301
+ 'Number of not run tests': 0,
1302
+ })
1303
+ );
1304
+ });
1305
+
1306
+ it('should extract SR ids from HTML/spacing and return unique ids per step text', () => {
1307
+ const text =
1308
+ 'A: <b>S</b><b>R</b> 0 0 0 1; B: SR0002; C: S R 0 0 0 3; D: SR0002; E: &lt;b&gt;SR&lt;/b&gt;0004';
1309
+ const codes = (resultDataProvider as any).extractRequirementCodesFromText(text);
1310
+ expect([...codes].sort()).toEqual(['SR1', 'SR2', 'SR3', 'SR4']);
1311
+ });
1312
+
1313
+ it('should not backfill definition steps as not-run when a real run exists but has no action results', async () => {
1314
+ jest.spyOn(resultDataProvider as any, 'fetchTestPlanName').mockResolvedValueOnce('Plan A');
1315
+ jest.spyOn(resultDataProvider as any, 'fetchTestSuites').mockResolvedValueOnce([{ testSuiteId: 1 }]);
1316
+ jest.spyOn(resultDataProvider as any, 'fetchTestData').mockResolvedValueOnce([
1317
+ {
1318
+ testPointsItems: [{ testCaseId: 101, lastRunId: 88, lastResultId: 99, testCaseName: 'TC 101' }],
1319
+ testCasesItems: [
1320
+ {
1321
+ workItem: {
1322
+ id: 101,
1323
+ workItemFields: [{ key: 'Steps', value: '<steps></steps>' }],
1324
+ },
1325
+ },
1326
+ ],
1327
+ },
1328
+ ]);
1329
+ jest.spyOn(resultDataProvider as any, 'fetchMewpL2Requirements').mockResolvedValueOnce([
1330
+ {
1331
+ workItemId: 7001,
1332
+ requirementId: 'SR2001',
1333
+ title: 'Has run but no actions',
1334
+ responsibility: 'ESUK',
1335
+ linkedTestCaseIds: [101],
1336
+ },
1337
+ ]);
1338
+ jest.spyOn(resultDataProvider as any, 'fetchAllResultDataTestReporter').mockResolvedValueOnce([
1339
+ {
1340
+ testCaseId: 101,
1341
+ lastRunId: 88,
1342
+ lastResultId: 99,
1343
+ iteration: {
1344
+ actionResults: [],
1345
+ },
1346
+ },
1347
+ ]);
1348
+
1349
+ const parseSpy = jest
1350
+ .spyOn((resultDataProvider as any).testStepParserHelper, 'parseTestSteps')
1351
+ .mockResolvedValueOnce([
1352
+ {
1353
+ stepId: '1',
1354
+ stepPosition: '1',
1355
+ action: 'SR2001 from definition',
1356
+ expected: '',
1357
+ isSharedStepTitle: false,
1358
+ },
1359
+ ]);
1360
+
1361
+ const result = await (resultDataProvider as any).getMewpL2CoverageFlatResults(
1362
+ '123',
1363
+ mockProjectName,
1364
+ [1]
1365
+ );
1366
+
1367
+ const row = result.rows.find(
1368
+ (item: any) => item['Customer ID'] === 'SR2001' && item['Test case id'] === 101
1369
+ );
1370
+ expect(parseSpy).not.toHaveBeenCalled();
1371
+ expect(row).toEqual(
1372
+ expect.objectContaining({
1373
+ 'Number of passed steps': 0,
1374
+ 'Number of failed steps': 0,
1375
+ 'Number of not run tests': 0,
1376
+ })
1377
+ );
1378
+ });
1379
+
1380
+ it('should not infer requirement id from unrelated SR text in non-identifier fields', () => {
1381
+ const requirementId = (resultDataProvider as any).extractMewpRequirementIdentifier(
1382
+ {
1383
+ 'System.Description': 'random text with SR9999 that is unrelated',
1384
+ 'Custom.CustomerId': 'customer id unknown',
1385
+ 'System.Title': 'Requirement without explicit SR code',
1386
+ },
1387
+ 4321
1388
+ );
1389
+
1390
+ expect(requirementId).toBe('4321');
1391
+ });
1392
+ });
1393
+
1077
1394
  describe('fetchResultDataForTestReporter (runResultField switch)', () => {
1078
1395
  it('should populate requested runResultField values including testCaseResult URL branches', async () => {
1079
1396
  jest
@@ -2586,6 +2903,244 @@ describe('ResultDataProvider', () => {
2586
2903
  expect.objectContaining({ stepIdentifier: '2', action: 'A2', isSharedStepTitle: true })
2587
2904
  );
2588
2905
  });
2906
+
2907
+ it('should fall back to parsed test steps when actionResults are missing for latest run', async () => {
2908
+ const point = { testCaseId: 1, lastRunId: 10, lastResultId: 20 };
2909
+ const fetchResultMethod = jest.fn().mockResolvedValue({
2910
+ testCase: { id: 1, name: 'TC' },
2911
+ stepsResultXml: '<steps></steps>',
2912
+ iterationDetails: [{}],
2913
+ });
2914
+
2915
+ const createResponseObject = (resultData: any) => ({ iteration: resultData.iterationDetails[0] });
2916
+
2917
+ const helper = (resultDataProvider as any).testStepParserHelper;
2918
+ helper.parseTestSteps.mockResolvedValueOnce([
2919
+ { stepId: 172, stepPosition: '1', action: 'Step 1', expected: 'Expected 1', isSharedStepTitle: false },
2920
+ { stepId: 173, stepPosition: '2', action: 'Step 2', expected: 'Expected 2', isSharedStepTitle: false },
2921
+ ]);
2922
+
2923
+ const res = await (resultDataProvider as any).fetchResultDataBase(
2924
+ mockProjectName,
2925
+ 'suite1',
2926
+ point,
2927
+ fetchResultMethod,
2928
+ createResponseObject,
2929
+ []
2930
+ );
2931
+
2932
+ const actionResults = res.iteration.actionResults;
2933
+ expect(actionResults).toHaveLength(2);
2934
+ expect(actionResults[0]).toEqual(
2935
+ expect.objectContaining({
2936
+ stepIdentifier: '172',
2937
+ stepPosition: '1',
2938
+ action: 'Step 1',
2939
+ expected: 'Expected 1',
2940
+ outcome: 'Unspecified',
2941
+ })
2942
+ );
2943
+ expect(actionResults[1]).toEqual(
2944
+ expect.objectContaining({
2945
+ stepIdentifier: '173',
2946
+ stepPosition: '2',
2947
+ action: 'Step 2',
2948
+ expected: 'Expected 2',
2949
+ outcome: 'Unspecified',
2950
+ })
2951
+ );
2952
+ });
2953
+
2954
+ it('should create synthetic iteration and fall back to parsed test steps when iterationDetails are missing', async () => {
2955
+ const point = { testCaseId: 1, lastRunId: 10, lastResultId: 20 };
2956
+ const fetchResultMethod = jest.fn().mockResolvedValue({
2957
+ testCase: { id: 1, name: 'TC' },
2958
+ stepsResultXml: '<steps></steps>',
2959
+ iterationDetails: [],
2960
+ });
2961
+
2962
+ const createResponseObject = (resultData: any) => ({ iteration: resultData.iterationDetails[0] });
2963
+
2964
+ const helper = (resultDataProvider as any).testStepParserHelper;
2965
+ helper.parseTestSteps.mockResolvedValueOnce([
2966
+ { stepId: 301, stepPosition: '1', action: 'S1', expected: 'E1', isSharedStepTitle: false },
2967
+ ]);
2968
+
2969
+ const res = await (resultDataProvider as any).fetchResultDataBase(
2970
+ mockProjectName,
2971
+ 'suite1',
2972
+ point,
2973
+ fetchResultMethod,
2974
+ createResponseObject,
2975
+ []
2976
+ );
2977
+
2978
+ expect(res.iteration).toBeDefined();
2979
+ expect(res.iteration.actionResults).toHaveLength(1);
2980
+ expect(res.iteration.actionResults[0]).toEqual(
2981
+ expect.objectContaining({
2982
+ stepIdentifier: '301',
2983
+ stepPosition: '1',
2984
+ action: 'S1',
2985
+ expected: 'E1',
2986
+ outcome: 'Unspecified',
2987
+ })
2988
+ );
2989
+ });
2990
+
2991
+ it('should fall back to parsed test steps when actionResults is an empty array', async () => {
2992
+ const point = { testCaseId: 1, lastRunId: 10, lastResultId: 20 };
2993
+ const fetchResultMethod = jest.fn().mockResolvedValue({
2994
+ testCase: { id: 1, name: 'TC' },
2995
+ stepsResultXml: '<steps></steps>',
2996
+ iterationDetails: [{ actionResults: [] }],
2997
+ });
2998
+
2999
+ const createResponseObject = (resultData: any) => ({ iteration: resultData.iterationDetails[0] });
3000
+
3001
+ const helper = (resultDataProvider as any).testStepParserHelper;
3002
+ helper.parseTestSteps.mockResolvedValueOnce([
3003
+ { stepId: 11, stepPosition: '1', action: 'A1', expected: 'E1', isSharedStepTitle: false },
3004
+ { stepId: 22, stepPosition: '2', action: 'A2', expected: 'E2', isSharedStepTitle: false },
3005
+ ]);
3006
+
3007
+ const res = await (resultDataProvider as any).fetchResultDataBase(
3008
+ mockProjectName,
3009
+ 'suite1',
3010
+ point,
3011
+ fetchResultMethod,
3012
+ createResponseObject,
3013
+ []
3014
+ );
3015
+
3016
+ expect(helper.parseTestSteps).toHaveBeenCalledTimes(1);
3017
+ expect(res.iteration.actionResults).toHaveLength(2);
3018
+ expect(res.iteration.actionResults[0]).toEqual(
3019
+ expect.objectContaining({
3020
+ stepIdentifier: '11',
3021
+ stepPosition: '1',
3022
+ action: 'A1',
3023
+ expected: 'E1',
3024
+ outcome: 'Unspecified',
3025
+ })
3026
+ );
3027
+ expect(res.iteration.actionResults[1]).toEqual(
3028
+ expect.objectContaining({
3029
+ stepIdentifier: '22',
3030
+ stepPosition: '2',
3031
+ action: 'A2',
3032
+ expected: 'E2',
3033
+ outcome: 'Unspecified',
3034
+ })
3035
+ );
3036
+ });
3037
+ });
3038
+
3039
+ describe('getTestReporterFlatResults', () => {
3040
+ it('should return flat rows with logical step numbering for fallback-generated action results', async () => {
3041
+ jest.spyOn(resultDataProvider as any, 'fetchTestPlanName').mockResolvedValueOnce('Plan 12');
3042
+ jest.spyOn(resultDataProvider as any, 'fetchTestSuites').mockResolvedValueOnce([
3043
+ {
3044
+ testSuiteId: 200,
3045
+ suiteId: 200,
3046
+ suiteName: 'suite 2.1',
3047
+ parentSuiteId: 100,
3048
+ parentSuiteName: 'Rel2',
3049
+ suitePath: 'Root/Rel2/suite 2.1',
3050
+ testGroupName: 'suite 2.1',
3051
+ },
3052
+ ]);
3053
+
3054
+ const testData = [
3055
+ {
3056
+ testSuiteId: 200,
3057
+ suiteId: 200,
3058
+ suiteName: 'suite 2.1',
3059
+ parentSuiteId: 100,
3060
+ parentSuiteName: 'Rel2',
3061
+ suitePath: 'Root/Rel2/suite 2.1',
3062
+ testGroupName: 'suite 2.1',
3063
+ testPointsItems: [
3064
+ {
3065
+ testCaseId: 17,
3066
+ testCaseName: 'TC 17',
3067
+ outcome: 'Unspecified',
3068
+ lastRunId: 99,
3069
+ lastResultId: 88,
3070
+ testPointId: 501,
3071
+ lastResultDetails: {
3072
+ dateCompleted: '2026-02-01T10:00:00.000Z',
3073
+ outcome: 'Unspecified',
3074
+ runBy: { displayName: 'tester user' },
3075
+ },
3076
+ },
3077
+ ],
3078
+ testCasesItems: [
3079
+ {
3080
+ workItem: {
3081
+ id: 17,
3082
+ workItemFields: [{ key: 'Steps', value: '<steps></steps>' }],
3083
+ },
3084
+ },
3085
+ ],
3086
+ },
3087
+ ];
3088
+ jest.spyOn(resultDataProvider as any, 'fetchTestData').mockResolvedValueOnce(testData);
3089
+ jest.spyOn(resultDataProvider as any, 'fetchAllResultDataTestReporter').mockResolvedValueOnce([
3090
+ {
3091
+ testCaseId: 17,
3092
+ lastRunId: 99,
3093
+ lastResultId: 88,
3094
+ executionDate: '2026-02-01T10:00:00.000Z',
3095
+ testCaseResult: { resultMessage: '' },
3096
+ customFields: { 'Custom.SubSystem': 'SYS' },
3097
+ runBy: 'tester user',
3098
+ iteration: {
3099
+ actionResults: [
3100
+ {
3101
+ stepIdentifier: '172',
3102
+ stepPosition: '1',
3103
+ actionPath: '1',
3104
+ action: 'fallback action',
3105
+ expected: 'fallback expected',
3106
+ outcome: 'Unspecified',
3107
+ errorMessage: '',
3108
+ isSharedStepTitle: false,
3109
+ },
3110
+ ],
3111
+ },
3112
+ },
3113
+ ]);
3114
+
3115
+ const result = await resultDataProvider.getTestReporterFlatResults(
3116
+ mockTestPlanId,
3117
+ mockProjectName,
3118
+ undefined,
3119
+ [],
3120
+ false
3121
+ );
3122
+
3123
+ expect(result.planId).toBe(mockTestPlanId);
3124
+ expect(result.planName).toBe('Plan 12');
3125
+ expect(result.rows).toHaveLength(1);
3126
+ expect(result.rows[0]).toEqual(
3127
+ expect.objectContaining({
3128
+ planId: mockTestPlanId,
3129
+ planName: 'Plan 12',
3130
+ suiteId: 200,
3131
+ suiteName: 'suite 2.1',
3132
+ parentSuiteId: 100,
3133
+ parentSuiteName: 'Rel2',
3134
+ suitePath: 'Root/Rel2/suite 2.1',
3135
+ testCaseId: 17,
3136
+ testCaseName: 'TC 17',
3137
+ testRunId: 99,
3138
+ testPointId: 501,
3139
+ stepOutcome: 'Unspecified',
3140
+ stepStepIdentifier: '1',
3141
+ })
3142
+ );
3143
+ });
2589
3144
  });
2590
3145
 
2591
3146
  describe('getCombinedResultsSummary - appendix branches', () => {