From b3dd26a7c3949b54114da030db0a12e2f779c0f7 Mon Sep 17 00:00:00 2001 From: fwojnar <44195048+wojnarfilip@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:57:58 +0100 Subject: [PATCH] Migrate WelcomeTestPage to testsuite framework (#34543) * Migrate WelcomeTestPage to testsuite framework Closes #34491 Signed-off-by: wojnarfilip * Refactor welcome page a bit Signed-off-by: stianst * Fixes for htmlunit Signed-off-by: stianst * Cleanup imports Signed-off-by: stianst --------- Signed-off-by: wojnarfilip Signed-off-by: stianst Co-authored-by: wojnarfilip Co-authored-by: stianst --- .../test/examples/WelcomePageTest.java | 38 ---- .../test/framework/ui/page/WelcomePage.java | 21 ++- .../test/welcomepage/WelcomePageTest.java | 157 +++++++++++++++++ .../welcomepage/WelcomePageTest.java | 166 ------------------ .../tests/base/testsuites/base-suite | 1 - 5 files changed, 174 insertions(+), 209 deletions(-) delete mode 100644 test-framework/examples/src/test/java/org/keycloak/test/examples/WelcomePageTest.java create mode 100644 tests/base/src/test/java/org/keycloak/test/welcomepage/WelcomePageTest.java delete mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/welcomepage/WelcomePageTest.java diff --git a/test-framework/examples/src/test/java/org/keycloak/test/examples/WelcomePageTest.java b/test-framework/examples/src/test/java/org/keycloak/test/examples/WelcomePageTest.java deleted file mode 100644 index a1586cdbae..0000000000 --- a/test-framework/examples/src/test/java/org/keycloak/test/examples/WelcomePageTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.keycloak.test.examples; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.keycloak.admin.client.Keycloak; -import org.keycloak.representations.idm.UserRepresentation; -import org.keycloak.test.framework.annotations.InjectAdminClient; -import org.keycloak.test.framework.ui.annotations.InjectWebDriver; -import org.keycloak.test.framework.annotations.KeycloakIntegrationTest; -import org.keycloak.test.framework.ui.page.WelcomePage; -import org.openqa.selenium.WebDriver; - -import java.util.List; - -@KeycloakIntegrationTest -public class WelcomePageTest { - - @InjectWebDriver - WebDriver driver; - - @InjectAdminClient - Keycloak adminClient; - - @Test - public void testCreateUser() { - final var welcomePage = new WelcomePage(driver); - welcomePage.navigateTo(); - welcomePage.fillRegistration("admin", "admin"); - welcomePage.submit(); - welcomePage.assertUserCreated(); - - List users = adminClient.realm("master").users().search("admin", true); - Assertions.assertEquals(1, users.size()); - - adminClient.realm("master").users().get(users.get(0).getId()).remove(); - } - -} diff --git a/test-framework/ui/src/main/java/org/keycloak/test/framework/ui/page/WelcomePage.java b/test-framework/ui/src/main/java/org/keycloak/test/framework/ui/page/WelcomePage.java index f8477ffdee..e503e1a1b3 100644 --- a/test-framework/ui/src/main/java/org/keycloak/test/framework/ui/page/WelcomePage.java +++ b/test-framework/ui/src/main/java/org/keycloak/test/framework/ui/page/WelcomePage.java @@ -1,6 +1,5 @@ package org.keycloak.test.framework.ui.page; -import org.junit.jupiter.api.Assertions; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; @@ -16,12 +15,18 @@ public class WelcomePage extends AbstractPage { @FindBy(id = "password-confirmation") private WebElement passwordConfirmationInput; - @FindBy(css = "[type=submit]") + @FindBy(xpath = "//button") private WebElement submitButton; @FindBy(css = ".pf-v5-c-alert") private WebElement pageAlert; + @FindBy(css = ".pf-v5-c-title") + private WebElement welcomeMessage; + + @FindBy(css = ".pf-v5-c-login__main-header-desc") + private WebElement welcomeDescription; + public WelcomePage(WebDriver driver) { super(driver); } @@ -40,8 +45,16 @@ public class WelcomePage extends AbstractPage { submitButton.click(); } - public void assertUserCreated() { - Assertions.assertTrue(pageAlert.getText().contains("User created")); + public String getWelcomeMessage() { + return welcomeMessage.getText(); + } + + public String getWelcomeDescription() { + return welcomeDescription.getText(); + } + + public String getPageAlert() { + return pageAlert.getText(); } } diff --git a/tests/base/src/test/java/org/keycloak/test/welcomepage/WelcomePageTest.java b/tests/base/src/test/java/org/keycloak/test/welcomepage/WelcomePageTest.java new file mode 100644 index 0000000000..9359423c83 --- /dev/null +++ b/tests/base/src/test/java/org/keycloak/test/welcomepage/WelcomePageTest.java @@ -0,0 +1,157 @@ +package org.keycloak.test.welcomepage; + +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.keycloak.admin.client.Keycloak; +import org.keycloak.common.util.KeycloakUriBuilder; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.test.framework.annotations.InjectAdminClient; +import org.keycloak.test.framework.annotations.KeycloakIntegrationTest; +import org.keycloak.test.framework.ui.annotations.InjectPage; +import org.keycloak.test.framework.ui.annotations.InjectWebDriver; +import org.keycloak.test.framework.ui.page.LoginPage; +import org.keycloak.test.framework.ui.page.WelcomePage; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.htmlunit.HtmlUnitDriver; +import org.openqa.selenium.support.ui.WebDriverWait; + +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; + +@KeycloakIntegrationTest +@TestMethodOrder(OrderAnnotation.class) +public class WelcomePageTest { + + @InjectWebDriver + WebDriver driver; + + @InjectAdminClient + Keycloak adminClient; + + @InjectPage + WelcomePage welcomePage; + + @InjectPage + LoginPage loginPage; + + @Test + @Order(1) + public void localAccessNoAdmin() { + welcomePage.navigateTo(); + + Assertions.assertEquals("Create a temporary administrative user", welcomePage.getWelcomeMessage()); + Assertions.assertTrue(welcomePage.getWelcomeDescription().startsWith("To get started with Keycloak, you first create a temporary administrative user")); + Assertions.assertTrue(driver.getPageSource().contains("form")); + } + + @Test + @Order(2) + public void remoteAccessNoAdmin() throws Exception { + driver.get(getPublicServerUrl().toString()); + + Assertions.assertEquals("Local access required", welcomePage.getWelcomeMessage()); + Assertions.assertTrue(welcomePage.getWelcomeDescription().startsWith("You will need local access to create the temporary administrative user.")); + Assertions.assertFalse(driver.getPageSource().contains("form")); + } + + @Test + @Order(3) + public void createAdminUser() { + welcomePage.navigateTo(); + welcomePage.fillRegistration("admin", "admin"); + welcomePage.submit(); + + Assertions.assertTrue(welcomePage.getPageAlert().contains("User created")); + + List users = adminClient.realm("master").users().search("admin", true); + Assertions.assertEquals(1, users.size()); + } + + @Test + @Order(4) + public void localAccessWithAdmin() { + welcomePage.navigateTo(); + + assertOnAdminConsole(); + } + + @Test + @Order(5) + public void remoteAccessWithAdmin() throws Exception { + driver.get(getPublicServerUrl().toString()); + + assertOnAdminConsole(); + } + + @Test + @Order(6) + public void accessCreatedAdminAccount() throws MalformedURLException { + welcomePage.navigateTo(); + + // 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()); + } + + loginPage.fillLogin("admin", "admin"); + loginPage.submit(); + + Assertions.assertEquals(driver.getTitle(), "Keycloak Administration Console"); + } + + /** + * Attempt to resolve the floating IP address. This is where Quarkus + * will be accessible. + * + * @return + * @throws Exception + */ + private String getFloatingIpAddress() throws Exception { + Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface ni : Collections.list(netInterfaces)) { + Enumeration inetAddresses = ni.getInetAddresses(); + for (InetAddress a : Collections.list(inetAddresses)) { + if (!a.isLoopbackAddress() && a.isSiteLocalAddress()) { + return a.getHostAddress(); + } + } + } + return null; + } + + private URL getPublicServerUrl() throws Exception { + String floatingIp = getFloatingIpAddress(); + if (floatingIp == null) { + throw new RuntimeException("Could not determine floating IP address."); + } + return new URL("http", floatingIp, 8080, ""); + } + + private void assertOnAdminConsole() { + 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"); + uriBuilder.queryParam("redirect_uri", "http://localhost:8080/admin/master/console/"); + uriBuilder.queryParam("state", "randomstate"); + uriBuilder.queryParam("response_mode", "query"); + uriBuilder.queryParam("response_type", "code"); + uriBuilder.queryParam("scope", "openid"); + uriBuilder.queryParam("nonce", "randomnonce"); + uriBuilder.queryParam("code_challenge", "UV90ZNinyGsxyNlz6A08FQzDXbA7NCjkrCZv7PgeVxA"); + uriBuilder.queryParam("code_challenge_method", "S256"); + return uriBuilder.build().toURL(); + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/welcomepage/WelcomePageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/welcomepage/WelcomePageTest.java deleted file mode 100644 index f689959e60..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/welcomepage/WelcomePageTest.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2017 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.testsuite.welcomepage; - -import org.hamcrest.Matchers; -import org.jboss.arquillian.drone.api.annotation.Drone; -import org.jboss.arquillian.graphene.page.Page; -import org.junit.After; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.testsuite.AbstractKeycloakTest; -import org.keycloak.testsuite.arquillian.annotation.RestartContainer; -import org.keycloak.testsuite.auth.page.WelcomePage; -import org.keycloak.testsuite.auth.page.login.OIDCLogin; -import org.keycloak.testsuite.util.DroneUtils; -import org.keycloak.testsuite.util.HtmlUnitBrowser; -import org.openqa.selenium.WebDriver; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.URL; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; - -import static org.keycloak.testsuite.util.URLUtils.navigateToUri; - -/** - * - */ -@SuppressWarnings("ArquillianDeploymentAbsent") -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@RestartContainer(initializeDatabase = true, intializeDatabaseWait = 0, withoutKeycloakAddUserFile = true) -public class WelcomePageTest extends AbstractKeycloakTest { - - @Drone - @HtmlUnitBrowser - private WebDriver htmlUnit; - - @Page - @HtmlUnitBrowser - protected OIDCLogin loginPage; - - @Page - @HtmlUnitBrowser - protected WelcomePage welcomePage; - - @Override - public void addTestRealms(List testRealms) { - // no operation - } - - /* - * Leave out client initialization and creation of a user account. We - * don't need those. - */ - @Before - @Override - public void beforeAbstractKeycloakTest() throws Exception { - Assume.assumeThat("Test skipped", - suiteContext.getAuthServerInfo().isJBossBased(), - Matchers.is(true)); - DroneUtils.replaceDefaultWebDriver(this, htmlUnit); - setDefaultPageUriParameters(); - } - - @After - @Override - public void afterAbstractKeycloakTest() { - // no need for this either - } - - /** - * Attempt to resolve the floating IP address. This is where EAP/WildFly - * will be accessible. See "-Djboss.bind.address=0.0.0.0". - * - * @return - * @throws Exception - */ - private String getFloatingIpAddress() throws Exception { - Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces(); - for (NetworkInterface ni : Collections.list(netInterfaces)) { - Enumeration inetAddresses = ni.getInetAddresses(); - for (InetAddress a : Collections.list(inetAddresses)) { - if (!a.isLoopbackAddress() && a.isSiteLocalAddress()) { - return a.getHostAddress(); - } - } - } - return null; - } - - private URL getPublicServerUrl() throws Exception { - String floatingIp = getFloatingIpAddress(); - if (floatingIp == null) { - throw new RuntimeException("Could not determine floating IP address."); - } - return new URL("http", floatingIp, welcomePage.getInjectedUrl().getPort(), ""); - } - - @Test - public void test_1_LocalAccessNoAdmin() throws Exception { - welcomePage.navigateTo(); - Assert.assertFalse("Welcome page did not ask to create a new admin user.", welcomePage.isPasswordSet()); - } - - @Test - public void test_2_RemoteAccessNoAdmin() throws Exception { - navigateToUri(getPublicServerUrl().toString()); - Assert.assertFalse("Welcome page did not ask to create a new admin user.", welcomePage.isPasswordSet()); - } - - @Test - public void test_3_LocalAccessWithAdmin() throws Exception { - welcomePage.navigateTo(); - welcomePage.setPassword("admin", "admin"); - Assert.assertTrue(driver.getPageSource().contains("User created")); - - welcomePage.navigateTo(); - Assert.assertTrue("Welcome page asked to set admin password.", welcomePage.isPasswordSet()); - } - - @Test - public void test_4_RemoteAccessWithAdmin() throws Exception { - navigateToUri(getPublicServerUrl().toString()); - Assert.assertTrue("Welcome page asked to set admin password.", welcomePage.isPasswordSet()); - } - - @Test - public void test_5_AccessCreatedAdminAccount() throws Exception { - welcomePage.navigateTo(); - welcomePage.navigateToAdminConsole(); - Assert.assertEquals("Keycloak Administration Console", htmlUnit.getTitle()); - } - - @Test - public void test_6_CheckProductNameOnWelcomePage() { - welcomePage.navigateTo(); - - String actualMessage = welcomePage.getWelcomeMessage(); - String expectedMessage = suiteContext.getAuthServerInfo().isEAP() ? "Red Hat Single Sign-On" : "Keycloak"; - - Assert.assertEquals("Welcome to " + expectedMessage, actualMessage); - } - -} diff --git a/testsuite/integration-arquillian/tests/base/testsuites/base-suite b/testsuite/integration-arquillian/tests/base/testsuites/base-suite index d842e047a7..1a5757ac02 100644 --- a/testsuite/integration-arquillian/tests/base/testsuites/base-suite +++ b/testsuite/integration-arquillian/tests/base/testsuites/base-suite @@ -46,5 +46,4 @@ util,4 validation,6 vault,4 webauthn,IGNORED -welcomepage,6 x509,4