diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d983d93ee25..9c6abfefc3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -379,6 +379,10 @@ jobs: echo "Tests: $TESTS" ./mvnw test ${{ env.SUREFIRE_RETRY }} -Pauth-server-quarkus "-Dwebdriver.chrome.driver=$CHROMEWEBDRIVER/chromedriver" -Dauth.server.feature.disable=persistent-user-sessions -Dtest=$TESTS -pl testsuite/integration-arquillian/tests/base 2>&1 | misc/log/trimmer.sh + - name: Run new base tests + run: | + ./mvnw package -f tests/pom.xml -Dtest=VolatileSessionsTestSuite + - uses: ./.github/actions/upload-flaky-tests name: Upload flaky tests env: @@ -394,7 +398,7 @@ jobs: timeout-minutes: 150 strategy: matrix: - variant: [ "clusterless,multi-site" ] + variant: [clusterless, multi-site] fail-fast: false steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -409,6 +413,11 @@ jobs: echo "Tests: $TESTS" ./mvnw test ${{ env.SUREFIRE_RETRY }} -Pauth-server-quarkus -Pinfinispan-server -Dauth.server.feature=${{ matrix.variant }} -Dauth.server.feature.disable=persistent-user-sessions -Dtest=$TESTS -pl testsuite/integration-arquillian/tests/base 2>&1 | misc/log/trimmer.sh + - name: Run new base tests without cache + run: | + CLASS_NAME=$(echo ${{ matrix.variant }} | sed 's/\([[:alpha:]]\)/\U\1/' | sed 's/-//')TestSuite + ./mvnw package -f tests/pom.xml -Dtest=$CLASS_NAME + - uses: ./.github/actions/upload-flaky-tests name: Upload flaky tests env: diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmConfigBuilder.java b/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmConfigBuilder.java index 5d06ccc44fd..9c1c6b24cf0 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmConfigBuilder.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmConfigBuilder.java @@ -226,6 +226,11 @@ public class RealmConfigBuilder { return this; } + public RealmConfigBuilder setRememberMe(boolean enabled) { + rep.setRememberMe(enabled); + return this; + } + /** * Best practice is to use other convenience methods when configuring a realm, but while the framework is under * active development there may not be a way to perform all updates required. In these cases this method allows diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java b/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java index db3037b412f..ae96b4e7e3f 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java @@ -211,11 +211,7 @@ public class KeycloakServerConfigBuilder { List args = new LinkedList<>(); args.add(command); for (Map.Entry e : options.entrySet()) { - if (e.getKey().startsWith("-D")) { - args.add(e.getKey() + "=" + e.getValue()); - } else { - args.add("--" + e.getKey() + "=" + e.getValue()); - } + args.add("--" + e.getKey() + "=" + e.getValue()); } if (!features.isEmpty()) { args.add("--features=" + String.join(",", features)); diff --git a/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/LoginPage.java b/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/LoginPage.java index 8bd0b2fcf70..77d3cd1f23b 100644 --- a/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/LoginPage.java +++ b/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/LoginPage.java @@ -1,7 +1,6 @@ package org.keycloak.testframework.ui.page; import org.openqa.selenium.By; -import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; @@ -17,6 +16,9 @@ public class LoginPage extends AbstractPage { @FindBy(css = "[type=submit]") private WebElement submitButton; + @FindBy(id = "rememberMe") + private WebElement rememberMe; + public LoginPage(WebDriver driver) { super(driver); } @@ -40,6 +42,17 @@ public class LoginPage extends AbstractPage { return driver.findElement(By.id(id)); } + public void rememberMe(boolean value) { + boolean selected = isRememberMe(); + if ((value && !selected) || !value && selected) { + rememberMe.click(); + } + } + + public boolean isRememberMe() { + return rememberMe.isSelected(); + } + @Override public String getExpectedPageId() { return "login-login"; diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/client/SessionTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/client/SessionTest.java new file mode 100644 index 00000000000..4124ec1c257 --- /dev/null +++ b/tests/base/src/test/java/org/keycloak/tests/admin/client/SessionTest.java @@ -0,0 +1,140 @@ +/* + * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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.tests.admin.client; + +import org.junit.jupiter.api.Test; +import org.keycloak.admin.client.resource.ClientResource; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.representations.idm.UserSessionRepresentation; +import org.keycloak.testframework.annotations.InjectRealm; +import org.keycloak.testframework.annotations.InjectUser; +import org.keycloak.testframework.annotations.KeycloakIntegrationTest; +import org.keycloak.testframework.oauth.OAuthClient; +import org.keycloak.testframework.oauth.annotations.InjectOAuthClient; +import org.keycloak.testframework.realm.ManagedRealm; +import org.keycloak.testframework.realm.ManagedUser; +import org.keycloak.testframework.realm.UserConfig; +import org.keycloak.testframework.realm.UserConfigBuilder; +import org.keycloak.testframework.ui.annotations.InjectPage; +import org.keycloak.testframework.ui.page.LoginPage; +import org.keycloak.tests.utils.admin.ApiUtil; +import org.keycloak.testsuite.util.AccountHelper; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +@KeycloakIntegrationTest +public class SessionTest { + + @InjectRealm + ManagedRealm managedRealm; + + @InjectUser(config = SessionTestUserConfig.class) + ManagedUser user; + + @InjectOAuthClient + OAuthClient oauth; + + @InjectPage + LoginPage loginPage; + + @Test + public void testGetAppSessionCount() { + ClientResource accountClient = ApiUtil.findClientByClientId(managedRealm.admin(), "test-app"); + int sessionCount = accountClient.getApplicationSessionCount().get("count"); + assertEquals(0, sessionCount); + + oauth.openLoginForm(); + loginPage.fillLogin(user.getUsername(), user.getPassword()); + loginPage.submit(); + + sessionCount = accountClient.getApplicationSessionCount().get("count"); + assertEquals(1, sessionCount); + + AccountHelper.logout(managedRealm.admin(), user.getUsername()); + + sessionCount = accountClient.getApplicationSessionCount().get("count"); + assertEquals(0, sessionCount); + } + + @Test + public void testGetUserSessions() { + ClientResource account = ApiUtil.findClientByClientId(managedRealm.admin(), "test-app"); + + oauth.openLoginForm(); + loginPage.fillLogin(user.getUsername(), user.getPassword()); + loginPage.submit(); + + List sessions = account.getUserSessions(0, 5); + assertEquals(1, sessions.size()); + + UserSessionRepresentation rep = sessions.get(0); + + UserRepresentation testUserRep = user.admin().toRepresentation(); + assertEquals(testUserRep.getId(), rep.getUserId()); + assertEquals(testUserRep.getUsername(), rep.getUsername()); + + String clientId = account.toRepresentation().getId(); + assertEquals("test-app", rep.getClients().get(clientId)); + assertNotNull(rep.getIpAddress()); + assertTrue(rep.getLastAccess() > 0); + assertTrue(rep.getStart() > 0); + assertFalse(rep.isRememberMe()); + + AccountHelper.logout(managedRealm.admin(), user.getUsername()); + } + + @Test + public void testGetUserSessionsWithRememberMe() { + managedRealm.updateWithCleanup(r -> r.setRememberMe(true)); + + oauth.openLoginForm(); + loginPage.rememberMe(true); + loginPage.fillLogin(user.getUsername(), user.getPassword()); + loginPage.submit(); + + ClientResource account = ApiUtil.findClientByClientId(managedRealm.admin(), "test-app"); + List sessions = account.getUserSessions(0, 5); + assertEquals(1, sessions.size()); + + UserSessionRepresentation rep = sessions.get(0); + assertTrue(rep.isRememberMe()); + + AccountHelper.logout(managedRealm.admin(), user.getUsername()); + } + + private static class SessionTestUserConfig implements UserConfig { + + @Override + public UserConfigBuilder configure(UserConfigBuilder config) { + return config.username("user") + .password("password") + .name("Session", "User") + .email("session@user.com") + .emailVerified(true); + } + } +} diff --git a/tests/base/src/test/java/org/keycloak/tests/suites/ClusterlessTestSuite.java b/tests/base/src/test/java/org/keycloak/tests/suites/ClusterlessTestSuite.java index 62c20a3f921..ddd91f6f8bf 100644 --- a/tests/base/src/test/java/org/keycloak/tests/suites/ClusterlessTestSuite.java +++ b/tests/base/src/test/java/org/keycloak/tests/suites/ClusterlessTestSuite.java @@ -8,10 +8,10 @@ import org.keycloak.common.Profile; import org.keycloak.testframework.injection.SuiteSupport; import org.keycloak.testframework.server.KeycloakServerConfig; import org.keycloak.testframework.server.KeycloakServerConfigBuilder; -import org.keycloak.tests.admin.ClientTest; +import org.keycloak.tests.admin.client.SessionTest; @Suite -@SelectClasses({ClientTest.class}) +@SelectClasses({SessionTest.class}) public class ClusterlessTestSuite { @BeforeSuite diff --git a/tests/base/src/test/java/org/keycloak/tests/suites/MultisiteTestSuite.java b/tests/base/src/test/java/org/keycloak/tests/suites/MultisiteTestSuite.java index 208f6eee25a..84f09054c1f 100644 --- a/tests/base/src/test/java/org/keycloak/tests/suites/MultisiteTestSuite.java +++ b/tests/base/src/test/java/org/keycloak/tests/suites/MultisiteTestSuite.java @@ -8,10 +8,10 @@ import org.keycloak.common.Profile; import org.keycloak.testframework.injection.SuiteSupport; import org.keycloak.testframework.server.KeycloakServerConfig; import org.keycloak.testframework.server.KeycloakServerConfigBuilder; -import org.keycloak.tests.admin.ClientTest; +import org.keycloak.tests.admin.client.SessionTest; @Suite -@SelectClasses({ClientTest.class}) +@SelectClasses({SessionTest.class}) public class MultisiteTestSuite { @BeforeSuite diff --git a/tests/base/src/test/java/org/keycloak/tests/suites/VolatileSessionsTestSuite.java b/tests/base/src/test/java/org/keycloak/tests/suites/VolatileSessionsTestSuite.java index 391247d9d99..b111fb5c89b 100644 --- a/tests/base/src/test/java/org/keycloak/tests/suites/VolatileSessionsTestSuite.java +++ b/tests/base/src/test/java/org/keycloak/tests/suites/VolatileSessionsTestSuite.java @@ -8,10 +8,10 @@ import org.keycloak.common.Profile; import org.keycloak.testframework.injection.SuiteSupport; import org.keycloak.testframework.server.KeycloakServerConfig; import org.keycloak.testframework.server.KeycloakServerConfigBuilder; -import org.keycloak.tests.admin.ClientTest; +import org.keycloak.tests.admin.client.SessionTest; @Suite -@SelectClasses(ClientTest.class) +@SelectClasses({SessionTest.class}) public class VolatileSessionsTestSuite { @BeforeSuite diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/SessionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/SessionTest.java deleted file mode 100644 index b8bf214054c..00000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/SessionTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @author tags. All rights reserved. - * - * 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.admin.client; - -import org.junit.Before; -import org.junit.Test; -import org.keycloak.admin.client.resource.ClientResource; -import org.keycloak.events.admin.OperationType; -import org.keycloak.events.admin.ResourceType; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.representations.idm.UserRepresentation; -import org.keycloak.representations.idm.UserSessionRepresentation; -import org.keycloak.testsuite.AbstractClientTest; -import org.keycloak.testsuite.util.AccountHelper; -import org.keycloak.testsuite.util.AdminEventPaths; - -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.keycloak.testsuite.auth.page.AuthRealm.TEST; - -/** - * - * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. - */ -public class SessionTest extends AbstractClientTest { - - @Before - public void init() { - // make user test user exists in test realm - createTestUserWithAdminClient(); - getCleanup().addUserId(testUser.getId()); - - assertAdminEvents.assertEvent(getRealmId(), OperationType.CREATE, AdminEventPaths.userResourcePath(testUser.getId()), ResourceType.USER); - assertAdminEvents.assertEvent(getRealmId(), OperationType.ACTION, AdminEventPaths.userResetPasswordPath(testUser.getId()), ResourceType.USER); - - createAppClientInRealm(testRealmResource().toRepresentation().getRealm()); - } - - @Override - public void setDefaultPageUriParameters() { - super.setDefaultPageUriParameters(); - loginPage.setAuthRealm(TEST); - } - - @Test - public void testGetAppSessionCount() { - ClientResource accountClient = findClientResourceById("test-app"); - int sessionCount = accountClient.getApplicationSessionCount().get("count"); - assertEquals(0, sessionCount); - - oauth.openLoginForm(); - loginPage.form().login(testUser); - - sessionCount = accountClient.getApplicationSessionCount().get("count"); - assertEquals(1, sessionCount); - - AccountHelper.logout(testRealmResource(), testUser.getUsername()); - - sessionCount = accountClient.getApplicationSessionCount().get("count"); - assertEquals(0, sessionCount); - } - - @Test - public void testGetUserSessions() { - //List> stats = this.testRealmResource().getClientSessionStats(); - ClientResource account = findClientResourceById("test-app"); - - oauth.openLoginForm(); - loginPage.form().login(testUser); - - List sessions = account.getUserSessions(0, 5); - assertEquals(1, sessions.size()); - - UserSessionRepresentation rep = sessions.get(0); - - UserRepresentation testUserRep = getFullUserRep(testUser.getUsername()); - assertEquals(testUserRep.getId(), rep.getUserId()); - assertEquals(testUserRep.getUsername(), rep.getUsername()); - - String clientId = account.toRepresentation().getId(); - assertEquals("test-app", rep.getClients().get(clientId)); - assertNotNull(rep.getIpAddress()); - assertNotNull(rep.getLastAccess()); - assertNotNull(rep.getStart()); - assertFalse(rep.isRememberMe()); - - AccountHelper.logout(testRealmResource(), testUser.getUsername()); - } - - @Test - public void testGetUserSessionsWithRememberMe() { - RealmRepresentation realm = adminClient.realm(TEST).toRepresentation(); - realm.setRememberMe(true); - adminClient.realm(TEST).update(realm); - - oauth.openLoginForm(); - loginPage.form().rememberMe(true); - loginPage.form().login(testUser); - - ClientResource account = findClientResourceById("test-app"); - List sessions = account.getUserSessions(0, 5); - assertEquals(1, sessions.size()); - - UserSessionRepresentation rep = sessions.get(0); - assertTrue(rep.isRememberMe()); - - AccountHelper.logout(testRealmResource(), testUser.getUsername()); - } -} diff --git a/testsuite/integration-arquillian/tests/base/testsuites/clusterless-suite b/testsuite/integration-arquillian/tests/base/testsuites/clusterless-suite index 9a0bfec7bcc..a727e210288 100644 --- a/testsuite/integration-arquillian/tests/base/testsuites/clusterless-suite +++ b/testsuite/integration-arquillian/tests/base/testsuites/clusterless-suite @@ -1,4 +1,3 @@ -SessionTest KcSamlBrokerSessionNotOnOrAfterTest OidcClaimToUserSessionNoteMapperTest KcOidcBrokerTransientSessionsTest diff --git a/testsuite/integration-arquillian/tests/base/testsuites/volatile-sessions-suite b/testsuite/integration-arquillian/tests/base/testsuites/volatile-sessions-suite index a46032a52bb..2e6f797ba55 100644 --- a/testsuite/integration-arquillian/tests/base/testsuites/volatile-sessions-suite +++ b/testsuite/integration-arquillian/tests/base/testsuites/volatile-sessions-suite @@ -1,4 +1,3 @@ -SessionTest KcSamlBrokerSessionNotOnOrAfterTest OidcClaimToUserSessionNoteMapperTest KcOidcBrokerTransientSessionsTest