From 183cd6c957f8bd30674177874f12e3d5d166d72b Mon Sep 17 00:00:00 2001 From: Hynek Mlnarik Date: Wed, 17 Jul 2024 10:17:25 +0200 Subject: [PATCH] Run tests with keycloak.v2 login theme The fixes (mostly selectors) are needed for tests. In the future, to switch the keycloak.v2 to the default theme, do the following: - Update `ThemeSelectorProvider`: Uncomment relevant lines - Update `testsuite/integration-arquillian/tests/pom.xml`: Revert the change in `` property - Update `ThemeSelectorTest` per comment Signed-off-by: Hynek Mlnarik --- .../login/DeleteAccountActionConfirmPage.java | 2 +- .../auth/page/login/FeedbackMessage.java | 19 ++- .../auth/page/login/OneTimeCode.java | 2 +- .../page/LoginPasswordUpdatePage.java | 2 +- .../testsuite/pages/IdpConfirmLinkPage.java | 2 +- .../pages/IdpConfirmOverrideLinkPage.java | 2 +- .../pages/InstalledAppRedirectPage.java | 2 +- .../pages/LanguageComboboxAwarePage.java | 35 +++++- .../testsuite/pages/LoginConfigTotpPage.java | 2 +- .../keycloak/testsuite/pages/LoginPage.java | 6 +- .../pages/LoginPasswordResetPage.java | 4 +- .../pages/LoginPasswordUpdatePage.java | 2 +- .../testsuite/pages/LoginTotpPage.java | 2 +- .../pages/LoginUpdateProfilePage.java | 10 +- .../pages/OAuth2DeviceVerificationPage.java | 6 +- .../testsuite/pages/PasswordPage.java | 2 +- .../testsuite/pages/RegisterPage.java | 22 ++-- .../pages/UpdateAccountInformationPage.java | 12 +- .../testsuite/pages/VerifyProfilePage.java | 10 +- .../x509/X509IdentityConfirmationPage.java | 4 +- .../keycloak/testsuite/util/OAuthClient.java | 20 ++-- .../org/keycloak/testsuite/util/UIUtils.java | 3 +- .../webauthn/pages/WebAuthnErrorPage.java | 2 +- .../testsuite/AbstractKeycloakTest.java | 4 +- ...ActionUpdateEmailWithVerificationTest.java | 2 +- .../RequiredActionUpdateProfileTest.java | 42 +++++-- ...ctionUpdateProfileWithUserProfileTest.java | 112 ++++++------------ .../servlet/SAMLServletAdapterTest.java | 2 +- .../admin/AdminConsoleWhoAmILocaleTest.java | 22 ++-- .../broker/AbstractDefaultIdpTest.java | 2 +- .../broker/KcOidcFirstBrokerLoginTest.java | 91 ++++---------- .../broker/KcOidcMultipleTabsBrokerTest.java | 5 + .../broker/KcSamlMultipleTabsBrokerTest.java | 4 + .../cluster/AbstractFailoverClusterTest.java | 2 +- .../error/UncaughtErrorPageTest.java | 2 + .../forms/RegisterWithUserProfileTest.java | 101 ++++------------ .../testsuite/forms/ThemeSelectorTest.java | 11 +- .../testsuite/forms/VerifyProfileTest.java | 88 ++++---------- .../testsuite/i18n/LoginPageTest.java | 2 +- .../migration/AbstractMigrationTest.java | 3 +- .../testsuite/oauth/RefreshTokenTest.java | 5 +- .../testsuite/saml/IdpInitiatedLoginTest.java | 14 ++- .../integration-arquillian/tests/pom.xml | 2 +- 43 files changed, 289 insertions(+), 400 deletions(-) diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/DeleteAccountActionConfirmPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/DeleteAccountActionConfirmPage.java index 539db4dcb7..a0f739ee3b 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/DeleteAccountActionConfirmPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/DeleteAccountActionConfirmPage.java @@ -35,7 +35,7 @@ public class DeleteAccountActionConfirmPage extends RequiredActions { } public boolean isErrorMessageDisplayed() { - return driver.findElements(By.cssSelector(".alert-error")).size() == 1; + return driver.findElements(By.cssSelector(".pf-v5-c-alert")).size() == 1; } public String getErrorMessageText() { diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/FeedbackMessage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/FeedbackMessage.java index 885ec9ac37..f5009673c7 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/FeedbackMessage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/FeedbackMessage.java @@ -33,12 +33,19 @@ import static org.keycloak.testsuite.util.UIUtils.getTextFromElement; */ public class FeedbackMessage { - private final String SUCCESS = "success"; - private final String WARNING = "warning"; - private final String ERROR = "error"; - private final String INFO = "info"; + private final static String SUCCESS = "success"; + private final static String WARNING = "warning"; + private final static String ERROR = "danger"; + private final static String INFO = "info"; - @FindBy(css = "div[class^='alert']") + private static final Pattern ALERT_TYPE_CLASS_PATTERN = Pattern.compile("(pf-m|alert)-(" + + SUCCESS + "|" + + WARNING + "|" + + ERROR + "|" + + INFO + + ")"); + + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert']") private WebElement alertRoot; @FindBy(css = "span[id^='input-error']") @@ -71,7 +78,7 @@ public class FeedbackMessage { public String getType() { try { String cssClass = alertRoot.getAttribute("class"); - Matcher classMatcher = Pattern.compile("alert-(.+)").matcher(cssClass); + Matcher classMatcher = ALERT_TYPE_CLASS_PATTERN.matcher(cssClass); if (!classMatcher.find()) { throw new RuntimeException("Failed to identify feedback message type"); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/OneTimeCode.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/OneTimeCode.java index 1e9d570ce7..bfa88cfdd6 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/OneTimeCode.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/auth/page/login/OneTimeCode.java @@ -34,7 +34,7 @@ public class OneTimeCode extends Authenticate { @FindBy(xpath = ".//label[@for='otp']") private WebElement otpInputLabel; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginErrorMessage; @FindBy(id = "input-error-otp-code") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/LoginPasswordUpdatePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/LoginPasswordUpdatePage.java index 7f36895d7f..1e71b4e101 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/LoginPasswordUpdatePage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/LoginPasswordUpdatePage.java @@ -43,7 +43,7 @@ public class LoginPasswordUpdatePage { @FindBy(css = "input[type=\"submit\"]") private WebElement submitButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginErrorMessage; public void changePassword(String newPassword, String passwordConfirm) { diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmLinkPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmLinkPage.java index 8692410d2f..6ef2143b0a 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmLinkPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmLinkPage.java @@ -31,7 +31,7 @@ public class IdpConfirmLinkPage extends LanguageComboboxAwarePage { @FindBy(id = "linkAccount") private WebElement linkAccountButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement message; @Override diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmOverrideLinkPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmOverrideLinkPage.java index 99f45fbf1b..8d4304bd18 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmOverrideLinkPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/IdpConfirmOverrideLinkPage.java @@ -25,7 +25,7 @@ public class IdpConfirmOverrideLinkPage extends LanguageComboboxAwarePage { @FindBy(id = "confirmOverride") private WebElement confirmOverrideButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement message; @Override diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InstalledAppRedirectPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InstalledAppRedirectPage.java index 12d101f244..51f12c07e3 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InstalledAppRedirectPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InstalledAppRedirectPage.java @@ -44,7 +44,7 @@ public class InstalledAppRedirectPage extends AbstractPage { @FindBy(id = "kc-page-title") private WebElement pageTitle; - @FindBy(className = "alert-error") + @FindBy(className = "pf-v5-c-alert") private WebElement errorBox; @Override diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java index e72d7f65ad..d1e002a486 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java @@ -20,6 +20,10 @@ package org.keycloak.testsuite.pages; import org.junit.Assert; import org.keycloak.testsuite.util.DroneUtils; import org.keycloak.testsuite.util.WaitUtils; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; @@ -33,12 +37,18 @@ import org.openqa.selenium.support.FindBy; */ public abstract class LanguageComboboxAwarePage extends AbstractPage { - @FindBy(id = "kc-current-locale-link") + @FindBy(xpath = "//select[@aria-label='languages']/option[@selected]") private WebElement languageText; - @FindBy(id = "kc-locale-dropdown") + @FindBy(xpath = "//select[@aria-label='languages']") private WebElement localeDropdown; + @FindBy(id = "kc-current-locale-link") + private WebElement languageTextBase; // base theme + + @FindBy(id = "kc-locale-dropdown") + private WebElement localeDropdownBase; // base theme + @FindBy(id = "try-another-way") private WebElement tryAnotherWayLink; @@ -52,13 +62,26 @@ public abstract class LanguageComboboxAwarePage extends AbstractPage { private WebElement accountLink; public String getLanguageDropdownText() { - return languageText.getText(); + try { + final String text = languageText.getText(); + return text == null ? text : text.trim(); + } catch (NoSuchElementException ex) { + return languageTextBase.getText(); + } } public void openLanguage(String language){ - WebElement langLink = localeDropdown.findElement(By.xpath("//a[text()[contains(.,'" + language + "')]]")); - String url = langLink.getAttribute("href"); - DroneUtils.getCurrentDriver().navigate().to(url); + try { + WebElement langLink = localeDropdown.findElement(By.xpath("//option[text()[contains(.,'" + language + "')]]")); + String url = langLink.getAttribute("value"); + DroneUtils.getCurrentDriver().navigate().to(new URI(DroneUtils.getCurrentDriver().getCurrentUrl()).resolve(url).toString()); + } catch (NoSuchElementException ex) { + WebElement langLink = localeDropdownBase.findElement(By.xpath("//a[text()[contains(.,'" + language + "')]]")); + String url = langLink.getAttribute("href"); + DroneUtils.getCurrentDriver().navigate().to(url); + } catch (URISyntaxException ex) { + Assert.fail(ex.getMessage()); + } WaitUtils.waitForPageToLoad(); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginConfigTotpPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginConfigTotpPage.java index 220c606ce6..89f683092c 100755 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginConfigTotpPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginConfigTotpPage.java @@ -48,7 +48,7 @@ public class LoginConfigTotpPage extends LogoutSessionsPage { @FindBy(id = "mode-manual") private WebElement manualLink; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginAlertErrorMessage; @FindBy(id = "input-error-otp-code") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java index 10d9cdbf56..04f54efd70 100755 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPage.java @@ -65,13 +65,13 @@ public class LoginPage extends LanguageComboboxAwarePage { @FindBy(linkText = "Forgot Password?") private WebElement resetPasswordLink; - @FindBy(className = "alert-error") + @FindBy(className = "pf-m-danger") private WebElement loginErrorMessage; - @FindBy(className = "alert-success") + @FindBy(className = "pf-m-success") private WebElement loginSuccessMessage; - @FindBy(className = "alert-info") + @FindBy(className = "pf-m-info") private WebElement loginInfoMessage; @FindBy(className = "instruction") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordResetPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordResetPage.java index 7919545e9e..d80a109dc6 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordResetPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordResetPage.java @@ -35,10 +35,10 @@ public class LoginPasswordResetPage extends LanguageComboboxAwarePage { @FindBy(css = "input[type=\"submit\"]") private WebElement submitButton; - @FindBy(className = "alert-success") + @FindBy(className = "pf-v5-c-success") private WebElement emailSuccessMessage; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement emailErrorMessage; @FindBy(partialLinkText = "Back to Login") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordUpdatePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordUpdatePage.java index ce068e943a..4bed0ee168 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordUpdatePage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginPasswordUpdatePage.java @@ -35,7 +35,7 @@ public class LoginPasswordUpdatePage extends LogoutSessionsPage { @FindBy(css = "input[type=\"submit\"]") private WebElement submitButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginErrorMessage; @FindBy(className = "kc-feedback-text") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginTotpPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginTotpPage.java index 74158401d2..b8b985212e 100755 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginTotpPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginTotpPage.java @@ -41,7 +41,7 @@ public class LoginTotpPage extends LanguageComboboxAwarePage { @FindBy(css = "input[type=\"submit\"]") private WebElement submitButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginErrorMessage; @FindBy(id = "input-error-otp-code") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginUpdateProfilePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginUpdateProfilePage.java index f75bc24b06..b740951b00 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginUpdateProfilePage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LoginUpdateProfilePage.java @@ -40,16 +40,16 @@ public class LoginUpdateProfilePage extends AbstractPage { @Page private UpdateProfileErrors errorsPage; - @FindBy(id = "firstName") + @FindBy(name = "firstName") private WebElement firstNameInput; - @FindBy(id = "lastName") + @FindBy(name = "lastName") private WebElement lastNameInput; - @FindBy(id = "email") + @FindBy(name = "email") private WebElement emailInput; - @FindBy(id = "department") + @FindBy(name = "department") private WebElement departmentInput; @FindBy(css = "input[type=\"submit\"]") @@ -58,7 +58,7 @@ public class LoginUpdateProfilePage extends AbstractPage { @FindBy(name = "cancel-aia") private WebElement cancelAIAButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginAlertErrorMessage; public void update(String firstName, String lastName) { diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/OAuth2DeviceVerificationPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/OAuth2DeviceVerificationPage.java index 9d3bb74253..2c00aae686 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/OAuth2DeviceVerificationPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/OAuth2DeviceVerificationPage.java @@ -34,7 +34,7 @@ public class OAuth2DeviceVerificationPage extends LanguageComboboxAwarePage { @FindBy(css = "input[type=\"submit\"]") private WebElement submitButton; - @FindBy(className = "alert-error") + @FindBy(className = "pf-v5-c-alert") private WebElement verifyErrorMessage; public void submit(String userCode) { @@ -108,7 +108,7 @@ public class OAuth2DeviceVerificationPage extends LanguageComboboxAwarePage { try { driver.findElement(By.id("device-user-code")); return driver.findElement(By.id("kc-page-title")).getText().equals("Device Login") - && driver.findElement(By.className("kc-feedback-text")).getText().equals("Invalid code, please try again."); + && driver.findElement(By.className("pf-m-danger")).getText().equals("Invalid code, please try again."); } catch (Throwable t) { } } @@ -120,7 +120,7 @@ public class OAuth2DeviceVerificationPage extends LanguageComboboxAwarePage { try { driver.findElement(By.id("device-user-code")); return driver.findElement(By.id("kc-page-title")).getText().equals("Device Login") - && driver.findElement(By.className("kc-feedback-text")).getText().equals("The code has expired. Please go back to your device and try connecting again."); + && driver.findElement(By.className("pf-m-danger")).getText().equals("The code has expired. Please go back to your device and try connecting again."); } catch (Throwable t) { } } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/PasswordPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/PasswordPage.java index 15390658c6..2fd683dd5e 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/PasswordPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/PasswordPage.java @@ -27,7 +27,7 @@ public class PasswordPage extends LanguageComboboxAwarePage { @FindBy(name = "login") private WebElement submitButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginErrorMessage; @FindBy(linkText = "Forgot Password?") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/RegisterPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/RegisterPage.java index c53b1ac445..b8319f7ff2 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/RegisterPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/RegisterPage.java @@ -44,34 +44,34 @@ public class RegisterPage extends AbstractPage { @Page private PasswordFields.PasswordErrors passwordErrors; - @FindBy(id = "firstName") + @FindBy(name = "firstName") private WebElement firstNameInput; - @FindBy(id = "lastName") + @FindBy(name = "lastName") private WebElement lastNameInput; - @FindBy(id = "email") + @FindBy(name = "email") private WebElement emailInput; - @FindBy(id = "username") + @FindBy(name = "username") private WebElement usernameInput; - @FindBy(id = "password") + @FindBy(name = "password") private WebElement passwordInput; - @FindBy(id = "password-confirm") + @FindBy(name = "password-confirm") private WebElement passwordConfirmInput; - @FindBy(id = "department") + @FindBy(name = "department") private WebElement departmentInput; - @FindBy(id = "termsAccepted") + @FindBy(name = "termsAccepted") private WebElement termsAcceptedInput; @FindBy(css = "input[type=\"submit\"]") private WebElement submitButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginAlertErrorMessage; @FindBy(className = "instruction") @@ -136,7 +136,7 @@ public class RegisterPage extends AbstractPage { if (attributes != null) { for (Entry attribute : attributes.entrySet()) { - driver.findElement(By.id(Constants.USER_ATTRIBUTES_PREFIX + attribute.getKey())).sendKeys(attribute.getValue()); + driver.findElement(By.name(Constants.USER_ATTRIBUTES_PREFIX + attribute.getKey())).sendKeys(attribute.getValue()); } } @@ -238,7 +238,7 @@ public class RegisterPage extends AbstractPage { public boolean isDepartmentPresent() { try { - return driver.findElement(By.id("department")).isDisplayed(); + return driver.findElement(By.name("department")).isDisplayed(); } catch (NoSuchElementException nse) { return false; } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/UpdateAccountInformationPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/UpdateAccountInformationPage.java index 04284958d5..7d21acc883 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/UpdateAccountInformationPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/UpdateAccountInformationPage.java @@ -9,19 +9,19 @@ import static org.keycloak.testsuite.util.UIUtils.clickLink; public class UpdateAccountInformationPage extends LanguageComboboxAwarePage { - @FindBy(id = "username") + @FindBy(name = "username") private WebElement usernameInput; - @FindBy(id = "email") + @FindBy(name = "email") private WebElement emailInput; - @FindBy(id = "firstName") + @FindBy(name = "firstName") private WebElement firstNameInput; - @FindBy(id = "lastName") + @FindBy(name = "lastName") private WebElement lastNameInput; - @FindBy(id = "department") + @FindBy(name = "department") private WebElement departmentInput; @FindBy(css = "input[type=\"submit\"]") @@ -106,7 +106,7 @@ public class UpdateAccountInformationPage extends LanguageComboboxAwarePage { public boolean isDepartmentPresent() { try { - return driver.findElement(By.id("department")).isDisplayed(); + return driver.findElement(By.name("department")).isDisplayed(); } catch (NoSuchElementException nse) { return false; } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/VerifyProfilePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/VerifyProfilePage.java index e1483ea8e6..f6e70ddd74 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/VerifyProfilePage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/VerifyProfilePage.java @@ -33,23 +33,23 @@ public class VerifyProfilePage extends AbstractPage { @Page private AccountFields.AccountErrors accountErrors; - @FindBy(id = "firstName") + @FindBy(name = "firstName") private WebElement firstNameInput; - @FindBy(id = "lastName") + @FindBy(name = "lastName") private WebElement lastNameInput; - @FindBy(id = "email") + @FindBy(name = "email") private WebElement emailInput; - @FindBy(id = "department") + @FindBy(name = "department") private WebElement departmentInput; @FindBy(css = "input[type=\"submit\"]") private WebElement submitButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginAlertErrorMessage; diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/x509/X509IdentityConfirmationPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/x509/X509IdentityConfirmationPage.java index 9ef5a5aac4..e1e95ea3c2 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/x509/X509IdentityConfirmationPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/x509/X509IdentityConfirmationPage.java @@ -44,10 +44,10 @@ public class X509IdentityConfirmationPage extends LanguageComboboxAwarePage { @FindBy(name = "cancel") private WebElement ignoreButton; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement loginErrorMessage; - @FindBy(className = "alert-warning") + @FindBy(className = "pf-v5-c-warning") private WebElement loginWarningMessage; @FindBy(className = "alert-success") diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java index 73b7e7f613..046bbdf3f5 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java @@ -345,19 +345,19 @@ public class OAuthClient { public void linkUsers(String username, String password) { WaitUtils.waitForPageToLoad(); - WebElement linkAccountButton = driver.findElement(By.id("linkAccount")); + WebElement linkAccountButton = driver.findElement(By.name("linkAccount")); waitUntilElement(linkAccountButton).is().clickable(); linkAccountButton.click(); WaitUtils.waitForPageToLoad(); - WebElement usernameInput = driver.findElement(By.id("username")); + WebElement usernameInput = driver.findElement(By.name("username")); usernameInput.clear(); usernameInput.sendKeys(username); - WebElement passwordInput = driver.findElement(By.id("password")); + WebElement passwordInput = driver.findElement(By.name("password")); passwordInput.clear(); passwordInput.sendKeys(password); - WebElement loginButton = driver.findElement(By.id("kc-login")); + WebElement loginButton = driver.findElement(By.name("kc-login")); waitUntilElement(loginButton).is().clickable(); loginButton.click(); } @@ -382,8 +382,8 @@ public class OAuthClient { WaitUtils.waitForPageToLoad(); String src = driver.getPageSource(); try { - driver.findElement(By.id("username")).sendKeys(username); - driver.findElement(By.id("password")).sendKeys(password); + driver.findElement(By.name("username")).sendKeys(username); + driver.findElement(By.name("password")).sendKeys(password); if (rememberMe) { driver.findElement(By.id("rememberMe")).click(); } @@ -396,19 +396,19 @@ public class OAuthClient { private void updateAccountInformation(String username, String email, String firstName, String lastName) { - WebElement usernameInput = driver.findElement(By.id("username")); + WebElement usernameInput = driver.findElement(By.name("username")); usernameInput.clear(); usernameInput.sendKeys(username); - WebElement emailInput = driver.findElement(By.id("email")); + WebElement emailInput = driver.findElement(By.name("email")); emailInput.clear(); emailInput.sendKeys(email); - WebElement firstNameInput = driver.findElement(By.id("firstName")); + WebElement firstNameInput = driver.findElement(By.name("firstName")); firstNameInput.clear(); firstNameInput.sendKeys(firstName); - WebElement lastNameInput = driver.findElement(By.id("lastName")); + WebElement lastNameInput = driver.findElement(By.name("lastName")); lastNameInput.clear(); lastNameInput.sendKeys(lastName); diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java index 3b0aa7fb29..89fc7e31cf 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UIUtils.java @@ -19,6 +19,7 @@ import java.time.Duration; import java.util.Optional; import java.util.function.Supplier; +import org.openqa.selenium.chrome.ChromeDriver; import static org.keycloak.testsuite.util.DroneUtils.getCurrentDriver; import static org.keycloak.testsuite.util.WaitUtils.log; import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; @@ -230,7 +231,7 @@ public final class UIUtils { } public static String getRawPageSource(WebDriver driver) { - if (driver instanceof FirefoxDriver) { + if ((driver instanceof FirefoxDriver) || (driver instanceof ChromeDriver)) { // firefox has some weird "bug" – it wraps xml in html return driver.findElement(By.tagName("body")).getText(); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnErrorPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnErrorPage.java index 6300174552..aad92af8ca 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnErrorPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/webauthn/pages/WebAuthnErrorPage.java @@ -26,7 +26,7 @@ public class WebAuthnErrorPage extends LanguageComboboxAwarePage { @FindBy(id = "cancelWebAuthnAIA") private WebElement cancelRegistrationAIA; - @FindBy(className = "alert-error") + @FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']") private WebElement errorMessage; public void clickTryAgain() { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java index 46f379b9b9..8802642024 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java @@ -159,7 +159,9 @@ public abstract class AbstractKeycloakTest { private boolean resetTimeOffset; - private static String PREFERRED_DEFAULT_LOGIN_THEME = System.getProperty("login.theme.default"); + public static final String PROPERTY_LOGIN_THEME_DEFAULT = "login.theme.default"; + + public static final String PREFERRED_DEFAULT_LOGIN_THEME = System.getProperty(PROPERTY_LOGIN_THEME_DEFAULT); @Before public void beforeAbstractKeycloakTest() throws Exception { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionUpdateEmailWithVerificationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionUpdateEmailWithVerificationTest.java index a5f1856c30..7d288a3d75 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionUpdateEmailWithVerificationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/AppInitiatedActionUpdateEmailWithVerificationTest.java @@ -173,7 +173,7 @@ public class AppInitiatedActionUpdateEmailWithVerificationTest extends AbstractA assertEquals(String.format("The account email has been successfully updated to %s.", "new@localhost"), infoPage.getInfo()); //Issue #15136 final WebElement backToApplicationLink = driver.findElement(By.linkText("« Back to Application")); - assertThat(backToApplicationLink.toString(), Matchers.containsString("/auth/realms/master/app/auth")); + assertThat(backToApplicationLink.getDomAttribute("href"), Matchers.containsString("/auth/realms/master/app/auth")); events.expect(EventType.UPDATE_EMAIL) .detail(Details.PREVIOUS_EMAIL, "test-user@localhost") diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java index b8202b1d66..fb21b982d1 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileTest.java @@ -16,10 +16,8 @@ */ package org.keycloak.testsuite.actions; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.keycloak.userprofile.config.UPConfigUtils.ROLE_ADMIN; import static org.keycloak.userprofile.config.UPConfigUtils.ROLE_USER; @@ -60,7 +58,10 @@ import org.keycloak.testsuite.pages.LoginUpdateProfileEditUsernameAllowedPage; import org.keycloak.testsuite.util.UserBuilder; import org.keycloak.userprofile.UserProfileContext; import org.keycloak.utils.StringUtil; +import java.util.HashSet; +import org.openqa.selenium.ElementClickInterceptedException; import org.openqa.selenium.htmlunit.HtmlUnitDriver; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author Stian Thorgersen @@ -457,6 +458,7 @@ public class RequiredActionUpdateProfileTest extends AbstractTestRealmKeycloakTe UPConfig testUpConfig = configuration.clone(); List attributes = List.of("foo", "bar", "zar"); List values = IntStream.range(0, 5).mapToObj(Integer::toString).collect(Collectors.toList()); + Set valuesSet = new HashSet<>(values); for (String attribute : attributes) { testUpConfig.addOrReplaceAttribute( @@ -487,17 +489,24 @@ public class RequiredActionUpdateProfileTest extends AbstractTestRealmKeycloakTe userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PROFILE.name())); testRealm().users().get(userRep.getId()).update(userRep); loginPage.open(); - for (String value : values) { - assertEquals(value, updateProfilePage.getAttribute(attribute + "-" + value)); - } + assertThat(IntStream.range(0, 5).mapToObj(value -> updateProfilePage.getAttribute(attribute + "-" + value)).collect(Collectors.toSet()), Matchers.equalTo(valuesSet)); + + final String lastValue = values.get(values.size() - 1); // remove multiple values, only the last value should be kept as you can't remove the last one for (String value : values) { - updateProfilePage.clickRemoveAttributeValue(attribute + "-0"); + try { + updateProfilePage.clickRemoveAttributeValue(attribute + "-0"); + } catch (ElementClickInterceptedException e) { + if (! lastValue.equals(value)) { // Ignore that the last value cannot be clicked / removed - this is by design + throw e; + } + } } updateProfilePage.update("f", "l", "e@keycloak.org"); userRep = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost"); - assertThat(userRep.getAttributes().get(attribute), Matchers.containsInAnyOrder(values.get(values.size() - 1))); + assertThat(userRep.getAttributes().get(attribute), Matchers.hasSize(1)); + assertThat(userRep.getAttributes().get(attribute).get(0), Matchers.in(values)); // make sure adding/removing within the same context works userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PROFILE.name())); @@ -508,19 +517,26 @@ public class RequiredActionUpdateProfileTest extends AbstractTestRealmKeycloakTe updateProfilePage.setAttribute(elementId, value); updateProfilePage.clickAddAttributeValue(elementId); } + + assertThat(IntStream.range(0, 5).mapToObj(value -> updateProfilePage.getAttribute(attribute + "-" + value)).collect(Collectors.toSet()), Matchers.equalTo(valuesSet)); + for (String value : values) { - assertEquals(value, updateProfilePage.getAttribute(attribute + "-" + value)); - } - for (String value : values) { - updateProfilePage.clickRemoveAttributeValue(attribute + "-0"); + try { + updateProfilePage.clickRemoveAttributeValue(attribute + "-0"); + } catch (ElementClickInterceptedException e) { + if (! lastValue.equals(value)) { // Ignore that the last value cannot be clicked / removed - this is by design + throw e; + } + } } // make sure the last attribute is set with a value if (StringUtil.isBlank(updateProfilePage.getAttribute(attribute + "-0"))) { - updateProfilePage.setAttribute(attribute + "-0", values.get(values.size() - 1)); + updateProfilePage.setAttribute(attribute + "-0", lastValue); } updateProfilePage.update("f", "l", "e@keycloak.org"); userRep = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost"); - assertThat(userRep.getAttributes().get(attribute), Matchers.containsInAnyOrder(values.get(values.size() - 1))); + assertThat(userRep.getAttributes().get(attribute), Matchers.hasSize(1)); + assertThat(userRep.getAttributes().get(attribute).get(0), Matchers.in(values)); // at the end the attribute is set with multiple values userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PROFILE.name())); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java index 7ba2f0a349..905e075b07 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java @@ -33,6 +33,7 @@ import static org.keycloak.testsuite.forms.VerifyProfileTest.CONFIGURATION_FOR_U import java.util.ArrayList; import java.util.Collections; +import java.util.List; import org.apache.commons.lang3.StringUtils; import org.jboss.arquillian.graphene.page.Page; @@ -61,6 +62,7 @@ import org.keycloak.testsuite.util.ClientScopeBuilder; import org.keycloak.testsuite.util.KeycloakModelUtils; import org.keycloak.testsuite.util.UserBuilder; import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; /** * Test update-profile required action with custom user profile configurations @@ -107,7 +109,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest @Before public void beforeTest() { - VerifyProfileTest.setUserProfileConfiguration(testRealm(),null); + VerifyProfileTest.setUserProfileConfiguration(testRealm(), null); ApiUtil.removeUserByUsername(testRealm(), "test-user@localhost"); UserRepresentation user = UserBuilder.create().enabled(true) @@ -146,11 +148,11 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest //assert field names // i18n replaced - Assert.assertEquals("First name",updateProfilePage.getLabelForField("firstName")); + Assert.assertEquals("First name", updateProfilePage.getLabelForField("firstName")); // attribute name used if no display name set - Assert.assertEquals("lastName",updateProfilePage.getLabelForField("lastName")); + Assert.assertEquals("lastName", updateProfilePage.getLabelForField("lastName")); // direct value in display name - Assert.assertEquals("Department",updateProfilePage.getLabelForField("department")); + Assert.assertEquals("Department", updateProfilePage.getLabelForField("department")); } @@ -172,49 +174,22 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest loginPage.login(USERNAME1, PASSWORD); updateProfilePage.assertCurrent(); - String htmlFormId="kc-update-profile-form"; //assert fields and groups location in form, attributes without a group appear first - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(1) > label#header-company") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > label#description-company") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-contact") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + List element = driver.findElements(By.cssSelector("form#kc-update-profile-form label")); + String[] labelOrder = new String[]{"lastName", "username", "firstName", "header-company", "description-company", "department", "header-contact", "email"}; + for (int i = 0; i < element.size(); i++) { + WebElement webElement = element.get(i); + String id; + if (webElement.getAttribute("for") != null) { + id = webElement.getAttribute("for"); + // see that the label has an element it belongs to + assertThat("Label with id: " + id + " should have component it belongs to", driver.findElement(By.id(id)).isDisplayed(), is(true)); + } else { + id = webElement.getAttribute("id"); + } + assertThat("Label at index: " + i + " with id: " + id + " was not in found in the same order in the dom", id, is(labelOrder[i])); + } } @@ -235,31 +210,14 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest updateProfilePage.assertCurrent(); //assert fields location in form - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(2) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(3) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(4) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(5) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + //assert fields and groups location in form, attributes without a group appear first + List element = driver.findElements(By.cssSelector("form#kc-update-profile-form input")); + String[] labelOrder = new String[]{"lastName", "department", "username", "firstName", "email"}; + for (int i = 0; i < labelOrder.length; i++) { + WebElement webElement = element.get(i); + String id = webElement.getAttribute("id"); + assertThat("Field at index: " + i + " with id: " + id + " was not in found in the same order in the dom", id, is(labelOrder[i])); + } } @Test @@ -343,7 +301,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest setUserProfileConfiguration("{\"attributes\": [" + "{\"name\": \"firstName\"," + PERMISSIONS_ALL + ", \"required\": {}}," - + "{\"name\": \"lastName\"," + PERMISSIONS_ALL +","+VALIDATIONS_LENGTH + "}," + + "{\"name\": \"lastName\"," + PERMISSIONS_ALL + "," + VALIDATIONS_LENGTH + "}," + "{\"name\": \"department\"," + PERMISSIONS_ADMIN_ONLY + "}" + "]}"); @@ -436,7 +394,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest updateProfilePage.assertCurrent(); Assert.assertEquals("Brady", updateProfilePage.getLastName()); - Assert.assertFalse("'department' field is visible" , updateProfilePage.isDepartmentPresent()); + Assert.assertFalse("'department' field is visible", updateProfilePage.isDepartmentPresent()); //update of the other attributes must be successful in this case updateProfilePage.prepareUpdate().username(USERNAME1).firstName("First").lastName("Last").email(USERNAME1).submit(); @@ -494,7 +452,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest setUserProfileConfiguration("{\"attributes\": [" + "{\"name\": \"firstName\"," + PERMISSIONS_ALL + ", \"required\": {}}," + "{\"name\": \"lastName\"," + PERMISSIONS_ALL + "}," - + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{\"scopes\":[\""+SCOPE_DEPARTMENT+"\"]}}" + + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{\"scopes\":[\"" + SCOPE_DEPARTMENT + "\"]}}" + "]}"); oauth.scope(SCOPE_DEPARTMENT).clientId(client_scope_optional.getClientId()).openLoginForm(); @@ -534,7 +492,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest setUserProfileConfiguration("{\"attributes\": [" + "{\"name\": \"firstName\"," + PERMISSIONS_ALL + ", \"required\": {}}," + "{\"name\": \"lastName\"," + PERMISSIONS_ALL + "}," - + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{\"scopes\":[\""+SCOPE_DEPARTMENT+"\"]}}" + + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{\"scopes\":[\"" + SCOPE_DEPARTMENT + "\"]}}" + "]}"); oauth.clientId(client_scope_default.getClientId()).openLoginForm(); @@ -568,7 +526,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest setUserProfileConfiguration("{\"attributes\": [" + "{\"name\": \"firstName\"," + PERMISSIONS_ALL + ", \"required\": {}}," + "{\"name\": \"lastName\"," + PERMISSIONS_ALL + "}," - + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{}, \"selector\":{\"scopes\":[\""+SCOPE_DEPARTMENT+"\"]}}" + + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{}, \"selector\":{\"scopes\":[\"" + SCOPE_DEPARTMENT + "\"]}}" + "]}"); oauth.scope(SCOPE_DEPARTMENT).clientId(client_scope_optional.getClientId()).openLoginForm(); @@ -602,7 +560,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest setUserProfileConfiguration("{\"attributes\": [" + "{\"name\": \"firstName\"," + PERMISSIONS_ALL + ", \"required\": {}}," + "{\"name\": \"lastName\"," + PERMISSIONS_ALL + ", \"required\": {}}," - + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"selector\":{\"scopes\":[\""+SCOPE_DEPARTMENT+"\"]}}" + + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"selector\":{\"scopes\":[\"" + SCOPE_DEPARTMENT + "\"]}}" + "]}"); oauth.scope(SCOPE_DEPARTMENT).clientId(client_scope_optional.getClientId()).openLoginForm(); @@ -631,7 +589,7 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest setUserProfileConfiguration("{\"attributes\": [" + "{\"name\": \"firstName\"," + PERMISSIONS_ALL + ", \"required\": {}}," + "{\"name\": \"lastName\"," + PERMISSIONS_ALL + ", \"required\": {}}," - + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{}, \"selector\":{\"scopes\":[\""+SCOPE_DEPARTMENT+"\"]}}" + + "{\"name\": \"department\"," + PERMISSIONS_ALL + ", \"required\":{}, \"selector\":{\"scopes\":[\"" + SCOPE_DEPARTMENT + "\"]}}" + "]}"); oauth.clientId(client_scope_optional.getClientId()).openLoginForm(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java index 2ffe1fce03..f642223208 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java @@ -1897,7 +1897,7 @@ public class SAMLServletAdapterTest extends AbstractSAMLServletAdapterTest { waitForPageToLoad(); assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage); // we are still in login Assert.assertEquals("Your login attempt timed out. Login will start from the beginning.", - UIUtils.getTextFromElement(driver.findElement(By.className("alert-error")))); + UIUtils.getTextFromElement(driver.findElement(By.cssSelector("div[class^='pf-v5-c-alert'], div[class^='alert-error']")))); // login successfully in tab2 after the error loginPage.form().login(bburkeUser); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminConsoleWhoAmILocaleTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminConsoleWhoAmILocaleTest.java index a233f81354..e086efb1c4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminConsoleWhoAmILocaleTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AdminConsoleWhoAmILocaleTest.java @@ -30,6 +30,7 @@ import org.keycloak.testsuite.util.AdminClientUtil; import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.RealmBuilder; import org.keycloak.testsuite.util.UserBuilder; +import static org.keycloak.models.Constants.ADMIN_CLI_CLIENT_ID; public class AdminConsoleWhoAmILocaleTest extends AbstractKeycloakTest { @@ -52,6 +53,10 @@ public class AdminConsoleWhoAmILocaleTest extends AbstractKeycloakTest { @Before public void createHttpClient() throws Exception { client = HttpClientBuilder.create().build(); + + getCleanup().addCleanup(ClientAttributeUpdater.forClient(adminClient, "master", ADMIN_CLI_CLIENT_ID).setAttribute(Constants.SECURITY_ADMIN_CONSOLE_ATTR, "true").update()); + getCleanup().addCleanup(ClientAttributeUpdater.forClient(adminClient, REALM_I18N_OFF, ADMIN_CLI_CLIENT_ID).setAttribute(Constants.SECURITY_ADMIN_CONSOLE_ATTR, "true").update()); + getCleanup().addCleanup(ClientAttributeUpdater.forClient(adminClient, REALM_I18N_ON, ADMIN_CLI_CLIENT_ID).setAttribute(Constants.SECURITY_ADMIN_CONSOLE_ATTR, "true").update()); } @After @@ -101,17 +106,7 @@ public class AdminConsoleWhoAmILocaleTest extends AbstractKeycloakTest { } private OAuthClient.AccessTokenResponse accessToken(String realmName, String username, String password) throws Exception { - String codeVerifier = PkceUtils.generateCodeVerifier(); - oauth.realm(realmName) - .codeVerifier(codeVerifier) - .codeChallenge(PkceUtils.generateS256CodeChallenge(codeVerifier)) - .codeChallengeMethod(OAuth2Constants.PKCE_METHOD_S256) - .clientId(Constants.ADMIN_CONSOLE_CLIENT_ID) - .redirectUri(adminConsole.createUriBuilder().build(realmName).toASCIIString()); - oauth.doLogin(username, password); - String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, null); - return response; + return oauth.doGrantAccessTokenRequest(realmName, username, password, null, ADMIN_CLI_CLIENT_ID, null); } private String whoAmiUrl(String realmName) { @@ -139,7 +134,7 @@ public class AdminConsoleWhoAmILocaleTest extends AbstractKeycloakTest { @Test public void testLocaleRealmI18nDisabledUserWithoutLocale() throws Exception { - OAuthClient.AccessTokenResponse response = accessToken(REALM_I18N_OFF, USER_WITHOUT_LOCALE, PASSWORD); + OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest(REALM_I18N_OFF, USER_WITHOUT_LOCALE, PASSWORD, null, ADMIN_CLI_CLIENT_ID, null); JsonNode whoAmI = SimpleHttpDefault .doGet(whoAmiUrl(REALM_I18N_OFF), client) .header("Accept", "application/json") @@ -276,7 +271,8 @@ public class AdminConsoleWhoAmILocaleTest extends AbstractKeycloakTest { @Test public void testLocaleRealmTokenForOtherClient() throws Exception { - try (Keycloak adminCliClient = AdminClientUtil.createAdminClient(true, REALM_I18N_ON, + try (var c = ClientAttributeUpdater.forClient(adminClient, REALM_I18N_ON, ADMIN_CLI_CLIENT_ID).setAttribute(Constants.SECURITY_ADMIN_CONSOLE_ATTR, null).update(); + Keycloak adminCliClient = AdminClientUtil.createAdminClient(true, REALM_I18N_ON, USER_WITH_LOCALE, PASSWORD, Constants.ADMIN_CLI_CLIENT_ID, null)) { AccessTokenResponse accessToken = adminCliClient.tokenManager().getAccessToken(); Assert.assertNotNull(accessToken); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractDefaultIdpTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractDefaultIdpTest.java index c03316a33f..62ddb9cb8d 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractDefaultIdpTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractDefaultIdpTest.java @@ -120,7 +120,7 @@ public abstract class AbstractDefaultIdpTest extends AbstractInitializedBaseBrok waitForPage(driver, "sign in to", true); - WebElement errorElement = driver.findElement(By.className("alert-error")); + WebElement errorElement = driver.findElement(By.className("pf-v5-c-alert")); assertNotNull("Page should show an error message but it's missing", errorElement); // Login to IDP failed due consent denied. Error message is displayed on the username/password screen of the consumer realm diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java index 3aac2006cf..ec8bc01390 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java @@ -1,6 +1,7 @@ package org.keycloak.testsuite.broker; import org.apache.commons.lang3.StringUtils; +import org.hamcrest.CoreMatchers; import org.jboss.arquillian.graphene.page.Page; import org.junit.Test; import org.keycloak.admin.client.resource.IdentityProviderResource; @@ -27,6 +28,7 @@ import org.keycloak.testsuite.util.ClientScopeBuilder; import org.keycloak.util.JsonSerialization; import org.openqa.selenium.By; import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; @@ -391,7 +393,7 @@ public class KcOidcFirstBrokerLoginTest extends AbstractFirstBrokerLoginTest { updateAccountInformationPage.assertCurrent(); assertEquals("Please specify username.", loginUpdateProfilePage.getInputErrors().getUsernameError()); - + updateAccountInformationPage.updateAccountInformation("new-username", "no-first-name@localhost.com", "First Name", "Last Name"); UserRepresentation userRepresentation = AccountHelper.getUserRepresentation(adminClient.realm(bc.consumerRealmName()), "new-username"); @@ -498,46 +500,20 @@ public class KcOidcFirstBrokerLoginTest extends AbstractFirstBrokerLoginTest { String htmlFormId = "kc-idp-review-profile-form"; //assert fields and groups location in form, attributes without a group appear first - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(1) > label#header-company") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > label#description-company") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-contact") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + List element = driver.findElements(By.cssSelector("form#kc-idp-review-profile-form label")); + String[] labelOrder = new String[]{"lastName", "username", "firstName", "header-company", "description-company", "department", "header-contact", "email"}; + for (int i = 0; i < element.size(); i++) { + WebElement webElement = element.get(i); + String id; + if (webElement.getAttribute("for") != null) { + id = webElement.getAttribute("for"); + // see that the label has an element it belongs to + assertThat("Label with id: " + id + " should have component it belongs to", driver.findElement(By.id(id)).isDisplayed(), is(true)); + } else { + id = webElement.getAttribute("id"); + } + assertThat("Label at index: " + i + " with id: " + id + " was not in found in the same order in the dom", labelOrder[i], is(id)); + } } @Test @@ -562,32 +538,13 @@ public class KcOidcFirstBrokerLoginTest extends AbstractFirstBrokerLoginTest { updateAccountInformationPage.assertCurrent(); //assert fields location in form - String htmlFormId = "kc-idp-review-profile-form"; - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - org.junit.Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + List element = driver.findElements(By.cssSelector("form#kc-idp-review-profile-form input")); + String[] labelOrder = new String[]{"lastName", "department", "username", "firstName", "email"}; + for (int i = 0; i < labelOrder.length; i++) { + WebElement webElement = element.get(i); + String id = webElement.getAttribute("id"); + assertThat("Field at index: " + i + " with id: " + id + " was not in found in the same order in the dom", id, is(labelOrder[i])); + } } @Test diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcMultipleTabsBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcMultipleTabsBrokerTest.java index 1fd9a6382e..f5da632726 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcMultipleTabsBrokerTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcMultipleTabsBrokerTest.java @@ -36,7 +36,9 @@ import org.keycloak.testsuite.util.BrowserTabUtil; import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule; import org.keycloak.testsuite.util.OAuthClient; +import org.openqa.selenium.htmlunit.HtmlUnitDriver; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assume.assumeTrue; import static org.keycloak.testsuite.AssertEvents.DEFAULT_REDIRECT_URI; import static org.keycloak.testsuite.broker.BrokerTestTools.waitForPage; @@ -62,6 +64,7 @@ public class KcOidcMultipleTabsBrokerTest extends AbstractInitializedBaseBroker // Similar to MultipleTabsLoginTest.multipleTabsParallelLogin but with IDP brokering test involved @Test public void testAuthenticationExpiredWithMoreBrowserTabs_clickIdpLoginInTab1AfterExpiration() { + assumeTrue("Since the JS engine in real browser does check the expiration regularly in all tabs, this test only works with HtmlUnit", driver instanceof HtmlUnitDriver); try (BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver)) { oauth.clientId("broker-app"); loginPage.open(bc.consumerRealmName()); @@ -100,6 +103,7 @@ public class KcOidcMultipleTabsBrokerTest extends AbstractInitializedBaseBroker // Similar to MultipleTabsLoginTest.multipleTabsParallelLogin but with IDP brokering test involved @Test public void testAuthenticationExpiredWithMoreBrowserTabs_loginExpiredInBothConsumerAndProvider() { + assumeTrue("Since the JS engine in real browser does check the expiration regularly in all tabs, this test only works with HtmlUnit", driver instanceof HtmlUnitDriver); try (BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver)) { // Open login page in tab1 and click "login with IDP" oauth.clientId("broker-app"); @@ -166,6 +170,7 @@ public class KcOidcMultipleTabsBrokerTest extends AbstractInitializedBaseBroker @Test public void testAuthenticationExpiredWithMoreBrowserTabs_loginExpiredInProvider() throws Exception { + assumeTrue("Since the JS engine in real browser does check the expiration regularly in all tabs, this test only works with HtmlUnit", driver instanceof HtmlUnitDriver); // Testing the scenario when authenticationSession expired only in "provider" realm and "consumer" is able to handle it at IDP. // So need to increase authSession timeout on "consumer" try (BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlMultipleTabsBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlMultipleTabsBrokerTest.java index 1166685ae5..c9d64787b1 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlMultipleTabsBrokerTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlMultipleTabsBrokerTest.java @@ -32,7 +32,9 @@ import org.keycloak.testsuite.util.BrowserTabUtil; import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule; import org.keycloak.testsuite.util.OAuthClient; +import org.openqa.selenium.htmlunit.HtmlUnitDriver; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assume.assumeTrue; import static org.keycloak.testsuite.broker.BrokerTestTools.waitForPage; /** @@ -58,6 +60,7 @@ public class KcSamlMultipleTabsBrokerTest extends AbstractInitializedBaseBrokerT // Similar to MultipleTabsLoginTest.multipleTabsParallelLogin but with IDP brokering test involved @Test public void testAuthenticationExpiredWithMoreBrowserTabs_loginExpiredInBothConsumerAndProvider() { + assumeTrue("Since the JS engine in real browser does check the expiration regularly in all tabs, this test only works with HtmlUnit", driver instanceof HtmlUnitDriver); try (BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver)) { // Open login page in tab1 and click "login with IDP" oauth.clientId("broker-app"); @@ -120,6 +123,7 @@ public class KcSamlMultipleTabsBrokerTest extends AbstractInitializedBaseBrokerT @Test public void testAuthenticationExpiredWithMoreBrowserTabs_loginExpiredInProvider() throws Exception { + assumeTrue("Since the JS engine in real browser does check the expiration regularly in all tabs, this test only works with HtmlUnit", driver instanceof HtmlUnitDriver); // Testing the scenario when authenticationSession expired only in "provider" realm and "consumer" is able to handle it at IDP. // So need to increase authSession timeout on "consumer" try (BrowserTabUtil tabUtil = BrowserTabUtil.getInstanceAndSetEnv(driver); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractFailoverClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractFailoverClusterTest.java index fe955bbb07..e68a2bd38c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractFailoverClusterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractFailoverClusterTest.java @@ -151,7 +151,7 @@ public abstract class AbstractFailoverClusterTest extends AbstractClusterTest { protected Cookie verifyLoggedIn(Cookie sessionCookieForVerification) { // verify on realm path - URLUtils.navigateToUri(AUTH_SERVER_ROOT + "/realms/test"); + URLUtils.navigateToUri(AUTH_SERVER_ROOT + "/realms/test/"); Cookie sessionCookieOnRealmPath = driver.manage().getCookieNamed(KEYCLOAK_SESSION_COOKIE); assertNotNull(sessionCookieOnRealmPath); assertEquals(sessionCookieOnRealmPath.getValue(), sessionCookieForVerification.getValue()); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/error/UncaughtErrorPageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/error/UncaughtErrorPageTest.java index 65d3808947..2b03c2f0e3 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/error/UncaughtErrorPageTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/error/UncaughtErrorPageTest.java @@ -223,6 +223,8 @@ public class UncaughtErrorPageTest extends AbstractKeycloakTest { try { checkPageNotFound("/auth/realms/master/nosuch"); + // Once keycloak.v2 would be the default login theme, uncomment the following line and remove the one below: + // String url = driver.findElement(By.xpath("//option[text()[contains(.,'Deutsch')]]")).getAttribute("value"); String url = driver.findElement(By.xpath("//a[text()[contains(.,'Deutsch')]]")).getAttribute("href"); driver.navigate().to(url); errorPage.assertCurrent(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java index 8d8ccd8857..73fee51715 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java @@ -55,6 +55,7 @@ import org.keycloak.testsuite.util.GreenMailRule; import org.keycloak.testsuite.util.KeycloakModelUtils; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; /** * Test user registration with customized user-profile configurations @@ -288,41 +289,13 @@ public class RegisterWithUserProfileTest extends AbstractTestRealmKeycloakTest { registerPage.assertCurrent(); //assert fields location in form - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-register-form > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-register-form > div:nth-child(2) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-register-form > div:nth-child(3) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("#password") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("#password-confirm") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-register-form > div:nth-child(6) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-register-form > div:nth-child(7) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + List element = driver.findElements(By.cssSelector("form#kc-register-form input")); + String[] labelOrder = new String[]{"lastName", "department", "username", "password", "password-confirm", "firstName", "email"}; + for (int i = 0; i < labelOrder.length; i++) { + WebElement webElement = element.get(i); + String id = webElement.getAttribute("id"); + assertThat("Field at index: " + i + " with id: " + id + " was not in found in the same order in the dom", id, is(labelOrder[i])); + } } public static final String UP_CONFIG_PART_INPUT_TYPES = "{\"name\": \"defaultType\"," + VerifyProfileTest.PERMISSIONS_ALL + "}," @@ -440,50 +413,22 @@ public class RegisterWithUserProfileTest extends AbstractTestRealmKeycloakTest { loginPage.clickRegister(); registerPage.assertCurrent(); - String htmlFormId="kc-register-form"; //assert fields and groups location in form, attributes without a group appear first - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - // password and password confirmation fields appear after the username field, in positions 3 and 4 - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-company") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(2) > label#description-company") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(8) > div:nth-child(1) > label#header-contact") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(9) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + List element = driver.findElements(By.cssSelector("form#kc-register-form label")); + String[] labelOrder = new String[]{"lastName", "username", "password", "password-confirm", "firstName", "header-company", "description-company", "department", "header-contact", "email"}; + for (int i = 0; i < element.size(); i++) { + WebElement webElement = element.get(i); + String id; + if (webElement.getAttribute("for") != null) { + id = webElement.getAttribute("for"); + // see that the label has an element it belongs to + assertThat("Label with id: " + id + " should have component it belongs to", driver.findElement(By.id(id)).isDisplayed(), is(true)); + } else { + id = webElement.getAttribute("id"); + } + assertThat("Label at index: " + i + " with id: " + id + " was not in found in the same order in the dom", id, is(labelOrder[i])); + } } @Test @@ -702,4 +647,4 @@ public class RegisterWithUserProfileTest extends AbstractTestRealmKeycloakTest { private UserRepresentation getUser(String userId) { return testRealm().users().get(userId).toRepresentation(); } -} \ No newline at end of file +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ThemeSelectorTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ThemeSelectorTest.java index 286fe9ce4d..3c8ba4023d 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ThemeSelectorTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ThemeSelectorTest.java @@ -7,10 +7,15 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.theme.ThemeSelectorProvider; import static org.junit.Assert.assertEquals; public class ThemeSelectorTest extends AbstractTestRealmKeycloakTest { + // At this moment, the default login theme as defined in ThemeSelectorProvider is "keycloak". + // Once the ThemeSelectorProvider.DEFAULT_V2 becomes default, this needs to be reflected in this constant. + private static final String SYSTEM_DEFAULT_LOGIN_THEME = ThemeSelectorProvider.DEFAULT; + @Page protected LoginPage loginPage; @@ -21,7 +26,7 @@ public class ThemeSelectorTest extends AbstractTestRealmKeycloakTest { @Test public void clientOverride() { loginPage.open(); - assertEquals("keycloak", detectTheme()); + assertEquals(System.getProperty(PROPERTY_LOGIN_THEME_DEFAULT, SYSTEM_DEFAULT_LOGIN_THEME), detectTheme()); ClientRepresentation rep = testRealm().clients().findByClientId("test-app").get(0); @@ -37,7 +42,7 @@ public class ThemeSelectorTest extends AbstractTestRealmKeycloakTest { testRealm().clients().get(rep.getId()).update(rep); loginPage.open(); - assertEquals("keycloak", detectTheme()); + assertEquals(SYSTEM_DEFAULT_LOGIN_THEME, detectTheme()); } finally { rep.getAttributes().put("login_theme", ""); testRealm().clients().get(rep.getId()).update(rep); @@ -48,6 +53,8 @@ public class ThemeSelectorTest extends AbstractTestRealmKeycloakTest { // for the purpose of the test does not matter which profile is used (product or community) if(driver.getPageSource().contains("/login/keycloak/css/login.css") || driver.getPageSource().contains("/login/rh-sso/css/login.css")) { return "keycloak"; + } else if (driver.getPageSource().contains("/login/keycloak.v2/css/styles.css") || driver.getPageSource().contains("/login/rh-sso/css/styles.css")) { + return "keycloak.v2"; } else { return "base"; } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java index 9aa668e5e9..15395c5fdf 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java @@ -73,6 +73,7 @@ import org.keycloak.testsuite.util.UserBuilder; import org.keycloak.userprofile.UserProfileContext; import org.keycloak.util.JsonSerialization; import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; /** * @author Vlastimil Elias @@ -218,49 +219,22 @@ public class VerifyProfileTest extends AbstractTestRealmKeycloakTest { loginPage.login("login-test5", "password"); verifyProfilePage.assertCurrent(); - String htmlFormId="kc-update-profile-form"; //assert fields and groups location in form, attributes without a group appear first - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(1) > label#header-company") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > label#description-company") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-contact") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + List element = driver.findElements(By.cssSelector("form#kc-update-profile-form label")); + String[] labelOrder = new String[]{"lastName", "username", "firstName", "header-company", "description-company", "department", "header-contact", "email"}; + for (int i = 0; i < element.size(); i++) { + WebElement webElement = element.get(i); + String id; + if (webElement.getAttribute("for") != null) { + id = webElement.getAttribute("for"); + // see that the label has an element it belongs to + assertThat("Label with id: " + id + " should have component it belongs to", driver.findElement(By.id(id)).isDisplayed(), is(true)); + } else { + id = webElement.getAttribute("id"); + } + assertThat("Label at index: " + i + " with id: " + id + " was not in found in the same order in the dom", id, is(labelOrder[i])); + } } @Test @@ -287,31 +261,13 @@ public class VerifyProfileTest extends AbstractTestRealmKeycloakTest { verifyProfilePage.assertCurrent(); //assert fields location in form - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(1) > div:nth-child(2) > input#lastName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(2) > div:nth-child(2) > input#department") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(3) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(4) > div:nth-child(2) > input#firstName") - ).isDisplayed() - ); - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#kc-update-profile-form > div:nth-child(5) > div:nth-child(2) > input#email") - ).isDisplayed() - ); + List element = driver.findElements(By.cssSelector("form#kc-update-profile-form input")); + String[] labelOrder = new String[]{"lastName", "department", "username", "firstName", "email"}; + for (int i = 0; i < labelOrder.length; i++) { + WebElement webElement = element.get(i); + String id = webElement.getAttribute("id"); + assertThat("Field at index: " + i + " with id: " + id + " was not in found in the same order in the dom", id, is(labelOrder[i])); + } } @Test diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java index 8a9c321457..a4c5b30c5c 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java @@ -167,7 +167,7 @@ public class LoginPageTest extends AbstractI18NTest { @Test public void testIdentityProviderCapitalization(){ loginPage.open(); - assertEquals("GitHub", loginPage.findSocialButton("github").getText()); + assertEquals("", loginPage.findSocialButton("github").getText()); // github is only displayed as an icon in keycloak.v2 theme assertEquals("mysaml", loginPage.findSocialButton("mysaml").getText()); assertEquals("MyOIDC", loginPage.findSocialButton("myoidc").getText()); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java index 986d2d4fa9..60b467dbab 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/AbstractMigrationTest.java @@ -118,6 +118,7 @@ import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT; import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT_LINKS; import static org.keycloak.models.AccountRoles.VIEW_GROUPS; import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID; +import static org.keycloak.testsuite.AbstractKeycloakTest.PREFERRED_DEFAULT_LOGIN_THEME; import static org.keycloak.testsuite.Assert.assertNames; import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER; import static org.keycloak.userprofile.DeclarativeUserProfileProvider.UP_COMPONENT_CONFIG_KEY; @@ -174,7 +175,7 @@ public abstract class AbstractMigrationTest extends AbstractKeycloakTest { protected void testRhssoThemes(RealmResource realm) { // check themes are removed RealmRepresentation rep = realm.toRepresentation(); - Assert.assertNull("Login theme was not modified", rep.getLoginTheme()); + assertThat("Login theme modified for test purposes", rep.getLoginTheme(), anyOf(nullValue(), equalTo(PREFERRED_DEFAULT_LOGIN_THEME))); Assert.assertNull("Email theme was not modified", rep.getEmailTheme()); // there should be either new default or left null if not set assertThat("Account theme was not modified", rep.getAccountTheme(), anyOf(equalTo("keycloak.v2"), nullValue())); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java index 362589a030..aea1c0e2d5 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java @@ -460,8 +460,9 @@ public class RefreshTokenTest extends AbstractKeycloakTest { oauth.fillLoginForm("alice", "alice"); String aliceCode = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - WebClient webClient = DroneHtmlUnitDriver.class.cast(driver).getWebClient(); - webClient.getCookieManager().clearCookies(); +// WebClient webClient = DroneHtmlUnitDriver.class.cast(driver).getWebClient(); +// webClient.getCookieManager().clearCookies(); + driver.manage().deleteAllCookies(); oauth.openLoginForm(); driver.manage().addCookie(authSessionCookie); oauth.fillLoginForm("bob", "bob"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IdpInitiatedLoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IdpInitiatedLoginTest.java index 3707972c55..23e24b472b 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IdpInitiatedLoginTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IdpInitiatedLoginTest.java @@ -50,6 +50,7 @@ import org.keycloak.broker.saml.SAMLIdentityProviderConfig; import org.keycloak.testsuite.updaters.ClientAttributeUpdater; import org.keycloak.testsuite.updaters.IdentityProviderCreator; import org.keycloak.testsuite.util.IdentityProviderBuilder; +import static org.hamcrest.Matchers.anyOf; import static org.keycloak.testsuite.util.Matchers.bodyHC; import static org.keycloak.testsuite.util.Matchers.statusCodeIsHC; @@ -197,9 +198,12 @@ public class IdpInitiatedLoginTest extends AbstractSamlTest { .execute(r -> { assertThat(r, statusCodeIsHC(Response.Status.OK)); assertThat(r, bodyHC(allOf( - containsString("Redirecting, please wait."), + anyOf( + containsString("Redirecting, please wait."), + containsString("Authentication Redirect") + ), containsString("") + containsString(" id=\"kc-page-title\"") ))); }); } @@ -219,9 +223,13 @@ public class IdpInitiatedLoginTest extends AbstractSamlTest { .execute(r -> { assertThat(r, statusCodeIsHC(Response.Status.OK)); assertThat(r, bodyHC(allOf( + anyOf( + containsString("Redirecting, please wait."), + containsString("Authentication Redirect") + ), containsString("Redirecting, please wait."), containsString("") + containsString(" id=\"kc-page-title\"") ))); }); } diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index 1db8bde425..8f0b75b525 100644 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -210,7 +210,7 @@ false true 60 - + keycloak.v2 Win32