11package org .cloudfoundry .identity .uaa .test ;
22
3- import java .time .Duration ;
4- import java .util .List ;
5- import java .util .Set ;
6-
73import org .jspecify .annotations .Nullable ;
84import org .openqa .selenium .By ;
95import org .openqa .selenium .ElementNotInteractableException ;
1915import org .openqa .selenium .support .ui .FluentWait ;
2016import org .openqa .selenium .support .ui .WebDriverWait ;
2117
18+ import java .time .Duration ;
19+ import java .util .List ;
20+ import java .util .Set ;
21+
2222/**
2323 * Thin wrapper around a "regular" webdriver, that allows you to "click-and-wait" until
2424 * an element has disappeared. This avoids explicit waits in test code.
2828 */
2929public class UaaWebDriver implements WebDriver {
3030
31+ public static final Duration WAIT_TIMEOUT = Duration .ofSeconds (30L );
32+ public static final Duration POLLING_TIME = Duration .ofMillis (100 );
33+
3134 private final WebDriver delegate ;
3235
3336 public UaaWebDriver (WebDriver delegate ) {
3437 this .delegate = delegate ;
3538 }
3639
3740 /**
38- * Click on the element, and wait for a page reload. This is accomplished by waiting
39- * for the reference to the clicked element to become "stale", ie not be in the current
40- * DOM anymore, throwing {@link StaleElementReferenceException}. Sometimes, the Chrome driver
41- * throws a 500 error, which body contains code -32000, so we use that as a signal as well.
41+ * Click on the element and wait for a page reload.
42+ * This is achieved by waiting for the reference to the clicked element to become "stale",
43+ * i.e., not be in the current DOM anymore, throwing {@link StaleElementReferenceException}.
44+ * Sometimes, the Chrome driver throws a 500 error, which body contains code -32000, so we use that as a signal as well.
4245 */
4346 public void clickAndWait (By locator ) {
4447 var clickableElement = this .delegate .findElement (locator );
4548 clickableElement .click ();
4649
47- new FluentWait <>(this .delegate ).withTimeout (Duration . ofSeconds ( 5 ) )
48- .pollingEvery (Duration . ofMillis ( 100 ) )
50+ new FluentWait <>(this .delegate ).withTimeout (WAIT_TIMEOUT )
51+ .pollingEvery (POLLING_TIME )
4952 .withMessage (() -> "Waiting for navigation after clicking on [%s]. Current URL [%s]." .formatted (locator , delegate .getCurrentUrl ()))
5053 .until ((d ) -> {
5154 try {
@@ -60,19 +63,26 @@ public void clickAndWait(By locator) {
6063 }
6164
6265 /**
63- * Press the UAA navigation element with the given id, and wait for the button with a given id
64- * Example: After Login to UAA there is a menu in the top right corner with. A user can click on it and get
66+ * Press the UAA navigation element with the given id and wait for the button with a given id
67+ * Example: After Login to UAA, there is a menu in the top right corner that a user can click on and get
6568 * the profile page or perform a logout.
6669 */
6770 public void pressUaaNavigation (String navigationElementId , String idButton ) {
68- WebDriverWait wait1 = new WebDriverWait ( this . delegate , Duration . ofSeconds ( 10 ) );
69- WebElement elm1 = wait1 .ignoreAll (List .of (StaleElementReferenceException .class , ElementNotInteractableException .class )).until (ExpectedConditions .visibilityOfElementLocated (By .id (navigationElementId )));
71+ WebDriverWait wait = createWebDriverWait ( );
72+ WebElement elm1 = wait .ignoreAll (List .of (StaleElementReferenceException .class , ElementNotInteractableException .class )).until (ExpectedConditions .visibilityOfElementLocated (By .id (navigationElementId )));
7073 elm1 .click ();
71- WebDriverWait wait2 = new WebDriverWait ( this . delegate , Duration . ofSeconds ( 30 ));
72- WebElement elm2 = wait2 .ignoreAll (List .of (StaleElementReferenceException .class , ElementNotInteractableException .class )).until (ExpectedConditions .visibilityOfElementLocated (By .id (idButton )));
74+
75+ WebElement elm2 = wait .ignoreAll (List .of (StaleElementReferenceException .class , ElementNotInteractableException .class )).until (ExpectedConditions .visibilityOfElementLocated (By .id (idButton )));
7376 elm2 .click ();
7477 }
7578
79+ /**
80+ * Provides a {@link WebDriverWait} instance configured with predefined timeout and polling settings.
81+ */
82+ public WebDriverWait createWebDriverWait () {
83+ return new WebDriverWait (this .delegate , WAIT_TIMEOUT , POLLING_TIME );
84+ }
85+
7686 public JavascriptExecutor getJavascriptExecutor () {
7787 return (JavascriptExecutor ) this .delegate ;
7888 }
@@ -143,7 +153,16 @@ public Options manage() {
143153 }
144154
145155 public SessionId getSessionId () {
146- return ((RemoteWebDriver ) this .delegate ).getSessionId ();
156+ if (!(this .delegate instanceof RemoteWebDriver )) {
157+ return null ;
158+ }
159+ try {
160+ return ((RemoteWebDriver ) this .delegate ).getSessionId ();
161+ } catch (Exception e ) {
162+ // If the WebDriver has been quit or closed, getSessionId() may throw an exception
163+ // Return null to indicate the session is no longer available
164+ return null ;
165+ }
147166 }
148167
149168 public TakesScreenshot getTakesScreenShot () {
0 commit comments