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:
parent
d6b01015c4
commit
b3dd26a7c3
5 changed files with 174 additions and 209 deletions
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -46,5 +46,4 @@ util,4
|
||||||
validation,6
|
validation,6
|
||||||
vault,4
|
vault,4
|
||||||
webauthn,IGNORED
|
webauthn,IGNORED
|
||||||
welcomepage,6
|
|
||||||
x509,4
|
x509,4
|
||||||
|
|
Loading…
Reference in a new issue