keycloak-uncached

Changes

testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java 800(+0 -800)

testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/ChangePasswordTest.java 87(+0 -87)

testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/RegistrationTest.java 134(+0 -134)

testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/RememberMeTest.java 70(+0 -70)

testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/ResetCredentialsTest.java 102(+0 -102)

testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/VerifyEmailTest.java 87(+0 -87)

Details

diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountUpdateProfilePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountUpdateProfilePage.java
index 833acc0..2159c2f 100755
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountUpdateProfilePage.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountUpdateProfilePage.java
@@ -56,7 +56,7 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
     @FindBy(className = "alert-error")
     private WebElement errorMessage;
 
-    private String getPath() {
+    public String getPath() {
         return RealmsResource.accountUrl(UriBuilder.fromUri(getAuthServerRoot())).build("test").toString();
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
old mode 100644
new mode 100755
index 2005d81..a4f7257
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -16,64 +16,656 @@
  */
 package org.keycloak.testsuite.account;
 
-import org.jboss.arquillian.graphene.page.Page;
-import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventType;
+import org.keycloak.models.utils.TimeBasedOTP;
+import org.keycloak.services.resources.AccountService;
+import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.pages.AccountApplicationsPage;
+import org.keycloak.testsuite.pages.AccountLogPage;
+import org.keycloak.testsuite.pages.AccountPasswordPage;
+import org.keycloak.testsuite.pages.AccountSessionsPage;
+import org.keycloak.testsuite.pages.AccountTotpPage;
+import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.AppPage.RequestType;
+import org.keycloak.testsuite.pages.ErrorPage;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.RegisterPage;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
 
-import static org.junit.Assert.assertEquals;
-import org.junit.Before;
-import org.keycloak.testsuite.auth.page.account.Account;
+import javax.ws.rs.core.UriBuilder;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.arquillian.graphene.page.Page;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testsuite.TestRealmKeycloakTest;
+import org.keycloak.testsuite.admin.ApiUtil;
+import org.keycloak.testsuite.drone.Different;
+import org.keycloak.testsuite.util.OAuthClient;
+import org.keycloak.testsuite.util.RealmBuilder;
+import org.keycloak.testsuite.util.UserBuilder;
 
 /**
- *
- * @author Petr Mensik
- * @author tkyjovsk
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
  */
-public class AccountTest extends AbstractAccountManagementTest {
+public class AccountTest extends TestRealmKeycloakTest {
+
+    @Override
+    public void configureTestRealm(RealmRepresentation testRealm) {
+        //UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost");
+        //ClientRepresentation accountApp = findClientInRealmRep(testRealm, ACCOUNT_MANAGEMENT_CLIENT_ID);
+        UserRepresentation user2 = UserBuilder.create()
+                                              .enabled(true)
+                                              .username("test-user-no-access@localhost")
+                                              .email("test-user-no-access@localhost")
+                                              .password("password")
+                                              .build();
 
-    private static final String UPDATED_EMAIL = "new-name@email.test";
-    private static final String NEW_FIRST_NAME = "John";
-    private static final String NEW_LAST_NAME = "Smith";
+        RealmBuilder.edit(testRealm)
+                    .user(user2);
+    }
+
+    private static final UriBuilder BASE = UriBuilder.fromUri("http://localhost:8180/auth");
+    private static final String ACCOUNT_URL = RealmsResource.accountUrl(BASE.clone()).build("test").toString();
+    public static String ACCOUNT_REDIRECT = AccountService.loginRedirectUrl(BASE.clone()).build("test").toString();
+
+    // Create second session
+    @Drone
+    @Different
+    WebDriver driver2;
+
+    @Rule
+    public AssertEvents events = new AssertEvents(this);
 
     @Page
-    private Account testRealmAccountPage;
+    protected AppPage appPage;
+
+    @Page
+    protected LoginPage loginPage;
+
+    @Page
+    protected RegisterPage registerPage;
+
+    @Page
+    protected AccountPasswordPage changePasswordPage;
+
+    @Page
+    protected AccountUpdateProfilePage profilePage;
+
+    @Page
+    protected AccountTotpPage totpPage;
+
+    @Page
+    protected AccountLogPage logPage;
+
+    @Page
+    protected AccountSessionsPage sessionsPage;
+
+    @Page
+    protected AccountApplicationsPage applicationsPage;
+
+    @Page
+    protected ErrorPage errorPage;
+
+    private TimeBasedOTP totp = new TimeBasedOTP();
+    private String userId;
 
-    @Override
-    public void setDefaultPageUriParameters() {
-        super.setDefaultPageUriParameters();
-        testRealmAccountPage.setAuthRealm(testRealmPage);
-    }
-    
     @Before
-    public void beforeAccountTest() {
-        testRealmAccountManagementPage.navigateTo();
-        testRealmLoginPage.form().login(testUser);
-    }
-
-    @After
-    public void afterAccountTest() {
-        testRealmAccountManagementPage.navigateTo();
-        testRealmAccountManagementPage.signOut();
-    }
-
-    @Test
-    public void editAccount() {
-        testRealmAccountManagementPage.account();
-        assertEquals(testRealmAccountPage.getUsername(), testUser.getUsername());
-        
-        testRealmAccountPage.setEmail(UPDATED_EMAIL);
-        testRealmAccountPage.setFirstName(NEW_FIRST_NAME);
-        testRealmAccountPage.setLastName(NEW_LAST_NAME);
-        testRealmAccountPage.save();
-        assertAlertSuccess();
-
-        testRealmAccountManagementPage.signOut();
-        testRealmLoginPage.form().login(testUser);
-        
-        testRealmAccountManagementPage.account();
-        assertEquals(testRealmAccountPage.getEmail(), UPDATED_EMAIL);
-        assertEquals(testRealmAccountPage.getFirstName(), NEW_FIRST_NAME);
-        assertEquals(testRealmAccountPage.getLastName(), NEW_LAST_NAME);
+    public void before() {
+        oauth.state("mystate"); // keycloak enforces that a state param has been sent by client
+        userId = findUser("test-user@localhost").getId();
+    }
+
+    @Test
+    public void returnToAppFromQueryParam() {
+        driver.navigate().to(profilePage.getPath() + "?referrer=test-app");
+        loginPage.login("test-user@localhost", "password");
+        Assert.assertTrue(profilePage.isCurrent());
+        profilePage.backToApplication();
+
+        Assert.assertTrue(appPage.isCurrent());
+
+        driver.navigate().to(profilePage.getPath() + "?referrer=test-app&referrer_uri=http://localhost:8180/auth/realms/master/app/auth?test");
+        Assert.assertTrue(profilePage.isCurrent());
+        profilePage.backToApplication();
+
+        Assert.assertTrue(appPage.isCurrent());
+        Assert.assertEquals(appPage.baseUrl + "?test", driver.getCurrentUrl());
+
+        driver.navigate().to(profilePage.getPath() + "?referrer=test-app");
+        Assert.assertTrue(profilePage.isCurrent());
+
+        driver.findElement(By.linkText("Authenticator")).click();
+        Assert.assertTrue(totpPage.isCurrent());
+
+        driver.findElement(By.linkText("Account")).click();
+        Assert.assertTrue(profilePage.isCurrent());
+
+        profilePage.backToApplication();
+
+        Assert.assertTrue(appPage.isCurrent());
+
+        events.clear();
+    }
+
+    @Test
+    public void changePassword() {
+        changePasswordPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        EventRepresentation event = events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
+        String sessionId = event.getSessionId();
+        String userId = event.getUserId();
+        changePasswordPage.changePassword("", "new-password", "new-password");
+
+        Assert.assertEquals("Please specify password.", profilePage.getError());
+
+        changePasswordPage.changePassword("password", "new-password", "new-password2");
+
+        Assert.assertEquals("Password confirmation doesn't match.", profilePage.getError());
+
+        changePasswordPage.changePassword("password", "new-password", "new-password");
+
+        Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+
+        events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+
+        changePasswordPage.logout();
+
+        events.expectLogout(sessionId).detail(Details.REDIRECT_URI, changePasswordPage.getPath()).assertEvent();
+
+        loginPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        Assert.assertEquals("Invalid username or password.", loginPage.getError());
+
+        events.expectLogin().session((String) null).error("invalid_user_credentials")
+                .removeDetail(Details.CONSENT)
+                .assertEvent();
+
+        loginPage.open();
+        loginPage.login("test-user@localhost", "new-password");
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        events.expectLogin().assertEvent();
+    }
+
+    private void setPasswordPolicy(String policy) {
+        RealmRepresentation testRealm = testRealm().toRepresentation();
+        testRealm.setPasswordPolicy(policy);
+        testRealm().update(testRealm);
+    }
+    @Test
+    public void changePasswordWithLengthPasswordPolicy() {
+        setPasswordPolicy("length");
+
+        changePasswordPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
+
+        changePasswordPage.changePassword("", "new", "new");
+
+        Assert.assertEquals("Please specify password.", profilePage.getError());
+
+        changePasswordPage.changePassword("password", "new-password", "new-password");
+
+        Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+
+        events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+    }
+
+    @Test
+    public void changePasswordWithPasswordHistoryPolicy() {
+        setPasswordPolicy("passwordHistory(2)");
+
+        changePasswordPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=password").assertEvent();
+
+        changePasswordPage.changePassword("password", "password", "password");
+
+        Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+
+        changePasswordPage.changePassword("password", "password1", "password1");
+
+        Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+
+        events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+
+        changePasswordPage.changePassword("password1", "password", "password");
+
+        Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+
+        changePasswordPage.changePassword("password1", "password1", "password1");
+
+        Assert.assertEquals("Invalid password: must not be equal to any of last 2 passwords.", profilePage.getError());
+
+        changePasswordPage.changePassword("password1", "password2", "password2");
+
+        Assert.assertEquals("Your password has been updated.", profilePage.getSuccess());
+
+        events.expectAccount(EventType.UPDATE_PASSWORD).assertEvent();
+    }
+
+    @Test
+    public void changeProfile() {
+        profilePage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+        Assert.assertEquals("Tom", profilePage.getFirstName());
+        Assert.assertEquals("Brady", profilePage.getLastName());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        // All fields are required, so there should be an error when something is missing.
+        profilePage.updateProfile("", "New last", "new@email.com");
+
+        Assert.assertEquals("Please specify first name.", profilePage.getError());
+        Assert.assertEquals("", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.updateProfile("New first", "", "new@email.com");
+
+        Assert.assertEquals("Please specify last name.", profilePage.getError());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.updateProfile("New first", "New last", "");
+
+        Assert.assertEquals("Please specify email.", profilePage.getError());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.clickCancel();
+
+        Assert.assertEquals("Tom", profilePage.getFirstName());
+        Assert.assertEquals("Brady", profilePage.getLastName());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.updateProfile("New first", "New last", "new@email.com");
+
+        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
+        events.expectAccount(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, "test-user@localhost").detail(Details.UPDATED_EMAIL, "new@email.com").assertEvent();
+
+        // reset user for other tests
+        profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
+        events.clear();
+    }
+
+    private void setEditUsernameAllowed() {
+        RealmRepresentation testRealm = testRealm().toRepresentation();
+        testRealm.setEditUsernameAllowed(true);
+        testRealm().update(testRealm);
+    }
+
+    @Test
+    public void changeUsername() {
+        // allow to edit the username in realm
+        setEditUsernameAllowed();
+
+        profilePage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
+        Assert.assertEquals("Tom", profilePage.getFirstName());
+        Assert.assertEquals("Brady", profilePage.getLastName());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        // All fields are required, so there should be an error when something is missing.
+        profilePage.updateProfile("", "New first", "New last", "new@email.com");
+
+        Assert.assertEquals("Please specify username.", profilePage.getError());
+        Assert.assertEquals("", profilePage.getUsername());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        // Change to the username already occupied by other user
+        profilePage.updateProfile("test-user-no-access@localhost", "New first", "New last", "new@email.com");
+
+        Assert.assertEquals("Username already exists.", profilePage.getError());
+        Assert.assertEquals("test-user-no-access@localhost", profilePage.getUsername());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        profilePage.updateProfile("test-user-new@localhost", "New first", "New last", "new@email.com");
+
+        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+        Assert.assertEquals("test-user-new@localhost", profilePage.getUsername());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("new@email.com", profilePage.getEmail());
+    }
+
+    private void addUser(String username, String email) {
+        UserRepresentation user = UserBuilder.create()
+                                             .username(username)
+                                             .enabled(true)
+                                             .email(email)
+                                             .firstName("first")
+                                             .lastName("last")
+                                             .build();
+        ApiUtil.createUserAndResetPasswordWithAdminClient(testRealm(), user, "password");
+    }
+
+    @Test
+    public void changeUsernameLoginWithOldUsername() {
+        addUser("change-username", "change-username@localhost");
+        setEditUsernameAllowed();
+
+        profilePage.open();
+        loginPage.login("change-username", "password");
+
+        profilePage.updateUsername("change-username-updated");
+
+        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+
+        profilePage.logout();
+
+        profilePage.open();
+
+        Assert.assertTrue(loginPage.isCurrent());
+
+        loginPage.login("change-username", "password");
+
+        Assert.assertTrue(loginPage.isCurrent());
+        Assert.assertEquals("Invalid username or password.", loginPage.getError());
+
+        loginPage.login("change-username-updated", "password");
+    }
+
+    @Test
+    public void changeEmailLoginWithOldEmail() {
+        addUser("change-email", "change-username@localhost");
+        setEditUsernameAllowed();
+
+        profilePage.open();
+        loginPage.login("change-username@localhost", "password");
+        profilePage.updateEmail("change-username-updated@localhost");
+
+        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+
+        profilePage.logout();
+
+        profilePage.open();
+
+        Assert.assertTrue(loginPage.isCurrent());
+
+        loginPage.login("change-username@localhost", "password");
+
+        Assert.assertTrue(loginPage.isCurrent());
+        Assert.assertEquals("Invalid username or password.", loginPage.getError());
+
+        loginPage.login("change-username-updated@localhost", "password");
+    }
+
+    // KEYCLOAK-1534
+    @Test
+    public void changeEmailToExisting() {
+        profilePage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+        Assert.assertEquals("test-user@localhost", profilePage.getUsername());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        // Change to the email, which some other user has
+        profilePage.updateProfile("New first", "New last", "test-user-no-access@localhost");
+
+        profilePage.assertCurrent();
+        Assert.assertEquals("Email already exists.", profilePage.getError());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("test-user-no-access@localhost", profilePage.getEmail());
+
+        events.assertEmpty();
+
+        // Change some other things, but not email
+        profilePage.updateProfile("New first", "New last", "test-user@localhost");
+
+        Assert.assertEquals("Your account has been updated.", profilePage.getSuccess());
+        Assert.assertEquals("New first", profilePage.getFirstName());
+        Assert.assertEquals("New last", profilePage.getLastName());
+        Assert.assertEquals("test-user@localhost", profilePage.getEmail());
+
+        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
+
+        // Change email and other things to original values
+        profilePage.updateProfile("Tom", "Brady", "test-user@localhost");
+        events.expectAccount(EventType.UPDATE_PROFILE).assertEvent();
+    }
+
+    @Test
+    public void setupTotp() {
+        totpPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=totp").assertEvent();
+
+        Assert.assertTrue(totpPage.isCurrent());
+
+        Assert.assertFalse(driver.getPageSource().contains("Remove Google"));
+
+        // Error with false code
+        totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret() + "123"));
+
+        Assert.assertEquals("Invalid authenticator code.", profilePage.getError());
+
+        totpPage.configure(totp.generateTOTP(totpPage.getTotpSecret()));
+
+        Assert.assertEquals("Mobile authenticator configured.", profilePage.getSuccess());
+
+        events.expectAccount(EventType.UPDATE_TOTP).assertEvent();
+
+        Assert.assertTrue(driver.getPageSource().contains("pficon-delete"));
+
+        totpPage.removeTotp();
+
+        events.expectAccount(EventType.REMOVE_TOTP).assertEvent();
+    }
+
+    @Test
+    public void changeProfileNoAccess() throws Exception {
+        profilePage.open();
+        loginPage.login("test-user-no-access@localhost", "password");
+
+        UserRepresentation noAccessUser = this.findUser("test-user-no-access@localhost");
+        events.expectLogin().client("account").user(noAccessUser.getId())
+                .detail(Details.USERNAME, "test-user-no-access@localhost")
+                .detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT).assertEvent();
+
+        Assert.assertTrue(errorPage.isCurrent());
+        Assert.assertEquals("No access", errorPage.getError());
+    }
+
+    private void setEventsEnabled() {
+        RealmRepresentation testRealm = testRealm().toRepresentation();
+        testRealm.setEventsEnabled(true);
+        testRealm().update(testRealm);
+    }
+
+    @Test
+    public void viewLog() {
+        setEventsEnabled();
+
+        List<EventRepresentation> expectedEvents = new LinkedList<>();
+
+        loginPage.open();
+        loginPage.clickRegister();
+
+        registerPage.register("view", "log", "view-log@localhost", "view-log", "password", "password");
+
+        expectedEvents.add(events.poll());
+        expectedEvents.add(events.poll());
+
+        profilePage.open();
+        profilePage.updateProfile("view", "log2", "view-log@localhost");
+
+        expectedEvents.add(events.poll());
+
+        logPage.open();
+
+        Assert.assertTrue(logPage.isCurrent());
+
+        List<List<String>> actualEvents = logPage.getEvents();
+
+        Assert.assertEquals(expectedEvents.size(), actualEvents.size());
+
+        for (EventRepresentation e : expectedEvents) {
+            boolean match = false;
+            for (List<String> a : logPage.getEvents()) {
+                if (e.getType().toString().replace('_', ' ').toLowerCase().equals(a.get(1)) &&
+                        e.getIpAddress().equals(a.get(2)) &&
+                        e.getClientId().equals(a.get(3))) {
+                    match = true;
+                    break;
+                }
+            }
+            if (!match) {
+                Assert.fail("Event not found " + e.getType());
+            }
+        }
+    }
+
+    @Test
+    public void sessions() {
+        loginPage.open();
+        loginPage.clickRegister();
+
+        registerPage.register("view", "sessions", "view-sessions@localhost", "view-sessions", "password", "password");
+
+        EventRepresentation registerEvent = events.expectRegister("view-sessions", "view-sessions@localhost").assertEvent();
+        String userId = registerEvent.getUserId();
+
+        events.expectLogin().user(userId).detail(Details.USERNAME, "view-sessions").assertEvent();
+
+        sessionsPage.open();
+
+        Assert.assertTrue(sessionsPage.isCurrent());
+
+        List<List<String>> sessions = sessionsPage.getSessions();
+        Assert.assertEquals(1, sessions.size());
+        Assert.assertEquals("127.0.0.1", sessions.get(0).get(0));
+
+        // Create second session
+        try {
+            OAuthClient oauth2 = new OAuthClient();
+            oauth2.init(adminClient, driver2);
+            oauth2.state("mystate");
+            oauth2.doLogin("view-sessions", "password");
+
+            EventRepresentation login2Event = events.expectLogin().user(userId).detail(Details.USERNAME, "view-sessions").assertEvent();
+
+            sessionsPage.open();
+            sessions = sessionsPage.getSessions();
+            Assert.assertEquals(2, sessions.size());
+
+            sessionsPage.logoutAll();
+
+            events.expectLogout(registerEvent.getSessionId());
+            events.expectLogout(login2Event.getSessionId());
+        } finally {
+            driver2.close();
+        }
+    }
+
+    // More tests (including revoke) are in OAuthGrantTest and OfflineTokenTest
+    @Test
+    public void applications() {
+        applicationsPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=applications").assertEvent();
+        Assert.assertTrue(applicationsPage.isCurrent());
+
+        Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
+        Assert.assertEquals(3, apps.size());
+
+        AccountApplicationsPage.AppEntry accountEntry = apps.get("Account");
+        Assert.assertEquals(2, accountEntry.getRolesAvailable().size());
+        Assert.assertTrue(accountEntry.getRolesAvailable().contains("Manage account in Account"));
+        Assert.assertTrue(accountEntry.getRolesAvailable().contains("View profile in Account"));
+        Assert.assertEquals(1, accountEntry.getRolesGranted().size());
+        Assert.assertTrue(accountEntry.getRolesGranted().contains("Full Access"));
+        Assert.assertEquals(1, accountEntry.getProtocolMappersGranted().size());
+        Assert.assertTrue(accountEntry.getProtocolMappersGranted().contains("Full Access"));
+
+        AccountApplicationsPage.AppEntry testAppEntry = apps.get("test-app");
+        Assert.assertEquals(5, testAppEntry.getRolesAvailable().size());
+        Assert.assertTrue(testAppEntry.getRolesAvailable().contains("Offline access"));
+        Assert.assertTrue(testAppEntry.getRolesGranted().contains("Full Access"));
+        Assert.assertTrue(testAppEntry.getProtocolMappersGranted().contains("Full Access"));
+
+        AccountApplicationsPage.AppEntry thirdPartyEntry = apps.get("third-party");
+        Assert.assertEquals(2, thirdPartyEntry.getRolesAvailable().size());
+        Assert.assertTrue(thirdPartyEntry.getRolesAvailable().contains("Have User privileges"));
+        Assert.assertTrue(thirdPartyEntry.getRolesAvailable().contains("Have Customer User privileges in test-app"));
+        Assert.assertEquals(0, thirdPartyEntry.getRolesGranted().size());
+        Assert.assertEquals(0, thirdPartyEntry.getProtocolMappersGranted().size());
+    }
+
+    @Test
+    public void loginToSpecificPage() {
+        changePasswordPage.open();
+        loginPage.login("test-user@localhost", "password");
+
+        Assert.assertTrue(changePasswordPage.isCurrent());
+
+        events.clear();
+    }
+
+    @Test
+    public void loginToSpecificPageWithReferrer() {
+        driver.navigate().to(changePasswordPage.getPath() + "?referrer=account");
+        System.out.println(driver.getCurrentUrl());
+
+        loginPage.login("test-user@localhost", "password");
+        System.out.println(driver.getCurrentUrl());
+
+        Assert.assertTrue(changePasswordPage.isCurrent());
+
+        events.clear();
     }
 
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java
index f73deb7..9b59a60 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/custom/AbstractCustomAccountManagementTest.java
@@ -23,7 +23,6 @@ import org.junit.Before;
 import org.keycloak.admin.client.resource.AuthenticationManagementResource;
 import org.keycloak.models.AuthenticationExecutionModel;
 import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
-import org.keycloak.testsuite.account.AbstractAccountManagementTest;
 
 /**
  *
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
index b98877d..5d066b0 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientBuilder.java
@@ -17,11 +17,14 @@
 
 package org.keycloak.testsuite.util;
 
+import java.util.ArrayList;
 import org.keycloak.dom.saml.v2.ac.BooleanType;
 import org.keycloak.representations.idm.ClientRepresentation;
 
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -29,14 +32,20 @@ import java.util.Map;
  */
 public class ClientBuilder {
 
-    private ClientRepresentation rep = new ClientRepresentation();
+    private ClientRepresentation rep;
 
     public static ClientBuilder create() {
-        return new ClientBuilder();
+        ClientRepresentation rep = new ClientRepresentation();
+        rep.setEnabled(Boolean.TRUE);
+        return new ClientBuilder(rep);
     }
 
-    private ClientBuilder() {
-        rep.setEnabled(true);
+    public static ClientBuilder edit(ClientRepresentation rep) {
+        return new ClientBuilder(rep);
+    }
+
+    private ClientBuilder(ClientRepresentation rep) {
+        this.rep = rep;
     }
 
     public ClientBuilder id(String id) {
@@ -100,6 +109,26 @@ public class ClientBuilder {
         return this;
     }
 
+    public ClientBuilder addWebOrigin(String webOrigin) {
+        List<String> uris = rep.getWebOrigins();
+        if (uris == null) {
+            uris = new LinkedList<>();
+            rep.setWebOrigins(uris);
+        }
+        uris.add(webOrigin);
+        return this;
+    }
+
+    public ClientBuilder addRedirectUri(String redirectUri) {
+        List<String> uris = rep.getRedirectUris();
+        if (uris == null) {
+            uris = new LinkedList<>();
+            rep.setRedirectUris(uris);
+        }
+        uris.add(redirectUri);
+        return this;
+    }
+
     public ClientBuilder redirectUris(String... redirectUris) {
         rep.setRedirectUris(Arrays.asList(redirectUris));
         return this;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
index 379d4ef..f127d7a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
@@ -56,6 +56,16 @@ public class UserBuilder {
         return this;
     }
 
+    public UserBuilder firstName(String firstName) {
+        rep.setFirstName(firstName);
+        return this;
+    }
+
+    public UserBuilder lastName(String lastName) {
+        rep.setLastName(lastName);
+        return this;
+    }
+
     /**
      * This method adds additional passwords to the user.
      */
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json
index 93624ef..e24b31e 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json
@@ -101,7 +101,7 @@
     {
       "clientId": "test-app",
       "enabled": true,
-      "baseUrl": "http://localhost:8180/auth/realms/master/app",
+      "baseUrl": "http://localhost:8180/auth/realms/master/app/auth",
       "redirectUris": [
         "http://localhost:8180/auth/realms/master/app/*"
       ],