Migrate WelcomeTestPage to testsuite framework (#34543)

* Migrate WelcomeTestPage to testsuite framework

Closes #34491

Signed-off-by: wojnarfilip <fwojnar@redhat.com>

* Refactor welcome page a bit

Signed-off-by: stianst <stianst@gmail.com>

* Fixes for htmlunit

Signed-off-by: stianst <stianst@gmail.com>

* Cleanup imports

Signed-off-by: stianst <stianst@gmail.com>

---------

Signed-off-by: wojnarfilip <fwojnar@redhat.com>
Signed-off-by: stianst <stianst@gmail.com>
Co-authored-by: wojnarfilip <fwojnar@redhat.com>
Co-authored-by: stianst <stianst@gmail.com>
This commit is contained in:
fwojnar 2024-11-05 10:57:58 +01:00 committed by GitHub
parent d6b01015c4
commit b3dd26a7c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 174 additions and 209 deletions

View file

@ -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<UserRepresentation> users = adminClient.realm("master").users().search("admin", true);
Assertions.assertEquals(1, users.size());
adminClient.realm("master").users().get(users.get(0).getId()).remove();
}
}

View file

@ -1,6 +1,5 @@
package org.keycloak.test.framework.ui.page; package org.keycloak.test.framework.ui.page;
import org.junit.jupiter.api.Assertions;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement; import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBy;
@ -16,12 +15,18 @@ public class WelcomePage extends AbstractPage {
@FindBy(id = "password-confirmation") @FindBy(id = "password-confirmation")
private WebElement passwordConfirmationInput; private WebElement passwordConfirmationInput;
@FindBy(css = "[type=submit]") @FindBy(xpath = "//button")
private WebElement submitButton; private WebElement submitButton;
@FindBy(css = ".pf-v5-c-alert") @FindBy(css = ".pf-v5-c-alert")
private WebElement pageAlert; 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) { public WelcomePage(WebDriver driver) {
super(driver); super(driver);
} }
@ -40,8 +45,16 @@ public class WelcomePage extends AbstractPage {
submitButton.click(); submitButton.click();
} }
public void assertUserCreated() { public String getWelcomeMessage() {
Assertions.assertTrue(pageAlert.getText().contains("User created")); return welcomeMessage.getText();
}
public String getWelcomeDescription() {
return welcomeDescription.getText();
}
public String getPageAlert() {
return pageAlert.getText();
} }
} }

View file

@ -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<UserRepresentation> 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<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface ni : Collections.list(netInterfaces)) {
Enumeration<InetAddress> 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();
}
}

View file

@ -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<RealmRepresentation> 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<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface ni : Collections.list(netInterfaces)) {
Enumeration<InetAddress> 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);
}
}

View file

@ -46,5 +46,4 @@ util,4
validation,6 validation,6
vault,4 vault,4
webauthn,IGNORED webauthn,IGNORED
welcomepage,6
x509,4 x509,4