33import com .publicissapient .kpidashboard .common .constant .ProcessorConstants ;
44import com .publicissapient .kpidashboard .common .exceptions .ClientErrorMessageEnum ;
55import com .publicissapient .kpidashboard .common .model .processortool .ProcessorToolConnection ;
6+ import com .publicissapient .kpidashboard .common .model .zephyr .TestCaseExecutionData ;
67import com .publicissapient .kpidashboard .common .model .zephyr .ZephyrTestCaseDTO ;
78import com .publicissapient .kpidashboard .common .processortool .service .ProcessorToolConnectionService ;
89import com .publicissapient .kpidashboard .zephyr .client .ZephyrClient ;
2930import org .springframework .web .util .UriComponentsBuilder ;
3031
3132import java .util .ArrayList ;
33+ import java .util .Collections ;
3234import java .util .HashMap ;
3335import java .util .HashSet ;
3436import java .util .Iterator ;
@@ -48,6 +50,8 @@ public class ZephyrCloudImpl implements ZephyrClient {
4850
4951 private static final String FOLDERS_RESOURCE_ENDPOINT = "https://api.zephyrscale.smartbear.com/v2/folders?maxResults=1000" ;
5052 private static final String TEST_CASE_ENDPOINT = "testcases" ;
53+ private static final String TEST_CASE_EXECUTION_DATA_ENDPOINT = "testexecutions" ;
54+ private static final String TEST_CASE = "testCase" ;
5155 private static final String PROJECT_KEY = "projectKey" ;
5256 private static final String START_AT = "startAt" ;
5357 private static final String MAX_RESULTS = "maxResults" ;
@@ -124,7 +128,7 @@ public List<ZephyrTestCaseDTO> getTestCase(int startAt, ProjectConfFieldMapping
124128 ResponseEntity <String > response = restTemplate .exchange (testCaseUrl , HttpMethod .GET , httpEntity ,
125129 String .class );
126130 if (response .getStatusCode () == HttpStatus .OK && Objects .nonNull (response .getBody ())) {
127- parseResponseAndPrepareTestCases (testCaseList , accessToken , jiraCloudCredential , response , folderMap );
131+ parseResponseAndPrepareTestCases (testCaseList , accessToken , jiraCloudCredential , response , folderMap , zephyrCloudUrl );
128132 } else {
129133 String statusCode = response .getStatusCode ().toString ();
130134 log .error ("Error while fetching projects from {}. with status {}" , testCaseUrl , statusCode );
@@ -166,7 +170,7 @@ private void isClientException(ProcessorToolConnection toolInfo, Exception excep
166170 * @param folderMap
167171 */
168172 private void parseResponseAndPrepareTestCases (List <ZephyrTestCaseDTO > testCaseList , String accessToken ,
169- String jiraCloudCredential , ResponseEntity <String > response , Map <String , String > folderMap )
173+ String jiraCloudCredential , ResponseEntity <String > response , Map <String , String > folderMap , String zephyrCloudUrl )
170174 throws ParseException {
171175 JSONArray testCaseArr = parseData (response .getBody (), VALUES );
172176 for (Object testCaseObj : testCaseArr ) {
@@ -188,6 +192,7 @@ private void parseResponseAndPrepareTestCases(List<ZephyrTestCaseDTO> testCaseLi
188192 zephyrTestCaseDTO .setFolder (folder );
189193 zephyrTestCaseDTO .setIssueLinks (issueLinks );
190194 zephyrTestCaseDTO .setCustomFields (customFields );
195+ zephyrTestCaseDTO .setTestCaseExecutionData (fetchExecutionsForTestCase (key , zephyrCloudUrl ,accessToken ));
191196 testCaseList .add (zephyrTestCaseDTO );
192197 }
193198 }
@@ -432,4 +437,72 @@ private static boolean folderFound(String currentId, ZephyrCloudFolderResponse f
432437 }
433438 return false ;
434439 }
440+
441+ public List <TestCaseExecutionData > fetchExecutionsForTestCase (String testCaseKey , String zephyrCloudUrl , String accessToken ) {
442+ try {
443+ String executionsUrl = UriComponentsBuilder .fromHttpUrl (zephyrCloudUrl )
444+ .path (TEST_CASE_EXECUTION_DATA_ENDPOINT )
445+ .queryParam (TEST_CASE , testCaseKey )
446+ .build (false )
447+ .toString ();
448+
449+ log .info ("Calling Zephyr executions API: {}" , executionsUrl );
450+
451+ HttpEntity <String > httpEntity = zephyrUtil .buildAuthHeaderUsingToken (accessToken );
452+ ResponseEntity <String > response = restTemplate .exchange (executionsUrl , HttpMethod .GET , httpEntity , String .class );
453+
454+ if (response .getStatusCode () == HttpStatus .OK && response .getBody () != null ) {
455+ return parseResponseAndPrepareTestCaseExecutionData (response .getBody ());
456+ } else {
457+ log .warn ("Failed to fetch executions for testCaseKey {}. Status: {}" , testCaseKey , response .getStatusCode ());
458+ }
459+
460+ } catch (Exception e ) {
461+ log .error ("Error while fetching executions for testCaseKey {}: {}" , testCaseKey , e .getMessage (), e );
462+ }
463+
464+ return Collections .emptyList ();
465+ }
466+ private List <TestCaseExecutionData > parseResponseAndPrepareTestCaseExecutionData (String responseBody ) throws ParseException {
467+ List <TestCaseExecutionData > executions = new ArrayList <>();
468+ JSONArray executionsArray = parseData (responseBody , VALUES );
469+
470+ for (Object obj : executionsArray ) {
471+ JSONObject executionJson = (JSONObject ) obj ;
472+ TestCaseExecutionData execution = new TestCaseExecutionData ();
473+
474+ execution .setExecutionId (safeInt (executionJson .get ("id" )) );
475+ execution .setKey ((String ) executionJson .get ("key" ));
476+ execution .setExecutionTime (safeInt (executionJson .get ("executionTime" )));
477+ execution .setEstimatedTime (safeInt (executionJson .get ("estimatedTime" )));
478+ execution .setActualEndDate ((String ) executionJson .get ("actualEndDate" ));
479+ execution .setComment ((String ) executionJson .get ("comment" ));
480+
481+ JSONObject testCycle = (JSONObject ) executionJson .get ("testCycle" );
482+ if (testCycle != null ) {
483+ execution .setTestCycleId (safeInt (testCycle .get ("id" )));
484+ }
485+
486+ JSONObject testCase = (JSONObject ) executionJson .get (TEST_CASE );
487+ if (testCase != null ) {
488+ execution .setTestCaseId (safeInt (testCase .get ("id" )));
489+ }
490+
491+ execution .setExecutedById ((String ) executionJson .get ("executedById" ));
492+ execution .setAssignedToId ((String ) executionJson .get ("assignedToId" ));
493+ executions .add (execution );
494+ }
495+
496+ return executions ;
497+ }
498+
499+ private int safeInt (Object value ) {
500+ try {
501+ return value != null ? Integer .parseInt (value .toString ()) : 0 ;
502+ } catch (NumberFormatException e ) {
503+ log .warn ("Unable to parse integer from value: {}" , value );
504+ return 0 ;
505+ }
506+ }
507+
435508}
0 commit comments