[java-idp-integration-tests] branch main updated: Attempt to fix Safari tests - retry stale element reference exceptions
Tom Zeller
tzeller at dragonacea.biz
Sun Sep 15 01:13:06 UTC 2024
This is an automated email from the git hooks/post-receive script.
tzeller pushed a commit to branch main
in repository java-idp-integration-tests.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-integration-tests.git;a=commit;h=4bdeea5521e9bd1349d20705d45309ac7a9f260d
The following commit(s) were added to refs/heads/main by this push:
new 4bdeea5 Attempt to fix Safari tests - retry stale element reference exceptions
4bdeea5 is described below
commit 4bdeea5521e9bd1349d20705d45309ac7a9f260d
Author: Tom Zeller <tzeller at dragonacea.biz>
AuthorDate: Sat Sep 14 20:12:55 2024 -0500
Attempt to fix Safari tests - retry stale element reference exceptions
Add a little sleep time when attempting to click.
Decrease some Sauce Labs logging.
---
.../idp/integration/tests/BaseIntegrationTest.java | 135 ++++++++++++++++-----
.../tests/consent/UserPrefsRevokeConsentTest.java | 2 +-
2 files changed, 106 insertions(+), 31 deletions(-)
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java b/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java
index c7fac2f..d732627 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/BaseIntegrationTest.java
@@ -1661,27 +1661,16 @@ public abstract class BaseIntegrationTest {
*/
public DesiredCapabilities setUpDesiredCapabilities() {
- log.trace("System property SAUCE_ONDEMAND_BROWSERS '{}'", System.getProperty("SAUCE_ONDEMAND_BROWSERS"));
- log.trace("System property SELENIUM_PLATFORM '{}'", System.getProperty("SELENIUM_PLATFORM"));
- log.trace("System property SELENIUM_BROWSER '{}'", System.getProperty("SELENIUM_BROWSER"));
- log.trace("System property SELENIUM_VERSION '{}'", System.getProperty("SELENIUM_VERSION"));
- log.trace("System property SELENIUM_DEVICE '{}'", System.getProperty("SELENIUM_DEVICE"));
- log.trace("Environment variable SAUCE_ONDEMAND_BROWSERS '{}'", System.getenv("SAUCE_ONDEMAND_BROWSERS"));
- log.trace("Environment variable SELENIUM_PLATFORM '{}'", System.getenv("SELENIUM_PLATFORM"));
- log.trace("Environment variable SELENIUM_BROWSER '{}'", System.getenv("SELENIUM_BROWSER"));
- log.trace("Environment variable SELENIUM_VERSION '{}'", System.getenv("SELENIUM_VERSION"));
- log.trace("Environment variable SELENIUM_DEVICE '{}'", System.getenv("SELENIUM_DEVICE"));
-
// prefer system properties to environment variable
final String platform = System.getProperty("SELENIUM_PLATFORM", System.getenv("SELENIUM_PLATFORM"));
- final String browser = System.getProperty("SELENIUM_BROWSER", System.getenv("SELENIUM_BROWSER"));
- final String version = System.getProperty("SELENIUM_VERSION", System.getenv("SELENIUM_VERSION"));
- final String device = System.getProperty("SELENIUM_DEVICE", System.getenv("SELENIUM_DEVICE"));
+ final String browser = System.getProperty("SELENIUM_BROWSER", System.getenv("SELENIUM_BROWSER"));
+ final String version = System.getProperty("SELENIUM_VERSION", System.getenv("SELENIUM_VERSION"));
+ final String device = System.getProperty("SELENIUM_DEVICE", System.getenv("SELENIUM_DEVICE"));
- log.debug("SELENIUM_PLATFORM '{}'", platform);
- log.debug("SELENIUM_BROWSER '{}'", browser);
- log.debug("SELENIUM_VERSION '{}'", version);
- log.debug("SELENIUM_DEVICE '{}'", device);
+ log.debug("SELENIUM_PLATFORM '{}' sys prop '{}' env var '{}'", platform, System.getProperty("SELENIUM_PLATFORM"), System.getenv("SELENIUM_PLATFORM"));
+ log.debug("SELENIUM_BROWSER '{}' sys prop '{}' env var '{}'", browser, System.getProperty("SELENIUM_BROWSER"), System.getenv("SELENIUM_BROWSER"));
+ log.debug("SELENIUM_VERSION '{}' sys prop '{}' env var '{}'", version, System.getProperty("SELENIUM_VERSION"), System.getenv("SELENIUM_VERSION"));
+ log.debug("SELENIUM_DEVICE '{}' sys prop '{}' env var '{}'", device, System.getProperty("SELENIUM_DEVICE"), System.getenv("SELENIUM_DEVICE"));
final DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
@@ -1848,12 +1837,25 @@ public abstract class BaseIntegrationTest {
/**
* Get the source of the last page loaded.
*
+ * Catches {@link StaleElementReferenceException} and retries 3 times.
+ *
* @return the source of the last page loaded or <code>null</code>
*/
@Nullable
public String getPageSource() {
- final String pageSource = driver.findElement(By.tagName("body")).getText();
- log.trace("get page source\n{}", pageSource);
+ String pageSource = null;
+ int retries = 0;
+ while (retries < 3) {
+ try {
+ pageSource = driver.findElement(By.tagName("body")).getText();
+ break;
+ } catch (final StaleElementReferenceException e) {
+ log.debug("Will retry attempt to get page source, caught stale element exception", e);
+ sleep(100);
+ retries++;
+ }
+ }
+ log.trace("Get page source :\n{}", pageSource);
return pageSource;
}
@@ -1972,7 +1974,7 @@ public abstract class BaseIntegrationTest {
public void acceptTermsOfUse() {
final WebElement element = driver.findElement(By.name(CONSENT_IDS_INPUT_NAME));
if (!element.isSelected()) {
- clickWorkaround(element);
+ clickWorkaroundWithRetry(element);
}
}
@@ -2099,22 +2101,22 @@ public abstract class BaseIntegrationTest {
public void releaseEmailAttributeOnly() {
final WebElement email = driver.findElement(By.id(EMAIL_ID));
if (!email.isSelected()) {
- clickWorkaround(email);
+ clickWorkaroundWithRetry(email);
}
final WebElement eduPersonAffiliation = driver.findElement(By.id(EDU_PERSON_AFFILIATION_ID));
if (eduPersonAffiliation.isSelected()) {
- clickWorkaround(eduPersonAffiliation);
+ clickWorkaroundWithRetry(eduPersonAffiliation);
}
final WebElement eduPersonPrincipalName = driver.findElement(By.id(EDU_PERSON_PRINCIPAL_NAME_ID));
if (eduPersonPrincipalName.isSelected()) {
- clickWorkaround(eduPersonPrincipalName);
+ clickWorkaroundWithRetry(eduPersonPrincipalName);
}
final WebElement uid = driver.findElement(By.id(UID_ID));
if (uid.isSelected()) {
- clickWorkaround(uid);
+ clickWorkaroundWithRetry(uid);
}
}
@@ -2124,7 +2126,7 @@ public abstract class BaseIntegrationTest {
public void rememberConsent() {
final WebElement element = driver.findElement(By.id(REMEMBER_CONSENT_ID));
if (!element.isSelected()) {
- clickWorkaround(element);
+ clickWorkaroundWithRetry(element);
}
}
@@ -2134,7 +2136,7 @@ public abstract class BaseIntegrationTest {
public void doNotRememberConsent() {
final WebElement element = driver.findElement(By.id(DO_NOT_REMEMBER_CONSENT_ID));
if (!element.isSelected()) {
- clickWorkaround(element);
+ clickWorkaroundWithRetry(element);
}
}
@@ -2144,7 +2146,7 @@ public abstract class BaseIntegrationTest {
public void globalConsent() {
final WebElement element = driver.findElement(By.id(GLOBAL_CONSENT_ID));
if (!element.isSelected()) {
- clickWorkaround(element);
+ clickWorkaroundWithRetry(element);
}
}
@@ -2231,7 +2233,7 @@ public abstract class BaseIntegrationTest {
*/
public void clickWorkaround(final WebElement element) throws RuntimeException {
boolean isSelected = element.isSelected();
- log.trace("ClickWorkaround element '{}' isSelected '{}'", element, element.isSelected());
+ log.trace("Click workaround element '{}' isSelected '{}'", element, element.isSelected());
try {
// Try clicking element
log.trace("Attempting to click element '{}'", element);
@@ -2242,6 +2244,7 @@ public abstract class BaseIntegrationTest {
// Try moving to element and clicking, element must be in viewport
try {
log.trace("Attempting to move to element and click '{}'", element);
+ sleep(100);
action.moveToElement(element).click().perform();
} catch (org.openqa.selenium.interactions.MoveTargetOutOfBoundsException e1) {
log.trace("Unable to move to element '{}' out of bounds, will try JavaScript", element);
@@ -2251,11 +2254,12 @@ public abstract class BaseIntegrationTest {
// If element is still not clicked, try JavaScript
if ((isSelected && element.isSelected()) || (!isSelected && !element.isSelected())) {
log.trace("Attempting JavaScript to click element '{}'", element);
+ sleep(100);
final JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();", element);
}
}
- log.trace("ClickWorkaround element '{}' isSelected '{}'", element, element.isSelected());
+ log.trace("Click workaround element '{}' isSelected '{}'", element, element.isSelected());
// If element is not clicked, throw runtime exception
if ((isSelected && element.isSelected()) || (!isSelected && !element.isSelected())) {
log.error("Unable to click element '{}'", element);
@@ -2263,6 +2267,63 @@ public abstract class BaseIntegrationTest {
}
}
+ /**
+ * Call {@link #clickWorkaround()} twice if {@link StaleElementReferenceException} is thrown.
+ *
+ * @param element
+ * element to be clicked
+ * @throws RuntimeException
+ * if element is not clicked
+ */
+ public void clickWorkaroundWithRetry(final WebElement element) throws RuntimeException {
+ try {
+ log.debug("Calling click workaround first for element '{}'", element);
+ clickWorkaround(element);
+ } catch (final StaleElementReferenceException e) {
+ log.debug("Caught stale element exception", e);
+ final By by = getByFromElement(element);
+ final WebElement refreshedElement = driver.findElement(by);
+ log.debug("Calling click workaround again for element '{}'", refreshedElement);
+ clickWorkaround(refreshedElement);
+ }
+ }
+
+ /**
+ * Get the {@link By} locator for the {@link WebElement}.
+ *
+ * @param element
+ * the {@link WebElement}
+ * @return the {@link By} locator
+ * @throws {@link
+ * IllegalStateException} if locator can not be determined
+ */
+ @Nonnull
+ protected By getByFromElement(@Nonnull final WebElement element) {
+ // Pattern should match [[SafariDriver: Safari on mac (UUID)] -> id: uid]
+ final Pattern pattern = Pattern.compile(".*? -> (\\w+): (\\w+)]");
+
+ final Matcher matcher = pattern.matcher(element.toString());
+ Assert.assertTrue(matcher.find());
+
+ final String selector = matcher.group(1);
+ final String value = matcher.group(2);
+
+ By by = null;
+ switch (selector) {
+ case "id" -> by = By.id(value);
+ case "className" -> by = By.className(value);
+ case "tagName" -> by = By.tagName(value);
+ case "xpath" -> by = By.xpath(value);
+ case "cssSelector" -> by = By.cssSelector(value);
+ case "linkText" -> by = By.linkText(value);
+ case "name" -> by = By.name(value);
+ case "partialLinkText" -> by = By.partialLinkText(value);
+ default -> throw new IllegalStateException("Unable to determine locator from element " + element);
+ }
+ log.debug("Get locator '{}' from element '{}'", by, element);
+ return by;
+ }
+
/**
* Log output of process.
*
@@ -3162,4 +3223,18 @@ public abstract class BaseIntegrationTest {
return matcher.find() ? matcher.group(1) : null;
}
+ /**
+ * Sleep and catch any {@link InterruptedException}.
+ *
+ * @param millis
+ * the length of time to sleep in milliseconds
+ */
+ public void sleep(@Nonnull final long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (final InterruptedException e) {
+ log.error("Unable to sleep", e);
+ }
+ }
+
}
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/consent/UserPrefsRevokeConsentTest.java b/src/test/java/net/shibboleth/idp/integration/tests/consent/UserPrefsRevokeConsentTest.java
index aa57fab..61da414 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/consent/UserPrefsRevokeConsentTest.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/consent/UserPrefsRevokeConsentTest.java
@@ -112,7 +112,7 @@ public class UserPrefsRevokeConsentTest extends AbstractSAML2IntegrationTest {
// check the un-checked revoke consent checkbox
WebElement revokeConsentCheckbox = driver.findElement(By.id(REVOKE_CONSENT_ID));
Assert.assertFalse(revokeConsentCheckbox.isSelected());
- clickWorkaround(revokeConsentCheckbox);
+ clickWorkaroundWithRetry(revokeConsentCheckbox);
// start login flow again, should prompt for consent
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list