11package org .jenkinsci .test .acceptance .po ;
22
33import java .time .Duration ;
4+ import java .util .concurrent .TimeUnit ;
5+
46import javax .annotation .Nullable ;
57
68import org .apache .commons .lang3 .StringUtils ;
79import org .jenkinsci .test .acceptance .selenium .Scroller ;
810import org .openqa .selenium .By ;
11+ import org .openqa .selenium .ElementClickInterceptedException ;
912import org .openqa .selenium .JavascriptExecutor ;
10- import org .openqa .selenium .Keys ;
1113import org .openqa .selenium .NoSuchElementException ;
1214import org .openqa .selenium .WebElement ;
1315import org .openqa .selenium .support .ui .Select ;
@@ -103,7 +105,14 @@ public void check(boolean state) {
103105 * @see #clickAndWaitToBecomeStale(Duration)
104106 */
105107 public void click () {
106- resolve ().click ();
108+ WebElement we = resolve ();
109+ // button may be obscured by say the "Save Apply" screen so we wait as Selenium will do a scroll but the CSS
110+ // can take a while to update the layout \o/
111+ waitFor (we ).
112+ withTimeout (1 , TimeUnit .SECONDS ).
113+ pollingEvery (100 , TimeUnit .MILLISECONDS ).
114+ ignoring (ElementClickInterceptedException .class ).
115+ until (() -> {we .click (); return true ;});
107116 }
108117
109118
@@ -184,17 +193,24 @@ public void set(Object text) {
184193 * @param type
185194 * Class with {@link Describable} annotation.
186195 */
187- public void selectDropdownMenu (Class type ) {
196+ public void selectDropdownMenu (Class <?> type ) {
188197 click ();
189- findCaption (type ,findDropDownMenuItem ).click ();
190- elasticSleep (1000 );
198+ WebElement we = findCaption (type ,findDropDownMenuItem );
199+ // the element may not yet be visible so wait for it to become shown after the click above
200+ waitFor (we ).pollingEvery (100L , TimeUnit .MILLISECONDS ).withTimeout (1 , TimeUnit .SECONDS ).until (() -> we .isDisplayed ());
201+ we .click ();
202+ // wait until the menu is hidden
203+ waitFor (we ).pollingEvery (100L , TimeUnit .MILLISECONDS ).withTimeout (1 , TimeUnit .SECONDS ).until (() -> !we .isDisplayed ());
191204 }
192205
193206 public void selectDropdownMenu (String displayName ) {
194207 click ();
195- elasticSleep (1000 );
196- findDropDownMenuItem .find (displayName ).click ();
197- elasticSleep (1000 );
208+ WebElement we = findDropDownMenuItem .find (displayName );
209+ // the element may not yet be visible so wait for it to become shown after the click above
210+ waitFor (we ).pollingEvery (100L , TimeUnit .MILLISECONDS ).withTimeout (1 , TimeUnit .SECONDS ).until (() -> we .isDisplayed ());
211+ we .click ();
212+ // wait until the menu is hidden
213+ waitFor (we ).pollingEvery (100L , TimeUnit .MILLISECONDS ).withTimeout (1 , TimeUnit .SECONDS ).until (() -> !we .isDisplayed ());
198214 }
199215
200216 /**
@@ -218,9 +234,9 @@ protected WebElement find(String caption) {
218234 " }" +
219235 ");"
220236 );
221-
222- WebElement context = findElement (menuButton , by .xpath ("ancestor::*[contains(@class,'yui-menu-button')]/.." ));
223- WebElement e = findElement (context , by .link (caption ));
237+ // we can not use `Select` as these are YUI menus and we need to wait for it to be visible
238+ WebElement menu = findElement (menuButton , by .xpath ("ancestor::*[contains(@class,'yui-menu-button')]/.." ));
239+ WebElement e = findElement (menu , by .link (caption ));
224240 return e ;
225241 }
226242 };
@@ -229,7 +245,7 @@ protected WebElement find(String caption) {
229245 * For alternative use when the 'yui-menu-button' doesn't exist.
230246 * @param type
231247 */
232- public void selectDropdownMenuAlt (Class type ) {
248+ public void selectDropdownMenuAlt (Class <?> type ) {
233249 findCaption (type ,findDropDownMenuItemBySelector );
234250 elasticSleep (1000 );
235251 }
0 commit comments