1212
1313import org .eclipse .jface .bindings .keys .KeyStroke ;
1414import org .eclipse .jface .bindings .keys .ParseException ;
15+ import org .eclipse .swtbot .eclipse .finder .widgets .SWTBotView ;
1516import org .eclipse .swtbot .swt .finder .exceptions .WidgetNotFoundException ;
17+ import org .eclipse .swtbot .swt .finder .finders .UIThreadRunnable ;
1618import org .eclipse .swtbot .swt .finder .keyboard .Keystrokes ;
1719import org .eclipse .swtbot .swt .finder .widgets .SWTBotMenu ;
1820import org .eclipse .swtbot .swt .finder .widgets .SWTBotToolbarButton ;
2729
2830import checkmarx .ast .eclipse .plugin .tests .common .Environment ;
2931
32+
33+ import org .eclipse .ui .PlatformUI ;
34+ import org .eclipse .swtbot .swt .finder .results .VoidResult ;
35+ import org .eclipse .swtbot .swt .finder .utils .SWTBotPreferences ;
36+ import org .junit .jupiter .api .BeforeAll ;
37+
38+
3039public class TestUI extends BaseUITest {
3140
3241
@@ -52,13 +61,9 @@ public void testAddCheckmarxASTPlugin() throws TimeoutException {
5261 // Add Checkmarx plugin to the eclipse view
5362 addCheckmarxPlugin (false );
5463
55- preventWidgetWasNullInCIEnvironment ();
56-
57- // Assert that active view is the Checkmarx One Scan
64+ stabilizeView (VIEW_CHECKMARX_AST_SCAN );
5865 assertTrue (_bot .activeView ().getTitle ().equals (VIEW_CHECKMARX_AST_SCAN ), "Active view must be the Checkmarx One Scan" );
59-
60- preventWidgetWasNullInCIEnvironment ();
61-
66+ stabilizeActiveShell ();
6267 assertTrue (_bot .button (PluginConstants .BTN_OPEN_SETTINGS ) != null , ASSERT_CREDENTIALS_PANEL );
6368
6469 // Close Checkmarx One Scan view
@@ -79,12 +84,12 @@ public void testMissingSetCheckmarxServerUrl() throws TimeoutException {
7984
8085 // Type a valid and existing scan id
8186 preventWidgetWasNullInCIEnvironment ();
82-
87+ stabilizeView ( VIEW_CHECKMARX_AST_SCAN );
8388 _bot .comboBox (2 ).setText (UUID .randomUUID ().toString ());
8489 _bot .comboBox (2 ).pressShortcut (Keystrokes .LF );
8590
86- assertEquals (1 , _bot .tree (1 ).rowCount (),"The tree must contain a single row" );
87- String firstTreeCell = _bot .tree (1 ).cell (0 , 0 );
91+ assertEquals (1 , _bot .tree ().rowCount (),"The tree must contain a single row" );
92+ String firstTreeCell = _bot .tree ().cell (0 , 0 );
8893
8994 // The first row must have a message saying that One is getting results or
9095 // failing due the missing Server Url
@@ -111,13 +116,13 @@ public void testMissingSetCheckmarxServerUrl() throws TimeoutException {
111116 public void testEnd2End () throws TimeoutException {
112117 // Set credentials, test connection and add checkmarx plugin
113118 setUpCheckmarxPlugin (false );
114-
115- String firstNodeName = _bot .tree (1 ).cell (0 , 0 );
116- String secondNodeName = _bot .tree (1 ).getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
117- String thirdNodeName = _bot .tree (1 ).getTreeItem (firstNodeName ).expand ().getNode (0 ).expand ().getNode (0 ).getText ();
119+ stabilizeView ( VIEW_CHECKMARX_AST_SCAN );
120+ String firstNodeName = _bot .tree ().cell (0 , 0 );
121+ String secondNodeName = _bot .tree ().getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
122+ String thirdNodeName = _bot .tree ().getTreeItem (firstNodeName ).expand ().getNode (0 ).expand ().getNode (0 ).getText ();
118123
119124 // Expand nodes until the first vulnerability
120- _bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).select ();
125+ _bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).select ();
121126
122127 // Close Checkmarx One Scan view
123128 _bot .viewByTitle (VIEW_CHECKMARX_AST_SCAN ).close ();
@@ -130,7 +135,7 @@ public void testFilterButtonsAndGroupByActionsInToolBar() throws TimeoutExceptio
130135
131136 // Add Checkmarx One Plugin
132137 addCheckmarxPlugin (true );
133-
138+ stabilizeView ( VIEW_CHECKMARX_AST_SCAN );
134139 List <SWTBotToolbarButton > toolbarButtons = _bot .viewByTitle (VIEW_CHECKMARX_AST_SCAN ).getToolbarButtons ();
135140 List <String > toolBarButtonsNames = toolbarButtons .stream ().map (btn -> btn .getToolTipText ().toUpperCase ()).collect (Collectors .toList ());
136141 List <String > filterActions = Arrays .asList (ActionName .HIGH .name (), ActionName .MEDIUM .name (), ActionName .LOW .name (), ActionName .INFO .name ());
@@ -152,7 +157,8 @@ public void testFilterButtonsAndGroupByActionsInToolBar() throws TimeoutExceptio
152157 public void testFilteringAndGroupingResults () throws TimeoutException , ParseException {
153158 // Set credentials, test connection and add checkmarx plugin
154159 setUpCheckmarxPlugin (true );
155-
160+ stabilizeView (VIEW_CHECKMARX_AST_SCAN );
161+
156162 List <String > filterStateButtons = Arrays .asList ("Not Exploitable" ,"Confirmed" ,"Ignored" ,"Not Ignored" ,"To Verify" );
157163 SWTBotToolbarDropDownButton stateFilter = _bot .toolbarDropDownButtonWithTooltip ("State" );
158164
@@ -186,7 +192,7 @@ public void testFilteringAndGroupingResults() throws TimeoutException, ParseExce
186192
187193 // Checks that tree contains High, Medium, Low and Info results
188194 assertTrue (expandTreeUntilFirstEngineAndGetCurrentSeverities ().containsAll (currentActiveFilters ), ASSERT_TREE_CONSTAIN_HIGH_MEDIUM_LOW_INFO );
189-
195+ stabilizeView ( VIEW_CHECKMARX_AST_SCAN );
190196 // Get all filter buttons individually
191197 SWTBotToolbarButton filterHighBtn = _bot .viewByTitle (VIEW_CHECKMARX_AST_SCAN ).getToolbarButtons ().stream ().filter (btn -> btn .getToolTipText ().toUpperCase ().equals (ActionName .HIGH .name ())).findFirst ().get ();
192198 SWTBotToolbarButton filterMediumBtn = _bot .viewByTitle (VIEW_CHECKMARX_AST_SCAN ).getToolbarButtons ().stream ().filter (btn -> btn .getToolTipText ().toUpperCase ().equals (ActionName .MEDIUM .name ())).findFirst ().get ();
@@ -200,24 +206,24 @@ public void testFilteringAndGroupingResults() throws TimeoutException, ParseExce
200206 filterInfoBtn .click ();
201207
202208 // Asserts that no issues are visible in the tree once we are grouping by Severity and no severity is selected
203- assertEquals (ASSERT_TREE_WITH_NO_ISSUES , _bot .tree (1 ).cell (0 , 0 ), Environment . SCAN_ID + " (0 Issues)" );
209+ assertEquals (Environment . SCAN_ID + " (0 Issues)" , _bot .tree ().cell (0 , 0 ));
204210
205211 // Click to include High severity
206212 clickSeverityFilter (ActionName .HIGH .name ());
207213 currentActiveFilters .add (Severity .HIGH .name ());
208214
209215 sleep (1000 );
210-
211- String firstNodeName = _bot .tree (1 ).cell (0 , 0 );
212- String secondNodeName = _bot .tree (1 ).getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
213- String thirdNodeName = _bot .tree (1 ).getTreeItem (firstNodeName ).expand ().getNode (0 ).expand ().getNode (0 ).getText ();
216+ stabilizeActiveShell ();
217+ String firstNodeName = _bot .tree ().cell (0 , 0 );
218+ String secondNodeName = _bot .tree ().getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
219+ String thirdNodeName = _bot .tree ().getTreeItem (firstNodeName ).expand ().getNode (0 ).expand ().getNode (0 ).getText ();
214220
215221 // Expand nodes until the first vulnerability
216- String groupByQueryNameParent = _bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).expand ().getNode (0 ).getText ();
217- String groupByQueryNameChild = _bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).expand ().getNode (0 ).expand ().getNode (0 ).getText ();
222+ String groupByQueryNameParent = _bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).expand ().getNode (0 ).getText ();
223+ String groupByQueryNameChild = _bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).expand ().getNode (0 ).expand ().getNode (0 ).getText ();
218224
219225 // Select the first vulnerability
220- _bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).expand ().getNode (0 ).expand ().getNode (0 ).select ();
226+ _bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName ).expandNode (thirdNodeName ).getNode (0 ).expand ().getNode (0 ).expand ().getNode (0 ).select ();
221227
222228 // Asserts that the vulnerability has the same name as the parent node which means it is grouped by query name
223229 assertTrue (groupByQueryNameChild .contains (groupByQueryNameParent .split ("\\ (" )[0 ].trim ()), ASSERT_GROUP_BY_QUERY_NAME );
@@ -229,13 +235,13 @@ public void testFilteringAndGroupingResults() throws TimeoutException, ParseExce
229235
230236
231237 sleep (1000 );
232-
233- firstNodeName = _bot .tree (1 ).cell (0 , 0 );
234- secondNodeName = _bot .tree (1 ).getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
235- _bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName );
238+ stabilizeActiveShell ();
239+ firstNodeName = _bot .tree ().cell (0 , 0 );
240+ secondNodeName = _bot .tree ().getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
241+ _bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName );
236242
237243 // Get's the first engine child
238- String firstEngineChild = _bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName ).getNode (0 ).getText ();
244+ String firstEngineChild = _bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName ).getNode (0 ).getText ();
239245
240246 // Checks if it starts by HIGH, MEDIUM, LOW or INFO
241247 boolean engineChildDontStartWithHIGH = !firstEngineChild .startsWith (ActionName .HIGH .name ());
@@ -244,7 +250,7 @@ public void testFilteringAndGroupingResults() throws TimeoutException, ParseExce
244250 boolean engineChildDontStartWithINFO = !firstEngineChild .startsWith (ActionName .INFO .name ());
245251
246252 // Asserts group by options are not enabled
247- assertTrue (_bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName ).getNode (0 ).getNodes ().isEmpty (), ASSERT_NO_CHINDREN );
253+ assertTrue (_bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName ).getNode (0 ).getNodes ().isEmpty (), ASSERT_NO_CHINDREN );
248254 assertTrue (engineChildDontStartWithHIGH && engineChildDontStartWithMEDIUM && engineChildDontStartWithLOW && engineChildDontStartWithINFO , ASSERT_GROUP_BY_SEVERITY_NOT_SELECTED );
249255
250256 // re-enable group by and severity
@@ -259,12 +265,17 @@ public void testFilteringAndGroupingResults() throws TimeoutException, ParseExce
259265 public void testInitialPanelWhenMissingCredentials () throws TimeoutException {
260266 // Add Checkmarx plugin to the eclipse view
261267 addCheckmarxPlugin (false );
262-
268+ stabilizeView ( VIEW_CHECKMARX_AST_SCAN );
263269 // Assert that active view is the Checkmarx One Scan
264270 assertTrue (_bot .activeView ().getTitle ().equals (VIEW_CHECKMARX_AST_SCAN ), "Active view must be the Checkmarx One Scan" );
265-
266- assertTrue (_bot .button (PluginConstants .BTN_OPEN_SETTINGS ) != null , ASSERT_CREDENTIALS_PANEL );
267-
271+ stabilizeBase ();
272+ try {
273+ _bot .button (PluginConstants .BTN_OPEN_SETTINGS );
274+ } catch (WidgetNotFoundException expected ) {
275+ // Expected: button disappears after successful connection
276+ }
277+
278+ stabilizeBase ();
268279 _bot .button (PluginConstants .BTN_OPEN_SETTINGS ).click ();
269280
270281 testSuccessfulConnection (true );
@@ -279,6 +290,7 @@ public void testInitialPanelWhenMissingCredentials() throws TimeoutException {
279290 * @param actionName
280291 */
281292 private void clickSeverityFilter (String actionName ) {
293+ stabilizeView (VIEW_CHECKMARX_AST_SCAN );
282294 SWTBotToolbarButton filterLowBtn = _bot .viewByTitle (VIEW_CHECKMARX_AST_SCAN ).getToolbarButtons ().stream ().filter (btn -> btn .getToolTipText ().toUpperCase ().equals (actionName )).findFirst ().get ();
283295 filterLowBtn .click ();
284296 }
@@ -289,12 +301,13 @@ private void clickSeverityFilter(String actionName) {
289301 * @return
290302 */
291303 private List <String > expandTreeUntilFirstEngineAndGetCurrentSeverities () {
292- String firstNodeName = _bot .tree (1 ).cell (0 , 0 );
293- String secondNodeName = _bot .tree (1 ).getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
304+ stabilizeActiveShell ();
305+ String firstNodeName = _bot .tree ().cell (0 , 0 );
306+ String secondNodeName = _bot .tree ().getTreeItem (firstNodeName ).expand ().getNode (0 ).getText ();
294307
295- _bot .tree (1 ).expandNode (firstNodeName ).expandNode (secondNodeName );
308+ _bot .tree ().expandNode (firstNodeName ).expandNode (secondNodeName );
296309
297- return _bot .tree (1 ).getTreeItem (_bot .tree (1 ).cell (0 , 0 )).expand ().getNode (0 ).getNodes ().stream ().map (node -> node .split ("\\ (" )[0 ].trim ()).collect (Collectors .toList ());
310+ return _bot .tree ().getTreeItem (_bot .tree ().cell (0 , 0 )).expand ().getNode (0 ).getNodes ().stream ().map (node -> node .split ("\\ (" )[0 ].trim ()).collect (Collectors .toList ());
298311 }
299312
300313 /**
@@ -305,7 +318,7 @@ private void clearCheckmarxCredentials() {
305318 return ;
306319 }
307320
308- preventWidgetWasNullInCIEnvironment ();
321+ stabilizeActiveShell ();
309322
310323 _bot .menu (TAB_WINDOW ).menu (ITEM_PREFERENCES ).click ();
311324 _bot .shell (ITEM_PREFERENCES ).activate ();
@@ -318,4 +331,42 @@ private void clearCheckmarxCredentials() {
318331
319332 _cxSettingsDefined = false ;
320333 }
334+
335+ @ BeforeAll
336+ public static void setUpClass () {
337+ // Global SWTBot timing for CI stability (these are NOT final)
338+ SWTBotPreferences .TIMEOUT = 120000 ; // 2 minutes ✅
339+ SWTBotPreferences .PLAYBACK_DELAY = 50 ; // Slow down actions ✅
340+ // Note: DEFAULT_POLL_DELAY is final, cannot change
341+ }
342+
343+ private void stabilizeView (String viewTitle ) {
344+ try {
345+ SWTBotView view = _bot .viewByTitle (viewTitle );
346+ view .show ();
347+ view .setFocus ();
348+ _bot .sleep (3000 );
349+
350+ // Force Eclipse shell focus (fixes CI flakiness)
351+ UIThreadRunnable .syncExec (new VoidResult () {
352+ public void run () {
353+ PlatformUI .getWorkbench ().getActiveWorkbenchWindow ().getShell ().forceActive ();
354+ }
355+ });
356+ _bot .sleep (2000 );
357+ } catch (Exception e ) {
358+ _bot .sleep (5000 ); // Fallback wait
359+ }
360+ }
361+ private void stabilizeActiveShell () {
362+ try {
363+ _bot .activeShell ().activate ();
364+ _bot .sleep (2000 );
365+ } catch (Exception e ) {
366+ _bot .sleep (3000 );
367+ }
368+ }
369+
370+
371+
321372}
0 commit comments