Repository: keycloak/keycloak
Pull request #38025: Move AdminEventTest, LoginEventsTest to the new testsuite
Author: login: vaceksimon
Labels: name: team/cloud-native
name: team/core-clients
name: team/core-iam
name: area/test-framework
Created: 2025-03-11T16:20:43Z | Merged: 2025-03-17T11:38:58Z

Part of: https://github.com/keycloak/keycloak/issues/34494

Signed-off-by: Simon Vacek [simonvacky@email.cz](mailto:simonvacky@email.cz)


Diff:
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 3836c0415ed4..b44c0e5fa00a 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
@@ -4,7 +4,6 @@
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RolesRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.representations.userprofile.config.UPConfig;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -37,6 +36,11 @@ public RealmConfigBuilder name(String name) {
         return this;
     }
 
+    public RealmConfigBuilder displayName(String displayName) {
+        rep.setDisplayName(displayName);
+        return this;
+    }
+
     public ClientConfigBuilder addClient(String clientId) {
         if (rep.getClients() == null) {
             rep.setClients(new LinkedList<>());
@@ -156,6 +160,11 @@ public RealmConfigBuilder smtp(String host, int port, String from) {
         return this;
     }
 
+    public RealmConfigBuilder organizationsEnabled(boolean organizationsEnabled) {
+        rep.setOrganizationsEnabled(organizationsEnabled);
+        return this;
+    }
+
     public RealmConfigBuilder bruteForceProtected(boolean enabled) {
         rep.setBruteForceProtected(enabled);
         return this;
diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/event/AdminEventTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/event/AdminEventTest.java
new file mode 100644
index 000000000000..d61b02d73ff8
--- /dev/null
+++ b/tests/base/src/test/java/org/keycloak/tests/admin/event/AdminEventTest.java
@@ -0,0 +1,432 @@
+/*
+ * 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.event;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.admin.AdminEvent;
+import org.keycloak.events.admin.AuthDetails;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.events.admin.ResourceType;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.AdminEventRepresentation;
+import org.keycloak.representations.idm.AuthDetailsRepresentation;
+import org.keycloak.representations.idm.OrganizationDomainRepresentation;
+import org.keycloak.representations.idm.OrganizationRepresentation;
+import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testframework.annotations.InjectAdminClient;
+import org.keycloak.testframework.annotations.InjectRealm;
+import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
+import org.keycloak.testframework.events.AdminEventAssertion;
+import org.keycloak.testframework.realm.ManagedRealm;
+import org.keycloak.testframework.realm.RealmConfig;
+import org.keycloak.testframework.realm.RealmConfigBuilder;
+import org.keycloak.testframework.realm.UserConfigBuilder;
+import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
+import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
+import org.keycloak.tests.utils.admin.ApiUtil;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Test getting and filtering admin events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class AdminEventTest {
+
+    @InjectRealm(attachTo = "master", ref = "master")
+    ManagedRealm masterRealm;
+
+    @InjectRealm(config = AdminEventRealmConfig.class, ref = "default")
+    ManagedRealm managedRealm;
+
+    @InjectAdminClient(mode = InjectAdminClient.Mode.BOOTSTRAP)
+    Keycloak adminClient;
+
+    @InjectRunOnServer(realmRef = "default")
+    RunOnServerClient runOnServerClient;
+
+
+    @BeforeEach
+    public void initConfig() {
+        managedRealm.admin().clearAdminEvents();
+    }
+
+    private List<AdminEventRepresentation> events() {
+        return managedRealm.admin().getAdminEvents();
+    }
+
+    private String createUser(String username) {
+        UserRepresentation user = UserConfigBuilder.create()
+                .username(username)
+                .email(username + "@foo.com")
+                .name("foo", "bar")
+                .password("password")
+                .build();
+        String userUuid = ApiUtil.getCreatedId(managedRealm.admin().users().create(user));
+        managedRealm.cleanup().add(r -> r.users().get(userUuid).remove());
+        return userUuid;
+    }
+
+    @Test
+    public void clearAdminEventsTest() {
+        createUser("user0");
+        Assertions.assertEquals(1, events().size());
+        managedRealm.admin().clearAdminEvents();
+        Assertions.assertEquals(0, events().size());
+    }
+
+    @Test
+    public void adminEventAttributeTest() {
+        createUser("user5");
+        List<AdminEventRepresentation> events = events();
+        Assertions.assertEquals(1, events.size());
+
+        AdminEventRepresentation event = events.get(0);
+        AdminEventAssertion.assertSuccess(event).operationType(OperationType.CREATE);
+        Assertions.assertTrue(event.getTime() > 0L);
+        Assertions.assertEquals(managedRealm.getId(), event.getRealmId());
+        Assertions.assertNotNull(event.getResourcePath());
+
+        AuthDetailsRepresentation details = event.getAuthDetails();
+        Assertions.assertEquals(masterRealm.getId(), details.getRealmId());
+        Assertions.assertNotNull(details.getClientId());
+        Assertions.assertNotNull(details.getUserId());
+        Assertions.assertNotNull(details.getIpAddress());
+    }
+
+    @Test
+    public void testEventDetails() {
+        String userUuid = createUser("user5");
+        UserRepresentation userRep = managedRealm.admin().users().get(userUuid).toRepresentation();
+
+        managedRealm.updateWithCleanup(r -> r.organizationsEnabled(true));
+        OrganizationRepresentation orgRep = new OrganizationRepresentation();
+        orgRep.setName("test-org");
+        orgRep.setAlias(orgRep.getName());
+        orgRep.addDomain(new OrganizationDomainRepresentation(orgRep.getName()));
+        managedRealm.admin().organizations().create(orgRep).close();
+        orgRep = managedRealm.admin().organizations().list(-1, -1).get(0);
+        managedRealm.admin().organizations().get(orgRep.getId()).members().addMember(userUuid).close();
+        String orgId = orgRep.getId();
+        managedRealm.cleanup().add(r -> r.organizations().get(orgId).delete());
+
+        List<AdminEventRepresentation> events = events();
+        Assertions.assertEquals(4, events.size());
+
+        AdminEventRepresentation event = events.get(0);
+        AdminEventAssertion.assertSuccess(event)
+                .operationType(OperationType.CREATE)
+                .resourceType(ResourceType.ORGANIZATION_MEMBERSHIP);
+        Assertions.assertEquals(managedRealm.getId(), event.getRealmId());
+        assertThat(event.getDetails(), is(equalTo(Map.of(UserModel.USERNAME, userRep.getUsername(), UserModel.EMAIL, userRep.getEmail()))));
+    }
+
+    @Test
+    public void retrieveAdminEventTest() {
+        createUser("user1");
+        List<AdminEventRepresentation> events = events();
+
+        Assertions.assertEquals(1, events.size());
+        AdminEventRepresentation event = events().get(0);
+        AdminEventAssertion.assertSuccess(event).operationType(OperationType.CREATE);
+
+        Assertions.assertEquals(managedRealm.getId(), event.getRealmId());
+        Assertions.assertEquals(masterRealm.getId(), event.getAuthDetails().getRealmId());
+        Assertions.assertNull(event.getRepresentation());
+    }
+
+    @Test
+    public void testGetRepresentation() {
+        managedRealm.updateWithCleanup(r -> r.adminEventsDetailsEnabled(true));
+
+        createUser("user2");
+        AdminEventRepresentation event = events().stream()
+                .filter(adminEventRep -> adminEventRep.getOperationType().equals("CREATE"))
+                .findFirst()
+                .orElseThrow(() -> new IllegalStateException("Wasn't able to obtain CREATE admin event."));
+        Assertions.assertNotNull(event.getRepresentation());
+        assertThat(event.getRepresentation(), allOf(containsString("foo"), containsString("bar")));
+    }
+
+    @Test
+    public void testFilterAdminEvents() {
+        // two CREATE and one UPDATE
+        createUser("user3");
+        createUser("user4");
+        managedRealm.updateWithCleanup(r -> r.displayName("Fury Road"));
+        Assertions.assertEquals(3, events().size());
+
+        List<AdminEventRepresentation> events = managedRealm.admin().getAdminEvents(List.of("CREATE"), null, null, null, null, null, null, null, null, null);
+        Assertions.assertEquals(2, events.size());
+    }
+
+    @Test
+    public void defaultMaxResults() {
+        RealmResource realm = managedRealm.admin();
+        String realmId = managedRealm.getId();
+
+        runOnServerClient.run(session -> {
+            EventStoreProvider provider = session.getProvider(EventStoreProvider.class);
+
+            AdminEvent event = new AdminEvent();
+            event.setOperationType(OperationType.CREATE);
+            event.setAuthDetails(new AuthDetails());
+            event.setRealmId(realmId);
+
+            for (int i = 0; i < 110; i++) {
+                event.setId(UUID.randomUUID().toString());
+                provider.onEvent(event, false);
+            }
+        });
+
+        Assertions.assertEquals(100,
+                realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null).size());
+        Assertions.assertEquals(105,
+                realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 105).size());
+        Assertions.assertEquals(110,
+                realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 1000).size());
+    }
+
+    @Test
+    public void adminEventRepresentationLenght() {
+        RealmResource realm = managedRealm.admin();
+        String realmId = managedRealm.getId();
+        String longValue = RandomStringUtils.secure().next(30000, true, true);
+
+        runOnServerClient.run(session -> {
+            EventStoreProvider provider = session.getProvider(EventStoreProvider.class);
+
+            AdminEvent event = new AdminEvent();
+            event.setOperationType(OperationType.CREATE);
+            event.setAuthDetails(new AuthDetails());
+            event.setRealmId(realmId);
+            event.setRepresentation(longValue);
+
+            provider.onEvent(event, true);
+        });
+
+        List<AdminEventRepresentation> adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null);
+
+        Assertions.assertEquals(1, adminEvents.size());
+        Assertions.assertEquals(longValue, adminEvents.get(0).getRepresentation());
+    }
+
+    @Test
+    public void orderResultsTest() {
+        RealmResource realm = managedRealm.admin();
+        String realmId = managedRealm.getId();
+
+        runOnServerClient.run(session -> {
+            EventStoreProvider provider = session.getProvider(EventStoreProvider.class);
+
+            AdminEvent firstEvent = new AdminEvent();
+            firstEvent.setOperationType(OperationType.CREATE);
+            firstEvent.setAuthDetails(new AuthDetails());
+            firstEvent.setRealmId(realmId);
+            firstEvent.setTime(System.currentTimeMillis() - 1000);
+
+            AdminEvent secondEvent = new AdminEvent();
+            secondEvent.setOperationType(OperationType.DELETE);
+            secondEvent.setAuthDetails(new AuthDetails());
+            secondEvent.setRealmId(realmId);
+            secondEvent.setTime(System.currentTimeMillis());
+
+            provider.onEvent(firstEvent, false);
+            provider.onEvent(secondEvent, false);
+        });
+
+        List<AdminEventRepresentation> adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null, null, "desc");
+        Assertions.assertEquals(2, adminEvents.size());
+        Assertions.assertEquals(OperationType.DELETE.toString(), adminEvents.get(0).getOperationType());
+        Assertions.assertEquals(OperationType.CREATE.toString(), adminEvents.get(1).getOperationType());
+
+        adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null, null, "asc");
+        Assertions.assertEquals(2, adminEvents.size());
+        Assertions.assertEquals(OperationType.DELETE.toString(), adminEvents.get(1).getOperationType());
+        Assertions.assertEquals(OperationType.CREATE.toString(), adminEvents.get(0).getOperationType());
+    }
+
+    @Test
+    public void filterByEpochTimeStamp() {
+        RealmResource realm = managedRealm.admin();
+
+        String realmId = managedRealm.getId();
+        long currentTime = System.currentTimeMillis();
+
+        runOnServerClient.run(session -> {
+            EventStoreProvider provider = session.getProvider(EventStoreProvider.class);
+
+            AdminEvent event = new AdminEvent();
+            event.setOperationType(OperationType.CREATE);
+            event.setAuthDetails(new AuthDetails());
+            event.setRealmId(realmId);
+
+            event.setTime(currentTime - 1000);
+            provider.onEvent(event, false);
+            event.setTime(currentTime);
+            provider.onEvent(event, false);
+            event.setTime(currentTime + 1000);
+            provider.onEvent(event, false);
+        });
+
+        List<AdminEventRepresentation> events = realm.getAdminEvents(null, null, null, null, null, null, null, currentTime, currentTime, null, null, null);
+        Assertions.assertEquals(1, events.size());
+        events = realm.getAdminEvents(null, null, null, null, null, null, null, currentTime - 1000, currentTime + 1000, null, null, null);
+        Assertions.assertEquals(3, events.size());
+    }
+
+    private void checkUpdateRealmEventsConfigEvent(int size) {
+        List<AdminEventRepresentation> events = events();
+        Assertions.assertEquals(size, events.size());
+
+        AdminEventRepresentation event = events.get(0);
+        AdminEventAssertion.assertSuccess(event)
+                .operationType(OperationType.UPDATE)
+                .resourcePath("events", "config");
+
+        Assertions.assertEquals(managedRealm.getId(), event.getRealmId());
+        Assertions.assertEquals(masterRealm.getId(), event.getAuthDetails().getRealmId());
+        Assertions.assertNotNull(event.getRepresentation());
+    }
+
+    private RealmEventsConfigRepresentation updateEventsConfig(RealmEventsConfigRepresentation configRep) {
+        managedRealm.admin().updateRealmEventsConfig(configRep);
+        return managedRealm.admin().getRealmEventsConfig();
+    }
+
+    @Test
+    public void updateRealmEventsConfig() {
+        // change from OFF to ON should be stored
+        RealmEventsConfigRepresentation configRep = managedRealm.admin().getRealmEventsConfig();
+        configRep.setAdminEventsDetailsEnabled(true);
+        configRep.setAdminEventsEnabled(true);
+        configRep = updateEventsConfig(configRep);
+        checkUpdateRealmEventsConfigEvent(1);
+
+        // any other change should be stored too
+        configRep.setEventsEnabled(true);
+        configRep = updateEventsConfig(configRep);
+        checkUpdateRealmEventsConfigEvent(2);
+
+        // change from ON to OFF should be stored too
+        configRep.setAdminEventsEnabled(false);
+        configRep = updateEventsConfig(configRep);
+        checkUpdateRealmEventsConfigEvent(3);
+
+        // another change should not be stored cos it was OFF already
+        configRep.setAdminEventsDetailsEnabled(false);
+        configRep = updateEventsConfig(configRep);
+        assertThat(events().size(), is(equalTo(3)));
+
+        // clean up the realm
+        configRep.setAdminEventsEnabled(true);
+        updateEventsConfig(configRep);
+    }
+
+    @Test
+    public void createAndDeleteRealm() {
+        // Enable admin events on "master" realm, since realm create/delete events will be stored in realm of
+        // the authenticated user who executes the operations (admin in master realm),
+        RealmEventsConfigRepresentation masterConfig = masterRealm.admin().getRealmEventsConfig();
+        masterConfig.setAdminEventsDetailsEnabled(true);
+        masterConfig.setAdminEventsEnabled(true);
+        masterRealm.admin().updateRealmEventsConfig(masterConfig);
+        masterRealm.admin().clearAdminEvents();
+
+        // Create realm.
+        String testRealm = "test-realm";
+        RealmRepresentation realm = new RealmRepresentation();
+        realm.setId(testRealm);
+        realm.setRealm(testRealm);
+        adminClient.realms().create(realm);
+
+        // Delete realm.
+        adminClient.realm(realm.getRealm()).remove();
+
+        // Check that events were logged.
+        List<AdminEventRepresentation> events = masterRealm.admin().getAdminEvents();
+        Assertions.assertEquals(2, events.size());
+
+        AdminEventRepresentation createEvent = events.get(1);
+        AdminEventAssertion.assertSuccess(createEvent)
+                .operationType(OperationType.CREATE)
+                .resourceType(ResourceType.REALM)
+                .resourcePath(testRealm);
+        Assertions.assertEquals(masterRealm.getId(), createEvent.getRealmId());
+        Assertions.assertNotNull(createEvent.getRepresentation());
+
+        AdminEventRepresentation deleteEvent = events.get(0);
+        AdminEventAssertion.assertSuccess(deleteEvent)
+                .operationType(OperationType.DELETE)
+                .resourceType(ResourceType.REALM)
+                .resourcePath(testRealm);
+        Assertions.assertEquals(masterRealm.getId(), deleteEvent.getRealmId());
+    }
+
+    @Test
+    public void testStripOutUserSensitiveData() throws IOException {
+        managedRealm.updateWithCleanup(r -> {
+            r.adminEventsDetailsEnabled(true);
+            r.adminEventsEnabled(true);
+            return r;
+        });
+
+        UserResource user = managedRealm.admin().users().get(createUser("sensitive"));
+        List<AdminEventRepresentation> events = events();
+        UserRepresentation eventUserRep = JsonSerialization.readValue(events.get(0).getRepresentation(), UserRepresentation.class);
+        Assertions.assertNull(eventUserRep.getCredentials());
+
+        UserRepresentation userRep = user.toRepresentation();
+        userRep = UserConfigBuilder.update(userRep).password("password").build();
+        user.update(userRep);
+        events = events();
+        eventUserRep = JsonSerialization.readValue(events.get(0).getRepresentation(), UserRepresentation.class);
+        Assertions.assertNull(eventUserRep.getCredentials());
+    }
+
+    private static class AdminEventRealmConfig implements RealmConfig {
+
+        @Override
+        public RealmConfigBuilder configure(RealmConfigBuilder realm) {
+            return realm.eventsEnabled(true)
+                    .adminEventsEnabled(true)
+                    .adminEventsDetailsEnabled(false);
+        }
+    }
+}
diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/event/LoginEventsTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/event/LoginEventsTest.java
new file mode 100644
index 000000000000..d93890804009
--- /dev/null
+++ b/tests/base/src/test/java/org/keycloak/tests/admin/event/LoginEventsTest.java
@@ -0,0 +1,249 @@
+/*
+ * 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.event;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.EventType;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.testframework.annotations.InjectRealm;
+import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
+import org.keycloak.testframework.events.EventMatchers;
+import org.keycloak.testframework.oauth.OAuthClient;
+import org.keycloak.testframework.oauth.annotations.InjectOAuthClient;
+import org.keycloak.testframework.realm.ManagedRealm;
+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 java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * Test getting and filtering login-related events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class LoginEventsTest {
+
+    @InjectRealm(config = LoginEventsRealmConfig.class)
+    ManagedRealm managedRealm;
+
+    @InjectOAuthClient
+    OAuthClient oAuthClient;
+
+    @InjectRunOnServer
+    RunOnServerClient runOnServerClient;
+
+    @BeforeEach
+    public void init() {
+        managedRealm.admin().clearEvents();
+    }
+
+    private List<EventRepresentation> events() {
+        return managedRealm.admin().getEvents();
+    }
+
+    private void badLogin() {
+        oAuthClient.doLogin("bad", "user");
+    }
+
+    private void pause(int seconds) {
+        try {
+            Thread.sleep(seconds * 1000L);
+        } catch (InterruptedException e) {
+            Assertions.fail(e.getMessage());
+        }
+    }
+
+    @Test
+    public void eventAttributesTest() {
+        badLogin();
+        List<EventRepresentation> events = events();
+        Assertions.assertEquals(1, events.size());
+        EventRepresentation event = events.get(0);
+        assertThat(event.getId(), EventMatchers.isUUID());
+        Assertions.assertTrue(event.getTime() > 0);
+        Assertions.assertNotNull(event.getIpAddress());
+        Assertions.assertEquals("LOGIN_ERROR", event.getType());
+        Assertions.assertEquals(managedRealm.getId(), event.getRealmId());
+        Assertions.assertNull(event.getUserId()); // no user for bad login
+        Assertions.assertNull(event.getSessionId()); // no session for bad login
+        Assertions.assertEquals("user_not_found", event.getError());
+
+        Map<String, String> details = event.getDetails();
+        Assertions.assertEquals("openid-connect", details.get("auth_method"));
+        Assertions.assertEquals("code", details.get("auth_type"));
+        Assertions.assertNotNull(details.get("redirect_uri"));
+        Assertions.assertNotNull(details.get("code_id"));
+        Assertions.assertEquals("bad", details.get("username"));
+    }
+
+    @Test
+    public void clearEventsTest() {
+        Assertions.assertEquals(0, events().size());
+        badLogin();
+        badLogin();
+        Assertions.assertEquals(2, events().size());
+        managedRealm.admin().clearEvents();
+        Assertions.assertEquals(0, events().size());
+    }
+
+    @Test
+    public void loggingOfCertainTypeTest() {
+        Assertions.assertEquals(0, events().size());
+        managedRealm.updateWithCleanup(r -> r.enabledEventTypes("REVOKE_GRANT"));
+
+        badLogin();
+        Assertions.assertEquals(0, events().size());
+
+        managedRealm.updateWithCleanup(r -> r.overwriteEnabledEventTypes("LOGIN_ERROR"));
+
+        badLogin();
+        Assertions.assertEquals(1, events().size());
+    }
+
+    @Test
+    public void filterTest() {
+        badLogin();
+        badLogin();
+        Assertions.assertEquals(2, events().size());
+
+        List<EventRepresentation> filteredEvents = managedRealm.admin().getEvents(List.of("REVOKE_GRANT"), null, null, null, null, null, null, null);
+        Assertions.assertEquals(0, filteredEvents.size());
+
+        filteredEvents = managedRealm.admin().getEvents(List.of("LOGIN_ERROR"), null, null, null, null, null, null, null);
+        Assertions.assertEquals(2, filteredEvents.size());
+    }
+
+    @Test
+    public void defaultMaxResults() {
+        String realmId = managedRealm.getId();
+
+        runOnServerClient.run(session -> {
+            EventStoreProvider provider = session.getProvider(EventStoreProvider.class);
+            Event event = new Event();
+            event.setRealmId(realmId);
+            event.setType(EventType.LOGIN);
+
+            for (int i = 0; i < 110; i++) {
+                provider.onEvent(event);
+            }
+        });
+
+        Assertions.assertEquals(100, managedRealm.admin().getEvents(null, null, null, null, null, null, null, null).size());
+        Assertions.assertEquals(105, managedRealm.admin().getEvents(null, null, null, null, null, null, 0, 105).size());
+        Assertions.assertTrue(managedRealm.admin().getEvents(null, null, null, null, null, null, 0, 1000).size() >= 110);
+    }
+
+    @Test
+    public void orderResultsTest() {
+        String realmId = managedRealm.getId();
+
+        runOnServerClient.run(session -> {
+            EventStoreProvider provider = session.getProvider(EventStoreProvider.class);
+
+            Event firstEvent = new Event();
+            firstEvent.setRealmId(realmId);
+            firstEvent.setType(EventType.LOGIN);
+            firstEvent.setTime(System.currentTimeMillis() - 1000);
+
+            Event secondEvent = new Event();
+            secondEvent.setRealmId(realmId);
+            secondEvent.setType(EventType.LOGOUT);
+            secondEvent.setTime(System.currentTimeMillis());
+
+            provider.onEvent(firstEvent);
+            provider.onEvent(secondEvent);
+        });
+
+        List<EventRepresentation> events = managedRealm.admin().getEvents(null, null, null, null, null, null, null, null, "desc");
+        Assertions.assertEquals(2, events.size());
+        Assertions.assertEquals(EventType.LOGOUT.toString(), events.get(0).getType());
+        Assertions.assertEquals(EventType.LOGIN.toString(), events.get(1).getType());
+
+        events = managedRealm.admin().getEvents(null, null, null, null, null, null, null, null, "asc");
+        Assertions.assertEquals(2, events.size());
+        Assertions.assertEquals(EventType.LOGOUT.toString(), events.get(1).getType());
+        Assertions.assertEquals(EventType.LOGIN.toString(), events.get(0).getType());
+    }
+
+
+    @Test
+    public void filterByEpochTimeStamp() {
+        long currentTime = System.currentTimeMillis();
+        String realmId = managedRealm.getId();
+
+        runOnServerClient.run(session -> {
+            EventStoreProvider provider = session.getProvider(EventStoreProvider.class);
+            Event event = new Event();
+            event.setType(EventType.LOGIN);
+            event.setRealmId(realmId);
+
+            event.setTime(currentTime - 1000);
+            provider.onEvent(event);
+            event.setTime(currentTime);
+            provider.onEvent(event);
+            event.setTime(currentTime + 1000);
+            provider.onEvent(event);
+        });
+
+        List<EventRepresentation> events = managedRealm.admin().getEvents(null, null, null, currentTime, currentTime, null, null, null, null);
+        Assertions.assertEquals(1, events.size());
+        events = managedRealm.admin().getEvents(null, null, null, currentTime - 1000, currentTime + 1000, null, null, null, null);
+        Assertions.assertEquals(3, events.size());
+    }
+
+    @Test
+    public void testErrorEventsAreNotStoredWhenDisabled() {
+        managedRealm.updateWithCleanup(r -> r.eventsEnabled(false));
+
+        badLogin();
+        Assertions.assertEquals(0, events().size());
+    }
+
+
+    /*
+    Removed this test because it takes too long.  The default interval for
+    event cleanup is 15 minutes (900 seconds).  I don't have time to figure out
+    a way to set the cleanup thread to a lower interval for testing.
+    @Test
+    public void eventExpirationTest() {
+        configRep.setEventsExpiration(1L); //  second
+        saveConfig();
+        badLogin();
+        assertEquals(1, events().size());
+        pause(900); // pause 900 seconds
+        assertEquals(0, events().size());
+    }**/
+
+    private static class LoginEventsRealmConfig implements RealmConfig {
+
+        @Override
+        public RealmConfigBuilder configure(RealmConfigBuilder realm) {
+            return realm.eventsEnabled(true);
+        }
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AbstractEventTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AbstractEventTest.java
index 5166ed4db749..d3574c9506ce 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AbstractEventTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AbstractEventTest.java
@@ -54,13 +54,6 @@ protected void saveConfig() {
         configRep = testRsc.getRealmEventsConfig();
     }
 
-    protected void enableEvents() {
-        configRep.setEventsEnabled(true);
-        configRep.setAdminEventsEnabled(Boolean.TRUE);
-
-        saveConfig();
-    }
-
     protected String realmName() {
         return testRealmResource().toRepresentation().getId();
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java
deleted file mode 100644
index 26caed19d20d..000000000000
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java
+++ /dev/null
@@ -1,365 +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.event;
-
-import org.apache.commons.lang3.RandomStringUtils;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.keycloak.admin.client.resource.RealmResource;
-import org.keycloak.admin.client.resource.UserResource;
-import org.keycloak.events.admin.OperationType;
-import org.keycloak.events.admin.ResourceType;
-import org.keycloak.models.UserModel;
-import org.keycloak.representations.idm.AdminEventRepresentation;
-import org.keycloak.representations.idm.AuthDetailsRepresentation;
-import org.keycloak.representations.idm.OrganizationDomainRepresentation;
-import org.keycloak.representations.idm.OrganizationRepresentation;
-import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.testsuite.AssertEvents;
-import org.keycloak.testsuite.admin.ApiUtil;
-import org.keycloak.testsuite.util.UserBuilder;
-import org.keycloak.util.JsonSerialization;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.empty;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.greaterThanOrEqualTo;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-import static org.junit.Assert.assertNull;
-import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
-
-/**
- * Test getting and filtering admin events.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
- */
-public class AdminEventTest extends AbstractEventTest {
-
-    private String masterRealmId;
-
-    @Before
-    public void initConfig() {
-        enableEvents();
-        testRealmResource().clearAdminEvents();
-        this.masterRealmId = adminClient.realm(MASTER).toRepresentation().getId();
-    }
-
-    private List<AdminEventRepresentation> events() {
-        return testRealmResource().getAdminEvents();
-    }
-
-    private String createUser(String username) {
-        UserRepresentation user = createUserRepresentation(username, username + "@foo.com", "foo", "bar", true);
-        UserBuilder.edit(user).password("password");
-        String userId = ApiUtil.createUserWithAdminClient(testRealmResource(), user);
-        getCleanup().addUserId(userId);
-        return userId;
-    }
-
-    private void updateRealm() {
-        RealmRepresentation realm = testRealmResource().toRepresentation();
-        realm.setDisplayName("Fury Road");
-        testRealmResource().update(realm);
-    }
-
-    @Test
-    public void clearAdminEventsTest() {
-        createUser("user0");
-        assertThat(events().size(), is(equalTo(1)));
-        testRealmResource().clearAdminEvents();
-        assertThat(events(), is(empty()));
-    }
-
-    @Test
-    public void adminEventAttributeTest() {
-        createUser("user5");
-        List<AdminEventRepresentation> events = events();
-        assertThat(events().size(), is(equalTo(1)));
-
-        AdminEventRepresentation event = events.get(0);
-        assertThat(event.getTime(), is(greaterThan(0L)));
-        assertThat(event.getRealmId(), is(equalTo(realmName())));
-        assertThat(event.getOperationType(), is(equalTo("CREATE")));
-        assertThat(event.getResourcePath(), is(notNullValue()));
-        assertThat(event.getError(), is(nullValue()));
-
-        AuthDetailsRepresentation details = event.getAuthDetails();
-        assertThat(details.getRealmId(), is(equalTo(masterRealmId)));
-        assertThat(details.getClientId(), is(notNullValue()));
-        assertThat(details.getUserId(), is(notNullValue()));
-        assertThat(details.getIpAddress(), is(notNullValue()));
-    }
-
-    @Test
-    public void testEventDetails() {
-        String userId = createUser("user5");
-        UserRepresentation userRep = testRealmResource().users().get(userId).toRepresentation();
-        RealmRepresentation realmRep = testRealmResource().toRepresentation();
-        realmRep.setOrganizationsEnabled(true);
-        testRealmResource().update(realmRep);
-        OrganizationRepresentation orgRep = new OrganizationRepresentation();
-        orgRep.setName("test-org");
-        orgRep.setAlias(orgRep.getName());
-        orgRep.addDomain(new OrganizationDomainRepresentation(orgRep.getName()));
-        testRealmResource().organizations().create(orgRep).close();
-        orgRep = testRealmResource().organizations().list(-1, -1).get(0);
-        testRealmResource().organizations().get(orgRep.getId()).members().addMember(userId).close();
-        List<AdminEventRepresentation> events = events();
-        assertThat(events().size(), is(equalTo(4)));
-
-        AdminEventRepresentation event = events.get(0);
-        assertThat(event.getId(), AssertEvents.isUUID());
-        assertThat(event.getRealmId(), is(equalTo(realmName())));
-        assertThat(event.getOperationType(), is(equalTo("CREATE")));
-        assertThat(event.getResourceType(), is(equalTo(ResourceType.ORGANIZATION_MEMBERSHIP.name())));
-        assertThat(event.getDetails(), is(equalTo(Map.of(UserModel.USERNAME, userRep.getUsername(), UserModel.EMAIL, userRep.getEmail()))));
-    }
-
-    @Test
-    public void retrieveAdminEventTest() {
-        createUser("user1");
-        List<AdminEventRepresentation> events = events();
-
-        assertThat(events.size(), is(equalTo(1)));
-        AdminEventRepresentation event = events().get(0);
-        assertThat(event.getOperationType(), is(equalTo("CREATE")));
-
-        assertThat(event.getRealmId(), is(equalTo(realmName())));
-        assertThat(event.getAuthDetails().getRealmId(), is(equalTo(masterRealmId)));
-        assertThat(event.getRepresentation(), is(nullValue()));
-    }
-
-    @Test
-    public void testGetRepresentation() {
-        configRep.setAdminEventsDetailsEnabled(Boolean.TRUE);
-        saveConfig();
-
-        createUser("user2");
-        AdminEventRepresentation event = events().stream()
-                .filter(adminEventRep -> adminEventRep.getOperationType().equals("CREATE"))
-                .findFirst()
-                .orElseThrow(() -> new IllegalStateException("Wasn't able to obtain CREATE admin event."));
-        assertThat(event.getRepresentation(), is(notNullValue()));
-        assertThat(event.getRepresentation(), allOf(containsString("foo"), containsString("bar")));
-    }
-
-    @Test
-    public void testFilterAdminEvents() {
-        // two CREATE and one UPDATE
-        createUser("user3");
-        createUser("user4");
-        updateRealm();
-        assertThat(events().size(), is(equalTo(3)));
-
-        List<AdminEventRepresentation> events = testRealmResource().getAdminEvents(Arrays.asList("CREATE"), null, null, null, null, null, null, null, null, null);
-        assertThat(events.size(), is(equalTo(2)));
-    }
-
-    @Test
-    public void defaultMaxResults() {
-        RealmResource realm = adminClient.realms().realm("test");
-        AdminEventRepresentation event = new AdminEventRepresentation();
-        event.setOperationType(OperationType.CREATE.toString());
-        event.setAuthDetails(new AuthDetailsRepresentation());
-        event.setRealmId(realm.toRepresentation().getId());
-
-        for (int i = 0; i < 110; i++) {
-            testingClient.testing("test").onAdminEvent(event, false);
-        }
-
-        assertThat(realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null).size(), is(equalTo(100)));
-        assertThat(realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 105).size(), is(equalTo(105)));
-        assertThat(realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 1000).size(), is(greaterThanOrEqualTo(110)));
-    }
-
-    @Test
-    public void adminEventRepresentationLenght() {
-        RealmResource realm = adminClient.realms().realm("test");
-        AdminEventRepresentation event = new AdminEventRepresentation();
-        event.setOperationType(OperationType.CREATE.toString());
-        event.setAuthDetails(new AuthDetailsRepresentation());
-        event.setRealmId(realm.toRepresentation().getId());
-        String longValue = RandomStringUtils.random(30000, true, true);
-        event.setRepresentation(longValue);
-
-        testingClient.testing("test").onAdminEvent(event, true);
-        List<AdminEventRepresentation> adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null);
-
-        assertThat(adminEvents, hasSize(1));
-        assertThat(adminEvents.get(0).getRepresentation(), equalTo(longValue));
-    }
-
-    @Test
-    public void orderResultsTest() {
-        RealmResource realm = adminClient.realms().realm("test");
-        AdminEventRepresentation firstEvent = new AdminEventRepresentation();
-        firstEvent.setOperationType(OperationType.CREATE.toString());
-        firstEvent.setAuthDetails(new AuthDetailsRepresentation());
-        firstEvent.setRealmId(realm.toRepresentation().getId());
-        firstEvent.setTime(System.currentTimeMillis() - 1000);
-
-        AdminEventRepresentation secondEvent = new AdminEventRepresentation();
-        secondEvent.setOperationType(OperationType.DELETE.toString());
-        secondEvent.setAuthDetails(new AuthDetailsRepresentation());
-        secondEvent.setRealmId(realm.toRepresentation().getId());
-        secondEvent.setTime(System.currentTimeMillis());
-
-        testingClient.testing("test").onAdminEvent(firstEvent, false);
-        testingClient.testing("test").onAdminEvent(secondEvent, false);
-
-        List<AdminEventRepresentation> adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null, null, "desc");
-        assertThat(adminEvents.size(), is(equalTo(2)));
-        assertThat(adminEvents.get(0).getOperationType(), is(equalTo(OperationType.DELETE.toString())));
-        assertThat(adminEvents.get(1).getOperationType(), is(equalTo(OperationType.CREATE.toString())));
-
-        adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null, null, "asc");
-        assertThat(adminEvents.size(), is(equalTo(2)));
-        assertThat(adminEvents.get(1).getOperationType(), is(equalTo(OperationType.DELETE.toString())));
-        assertThat(adminEvents.get(0).getOperationType(), is(equalTo(OperationType.CREATE.toString())));
-    }
-
-    @Test
-    public void filterByEpochTimeStamp() {
-        RealmResource realm = adminClient.realms().realm("test");
-        AdminEventRepresentation event = new AdminEventRepresentation();
-        event.setOperationType(OperationType.CREATE.toString());
-        event.setAuthDetails(new AuthDetailsRepresentation());
-        event.setRealmId(realm.toRepresentation().getId());
-
-        long currentTime = System.currentTimeMillis();
-
-        event.setTime(currentTime - 1000);
-        testingClient.testing("test").onAdminEvent(event, false);
-        event.setTime(currentTime);
-        testingClient.testing("test").onAdminEvent(event, false);
-        event.setTime(currentTime + 1000);
-        testingClient.testing("test").onAdminEvent(event, false);
-
-        List<AdminEventRepresentation> events = realm.getAdminEvents(null, null, null, null, null, null, null, currentTime, currentTime, null, null, null);
-        Assert.assertEquals(1, events.size());
-        events = realm.getAdminEvents(null, null, null, null, null, null, null, currentTime - 1000, currentTime + 1000, null, null, null);
-        Assert.assertEquals(3, events.size());
-    }
-
-    private void checkUpdateRealmEventsConfigEvent(int size) {
-        List<AdminEventRepresentation> events = events();
-        assertThat(events.size(), is(equalTo(size)));
-
-        AdminEventRepresentation event = events().get(0);
-        assertThat(event.getOperationType(), is(equalTo("UPDATE")));
-        assertThat(event.getRealmId(), is(equalTo(realmName())));
-        assertThat(event.getResourcePath(), is(equalTo("events/config")));
-        assertThat(event.getAuthDetails().getRealmId(), is(equalTo(masterRealmId)));
-        assertThat(event.getRepresentation(), is(notNullValue()));
-    }
-
-    @Test
-    public void updateRealmEventsConfig() {
-        // change from OFF to ON should be stored
-        configRep.setAdminEventsDetailsEnabled(Boolean.TRUE);
-        configRep.setAdminEventsEnabled(Boolean.TRUE);
-        saveConfig();
-        checkUpdateRealmEventsConfigEvent(1);
-
-        // any other change should be store too
-        configRep.setEventsEnabled(Boolean.TRUE);
-        saveConfig();
-        checkUpdateRealmEventsConfigEvent(2);
-
-        // change from ON to OFF should be stored too
-        configRep.setAdminEventsEnabled(Boolean.FALSE);
-        saveConfig();
-        checkUpdateRealmEventsConfigEvent(3);
-
-        // another change should not be stored cos it was OFF already
-        configRep.setAdminEventsDetailsEnabled(Boolean.FALSE);
-        saveConfig();
-        assertThat(events().size(), is(equalTo(3)));
-    }
-
-    @Test
-    public void createAndDeleteRealm() {
-        // Enable admin events on "master" realm, since realm create/delete events will be stored in realm of
-        // the authenticated user who executes the operations (admin in master realm),
-        RealmResource master = adminClient.realm(MASTER);
-        RealmEventsConfigRepresentation masterConfig = master.getRealmEventsConfig();
-        masterConfig.setAdminEventsDetailsEnabled(true);
-        masterConfig.setAdminEventsEnabled(true);
-        master.updateRealmEventsConfig(masterConfig);
-        master.clearAdminEvents();
-
-        // Create realm.
-        RealmRepresentation realm = new RealmRepresentation();
-        realm.setId("test-realm");
-        realm.setRealm("test-realm");
-        importRealm(realm);
-
-        // Delete realm.
-        removeRealm("test-realm");
-
-        // Check that events were logged.
-        List<AdminEventRepresentation> events = master.getAdminEvents();
-        assertThat(events.size(), is(equalTo(2)));
-
-        AdminEventRepresentation createEvent = events.get(1);
-        assertThat(createEvent.getOperationType(), is(equalTo("CREATE")));
-        assertThat(createEvent.getRealmId(), is(equalTo(masterRealmId)));
-        assertThat(createEvent.getResourceType(), is(equalTo("REALM")));
-        assertThat(createEvent.getResourcePath(), is(equalTo("test-realm")));
-        assertThat(createEvent.getRepresentation(), is(notNullValue()));
-
-        AdminEventRepresentation deleteEvent = events.get(0);
-        assertThat(deleteEvent.getOperationType(), is(equalTo("DELETE")));
-        assertThat(deleteEvent.getRealmId(), is(equalTo(masterRealmId)));
-        assertThat(deleteEvent.getResourceType(), is(equalTo("REALM")));
-        assertThat(deleteEvent.getResourcePath(), is(equalTo("test-realm")));
-    }
-
-    @Test
-    public void testStripOutUserSensitiveData() throws IOException {
-        configRep.setAdminEventsDetailsEnabled(Boolean.TRUE);
-        configRep.setAdminEventsEnabled(Boolean.TRUE);
-        saveConfig();
-
-        UserResource user = testRealmResource().users().get(createUser("sensitive"));
-        List<AdminEventRepresentation> events = events();
-        UserRepresentation eventUserRep = JsonSerialization.readValue(events.get(0).getRepresentation(), UserRepresentation.class);
-        assertNull(eventUserRep.getCredentials());
-
-        UserRepresentation userRep = user.toRepresentation();
-        UserBuilder.edit(userRep).password("password");
-        user.update(userRep);
-        events = events();
-        eventUserRep = JsonSerialization.readValue(events.get(0).getRepresentation(), UserRepresentation.class);
-        assertNull(eventUserRep.getCredentials());
-    }
-}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java
deleted file mode 100644
index c17dc85aa096..000000000000
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java
+++ /dev/null
@@ -1,221 +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.event;
-
-import org.hamcrest.MatcherAssert;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.keycloak.admin.client.resource.RealmResource;
-import org.keycloak.events.EventType;
-import org.keycloak.representations.idm.EventRepresentation;
-import org.keycloak.testsuite.AssertEvents;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-/**
- * Test getting and filtering login-related events.
- *
- * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
- */
-public class LoginEventsTest extends AbstractEventTest {
-
-    @Before
-    public void init() {
-        configRep.setEventsEnabled(true);
-        saveConfig();
-        testRealmResource().clearEvents();
-        createAppClientInRealm(testRealmResource().toRepresentation().getRealm());
-    }
-
-    private List<EventRepresentation> events() {
-        return testRealmResource().getEvents();
-    }
-
-    private void badLogin() {
-        oauth.openLoginForm();
-        loginPage.form().login("bad", "user");
-    }
-
-    private void pause(int seconds) {
-        try {
-            Thread.sleep(seconds * 1000L);
-        } catch (InterruptedException e) {
-            fail(e.getMessage());
-        }
-    }
-
-    @Test
-    public void eventAttributesTest() {
-        badLogin();
-        List<EventRepresentation> events = events();
-        assertEquals(1, events.size());
-        EventRepresentation event = events.get(0);
-        MatcherAssert.assertThat(event.getId(), AssertEvents.isUUID());
-        assertTrue(event.getTime() > 0);
-        assertNotNull(event.getIpAddress());
-        assertEquals("LOGIN_ERROR", event.getType());
-        assertEquals(realmName(), event.getRealmId());
-        assertNull(event.getUserId()); // no user for bad login
-        assertNull(event.getSessionId()); // no session for bad login
-        assertEquals("user_not_found", event.getError());
-
-        Map<String, String> details = event.getDetails();
-        assertEquals("openid-connect", details.get("auth_method"));
-        assertEquals("code", details.get("auth_type"));
-        assertNotNull(details.get("redirect_uri"));
-        assertNotNull(details.get("code_id"));
-        assertEquals("bad", details.get("username"));
-    }
-
-    @Test
-    public void clearEventsTest() {
-        assertEquals(0, events().size());
-        badLogin();
-        badLogin();
-        assertEquals(2, events().size());
-        testRealmResource().clearEvents();
-        assertEquals(0, events().size());
-    }
-
-    @Test
-    public void loggingOfCertainTypeTest() {
-        assertEquals(0, events().size());
-        configRep.setEnabledEventTypes(Arrays.asList("REVOKE_GRANT"));
-        saveConfig();
-
-        badLogin();
-        assertEquals(0, events().size());
-
-        configRep.setEnabledEventTypes(Arrays.asList("LOGIN_ERROR"));
-        saveConfig();
-
-        badLogin();
-        assertEquals(1, events().size());
-    }
-
-    @Test
-    public void filterTest() {
-        badLogin();
-        badLogin();
-        assertEquals(2, events().size());
-
-        List<EventRepresentation> filteredEvents = testRealmResource().getEvents(Arrays.asList("REVOKE_GRANT"), null, null, null, null, null, null, null);
-        assertEquals(0, filteredEvents.size());
-
-        filteredEvents = testRealmResource().getEvents(Arrays.asList("LOGIN_ERROR"), null, null, null, null, null, null, null);
-        assertEquals(2, filteredEvents.size());
-    }
-
-    @Test
-    public void defaultMaxResults() {
-        RealmResource realm = adminClient.realms().realm("test");
-        EventRepresentation event = new EventRepresentation();
-        event.setRealmId(realm.toRepresentation().getId());
-        event.setType(EventType.LOGIN.toString());
-
-        for (int i = 0; i < 110; i++) {
-            testingClient.testing("test").onEvent(event);
-        }
-
-        assertEquals(100, realm.getEvents(null, null, null, null, null, null, null, null).size());
-        assertEquals(105, realm.getEvents(null, null, null, null, null, null, 0, 105).size());
-        assertTrue(realm.getEvents(null, null, null, null, null, null, 0, 1000).size() >= 110);
-    }
-
-    @Test
-    public void orderResultsTest() {
-        RealmResource realm = adminClient.realms().realm("test");
-        EventRepresentation firstEvent = new EventRepresentation();
-        firstEvent.setRealmId(realm.toRepresentation().getId());
-        firstEvent.setType(EventType.LOGIN.toString());
-        firstEvent.setTime(System.currentTimeMillis() - 1000);
-
-        EventRepresentation secondEvent = new EventRepresentation();
-        secondEvent.setRealmId(realm.toRepresentation().getId());
-        secondEvent.setType(EventType.LOGOUT.toString());
-        secondEvent.setTime(System.currentTimeMillis());
-
-        testingClient.testing("test").onEvent(firstEvent);
-        testingClient.testing("test").onEvent(secondEvent);
-
-        List<EventRepresentation> events = realm.getEvents(null, null, null, null, null, null, null, null, "desc");
-        assertEquals(2, events.size());
-        assertEquals(EventType.LOGOUT.toString(), events.get(0).getType());
-        assertEquals(EventType.LOGIN.toString(), events.get(1).getType());
-
-        events = realm.getEvents(null, null, null, null, null, null, null, null, "asc");
-        assertEquals(2, events.size());
-        assertEquals(EventType.LOGOUT.toString(), events.get(1).getType());
-        assertEquals(EventType.LOGIN.toString(), events.get(0).getType());
-    }
-
-
-    @Test
-    public void filterByEpochTimeStamp() {
-        RealmResource realm = adminClient.realms().realm("test");
-        EventRepresentation event = new EventRepresentation();
-        event.setType(EventType.LOGIN.toString());
-        event.setRealmId(realm.toRepresentation().getId());
-
-        long currentTime = System.currentTimeMillis();
-
-        event.setTime(currentTime - 1000);
-        testingClient.testing("test").onEvent(event);
-        event.setTime(currentTime);
-        testingClient.testing("test").onEvent(event);
-        event.setTime(currentTime + 1000);
-        testingClient.testing("test").onEvent(event);
-
-        List<EventRepresentation> events = realm.getEvents(null, null, null, currentTime, currentTime, null, null, null, null);
-        Assert.assertEquals(1, events.size());
-        events = realm.getEvents(null, null, null, currentTime - 1000, currentTime + 1000, null, null, null, null);
-        Assert.assertEquals(3, events.size());
-    }
-
-    @Test
-    public void testErrorEventsAreNotStoredWhenDisabled() {
-        configRep.setEventsEnabled(false);
-        saveConfig();
-
-        badLogin();
-        assertEquals(0, events().size());
-    }
-
-    /*
-    Removed this test because it takes too long.  The default interval for
-    event cleanup is 15 minutes (900 seconds).  I don't have time to figure out
-    a way to set the cleanup thread to a lower interval for testing.
-    @Test
-    public void eventExpirationTest() {
-        configRep.setEventsExpiration(1L); //  second
-        saveConfig();
-        badLogin();
-        assertEquals(1, events().size());
-        pause(900); // pause 900 seconds
-        assertEquals(0, events().size());
-    }**/
-}


Reviews:
user: login: lhanusov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:08:59Z
user: login: lhanusov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:11:23Z
user: login: lhanusov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:18:09Z
user: login: stianst
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T12:58:23Z
user: login: lhanusov
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T07:49:09Z
user: login: lhanusov
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T07:51:18Z
user: login: lhanusov
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T07:55:15Z
user: login: stianst
body: For AdminEventAssertion I propose something like the following to verify the event ID is a UUID:
https://github.com/keycloak/keycloak/pull/38103

Then use the same pattern to verify LoginEvent#id is a UUID.

At some point we should add `EventAssertion` (following the pattern from `AdminEventAssertion`) to replace `AssertEvents` in the old testsuite, but since `LoginTest` doesn't use `AssertEvents` we don't need that now.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T09:12:18Z
user: login: lhanusov
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T16:46:47Z
user: login: stianst
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T11:38:48Z

Review comments:
diff_hunk: @@ -0,0 +1,255 @@
+/*
+ * 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.event;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.EventType;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.testframework.annotations.InjectRealm;
+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.RealmConfig;
+import org.keycloak.testframework.realm.RealmConfigBuilder;
+import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
+import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Test getting and filtering login-related events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class LoginEventsTest {
+
+    @InjectRealm(config = LoginEventsRealmConfig.class)
+    ManagedRealm managedRealm;
+
+    @InjectOAuthClient
+    OAuthClient oAuthClient;
+
+    @InjectRunOnServer
+    RunOnServerClient runOnServerClient;
+
+    @BeforeEach
+    public void init() {
+        managedRealm.admin().clearEvents();
+    }
+
+    private List<EventRepresentation> events() {
+        return managedRealm.admin().getEvents();
path: tests/base/src/test/java/org/keycloak/tests/admin/event/LoginEventsTest.java
user: login: lhanusov
body: @vaceksimon Don't you want to use @InjectEvents instead?
created_at: 2025-03-12T10:08:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,255 @@
+/*
+ * 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.event;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.EventType;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.testframework.annotations.InjectRealm;
+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.RealmConfig;
+import org.keycloak.testframework.realm.RealmConfigBuilder;
+import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
+import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Test getting and filtering login-related events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class LoginEventsTest {
+
+    @InjectRealm(config = LoginEventsRealmConfig.class)
+    ManagedRealm managedRealm;
+
+    @InjectOAuthClient
+    OAuthClient oAuthClient;
+
+    @InjectRunOnServer
+    RunOnServerClient runOnServerClient;
+
+    @BeforeEach
+    public void init() {
+        managedRealm.admin().clearEvents();
+    }
+
+    private List<EventRepresentation> events() {
+        return managedRealm.admin().getEvents();
path: tests/base/src/test/java/org/keycloak/tests/admin/event/LoginEventsTest.java
user: login: lhanusov
body: Discussed with Simon personally, no need to change anything -> testing Event API.
created_at: 2025-03-12T10:11:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,433 @@
+/*
+ * 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.event;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.admin.AdminEvent;
+import org.keycloak.events.admin.AuthDetails;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.events.admin.ResourceType;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.AdminEventRepresentation;
+import org.keycloak.representations.idm.AuthDetailsRepresentation;
+import org.keycloak.representations.idm.OrganizationDomainRepresentation;
+import org.keycloak.representations.idm.OrganizationRepresentation;
+import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testframework.annotations.InjectAdminClient;
+import org.keycloak.testframework.annotations.InjectRealm;
+import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
+import org.keycloak.testframework.events.AdminEventAssertion;
+import org.keycloak.testframework.realm.ManagedRealm;
+import org.keycloak.testframework.realm.RealmConfig;
+import org.keycloak.testframework.realm.RealmConfigBuilder;
+import org.keycloak.testframework.realm.UserConfigBuilder;
+import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
+import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
+import org.keycloak.tests.utils.admin.ApiUtil;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Test getting and filtering admin events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class AdminEventTest {
+
+    @InjectRealm(attachTo = "master", ref = "master")
+    ManagedRealm masterRealm;
+
+    @InjectRealm(config = AdminEventRealmConfig.class, ref = "default")
+    ManagedRealm managedRealm;
+
+    @InjectAdminClient(mode = InjectAdminClient.Mode.BOOTSTRAP)
+    Keycloak adminClient;
+
+    @InjectRunOnServer(realmRef = "default")
+    RunOnServerClient runOnServerClient;
+
+
+    @BeforeEach
+    public void initConfig() {
+        managedRealm.admin().clearAdminEvents();
+    }
+
+    private List<AdminEventRepresentation> events() {
+        return managedRealm.admin().getAdminEvents();
+    }
+
+    private String createUser(String username) {
+        UserRepresentation user = UserConfigBuilder.create()
path: tests/base/src/test/java/org/keycloak/tests/admin/event/AdminEventTest.java
user: login: lhanusov
body: @vaceksimon @stianst @miquelsi  Don't we want to introduce a util class instead, not mixing test util classes and framework helper classes? To avoid boiler plating we can create UserConfigBuilderUtil class (placed in the utils module) which will extend UserConfigBuilder class? WDYT?
created_at: 2025-03-12T10:17:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,433 @@
+/*
+ * 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.event;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.admin.AdminEvent;
+import org.keycloak.events.admin.AuthDetails;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.events.admin.ResourceType;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.AdminEventRepresentation;
+import org.keycloak.representations.idm.AuthDetailsRepresentation;
+import org.keycloak.representations.idm.OrganizationDomainRepresentation;
+import org.keycloak.representations.idm.OrganizationRepresentation;
+import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testframework.annotations.InjectAdminClient;
+import org.keycloak.testframework.annotations.InjectRealm;
+import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
+import org.keycloak.testframework.events.AdminEventAssertion;
+import org.keycloak.testframework.realm.ManagedRealm;
+import org.keycloak.testframework.realm.RealmConfig;
+import org.keycloak.testframework.realm.RealmConfigBuilder;
+import org.keycloak.testframework.realm.UserConfigBuilder;
+import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
+import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
+import org.keycloak.tests.utils.admin.ApiUtil;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Test getting and filtering admin events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class AdminEventTest {
+
+    @InjectRealm(attachTo = "master", ref = "master")
+    ManagedRealm masterRealm;
+
+    @InjectRealm(config = AdminEventRealmConfig.class, ref = "default")
+    ManagedRealm managedRealm;
+
+    @InjectAdminClient(mode = InjectAdminClient.Mode.BOOTSTRAP)
+    Keycloak adminClient;
+
+    @InjectRunOnServer(realmRef = "default")
+    RunOnServerClient runOnServerClient;
+
+
+    @BeforeEach
+    public void initConfig() {
+        managedRealm.admin().clearAdminEvents();
+    }
+
+    private List<AdminEventRepresentation> events() {
+        return managedRealm.admin().getAdminEvents();
+    }
+
+    private String createUser(String username) {
+        UserRepresentation user = UserConfigBuilder.create()
path: tests/base/src/test/java/org/keycloak/tests/admin/event/AdminEventTest.java
user: login: stianst
body: This is probably quite a common pattern that you need to create for example a user, and obtain the returned UUID. Could be something part of the core framework I'd say. Not quite sure how (could be ManagedRealm#createUser), but create an issue for it and we can discuss it as a follow-up.

Then again this may just be a bit specific to admin package testing; and not a general thing as usually you'd just do a ManagedRealm and a ManagedUser as part of the test class; and not create tests within the test itself. So, maybe it's not worth considering and just leave it as is here.
created_at: 2025-03-13T12:58:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,255 @@
+/*
+ * 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.event;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.events.Event;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.EventType;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.testframework.annotations.InjectRealm;
+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.RealmConfig;
+import org.keycloak.testframework.realm.RealmConfigBuilder;
+import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
+import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Test getting and filtering login-related events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class LoginEventsTest {
+
+    @InjectRealm(config = LoginEventsRealmConfig.class)
+    ManagedRealm managedRealm;
+
+    @InjectOAuthClient
+    OAuthClient oAuthClient;
+
+    @InjectRunOnServer
+    RunOnServerClient runOnServerClient;
+
+    @BeforeEach
+    public void init() {
+        managedRealm.admin().clearEvents();
+    }
+
+    private List<EventRepresentation> events() {
+        return managedRealm.admin().getEvents();
+    }
+
+    private void badLogin() {
+        oAuthClient.doLogin("bad", "user");
+    }
+
+    private void pause(int seconds) {
+        try {
+            Thread.sleep(seconds * 1000L);
+        } catch (InterruptedException e) {
+            Assertions.fail(e.getMessage());
+        }
+    }
+
+    // todo Where should the isUUID function be?
+
+    /**
+     * @see org.keycloak.testsuite.AssertEvents#isUUID()
+     */
path: tests/base/src/test/java/org/keycloak/tests/admin/event/LoginEventsTest.java
user: login: lhanusov
body: ```suggestion
```
created_at: 2025-03-14T07:51:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,433 @@
+/*
+ * 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.event;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.events.EventStoreProvider;
+import org.keycloak.events.admin.AdminEvent;
+import org.keycloak.events.admin.AuthDetails;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.events.admin.ResourceType;
+import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.AdminEventRepresentation;
+import org.keycloak.representations.idm.AuthDetailsRepresentation;
+import org.keycloak.representations.idm.OrganizationDomainRepresentation;
+import org.keycloak.representations.idm.OrganizationRepresentation;
+import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testframework.annotations.InjectAdminClient;
+import org.keycloak.testframework.annotations.InjectRealm;
+import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
+import org.keycloak.testframework.events.AdminEventAssertion;
+import org.keycloak.testframework.realm.ManagedRealm;
+import org.keycloak.testframework.realm.RealmConfig;
+import org.keycloak.testframework.realm.RealmConfigBuilder;
+import org.keycloak.testframework.realm.UserConfigBuilder;
+import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
+import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
+import org.keycloak.tests.utils.admin.ApiUtil;
+import org.keycloak.util.JsonSerialization;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Test getting and filtering admin events.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+@KeycloakIntegrationTest
+public class AdminEventTest {
+
+    @InjectRealm(attachTo = "master", ref = "master")
+    ManagedRealm masterRealm;
+
+    @InjectRealm(config = AdminEventRealmConfig.class, ref = "default")
+    ManagedRealm managedRealm;
+
+    @InjectAdminClient(mode = InjectAdminClient.Mode.BOOTSTRAP)
+    Keycloak adminClient;
+
+    @InjectRunOnServer(realmRef = "default")
+    RunOnServerClient runOnServerClient;
+
+
+    @BeforeEach
+    public void initConfig() {
+        managedRealm.admin().clearAdminEvents();
+    }
+
+    private List<AdminEventRepresentation> events() {
+        return managedRealm.admin().getAdminEvents();
+    }
+
+    private String createUser(String username) {
+        UserRepresentation user = UserConfigBuilder.create()
path: tests/base/src/test/java/org/keycloak/tests/admin/event/AdminEventTest.java
user: login: lhanusov
body: I agree, let's leave it as it is :+1: 
created_at: 2025-03-14T07:55:15Z
author_association: CONTRIBUTOR

PR comments:
user: login: vaceksimon
created_at: 2025-03-11T16:28:47Z
body: One problem I encountered was checking an event ID with the `isUUID` matcher, which is in the [`AssertEvents` class of the old test suite](https://github.com/keycloak/keycloak/blob/main/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AssertEvents.java#L462-L474). I added a similar method to the `AdminEventAssertion` and a temporary thing in the `LoginEventsTest` to open it for discussion. 

Currently, we only have `AdminEventAssertion` but no equivalent for regular Events. Do you think it would be worth it to have something similar @stianst? 
author_association: CONTRIBUTOR
user: login: vaceksimon
created_at: 2025-03-12T09:51:02Z
body: Also, what are your thoughts on using the `*ConfigBuilder` classes in tests to get/update a `*Representation`? For example, the way I used `UserConfigBuilder` to create and update `UserRepresentation` in `AdminEventTest`
author_association: CONTRIBUTOR