keycloak-aplcache

Merge pull request #1952 from vmuzikar/ui-stability KEYCLOAK-1865

12/21/2015 5:50:11 AM

Details

diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java
index fb4dacf..73957bc 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/mappers/CreateClientMappersForm.java
@@ -43,40 +43,40 @@ public class CreateClientMappersForm extends Form {
     @FindBy(id = "mapperTypeCreate")
     private Select mapperTypeSelect;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Property']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Property']//following-sibling::node()//input[@type='text']")
     private WebElement propertyInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Attribute']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='User Attribute']//following-sibling::node()//input[@type='text']")
     private WebElement userAttributeInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='User Session Note']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='User Session Note']//following-sibling::node()//input[@type='text']")
     private WebElement userSessionNoteInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Multivalued']//following-sibling::node()//div[@class='onoffswitch']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Multivalued']//following-sibling::node()//div[@class='onoffswitch']")
     private OnOffSwitch multivaluedInput;
 
     @FindBy(xpath = ".//button[text() = 'Select Role']/../..//input")
     private WebElement roleInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='New Role Name']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='New Role Name']//following-sibling::node()//input[@type='text']")
     private WebElement newRoleInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Token Claim Name']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Token Claim Name']//following-sibling::node()//input[@type='text']")
     private WebElement tokenClaimNameInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim value']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Claim value']//following-sibling::node()//input[@type='text']")
     private WebElement tokenClaimValueInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Claim JSON Type']//following-sibling::node()//select")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Claim JSON Type']//following-sibling::node()//select")
     private Select claimJSONTypeInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to ID token']//following-sibling::node()//div[@class='onoffswitch']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Add to ID token']//following-sibling::node()//div[@class='onoffswitch']")
     private OnOffSwitch addToIDTokenInput;
 
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Add to access token']//following-sibling::node()//div[@class='onoffswitch']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Add to access token']//following-sibling::node()//div[@class='onoffswitch']")
     private OnOffSwitch addToAccessTokenInput;
     
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Full group path']//following-sibling::node()//div[@class='onoffswitch']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Full group path']//following-sibling::node()//div[@class='onoffswitch']")
     private OnOffSwitch fullGroupPath;
 
     @FindBy(xpath = ".//button[text() = 'Select Role']")
@@ -260,25 +260,25 @@ public class CreateClientMappersForm extends Form {
     }
     
     //SAML
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Role attribute name']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Role attribute name']//following-sibling::node()//input[@type='text']")
     private WebElement roleAttributeNameInput;
     
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Friendly Name']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Friendly Name']//following-sibling::node()//input[@type='text']")
     private WebElement friendlyNameInput;
     
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='SAML Attribute NameFormat']//following-sibling::node()//select")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='SAML Attribute NameFormat']//following-sibling::node()//select")
     private Select samlAttributeNameFormatSelect;
     
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Single Role Attribute']//following-sibling::node()//div[@class='onoffswitch']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Single Role Attribute']//following-sibling::node()//div[@class='onoffswitch']")
     private OnOffSwitch singleRoleAttributeSwitch;
     
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Attribute value']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Attribute value']//following-sibling::node()//input[@type='text']")
     private WebElement attributeValueInput;
     
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Group attribute name']//following-sibling::node()//input[@type='text']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Group attribute name']//following-sibling::node()//input[@type='text']")
     private WebElement groupAttributeNameInput;
     
-    @FindBy(xpath = ".//div[@properties='mapperType.properties']//label[text()='Single Group Attribute']//following-sibling::node()//div[@class='onoffswitch']")
+    @FindBy(xpath = ".//div[@properties='model.mapperType.properties']//label[text()='Single Group Attribute']//following-sibling::node()//div[@class='onoffswitch']")
     private OnOffSwitch singleGroupAttributeSwitch;
     
     public void setRoleAttributeName(String value) {
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/BruteForceDetection.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/BruteForceDetection.java
index 75e54b2..e772a5d 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/BruteForceDetection.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/BruteForceDetection.java
@@ -73,7 +73,7 @@ public class BruteForceDetection extends SecurityDefenses {
         }
 
         public void setWaitIncrementSelect(TimeSelectValues value) {
-            waitIncrementSelect.selectByVisibleText(value.getName());
+            waitIncrementSelect.selectByValue(value.getName());
         }
 
         public void setQuickLoginCheckInput(String value) {
@@ -85,7 +85,7 @@ public class BruteForceDetection extends SecurityDefenses {
         }
 
         public void setMinQuickLoginWaitSelect(TimeSelectValues value) {
-            minQuickLoginWaitSelect.selectByVisibleText(value.getName());
+            minQuickLoginWaitSelect.selectByValue(value.getName());
         }
 
         public void setMaxWaitInput(String value) {
@@ -93,7 +93,7 @@ public class BruteForceDetection extends SecurityDefenses {
         }
 
         public void setMaxWaitSelect(TimeSelectValues value) {
-            maxWaitSelect.selectByVisibleText(value.getName());
+            maxWaitSelect.selectByValue(value.getName());
         }
 
         public void setFailureResetTimeInput(String value) {
@@ -101,7 +101,7 @@ public class BruteForceDetection extends SecurityDefenses {
         }
 
         public void setFailureResetTimeSelect(TimeSelectValues value) {
-            failureResetTimeSelect.selectByVisibleText(value.getName());
+            failureResetTimeSelect.selectByValue(value.getName());
         }
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/LoginSettings.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/LoginSettings.java
index 2cfcace..871167b 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/LoginSettings.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/realm/LoginSettings.java
@@ -80,6 +80,10 @@ public class LoginSettings extends RealmSettings {
         public void setEmailAsUsername(boolean emailAsUsername) {
             emailAsUsernameOnOffSwitch.setOn(emailAsUsername);
         }
+
+        public boolean isEmailAsUsername() {
+            return emailAsUsernameOnOffSwitch.isOn();
+        }
         
         public boolean isEditUsernameAllowed() {
             return editUsernameAllowed.isOn();
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/users/UserCredentials.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/users/UserCredentials.java
index 830d789..0652fa4 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/users/UserCredentials.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/users/UserCredentials.java
@@ -4,6 +4,7 @@ import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
 import static org.keycloak.testsuite.page.Form.setInputValue;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
+import static org.keycloak.testsuite.util.WaitUtils.*;
 
 /**
  *
@@ -25,7 +26,7 @@ public class UserCredentials extends User {
     @FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='temporaryPassword']]")
     private OnOffSwitch temporaryOnOffSwitch;
 
-    @FindBy(xpath = ".//button[contains(@data-ng-click, 'resetPassword')]")
+    @FindBy(xpath = ".//div[not(contains(@class, 'ng-hide'))]/button[contains(@data-ng-click, 'resetPassword')]")
     private WebElement resetPasswordButton;
 
     public void setNewPassword(String newPassword) {
@@ -41,6 +42,7 @@ public class UserCredentials extends User {
     }
 
     public void clickResetPasswordAndConfirm() {
+        waitUntilElement(resetPasswordButton);
         resetPasswordButton.click();
         modalDialog.ok();
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java
index 7f664c7..0d055da 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/page/Form.java
@@ -21,9 +21,9 @@ public class Form {
 
     public static final String ACTIVE_DIV_XPATH = ".//div[not(contains(@class,'ng-hide'))]";
 
-    @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Save']")
+    @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[@kc-save or @data-kc-save]")
     private WebElement save;
-    @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[text()='Cancel']")
+    @FindBy(xpath = ACTIVE_DIV_XPATH + "/button[@kc-reset or @data-kc-reset]")
     private WebElement cancel;
 
     public void save() {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java
index b087366..0a6b6a5 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/LoginSettingsTest.java
@@ -24,7 +24,6 @@ import org.junit.Assert;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -41,13 +40,13 @@ import org.keycloak.testsuite.console.page.realm.LoginSettings.RequireSSLOption;
 import org.keycloak.testsuite.util.MailServer;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
+
 import org.openqa.selenium.Cookie;
 
 /**
  *
  * @author tkyjovsk
  */
-@Ignore
 public class LoginSettingsTest extends AbstractRealmTest {
 
     private static final String NEW_USERNAME = "newUsername";
@@ -84,7 +83,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
 
         log.info("enabling registration");
         loginSettingsPage.form().setRegistrationAllowed(true);
+        assertTrue(loginSettingsPage.form().isRegistrationAllowed());
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("enabled");
         
         testRealmAdminConsolePage.navigateTo();
@@ -98,7 +99,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         log.info("enabling email as username");
         loginSettingsPage.navigateTo();
         loginSettingsPage.form().setEmailAsUsername(true);
+        assertTrue(loginSettingsPage.form().isEmailAsUsername());
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("enabled");
 
         testRealmAdminConsolePage.navigateTo();
@@ -112,8 +115,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         log.info("disabling registration");
         loginSettingsPage.navigateTo();
         loginSettingsPage.form().setRegistrationAllowed(false);
-        loginSettingsPage.form().save();
         assertFalse(loginSettingsPage.form().isRegistrationAllowed());
+        loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("disabled");
         
         testRealmAdminConsolePage.navigateTo();
@@ -125,7 +129,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
     public void editUsername() {
         log.info("enabling edit username");
         loginSettingsPage.form().setEditUsernameAllowed(true);
+        assertTrue(loginSettingsPage.form().isEditUsernameAllowed());
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("enabled");
         
         log.info("edit username");
@@ -145,7 +151,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         log.info("disabling edit username");
         loginSettingsPage.navigateTo();
         loginSettingsPage.form().setEditUsernameAllowed(false);
+        assertFalse(loginSettingsPage.form().isEditUsernameAllowed());
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("disabled");
         
         
@@ -156,7 +164,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         
         log.info("enabling reset password");
         loginSettingsPage.form().setResetPasswordAllowed(true);
+        assertTrue(loginSettingsPage.form().isResetPasswordAllowed());
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("enabled");
         
         testRealmAdminConsolePage.navigateTo();
@@ -169,8 +179,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         log.info("disabling reset password");
         loginSettingsPage.navigateTo();
         loginSettingsPage.form().setResetPasswordAllowed(false);
-        loginSettingsPage.form().save();
         assertFalse(loginSettingsPage.form().isResetPasswordAllowed());
+        loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("disabled");
         
         testRealmAdminConsolePage.navigateTo();
@@ -183,7 +194,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         
         log.info("enabling remember me");
         loginSettingsPage.form().setRememberMeAllowed(true);
+        assertTrue(loginSettingsPage.form().isRememberMeAllowed());
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("enabled");
         
         log.info("login with remember me checked");
@@ -198,8 +211,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         log.info("disabling remember me");
         loginSettingsPage.navigateTo();
         loginSettingsPage.form().setRememberMeAllowed(false);
-        loginSettingsPage.form().save();
         assertFalse(loginSettingsPage.form().isRememberMeAllowed());
+        loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("disabled");
         
         testAccountPage.navigateTo();
@@ -218,10 +232,12 @@ public class LoginSettingsTest extends AbstractRealmTest {
         
         log.info("enabling verify email in login settings");
         loginSettingsPage.form().setVerifyEmailAllowed(true);
+        assertTrue(loginSettingsPage.form().isVerifyEmailAllowed());
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("enabled");
 
-        log.info("configure smpt server in test realm");
+        log.info("configure smtp server in test realm");
         RealmRepresentation testRealmRep = testRealmResource().toRepresentation();
         testRealmRep.setSmtpServer(suiteContext.getSmtpServer());
         testRealmResource().update(testRealmRep);
@@ -236,8 +252,9 @@ public class LoginSettingsTest extends AbstractRealmTest {
         log.info("disabling verify email");
         loginSettingsPage.navigateTo();
         loginSettingsPage.form().setVerifyEmailAllowed(false);
-        loginSettingsPage.form().save();
         assertFalse(loginSettingsPage.form().isVerifyEmailAllowed());
+        loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("disabled");
         
         log.debug("create new test user");
@@ -261,6 +278,7 @@ public class LoginSettingsTest extends AbstractRealmTest {
         log.info("set require ssl for all requests");
         loginSettingsPage.form().selectRequireSSL(RequireSSLOption.all);
         loginSettingsPage.form().save();
+        assertAlertSuccess();
         log.debug("set");
         
         log.info("check HTTPS required");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/SecurityDefensesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/SecurityDefensesTest.java
index e5b8e74..72bcd7f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/SecurityDefensesTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/SecurityDefensesTest.java
@@ -19,28 +19,31 @@ package org.keycloak.testsuite.console.realm;
 
 import org.jboss.arquillian.graphene.page.Page;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.keycloak.testsuite.auth.page.account.Account;
 import org.keycloak.testsuite.console.page.realm.BruteForceDetection;
 import org.keycloak.testsuite.console.page.users.UserAttributes;
 import org.keycloak.testsuite.console.page.users.Users;
-import org.openqa.selenium.By;
-
-import java.util.Date;
-
-import static org.jboss.arquillian.graphene.Graphene.waitGui;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
 import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
 import static org.keycloak.testsuite.admin.Users.setPasswordFor;
 import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
 import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
+import static org.keycloak.testsuite.util.WaitUtils.*;
+import static org.junit.Assert.*;
 
 /**
  * @author Filip Kiss
  * @author mhajas
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
  */
-@Ignore
 public class SecurityDefensesTest extends AbstractRealmTest {
+    
+    public static final String INVALID_PWD_MSG = "Invalid username or password.";
+    public static final String ACC_DISABLED_MSG = "Account is temporarily disabled, contact admin or try again later.";
+    public static final short ATTEMPTS_BAD_PWD = 2;
+    public static final short ATTEMPTS_GOOD_PWD = 1;
 
     @Page
     private BruteForceDetection bruteForceDetectionPage;
@@ -54,6 +57,9 @@ public class SecurityDefensesTest extends AbstractRealmTest {
     @Page
     private UserAttributes userAttributesPage;
 
+    @FindBy(className = "kc-feedback-text")
+    private WebElement feedbackTextElement;
+
     @Override
     public void setDefaultPageUriParameters() {
         super.setDefaultPageUriParameters();
@@ -66,157 +72,72 @@ public class SecurityDefensesTest extends AbstractRealmTest {
     }
 
     @Test
-    public void maxLoginFailuresTest() {
-        int secondsToWait = 3;
+    public void maxLoginFailuresTest() throws InterruptedException {
+        final short secondsToWait = 3;
+        final short maxLoginFailures = 2;
 
         bruteForceDetectionPage.form().setProtectionEnabled(true);
-        bruteForceDetectionPage.form().setMaxLoginFailures("1");
+        bruteForceDetectionPage.form().setMaxLoginFailures(String.valueOf(maxLoginFailures));
         bruteForceDetectionPage.form().setWaitIncrementSelect(BruteForceDetection.TimeSelectValues.SECONDS);
         bruteForceDetectionPage.form().setWaitIncrementInput(String.valueOf(secondsToWait));
+        bruteForceDetectionPage.form().setQuickLoginCheckInput("1");
         bruteForceDetectionPage.form().save();
         assertAlertSuccess();
 
-        testRealmAccountPage.navigateTo();
-
-        setPasswordFor(testUser, PASSWORD + "-mismatch");
-
-        testRealmLoginPage.form().login(testUser);
-        waitForFeedbackText("Invalid username or password.");
-        Date endTime = new Date(new Date().getTime() + secondsToWait * 1000);
-
-        testRealmLoginPage.form().login(testUser);
-        waitGui().until().element(By.className("instruction"))
-                .text().contains("Account is temporarily disabled, contact admin or try again later.");
-        endTime = new Date(endTime.getTime() + secondsToWait * 1000);
-        testRealmAccountPage.navigateTo();
-        testRealmLoginPage.form().login(testUser);
-        endTime = new Date(endTime.getTime() + secondsToWait * 1000);
-
-        while (new Date().compareTo(endTime) < 0) {
-            try {
-                Thread.sleep(50);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
-
-        setPasswordFor(testUser, PASSWORD);
-        testRealmLoginPage.form().login(testUser);
-        assertCurrentUrlStartsWith(testRealmAccountPage);
+        tryToLogin(secondsToWait * (ATTEMPTS_BAD_PWD + ATTEMPTS_GOOD_PWD) / maxLoginFailures);
     }
 
     @Test
-    public void quickLoginCheck() {
-        int secondsToWait = 3;
+    public void quickLoginCheck() throws InterruptedException {
+        final short secondsToWait = 3;
 
         bruteForceDetectionPage.form().setProtectionEnabled(true);
         bruteForceDetectionPage.form().setMaxLoginFailures("100");
-        bruteForceDetectionPage.form().setQuickLoginCheckInput("1500");
+        bruteForceDetectionPage.form().setQuickLoginCheckInput("10000");
         bruteForceDetectionPage.form().setMinQuickLoginWaitSelect(BruteForceDetection.TimeSelectValues.SECONDS);
         bruteForceDetectionPage.form().setMinQuickLoginWaitInput(String.valueOf(secondsToWait));
         bruteForceDetectionPage.form().save();
         assertAlertSuccess();
 
-        testRealmAccountPage.navigateTo();
-
-        setPasswordFor(testUser, PASSWORD + "-mismatch");
-
-        testRealmLoginPage.form().login(testUser);
-        testRealmLoginPage.form().login(testUser);
-        Date endTime = new Date(new Date().getTime() + secondsToWait * 1000);
-        testRealmLoginPage.form().login(testUser);
-        waitGui().until().element(By.className("instruction"))
-                .text().contains("Account is temporarily disabled, contact admin or try again later.");
-        endTime = new Date(endTime.getTime() + secondsToWait * 1000);
-
-        testRealmAccountPage.navigateTo();
-        testRealmLoginPage.form().login(testUser);
-        endTime = new Date(endTime.getTime() + secondsToWait * 1000);
-
-        while (new Date().compareTo(endTime) < 0) {
-            try {
-                Thread.sleep(50);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
-
-        setPasswordFor(testUser, PASSWORD);
-        testRealmLoginPage.form().login(testUser);
-        assertCurrentUrlStartsWith(testRealmAccountPage);
+        tryToLogin(secondsToWait);
     }
 
     @Test
-    public void maxWaitLoginFailures() {
-        int secondsToWait = 5;
+    public void maxWaitLoginFailures() throws InterruptedException {
+        final short secondsToWait = 5;
 
         bruteForceDetectionPage.form().setProtectionEnabled(true);
         bruteForceDetectionPage.form().setMaxLoginFailures("1");
+        bruteForceDetectionPage.form().setWaitIncrementSelect(BruteForceDetection.TimeSelectValues.SECONDS);
+        bruteForceDetectionPage.form().setWaitIncrementInput("10");
         bruteForceDetectionPage.form().setMaxWaitSelect(BruteForceDetection.TimeSelectValues.SECONDS);
         bruteForceDetectionPage.form().setMaxWaitInput(String.valueOf(secondsToWait));
         bruteForceDetectionPage.form().save();
 
-        testRealmAccountPage.navigateTo();
-
-        setPasswordFor(testUser, PASSWORD + "-mismatch");
-
-        testRealmLoginPage.form().login(testUser);
-        Date endTime = new Date(new Date().getTime() + secondsToWait * 1000);
-        waitForFeedbackText("Invalid username or password.");
-
-        testRealmLoginPage.form().login(testUser);
-        endTime = new Date(endTime.getTime() + secondsToWait * 1000);
-        waitGui().until().element(By.className("instruction"))
-                .text().contains("Account is temporarily disabled, contact admin or try again later.");
-        testRealmAccountPage.navigateTo();
-        testRealmLoginPage.form().login(testUser);
-        endTime = new Date(endTime.getTime() + secondsToWait * 1000);
-        waitForFeedbackText("Account is temporarily disabled, contact admin or try again later.");
-
-        while (new Date().compareTo(endTime) < 0) {
-            try {
-                Thread.sleep(50);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
-
-        setPasswordFor(testUser, PASSWORD);
-        testRealmLoginPage.form().login(testUser);
-        assertCurrentUrlStartsWith(testRealmAccountPage);
+        tryToLogin(secondsToWait);
     }
 
     @Test
-    public void failureResetTime() {
-        int secondsToWait = 3;
+    public void failureResetTime() throws InterruptedException {
+        final short failureResetTime = 3;
+        final short waitIncrement = 3;
 
         bruteForceDetectionPage.form().setProtectionEnabled(true);
-        bruteForceDetectionPage.form().setMaxLoginFailures("2");
+        bruteForceDetectionPage.form().setMaxLoginFailures("1");
+        bruteForceDetectionPage.form().setWaitIncrementSelect(BruteForceDetection.TimeSelectValues.SECONDS);
+        bruteForceDetectionPage.form().setWaitIncrementInput(String.valueOf(waitIncrement));
         bruteForceDetectionPage.form().setFailureResetTimeSelect(BruteForceDetection.TimeSelectValues.SECONDS);
-        bruteForceDetectionPage.form().setFailureResetTimeInput(String.valueOf(secondsToWait));
+        bruteForceDetectionPage.form().setFailureResetTimeInput(String.valueOf(failureResetTime));
         bruteForceDetectionPage.form().save();
         assertAlertSuccess();
 
-        testRealmAccountPage.navigateTo();
-
-        setPasswordFor(testUser, PASSWORD + "-mismatch");
+        tryToLogin(failureResetTime, false);
 
         testRealmLoginPage.form().login(testUser);
-        waitForFeedbackText("Invalid username or password.");
-        Date endTime = new Date(new Date().getTime() + secondsToWait * 1000);
-
-        while (new Date().compareTo(endTime) < 0) {
-            try {
-                Thread.sleep(50);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
+        assertFeedbackText(ACC_DISABLED_MSG);
 
-        testRealmLoginPage.form().login(testUser);
-        waitForFeedbackText("Invalid username or password.");
+        Thread.sleep(waitIncrement * 1000);
 
-        setPasswordFor(testUser, PASSWORD);
         testRealmLoginPage.form().login(testUser);
         assertCurrentUrlStartsWith(testRealmAccountPage);
     }
@@ -240,6 +161,7 @@ public class SecurityDefensesTest extends AbstractRealmTest {
 
         usersPage.table().searchUsers(testUser.getUsername());
         usersPage.table().editUser(testUser.getUsername());
+        assertFalse(userAttributesPage.form().isEnabled());
         userAttributesPage.form().unlockUser();
 
         testRealmAccountPage.navigateTo();
@@ -250,8 +172,39 @@ public class SecurityDefensesTest extends AbstractRealmTest {
         assertCurrentUrlStartsWith(testRealmAccountPage);
     }
 
-    private void waitForFeedbackText(String text) {
-        waitGui().until().element(By.className("kc-feedback-text"))
-                .text().contains(text);
+    private void assertFeedbackText(String text) {
+        waitUntilElement(feedbackTextElement);
+        assertEquals(text, feedbackTextElement.getText());
+    }
+
+    private void tryToLogin(int wait) throws InterruptedException {
+        tryToLogin(wait, true);
+    }
+
+    private void tryToLogin(int wait, boolean finalLogin) throws InterruptedException {
+        testRealmAccountPage.navigateTo();
+
+        setPasswordFor(testUser, PASSWORD + "-mismatch");
+
+        for (int i = 0; i < ATTEMPTS_BAD_PWD; i++) {
+            testRealmLoginPage.form().login(testUser);
+            assertFeedbackText(INVALID_PWD_MSG);
+        }
+
+        setPasswordFor(testUser, PASSWORD);
+        for (int i = 0; i < ATTEMPTS_GOOD_PWD; i++) {
+            testRealmLoginPage.form().login(testUser);
+            assertFeedbackText(ACC_DISABLED_MSG);
+        }
+
+        wait *= 1000;
+
+        log.debug("Wait: " + wait);
+        Thread.sleep(wait);
+
+        if (finalLogin) {
+            testRealmLoginPage.form().login(testUser);
+            assertCurrentUrlStartsWith(testRealmAccountPage);
+        }
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/TokensTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/TokensTest.java
index 33cfeb5..975a619 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/TokensTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/realm/TokensTest.java
@@ -31,7 +31,6 @@ import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
  *
  * @author Petr Mensik
  */
-@Ignore
 public class TokensTest extends AbstractRealmTest {
 
     @Page