Introduces a ManagedWebDriver to provide a single entry point for utilities around WebDriver

This will make it easier to discover various utilities without having to find static methods in various classes; and will also provides us with a wrapper around Selenium where we can add any tweaks needed. It is also now possible to construct a page instance without injection using `page().createPage(MyPage.class)`

Closes #44464

Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
Stian Thorgersen 2025-11-26 15:20:23 +01:00 committed by GitHub
parent cbb823bc0e
commit 33b6065c2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 439 additions and 208 deletions

View File

@ -2,19 +2,20 @@ package org.keycloak.test.examples;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.testframework.annotations.InjectAdminClient;
import org.keycloak.testframework.annotations.InjectKeycloakUrls;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.page.WelcomePage;
import org.keycloak.testframework.ui.webdriver.BrowserType;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
@KeycloakIntegrationTest
public class PagesTest {
@ -26,25 +27,23 @@ public class PagesTest {
RunOnServerClient runOnServer;
@InjectWebDriver
WebDriver webDriver;
@InjectPage
WelcomePage welcomePage;
ManagedWebDriver webDriver;
@InjectPage
LoginPage loginPage;
@InjectKeycloakUrls
KeycloakUrls keycloakUrls;
@Test
public void testLoginFromWelcome() {
welcomePage.navigateTo();
webDriver.open(keycloakUrls.getBaseUrl());
if (webDriver instanceof HtmlUnitDriver) {
if (webDriver.getBrowserType().equals(BrowserType.HTML_UNIT)) {
String pageId = webDriver.findElement(By.xpath("//body")).getAttribute("data-page-id");
Assertions.assertEquals("admin", pageId);
Assertions.assertTrue(webDriver.getCurrentUrl().endsWith("/admin/master/console/"));
} else {
loginPage.waitForPage();
loginPage.assertCurrent();
loginPage.fillLogin("admin", "admin");

View File

@ -3,17 +3,21 @@ package org.keycloak.testframework.oauth;
import org.keycloak.OAuth2Constants;
import org.keycloak.client.registration.ClientRegistration;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testsuite.util.oauth.AbstractOAuthClient;
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
import org.keycloak.testsuite.util.oauth.OAuthClientConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
public class OAuthClient extends AbstractOAuthClient<OAuthClient> {
public OAuthClient(String baseUrl, CloseableHttpClient httpClient, WebDriver webDriver) {
super(baseUrl, httpClient, webDriver);
private final ManagedWebDriver managedWebDriver;
public OAuthClient(String baseUrl, CloseableHttpClient httpClient, ManagedWebDriver managedWebDriver) {
super(baseUrl, httpClient, managedWebDriver.driver());
this.managedWebDriver = managedWebDriver;
config = new OAuthClientConfig()
.responseType(OAuth2Constants.CODE);
@ -21,12 +25,18 @@ public class OAuthClient extends AbstractOAuthClient<OAuthClient> {
@Override
public void fillLoginForm(String username, String password) {
LoginPage loginPage = new LoginPage(driver);
LoginPage loginPage = new LoginPage(managedWebDriver);
PageFactory.initElements(driver, loginPage);
loginPage.fillLogin(username, password);
loginPage.submit();
}
@Override
public AuthorizationEndpointResponse parseLoginResponse() {
managedWebDriver.waiting().waitForOAuthCallback();
return super.parseLoginResponse();
}
public ClientRegistration clientRegistration() {
return ClientRegistration.create().httpClient(httpClient().get()).url(baseUrl, config.getRealm()).build();
}

View File

@ -10,11 +10,11 @@ import org.keycloak.testframework.realm.ClientConfig;
import org.keycloak.testframework.realm.ClientConfigBuilder;
import org.keycloak.testframework.realm.ManagedRealm;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testframework.util.ApiUtil;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.openqa.selenium.WebDriver;
public class OAuthClientSupplier implements Supplier<OAuthClient, InjectOAuthClient> {
@ -24,7 +24,7 @@ public class OAuthClientSupplier implements Supplier<OAuthClient, InjectOAuthCli
KeycloakUrls keycloakUrls = instanceContext.getDependency(KeycloakUrls.class);
CloseableHttpClient httpClient = (CloseableHttpClient) instanceContext.getDependency(HttpClient.class);
WebDriver webDriver = instanceContext.getDependency(WebDriver.class);
ManagedWebDriver webDriver = instanceContext.getDependency(ManagedWebDriver.class);
TestApp testApp = instanceContext.getDependency(TestApp.class);
ManagedRealm realm = instanceContext.getDependency(ManagedRealm.class, annotation.realmRef());

View File

@ -11,8 +11,8 @@ import org.keycloak.testframework.ui.webdriver.ChromeWebDriverSupplier;
import org.keycloak.testframework.ui.webdriver.FirefoxHeadlessWebDriverSupplier;
import org.keycloak.testframework.ui.webdriver.FirefoxWebDriverSupplier;
import org.keycloak.testframework.ui.webdriver.HtmlUnitWebDriverSupplier;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.WebDriver;
public class UITestFrameworkExtension implements TestFrameworkExtension {
@ -31,7 +31,7 @@ public class UITestFrameworkExtension implements TestFrameworkExtension {
@Override
public Map<Class<?>, String> valueTypeAliases() {
return Map.of(
WebDriver.class, "browser"
ManagedWebDriver.class, "browser"
);
}

View File

@ -1,45 +1,18 @@
package org.keycloak.testframework.ui.page;
import java.time.Duration;
import org.junit.jupiter.api.Assertions;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
public abstract class AbstractPage {
@FindBy(xpath = "//body")
private WebElement body;
protected final ManagedWebDriver driver;
protected final WebDriver driver;
public AbstractPage(WebDriver driver) {
public AbstractPage(ManagedWebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public abstract String getExpectedPageId();
public String getCurrentPageId() {
return body.getAttribute("data-page-id");
}
public void waitForPage() {
try {
new WebDriverWait(driver, Duration.ofSeconds(10)).until(d -> isActivePage());
} catch (RuntimeException e) {
throw new RuntimeException("Waiting for '" + getExpectedPageId() + "', but was '" + getCurrentPageId() + "'");
}
}
private boolean isActivePage() {
return getExpectedPageId().equals(getCurrentPageId());
}
public void assertCurrent() {
Assertions.assertEquals(getExpectedPageId(), getCurrentPageId(), "Not on the expected page");
driver.waiting().waitForPage(this);
}
}

View File

@ -0,0 +1,16 @@
package org.keycloak.testframework.ui.page;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
public class AdminPage extends AbstractPage {
public AdminPage(ManagedWebDriver driver) {
super(driver);
}
@Override
public String getExpectedPageId() {
return "admin";
}
}

View File

@ -17,7 +17,8 @@
package org.keycloak.testframework.ui.page;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -32,7 +33,7 @@ public class ConsentPage extends AbstractPage {
@FindBy(id = "kc-cancel")
private WebElement cancelButton;
public ConsentPage(WebDriver driver) { super(driver); }
public ConsentPage(ManagedWebDriver driver) { super(driver); }
public void confirm() {
submitButton.click();

View File

@ -16,7 +16,8 @@
*/
package org.keycloak.testframework.ui.page;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -31,7 +32,7 @@ public class ErrorPage extends AbstractPage {
@FindBy(id = "backToApplication")
private WebElement backToApplicationLink;
public ErrorPage(WebDriver driver) {
public ErrorPage(ManagedWebDriver driver) {
super(driver);
}

View File

@ -17,7 +17,8 @@
package org.keycloak.testframework.ui.page;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -29,7 +30,7 @@ public class InfoPage extends AbstractPage {
@FindBy(className = "instruction")
private WebElement infoMessage;
public InfoPage(WebDriver driver) {
public InfoPage(ManagedWebDriver driver) {
super(driver);
}

View File

@ -1,7 +1,8 @@
package org.keycloak.testframework.ui.page;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -19,7 +20,7 @@ public class LoginPage extends AbstractPage {
@FindBy(id = "rememberMe")
private WebElement rememberMe;
public LoginPage(WebDriver driver) {
public LoginPage(ManagedWebDriver driver) {
super(driver);
}

View File

@ -16,7 +16,8 @@
*/
package org.keycloak.testframework.ui.page;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -43,7 +44,7 @@ public class LoginPasswordUpdatePage extends AbstractPage {
@FindBy(name = "cancel-aia")
private WebElement cancelAIAButton;
public LoginPasswordUpdatePage(WebDriver driver) {
public LoginPasswordUpdatePage(ManagedWebDriver driver) {
super(driver);
}

View File

@ -1,20 +1,17 @@
package org.keycloak.testframework.ui.page;
import java.lang.reflect.Constructor;
import org.keycloak.testframework.injection.InstanceContext;
import org.keycloak.testframework.injection.RequestedInstance;
import org.keycloak.testframework.injection.Supplier;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
public class PageSupplier implements Supplier<AbstractPage, InjectPage> {
@Override
public AbstractPage getValue(InstanceContext<AbstractPage, InjectPage> instanceContext) {
WebDriver webDriver = instanceContext.getDependency(WebDriver.class);
return createPage(webDriver, instanceContext.getRequestedValueType());
ManagedWebDriver webDriver = instanceContext.getDependency(ManagedWebDriver.class);
return webDriver.page().createPage(instanceContext.getRequestedValueType());
}
@Override
@ -22,12 +19,4 @@ public class PageSupplier implements Supplier<AbstractPage, InjectPage> {
return true;
}
private <S extends AbstractPage> S createPage(WebDriver webDriver, Class<S> valueType) {
try {
Constructor<S> constructor = valueType.getDeclaredConstructor(WebDriver.class);
return constructor.newInstance(webDriver);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -16,7 +16,8 @@
*/
package org.keycloak.testframework.ui.page;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -32,7 +33,7 @@ public class ProceedPage extends AbstractPage {
@FindBy(linkText = "» Click here to proceed")
private WebElement proceedLink;
public ProceedPage(WebDriver driver) {
public ProceedPage(ManagedWebDriver driver) {
super(driver);
}

View File

@ -1,6 +1,7 @@
package org.keycloak.testframework.ui.page;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -30,14 +31,10 @@ public class WelcomePage extends AbstractPage {
@FindBy(css = ".pf-v5-c-button")
private WebElement openAdminConsoleLink;
public WelcomePage(WebDriver driver) {
public WelcomePage(ManagedWebDriver driver) {
super(driver);
}
public void navigateTo() {
driver.get("http://localhost:8080");
}
public void fillRegistration(String username, String password) {
usernameInput.sendKeys(username);
passwordInput.sendKeys(password);

View File

@ -14,15 +14,15 @@ import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.CapabilityType;
public abstract class AbstractWebDriverSupplier implements Supplier<WebDriver, InjectWebDriver> {
public abstract class AbstractWebDriverSupplier implements Supplier<ManagedWebDriver, InjectWebDriver> {
@Override
public WebDriver getValue(InstanceContext<WebDriver, InjectWebDriver> instanceContext) {
return getWebDriver();
public ManagedWebDriver getValue(InstanceContext<ManagedWebDriver, InjectWebDriver> instanceContext) {
return new ManagedWebDriver(getWebDriver());
}
@Override
public boolean compatible(InstanceContext<WebDriver, InjectWebDriver> a, RequestedInstance<WebDriver, InjectWebDriver> b) {
public boolean compatible(InstanceContext<ManagedWebDriver, InjectWebDriver> a, RequestedInstance<ManagedWebDriver, InjectWebDriver> b) {
return true;
}
@ -32,8 +32,8 @@ public abstract class AbstractWebDriverSupplier implements Supplier<WebDriver, I
}
@Override
public void close(InstanceContext<WebDriver, InjectWebDriver> instanceContext) {
instanceContext.getValue().quit();
public void close(InstanceContext<ManagedWebDriver, InjectWebDriver> instanceContext) {
instanceContext.getValue().driver().quit();
}
public abstract WebDriver getWebDriver();

View File

@ -0,0 +1,17 @@
package org.keycloak.testframework.ui.webdriver;
import org.junit.jupiter.api.Assertions;
public class AssertionUtils {
private final ManagedWebDriver managed;
AssertionUtils(ManagedWebDriver managed) {
this.managed = managed;
}
public void assertTitle(String title) {
Assertions.assertEquals(title, managed.page().getTitle());
}
}

View File

@ -0,0 +1,9 @@
package org.keycloak.testframework.ui.webdriver;
public enum BrowserType {
CHROME,
FIREFOX,
HTML_UNIT
}

View File

@ -0,0 +1,21 @@
package org.keycloak.testframework.ui.webdriver;
import org.openqa.selenium.Cookie;
public class CookieUtils {
private final ManagedWebDriver managed;
CookieUtils(ManagedWebDriver managed) {
this.managed = managed;
}
public void add(Cookie cookie) {
managed.driver().manage().addCookie(cookie);
}
public void deleteAll() {
managed.driver().manage().deleteAllCookies();
}
}

View File

@ -0,0 +1,72 @@
package org.keycloak.testframework.ui.webdriver;
import java.net.URL;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
public class ManagedWebDriver {
private WebDriver driver;
private AssertionUtils assertionUtils = new AssertionUtils(this);
private CookieUtils cookieUtils = new CookieUtils(this);
private PageUtils pageUtils = new PageUtils(this);
private WaitUtils waitUtils = new WaitUtils(this);
public ManagedWebDriver(WebDriver driver) {
this.driver = driver;
}
public WebDriver driver() {
return driver;
}
public BrowserType getBrowserType() {
if (driver instanceof HtmlUnitDriver) {
return BrowserType.HTML_UNIT;
} else if (driver instanceof ChromeDriver) {
return BrowserType.CHROME;
} else if (driver instanceof FirefoxDriver) {
return BrowserType.FIREFOX;
}
throw new RuntimeException("Unknown browser type: " + driver.getClass());
}
public String getCurrentUrl() {
return driver.getCurrentUrl();
}
public WebElement findElement(By by) {
return driver.findElement(by);
}
public void open(String url) {
driver.navigate().to(url);
}
public void open(URL url) {
driver.navigate().to(url);
}
public AssertionUtils assertions() {
return assertionUtils;
}
public CookieUtils cookies() {
return cookieUtils;
}
public PageUtils page() {
return pageUtils;
}
public WaitUtils waiting() {
return waitUtils;
}
}

View File

@ -0,0 +1,41 @@
package org.keycloak.testframework.ui.webdriver;
import java.lang.reflect.Constructor;
import org.keycloak.testframework.ui.page.AbstractPage;
import org.openqa.selenium.By;
import org.openqa.selenium.support.PageFactory;
public class PageUtils {
private final ManagedWebDriver managed;
PageUtils(ManagedWebDriver managed) {
this.managed = managed;
}
public <S extends AbstractPage> S createPage(Class<S> valueType) {
try {
Constructor<S> constructor = valueType.getDeclaredConstructor(ManagedWebDriver.class);
S page = constructor.newInstance(managed);
PageFactory.initElements(managed.driver(), page);
return page;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getCurrentPageId() {
return managed.findElement(By.xpath("//body")).getAttribute("data-page-id");
}
public String getTitle() {
return managed.driver().getTitle();
}
public String getPageSource() {
return managed.driver().getPageSource();
}
}

View File

@ -0,0 +1,53 @@
package org.keycloak.testframework.ui.webdriver;
import java.time.Duration;
import java.util.function.Function;
import org.keycloak.testframework.ui.page.AbstractPage;
import org.junit.jupiter.api.Assertions;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
public class WaitUtils {
private final ManagedWebDriver managed;
WaitUtils(ManagedWebDriver managed) {
this.managed = managed;
}
public WaitUtils waitForPage(AbstractPage page) {
String expectedPageId = page.getExpectedPageId();
try {
createDefaultWait().until(d -> expectedPageId.equals(managed.page().getCurrentPageId()));
} catch (TimeoutException e) {
Assertions.fail("Expected page '" + expectedPageId + "' to be loaded, but currently on page '" + managed.page().getCurrentPageId() + "' after timeout");
}
return this;
}
public WaitUtils waitForOAuthCallback() {
try {
createDefaultWait().until(d -> d.getCurrentUrl().contains("code=") || d.getCurrentUrl().contains("error="));
} catch (TimeoutException e) {
Assertions.fail("Expected OAuth callback, but URL was '" + managed.getCurrentUrl() + "' after timeout");
}
return this;
}
public WaitUtils waitForTitle(String title) {
createDefaultWait().until(d -> d.getTitle().equals(title));
return this;
}
public <V> V until(Function<WebDriver, V> isTrue) {
return createDefaultWait().until(isTrue);
}
private WebDriverWait createDefaultWait() {
return new WebDriverWait(managed.driver(), Duration.ofSeconds(5), Duration.ofMillis(50));
}
}

View File

@ -59,6 +59,7 @@ import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.ConsentPage;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testsuite.util.AccountHelper;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
@ -68,7 +69,6 @@ import org.jboss.logging.Logger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import static org.keycloak.tests.utils.admin.AdminApiUtil.findClientByClientId;
@ -113,7 +113,7 @@ public class ConsentsTest {
Events userRealmEvents;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectPage
LoginPage loginPage;
@ -149,11 +149,10 @@ public class ConsentsTest {
loginPage.fillLogin(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
loginPage.submit();
consentPage.waitForPage();
consentPage.assertCurrent();
consentPage.confirm();
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
UsersResource consumerUsers = consumerRealm.admin().users();
Assertions.assertTrue(consumerUsers.count() > 0, "There must be at least one user");
@ -231,12 +230,12 @@ public class ConsentsTest {
// navigate to account console and login
providerRealmOAuth.openLoginForm();
loginPage.waitForPage();
loginPage.assertCurrent();
LOGGER.debug("Logging in");
loginPage.fillLogin(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
loginPage.submit();
consentPage.waitForPage();
consentPage.assertCurrent();
LOGGER.debug("Grant consent for offline_access");
consentPage.assertCurrent();
consentPage.confirm();
@ -278,7 +277,7 @@ public class ConsentsTest {
consentPage.cancel();
// check an error page after cancelling the consent
assertTrue(driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource().contains("Happy days"));
assertTrue(driver.getCurrentUrl().contains("error=access_denied"));
providerRealmOAuth.openLoginForm();
@ -288,7 +287,7 @@ public class ConsentsTest {
// successful login
assertFalse(driver.getCurrentUrl().contains("error"));
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
}
@Test
@ -297,7 +296,7 @@ public class ConsentsTest {
AccessTokenResponse accessTokenResponse = userRealmOAuth.doAccessTokenRequest(response.getCode());
Assertions.assertNotNull(userRealmOAuth.parseLoginResponse().getCode());
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
EventRepresentation loginEvent = userRealmEvents.poll();
Assertions.assertNotNull(loginEvent);
@ -369,7 +368,7 @@ public class ConsentsTest {
consentPage.confirm();
// successful login
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
AccountHelper.logout(providerRealm.admin(), userFromProviderRealm.getUsername());
}

View File

@ -77,6 +77,7 @@ import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testframework.util.ApiUtil;
import org.keycloak.tests.utils.admin.AdminApiUtil;
import org.keycloak.testsuite.util.CredentialBuilder;
@ -92,7 +93,6 @@ import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
@ -132,7 +132,7 @@ public class ImpersonationTest {
KeycloakUrls keycloakUrls;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectPage
LoginPage loginPage;
@ -222,7 +222,7 @@ public class ImpersonationTest {
// Impersonate and get SSO cookie. Setup that cookie for webDriver
for (Cookie cookie : testSuccessfulImpersonation("realm-admin", managedRealm.getName())) {
driver.manage().addCookie(cookie);
driver.cookies().add(cookie);
}
// Open the URL again - should be directly redirected to the app due the SSO login

View File

@ -63,6 +63,7 @@ import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testframework.util.ApiUtil;
import org.keycloak.tests.utils.admin.AdminApiUtil;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
@ -86,7 +87,6 @@ import org.jboss.logging.Logger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import static org.hamcrest.MatcherAssert.assertThat;
@ -115,7 +115,7 @@ public class ConcurrentLoginTest extends AbstractConcurrencyTest {
OAuthClient oauth;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectKeycloakUrls
KeycloakUrls keycloakUrls;

View File

@ -37,6 +37,8 @@ import org.keycloak.testframework.realm.RealmConfig;
import org.keycloak.testframework.realm.RealmConfigBuilder;
import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.page.LoginPage;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@ -61,6 +63,9 @@ public class LoginEventsTest {
@InjectRunOnServer
RunOnServerClient runOnServerClient;
@InjectPage
LoginPage loginPage;
@BeforeEach
public void init() {
managedRealm.admin().clearEvents();
@ -71,7 +76,9 @@ public class LoginEventsTest {
}
private void badLogin() {
oAuthClient.doLogin("bad", "user");
oAuthClient.openLoginForm();
oAuthClient.fillLoginForm("bad", "user");
loginPage.assertCurrent();
}
private void pause(int seconds) {

View File

@ -18,7 +18,8 @@ import org.keycloak.testframework.realm.UserConfigBuilder;
import org.keycloak.testframework.server.KeycloakServerConfig;
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
import org.apache.http.client.HttpClient;
@ -45,12 +46,19 @@ public class PasswordValidationMetricCustomTagsTest {
@InjectHttpClient
HttpClient httpClient;
@InjectPage
LoginPage loginPage;
Pattern passValidationRegex = Pattern.compile("keycloak_credentials_password_hashing_validations_total\\{realm=\"([^\"]+)\"} ([.0-9]*)");
@Test
void testValidAndInvalidPasswordValidation() throws IOException {
runAuthorizationCodeFlow(user.getUsername(), "invalid_password", false);
runAuthorizationCodeFlow(user.getUsername(), user.getPassword(), true);
oAuthClient.openLoginForm();
oAuthClient.fillLoginForm(user.getUsername(), "invalid_password");
loginPage.assertCurrent();
AuthorizationEndpointResponse authorizationEndpointResponse = oAuthClient.doLogin(user.getUsername(), user.getPassword());
Assertions.assertTrue(oAuthClient.doAccessTokenRequest(authorizationEndpointResponse.getCode()).isSuccess());
String metrics = EntityUtils.toString(httpClient.execute(new HttpGet(keycloakUrls.getMetric())).getEntity());
Matcher matcher = passValidationRegex.matcher(metrics);
@ -61,16 +69,6 @@ public class PasswordValidationMetricCustomTagsTest {
Assertions.assertFalse(matcher.find());
}
private void runAuthorizationCodeFlow(String username, String password, boolean success) {
AuthorizationEndpointResponse authorizationEndpointResponse = oAuthClient.doLogin(username, password);
if (!success) {
Assertions.assertFalse(authorizationEndpointResponse.isRedirected());
return;
}
AccessTokenResponse accessTokenResponse = oAuthClient.doAccessTokenRequest(authorizationEndpointResponse.getCode());
Assertions.assertTrue(accessTokenResponse.isSuccess());
}
public static class ServerConfigWithMetrics implements KeycloakServerConfig {
@Override

View File

@ -18,7 +18,10 @@ import org.keycloak.testframework.realm.UserConfigBuilder;
import org.keycloak.testframework.server.KeycloakServerConfig;
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
@ -27,7 +30,6 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
@KeycloakIntegrationTest(config = PasswordValidationMetricTest.ServerConfigWithMetrics.class)
public class PasswordValidationMetricTest {
@ -48,15 +50,25 @@ public class PasswordValidationMetricTest {
HttpClient httpClient;
@InjectWebDriver
WebDriver webDriver;
ManagedWebDriver webDriver;
@InjectPage
LoginPage loginPage;
Pattern passValidationRegex = Pattern.compile("keycloak_credentials_password_hashing_validations_total\\{algorithm=\"([^\"]+)\",hashing_strength=\"([^\"]+)\",outcome=\"([^\"]+)\",realm=\"([^\"]+)\"} ([.0-9]*)");
@Test
void testValidAndInvalidPasswordValidation() throws IOException {
runAuthorizationCodeFlow(user.getUsername(), "invalid_password");
webDriver.manage().deleteAllCookies();
runAuthorizationCodeFlow(user.getUsername(), user.getPassword());
oAuthClient.openLoginForm();
oAuthClient.fillLoginForm(user.getUsername(), "invalid_password");
loginPage.assertCurrent();
webDriver.cookies().deleteAll();
oAuthClient.doLogin(user.getUsername(), user.getPassword());
AccessTokenResponse tokenResponse = oAuthClient.doAccessTokenRequest(oAuthClient.parseLoginResponse().getCode());
Assertions.assertTrue(tokenResponse.isSuccess());
String metrics = EntityUtils.toString(httpClient.execute(new HttpGet(keycloakUrls.getMetric())).getEntity());
Matcher matcher = passValidationRegex.matcher(metrics);

View File

@ -15,8 +15,7 @@ import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.LoginPage;
import org.openqa.selenium.WebDriver;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
public abstract class AbstractWorkflowTest {
@ -29,7 +28,7 @@ public abstract class AbstractWorkflowTest {
ManagedRealm managedRealm;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectPage
LoginPage loginPage;

View File

@ -60,13 +60,13 @@ import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.ConsentPage;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testframework.util.ApiUtil;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.WebDriver;
import static org.keycloak.models.workflow.ResourceOperationType.USER_ADDED;
import static org.keycloak.models.workflow.ResourceOperationType.USER_LOGGED_IN;
@ -110,7 +110,7 @@ public class BrokeredUserSessionRefreshTimeWorkflowTest extends AbstractWorkflow
ManagedClient providerRealmClient;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectPage
LoginPage loginPage;
@ -208,7 +208,7 @@ public class BrokeredUserSessionRefreshTimeWorkflowTest extends AbstractWorkflow
consumerRealmOAuth.openLoginForm();
loginPage.fillLogin(bobFromConsumerRealm.getUsername(), bobFromConsumerRealm.getPassword());
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
// run the scheduled tasks - bob should not be affected.
runScheduledSteps(Duration.ZERO);
@ -296,10 +296,9 @@ public class BrokeredUserSessionRefreshTimeWorkflowTest extends AbstractWorkflow
Assertions.assertTrue(driver.getCurrentUrl().contains("/realms/" + providerRealm.getName() + "/"), "Driver should be on the provider realm page right now");
loginPage.fillLogin(aliceFromProviderRealm.getUsername(), aliceFromProviderRealm.getPassword());
loginPage.submit();
consentPage.waitForPage();
consentPage.assertCurrent();
consentPage.confirm();
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
}
private static IdentityProviderRepresentation setUpIdentityProvider() {

View File

@ -49,6 +49,7 @@ import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.ConsentPage;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testframework.util.ApiUtil;
import org.keycloak.tests.admin.model.workflow.DeleteUserWorkflowStepTest.DeleteUserWorkflowServerConf;
import org.keycloak.testsuite.federation.DummyUserFederationProvider;
@ -58,7 +59,6 @@ import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.openqa.selenium.WebDriver;
import static org.keycloak.models.workflow.DeleteUserStepProvider.PROPAGATE_TO_SP;
@ -82,7 +82,7 @@ public class DeleteUserWorkflowStepTest extends AbstractWorkflowTest {
OAuthClient consumerRealmOAuth;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectPage
LoginPage loginPage;
@ -124,7 +124,7 @@ public class DeleteUserWorkflowStepTest extends AbstractWorkflowTest {
consumerRealmOAuth.openLoginForm();
loginPage.fillLogin(USER_NAME, USER_PASSWORD);
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
runScheduledSteps(Duration.ZERO);

View File

@ -122,7 +122,7 @@ public class ExpressionConditionWorkflowTest extends AbstractWorkflowTest {
oauth.openLoginForm();
loginPage.fillLogin(username, username);
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource().contains("Happy days"));
// step 2 - use time offset to trigger the scheduled step for those users who match the condition
// set offset to 6 days to trigger the scheduled step (which is set to run after 5 days)

View File

@ -92,7 +92,7 @@ public class UserResourceTypeSelectorTest extends AbstractWorkflowTest {
oauth.openLoginForm();
loginPage.fillLogin("alice", "alice");
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource().contains("Happy days"));
// set offset to 11 days - disable step should run now
runScheduledSteps(Duration.ofDays(12));

View File

@ -78,7 +78,7 @@ public class UserSessionRefreshTimeWorkflowTest extends AbstractWorkflowTest {
String username = userAlice.getUsername();
loginPage.fillLogin(username, userAlice.getPassword());
loginPage.submit();
assertTrue(driver.getPageSource() != null && driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource() != null && driver.page().getPageSource().contains("Happy days"));
// test running the scheduled steps
runOnServer.run((session -> {
@ -160,7 +160,7 @@ public class UserSessionRefreshTimeWorkflowTest extends AbstractWorkflowTest {
String username = userAlice.getUsername();
loginPage.fillLogin(username, userAlice.getPassword());
loginPage.submit();
assertTrue(driver.getPageSource() != null && driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource() != null && driver.page().getPageSource().contains("Happy days"));
runOnServer.run(session -> {
RealmModel realm = session.getContext().getRealm();

View File

@ -41,6 +41,7 @@ import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testframework.util.ApiUtil;
import org.keycloak.tests.utils.admin.AdminEventPaths;
import org.keycloak.tests.utils.runonserver.RunHelpers;
@ -50,7 +51,6 @@ import org.keycloak.util.JsonSerialization;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.openqa.selenium.WebDriver;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -66,7 +66,7 @@ public class AbstractUserTest {
AdminEvents adminEvents;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectRunOnServer
RunOnServerClient runOnServer;

View File

@ -78,7 +78,7 @@ public class UserCredentialTest extends AbstractUserTest {
loginPage.fillLogin("user1", "paSSw0rd");
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource().contains("Happy days"));
AccountHelper.logout(managedRealm.admin(), "user1");
}
@ -113,7 +113,7 @@ public class UserCredentialTest extends AbstractUserTest {
loginPage.assertCurrent();
loginPage.fillLogin(userName, userPass);
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
assertTrue(driver.page().getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
AccountHelper.logout(managedRealm.admin(), userName);
Optional<CredentialRepresentation> passwordCredential =

View File

@ -189,7 +189,7 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(body);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -202,7 +202,7 @@ public class UserEmailTest extends AbstractUserTest {
assertEquals("Your account has been updated.", infoPage.getInfo());
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
}
@ -235,7 +235,7 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(body);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -318,7 +318,7 @@ public class UserEmailTest extends AbstractUserTest {
}
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -329,7 +329,7 @@ public class UserEmailTest extends AbstractUserTest {
assertEquals("Your account has been updated.", infoPage.getInfo());
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
}
@ -355,7 +355,7 @@ public class UserEmailTest extends AbstractUserTest {
for (MimeMessage message : mailServer.getReceivedMessages()) {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -370,7 +370,7 @@ public class UserEmailTest extends AbstractUserTest {
for (MimeMessage message : mailServer.getReceivedMessages()) {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
}
}
@ -398,7 +398,7 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -413,7 +413,7 @@ public class UserEmailTest extends AbstractUserTest {
for (MimeMessage message : mailServer.getReceivedMessages()) {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
}
}
@ -437,17 +437,17 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
proceedPage.clickProceedLink();
passwordUpdatePage.assertCurrent();
driver.manage().deleteAllCookies();
driver.navigate().to("about:blank");
driver.cookies().deleteAll();
driver.open("about:blank");
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -487,7 +487,7 @@ public class UserEmailTest extends AbstractUserTest {
timeOffSet.set(70);
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
assertEquals("Action expired.", errorPage.getError());
@ -533,7 +533,7 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
}
user.executeActionsEmail(actions);
@ -545,7 +545,7 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -556,7 +556,7 @@ public class UserEmailTest extends AbstractUserTest {
assertEquals("Your account has been updated.", infoPage.getInfo());
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
}
@ -605,7 +605,7 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -616,12 +616,12 @@ public class UserEmailTest extends AbstractUserTest {
assertEquals("Your account has been updated.", driver.findElement(By.id("kc-page-title")).getText());
String pageSource = driver.getPageSource();
String pageSource = driver.page().getPageSource();
// check to make sure the back link is set.
Assertions.assertTrue(pageSource.contains("http://myclient.com/home.html"));
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
}
@ -687,7 +687,7 @@ public class UserEmailTest extends AbstractUserTest {
throw new IOException(e);
}
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Update Password"));
@ -698,12 +698,12 @@ public class UserEmailTest extends AbstractUserTest {
assertEquals("Your account has been updated.", driver.findElement(By.id("kc-page-title")).getText());
String pageSource = driver.getPageSource();
String pageSource = driver.page().getPageSource();
// check to make sure the back link is set.
Assertions.assertTrue(pageSource.contains("http://myclient.com/home.html"));
driver.navigate().to(link);
driver.open(link);
errorPage.assertCurrent();
}
@ -762,16 +762,16 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(mailServer.getReceivedMessages()[0]);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Confirm validity of e-mail address"));
proceedPage.clickProceedLink();
Assertions.assertEquals("Your account has been updated.", infoPage.getInfo());
driver.navigate().to("about:blank");
driver.open("about:blank");
driver.navigate().to(link);
driver.open(link);
infoPage.assertCurrent();
assertEquals("Your email address has been verified already.", infoPage.getInfo());
}
@ -808,7 +808,7 @@ public class UserEmailTest extends AbstractUserTest {
String link = MailUtils.getPasswordResetEmailLink(message);
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Confirm validity of e-mail address"));
@ -816,7 +816,7 @@ public class UserEmailTest extends AbstractUserTest {
assertEquals("Your account has been updated.", infoPage.getInfo());
String pageSource = driver.getPageSource();
String pageSource = driver.page().getPageSource();
Assertions.assertTrue(pageSource.contains(redirectUri));
}
@ -863,7 +863,7 @@ public class UserEmailTest extends AbstractUserTest {
throw new IOException(e);
}
driver.navigate().to(link);
driver.open(link);
proceedPage.assertCurrent();
assertThat(proceedPage.getInfo(), Matchers.containsString("Confirm validity of e-mail address"));
@ -871,7 +871,7 @@ public class UserEmailTest extends AbstractUserTest {
assertEquals("Your account has been updated.", infoPage.getInfo());
String pageSource = driver.getPageSource();
String pageSource = driver.page().getPageSource();
Assertions.assertTrue(pageSource.contains(redirectUri));
}

View File

@ -77,7 +77,7 @@ public class UserUpdateTest extends AbstractUserTest {
loginPage.fillLogin("user_hashed_creds", "admin");
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource().contains("Happy days"));
AccountHelper.logout(managedRealm.admin(), "user_hashed_creds");
}

View File

@ -13,13 +13,13 @@ import org.keycloak.testframework.realm.UserConfigBuilder;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.keycloak.testsuite.util.AccountHelper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.openqa.selenium.WebDriver;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -31,7 +31,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
public class AuthzEndpointRequestParserTest {
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectRealm
ManagedRealm realm;
@ -95,7 +95,7 @@ public class AuthzEndpointRequestParserTest {
loginPage.fillLogin("test-user", "password");
loginPage.submit();
assertTrue(driver.getPageSource().contains("Happy days"));
assertTrue(driver.page().getPageSource().contains("Happy days"));
// String currentUrl = driver.getCurrentUrl();
String state = oauth.parseLoginResponse().getState();
Assertions.assertEquals(stateExpected, state);

View File

@ -50,6 +50,8 @@ import org.keycloak.testframework.oauth.OAuthClient;
import org.keycloak.testframework.oauth.annotations.InjectOAuthClient;
import org.keycloak.testframework.realm.ClientConfigBuilder;
import org.keycloak.testframework.realm.ManagedRealm;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.util.ApiUtil;
import org.keycloak.tests.common.BasicRealmWithUserConfig;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
@ -60,7 +62,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ -80,6 +81,9 @@ public class KeyRotationTest {
@InjectCryptoHelper
CryptoHelper cryptoHelper;
@InjectPage
LoginPage loginPage;
@Test
public void testIdentityCookie() {
// Create keys #1
@ -108,7 +112,7 @@ public class KeyRotationTest {
// Login again with key #2 dropped - should fail as cookie hasn't been refreshed
oauth.openLoginForm();
assertFalse(oauth.parseLoginResponse().isRedirected());
loginPage.assertCurrent();
}
@Test

View File

@ -4,7 +4,6 @@ import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.URL;
import java.time.Duration;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
@ -14,25 +13,27 @@ import org.keycloak.common.util.KeycloakUriBuilder;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.testframework.annotations.InjectAdminClient;
import org.keycloak.testframework.annotations.InjectKeycloakUrls;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.config.Config;
import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.testframework.server.KeycloakServerConfig;
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.AdminPage;
import org.keycloak.testframework.ui.page.LoginPage;
import org.keycloak.testframework.ui.page.WelcomePage;
import org.keycloak.testframework.ui.webdriver.BrowserType;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -52,17 +53,23 @@ public class WelcomePageTest {
RunOnServerClient runOnServer;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectAdminClient
Keycloak adminClient;
@InjectPage
AdminPage adminPage;
@InjectPage
WelcomePage welcomePage;
@InjectPage
LoginPage loginPage;
@InjectKeycloakUrls
KeycloakUrls keycloakUrls;
@Test
@Order(1)
public void localAccessNoAdminNorServiceAccount() {
@ -73,27 +80,27 @@ public class WelcomePageTest {
var clients = adminClient.realms().realm("master").clients();
clients.findByClientId(Config.getAdminClientId()).stream().findFirst().ifPresent(client -> clients.delete(client.getId()));
welcomePage.navigateTo();
driver.open(keycloakUrls.getBaseUrl());
Assertions.assertEquals("Create an administrative user", welcomePage.getWelcomeMessage());
Assertions.assertTrue(welcomePage.getWelcomeDescription().startsWith("To get started with Keycloak, you first create an administrative user"));
Assertions.assertTrue(driver.getPageSource().contains("form"));
Assertions.assertTrue(driver.page().getPageSource().contains("form"));
}
@Test
@Order(2)
public void remoteAccessNoAdmin() throws Exception {
driver.get(getPublicServerUrl().toString());
driver.open(getPublicServerUrl());
Assertions.assertEquals("Local access required", welcomePage.getWelcomeMessage());
Assertions.assertTrue(welcomePage.getWelcomeDescription().startsWith("You will need local access to create the administrative user."));
Assertions.assertFalse(driver.getPageSource().contains("form"));
Assertions.assertFalse(driver.page().getPageSource().contains("form"));
}
@Test
@Order(3)
public void createAdminUser() {
welcomePage.navigateTo();
driver.open(keycloakUrls.getBaseUrl());
welcomePage.fillRegistration(Config.getAdminUsername(), Config.getAdminPassword());
welcomePage.submit();
@ -112,33 +119,32 @@ public class WelcomePageTest {
@Test
@Order(4)
public void localAccessWithAdmin() {
welcomePage.navigateTo();
assertOnAdminConsole(driver);
driver.open(keycloakUrls.getBaseUrl());
adminPage.assertCurrent();
}
@Test
@Order(5)
public void remoteAccessWithAdmin() throws Exception {
driver.get(getPublicServerUrl().toString());
assertOnAdminConsole(driver);
driver.open(getPublicServerUrl().toString());
adminPage.assertCurrent();
}
@Test
@Order(6)
public void accessCreatedAdminAccount() throws MalformedURLException {
welcomePage.navigateTo();
driver.open(keycloakUrls.getBaseUrl());
// HtmlUnit does not support Admin Console as it uses JavaScript modules, so faking the redirect to login pages
if (driver.getClass().equals(HtmlUnitDriver.class)) {
driver.navigate().to(getFakeLoginRedirect());
if (driver.getBrowserType().equals(BrowserType.HTML_UNIT)) {
driver.open(getFakeLoginRedirect());
}
loginPage.assertCurrent();
loginPage.fillLogin(Config.getAdminUsername(), Config.getAdminPassword());
loginPage.submit();
Assertions.assertEquals("Keycloak Administration Console", driver.getTitle());
adminPage.assertCurrent();
}
/**
@ -169,10 +175,6 @@ public class WelcomePageTest {
return new URL("http", floatingIp, 8080, "");
}
static void assertOnAdminConsole(WebDriver driver) {
new WebDriverWait(driver, Duration.ofSeconds(10)).until(d -> driver.getTitle().equals("Keycloak Administration Console") || driver.getTitle().equals("Sign in to Keycloak"));
}
private URL getFakeLoginRedirect() throws MalformedURLException {
KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri("http://localhost:8080/realms/master/protocol/openid-connect/auth");
uriBuilder.queryParam("client_id", "security-admin-console");

View File

@ -5,23 +5,25 @@ import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.testframework.annotations.InjectAdminClient;
import org.keycloak.testframework.annotations.InjectKeycloakUrls;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.config.Config;
import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
import org.keycloak.testframework.server.KeycloakServerConfig;
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
import org.keycloak.testframework.server.KeycloakUrls;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.AdminPage;
import org.keycloak.testframework.ui.page.WelcomePage;
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.openqa.selenium.WebDriver;
import static org.keycloak.tests.welcomepage.WelcomePageTest.assertOnAdminConsole;
import static org.keycloak.tests.welcomepage.WelcomePageTest.getPublicServerUrl;
import static org.junit.Assert.assertTrue;
@ -43,14 +45,20 @@ public class WelcomePageWithServiceAccountTest {
RunOnServerClient runOnServer;
@InjectWebDriver
WebDriver driver;
ManagedWebDriver driver;
@InjectAdminClient
Keycloak adminClient;
@InjectPage
AdminPage adminPage;
@InjectPage
WelcomePage welcomePage;
@InjectKeycloakUrls
KeycloakUrls keycloakUrls;
@Test
@Order(1)
public void localAccessWithServiceAccount() {
@ -59,17 +67,17 @@ public class WelcomePageWithServiceAccountTest {
UsersResource users = masterRealm.users();
masterRealm.users().searchByUsername(Config.getAdminUsername(), true).stream().findFirst().ifPresent(admin -> users.delete(admin.getId()));
welcomePage.navigateTo();
driver.open(keycloakUrls.getBaseUrl());
assertOnAdminConsole(driver);
adminPage.assertCurrent();
}
@Test
@Order(2)
public void remoteAccessWithServiceAccount() throws Exception {
driver.get(getPublicServerUrl().toString());
driver.open(getPublicServerUrl().toString());
assertOnAdminConsole(driver);
adminPage.assertCurrent();
}
@Test