Merge pull request #2263 from vmuzikar/master

[KEYCLOAK-2532] Fix Console UI tests
This commit is contained in:
Stian Thorgersen 2016-02-23 19:25:05 +01:00
commit f34260478e
17 changed files with 93 additions and 39 deletions

View file

@ -40,11 +40,11 @@ public class LoginActions extends AuthRealm {
@FindBy(css = "div[id='kc-form-options'] span a")
private WebElement backToLoginForm;
@FindBy(css = "span.kc-feedback-text")
@FindBy(xpath = "//span[@class='kc-feedback-text' and string-length(text())>1]")
private WebElement feedbackText;
public String getFeedbackText() {
waitUntilElement(feedbackText, "Feedback message should be present").is().present();
waitUntilElement(feedbackText, "Feedback message should be present").is().visible();
return feedbackText.getText();
}

View file

@ -42,7 +42,7 @@ public class LoginForm extends Form {
// @FindBy(name = "cancel")
// private WebElement cancelButton;
@FindBy(linkText = "Register")
@FindBy(xpath = "//div[@id='kc-registration']/span/a")
private WebElement registerLink;
@FindBy(linkText = "Forgot Password?")
private WebElement forgottenPassword;

View file

@ -6,6 +6,8 @@ import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import static org.keycloak.testsuite.util.WaitUtils.*;
/**
* @author Vaclav Muzikar <vmuzikar@redhat.com>
*/
@ -17,11 +19,14 @@ public class Dropdown {
private WebDriver driver;
public String getSelected() {
return dropDownRoot.findElement(By.xpath("./a")).getText();
waitUntilElement(dropDownRoot).is().present();
WebElement element = dropDownRoot.findElement(By.xpath("./a"));
return element.getText();
}
public void selectByText(String text) {
String href = dropDownRoot.findElement(By.xpath("./ul/li/a[text()='" + text + "']")).getAttribute("href");
driver.navigate().to(href);
waitUntilElement(dropDownRoot).is().present();
WebElement element = dropDownRoot.findElement(By.xpath("./ul/li/a[text()='" + text + "']"));
driver.navigate().to(element.getAttribute("href"));
}
}

View file

@ -24,6 +24,9 @@ import javax.ws.rs.core.UriBuilder;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.logging.Logger;
import static org.keycloak.testsuite.util.WaitUtils.pause;
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
/**
@ -90,6 +93,7 @@ public abstract class AbstractPage {
log.info("navigating to " + uri);
driver.navigate().to(uri);
pause(300); // this is needed for FF for some reason
waitUntilElement(By.tagName("body")).is().visible();
log.info("current URL: " + driver.getCurrentUrl());
}

View file

@ -70,8 +70,9 @@ public class RegistrationTest extends AbstractAccountManagementTest {
}
public void assertMessageAttributeMissing(String attributeName) {
assertTrue(testRealmRegistrationPage.getFeedbackText()
.contains("Please specify " + attributeName + "."));
String feedbackTest = testRealmRegistrationPage.getFeedbackText();
String contains = "Please specify " + attributeName + ".";
assertTrue("'" + feedbackTest + "' doesn't contain '" + contains + "'", feedbackTest.contains(contains));
}
@Test
@ -84,8 +85,7 @@ public class RegistrationTest extends AbstractAccountManagementTest {
public void invalidEmail() {
newUser.setEmail("invalid.email.value");
testRealmRegistrationPage.register(newUser);
assertTrue(testRealmRegistrationPage.getFeedbackText()
.equals("Invalid email address."));
assertEquals("Invalid email address.", testRealmRegistrationPage.getFeedbackText());
assertUserDoesntExistWithAdminClient(newUser);
}
@ -121,8 +121,7 @@ public class RegistrationTest extends AbstractAccountManagementTest {
public void notMatchingPasswords() {
testRealmRegistrationPage.setValues(newUser, "not-matching-password");
testRealmRegistrationPage.submit();
assertTrue(testRealmRegistrationPage.getFeedbackText()
.equals("Password confirmation doesn't match."));
assertEquals("Password confirmation doesn't match.", testRealmRegistrationPage.getFeedbackText());
testRealmRegistrationPage.register(newUser);
assertUserExistsWithAdminClient(newUser);

View file

@ -47,7 +47,7 @@ public class URLAssert {
// }
// };
// wait.until(urlStartsWith);
assertEqualsNormalized(driver.getCurrentUrl(), page.toString());
assertEqualsNormalized(page.toString(), driver.getCurrentUrl());
}
public static void assertCurrentUrlStartsWith(AbstractPage page) {

View file

@ -25,6 +25,7 @@ import org.keycloak.testsuite.page.Form;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.ui.Select;
import static org.keycloak.testsuite.util.WaitUtils.*;
/**
*
@ -35,14 +36,14 @@ public class ClientCredentialsForm extends Form {
@FindBy(id = "clientAuthenticatorType")
private Select clientAuthenticatorType;
@FindBy(xpath = "//button[text()='Regenerate Secret']")
private WebElement regenerateSecretButton;
@FindBy(xpath = "//button[@data-ng-click='changePassword()']")
private WebElement regenerateSecretButton; // Regenerate Secret
@FindBy(xpath = "//button[text()='Generate new keys and certificate']")
private WebElement generateNewKeysAndCert;
@FindBy(xpath = "//button[@data-ng-click='generateSigningKey()']")
private WebElement generateNewKeysAndCert; // Generate new keys and certificate
@FindBy(xpath = "//button[text()='Regenerate registration access token']")
private WebElement regenerateRegistrationAccessTokenButton;
@FindBy(xpath = "//button[@data-ng-click='regenerateRegistrationAccessToken()']")
private WebElement regenerateRegistrationAccessTokenButton; // Regenerate registration access token
public void selectClientIdAndSecret() {
clientAuthenticatorType.selectByVisibleText("Client Id and Secret");
@ -53,14 +54,17 @@ public class ClientCredentialsForm extends Form {
}
public void regenerateSecret() {
waitUntilElement(regenerateSecretButton).is().visible();
regenerateSecretButton.click();
}
public void regenerateRegistrationAccessToken() {
waitUntilElement(regenerateRegistrationAccessTokenButton).is().visible();
regenerateRegistrationAccessTokenButton.click();
}
public void generateNewKeysAndCert() {
waitUntilElement(generateNewKeysAndCert).is().visible();
generateNewKeysAndCert.click();
}
}

View file

@ -31,7 +31,7 @@ import org.openqa.selenium.support.FindBy;
*/
public class ClientScopeForm extends Form {
@FindBy(className = "onoffswitch")
@FindBy(xpath = ".//div[@class='onoffswitch' and ./input[@id='fullScopeAllowed']]")
private OnOffSwitch fullScopeAllowedSwitch;

View file

@ -4,6 +4,8 @@ import org.keycloak.testsuite.console.page.AdminConsoleRealm;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import static org.keycloak.testsuite.util.WaitUtils.*;
/**
*
* @author tkyjovsk
@ -37,34 +39,42 @@ public class RealmSettings extends AdminConsoleRealm {
private WebElement defenseTab;
public void general() {
waitUntilElement(generalSettingsTab).is().present();
generalSettingsTab.click();
}
public void login() {
waitUntilElement(loginSettingsTab).is().present();
loginSettingsTab.click();
}
public void keys() {
waitUntilElement(keysSettingsTab).is().present();
keysSettingsTab.click();
}
public void email() {
waitUntilElement(emailSettingsTab).is().present();
emailSettingsTab.click();
}
public void themes() {
waitUntilElement(themeSettingsTab).is().present();
themeSettingsTab.click();
}
public void cache() {
waitUntilElement(cacheSettingsTab).is().present();
cacheSettingsTab.click();
}
public void tokens() {
waitUntilElement(tokenSettingsTab).is().present();
tokenSettingsTab.click();
}
public void securityDefenses() {
waitUntilElement(defenseTab).is().present();
defenseTab.click();
}

View file

@ -5,6 +5,8 @@ import static org.keycloak.testsuite.console.page.fragment.Breadcrumb.BREADCRUMB
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import static org.keycloak.testsuite.util.WaitUtils.*;
/**
*
* @author tkyjovsk
@ -54,22 +56,27 @@ public class User extends Users {
private WebElement sessionsLink;
public void attributes() {
waitUntilElement(attributesLink).is().present();
attributesLink.click();
}
public void credentials() {
waitUntilElement(consentsLink).is().present();
credentialsLink.click();
}
public void roleMappings() {
waitUntilElement(roleMappingsLink).is().present();
roleMappingsLink.click();
}
public void consents() {
waitUntilElement(consentsLink).is().present();
consentsLink.click();
}
public void sessions() {
waitUntilElement(sessionsLink).is().present();
sessionsLink.click();
}

View file

@ -17,6 +17,7 @@
*/
package org.keycloak.testsuite.console.page.users;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -42,8 +43,8 @@ public class Users extends AdminConsoleRealm {
}
public static final String VIEW_ALL_USERS = "View all users";
public static final String UNLOCK_USERS = "Unlock Users";
public static final String ADD_USER = "Add User";
public static final String UNLOCK_USERS = "Unlock users";
public static final String ADD_USER = "Add user";
public static final String EDIT = "Edit";
public static final String IMPERSONATE = "Impersonate";
@ -73,19 +74,22 @@ public class Users extends AdminConsoleRealm {
public void clickUser(String username) {
waitUntilElement(body()).is().present();
body().findElement(linkText(username)).click();
WebElement link = body().findElement(
By.xpath(".//tr/td[./following::td[text()='" + username + "']]/a")
);
link.click();
}
public void editUser(String username) {
clickRowActionButton(getRowByLinkText(username), EDIT);
clickRowActionButton(getRowByUsername(username), EDIT);
}
public void impersonateUser(String username) {
clickRowActionButton(getRowByLinkText(username), IMPERSONATE);
clickRowActionButton(getRowByUsername(username), IMPERSONATE);
}
public void deleteUser(String username) {
clickRowActionButton(getRowByLinkText(username), DELETE);
clickRowActionButton(getRowByUsername(username), DELETE);
modalDialog.confirmDeletion();
}
@ -132,6 +136,14 @@ public class Users extends AdminConsoleRealm {
return users;
}
protected WebElement getRowByUsername(String userName) {
WebElement row = body().findElement(
By.xpath(".//tr[./td/following::td[text()='" + userName + "']]")
);
waitUntilElement(row).is().present();
return row;
}
}
}

View file

@ -107,13 +107,13 @@ public abstract class AbstractConsoleTest extends AbstractAuthTest {
public void assertAlertSuccess() {
alert.waitUntilPresentAndClassSet();
assertTrue(alert.isSuccess());
assertTrue("Is not success; @class=" + alert.getAttributeClass(), alert.isSuccess());
alert.close();
}
public void assertAlertDanger() {
alert.waitUntilPresentAndClassSet();
assertTrue(alert.isDanger());
assertTrue("Is not danger; @class=" + alert.getAttributeClass(), alert.isDanger());
alert.close();
}

View file

@ -43,6 +43,7 @@ import static org.keycloak.testsuite.util.AttributesAssert.assertEqualsBooleanAt
import static org.keycloak.testsuite.util.AttributesAssert.assertEqualsListAttributes;
import static org.keycloak.testsuite.util.AttributesAssert.assertEqualsStringAttributes;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
import static org.keycloak.testsuite.util.WaitUtils.pause;
/**
*
@ -69,11 +70,14 @@ public abstract class AbstractClientTest extends AbstractConsoleTest {
}
public void createClient(ClientRepresentation client) {
WaitUtils.waitUntilElement(By.tagName("body"));
WaitUtils.waitUntilElement(By.tagName("body")).is().present();
assertCurrentUrlEquals(clientsPage);
clientsPage.table().createClient();
createClientPage.form().setValues(client);
createClientPage.form().save();
assertAlertSuccess();
pause(500); // To ensure that the form will be loaded completely
clientSettingsPage.form().setValues(client);
if (SAML.equals(client.getProtocol())) {

View file

@ -41,7 +41,7 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
createLdapUserProvider.form().setLdapBindDnInput("KEYCLOAK/Administrator");
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(false);
// createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(false);
// enable kerberos
createLdapUserProvider.form().setAllowKerberosAuthEnabled(true);
createLdapUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");
@ -119,7 +119,7 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(true);
// createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(true);
createLdapUserProvider.form().save();
assertAlertSuccess();
LDAPEmbeddedServer ldapServer = null;
@ -152,7 +152,7 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
assertEquals(searchScope, ufpr.getConfig().get("searchScope"));
assertEquals(connectionPooling, ufpr.getConfig().get("connectionPooling"));
assertEquals(pagination, ufpr.getConfig().get("pagination"));
assertEquals(enableAccountAfterPasswordUpdate, ufpr.getConfig().get("userAccountControlsAfterPasswordUpdate"));
// assertEquals(enableAccountAfterPasswordUpdate, ufpr.getConfig().get("userAccountControlsAfterPasswordUpdate"));
}
private void assertLdapBasicMapping(UserFederationProviderRepresentation ufpr, String usernameLdapAttribute,

View file

@ -29,6 +29,7 @@ public class InternationalizationTest extends AbstractRealmTest {
tabs().themes();
themeSettingsPage.setInternatEnabled(true);
themeSettingsPage.saveTheme();
assertAlertSuccess();
realmSettingsPage.setAdminRealm(AuthRealm.TEST);
accountPage.setAuthRealm(testRealmPage);
deleteAllCookiesForTestRealm();
@ -76,11 +77,13 @@ public class InternationalizationTest extends AbstractRealmTest {
}
private void assertConsoleLocale(String expected) {
pause(500);
assertCurrentUrlEquals(realmSettingsPage);
assertLocale(".//a[contains(@href,'/theme-settings')]", expected); // Themes
}
private void assertAccountLocale(String expected) {
pause(500);
assertCurrentUrlEquals(accountPage);
assertLocale(".//div[contains(@class,'bs-sidebar')]/ul/li", expected); // Account
}

View file

@ -173,7 +173,7 @@ public class SecurityDefensesTest extends AbstractRealmTest {
}
private void assertFeedbackText(String text) {
waitUntilElement(feedbackTextElement);
waitUntilElement(feedbackTextElement).is().present();
assertEquals(text, feedbackTextElement.getText());
}

View file

@ -36,8 +36,8 @@ public class TokensTest extends AbstractRealmTest {
@Page
private TokenSettings tokenSettingsPage;
private static final int TIMEOUT = 4;
private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
private static final int TIMEOUT = 1;
private static final TimeUnit TIME_UNIT = TimeUnit.MINUTES;
@Before
public void beforeTokensTest() {
@ -52,7 +52,7 @@ public class TokensTest extends AbstractRealmTest {
tokenSettingsPage.form().save();
loginToTestRealmConsoleAs(testUser);
TIME_UNIT.sleep(TIMEOUT + 2);
waitForTimeout(TIMEOUT + 2);
driver.navigate().refresh();
@ -66,16 +66,22 @@ public class TokensTest extends AbstractRealmTest {
tokenSettingsPage.form().save();
loginToTestRealmConsoleAs(testUser);
TIME_UNIT.sleep(TIMEOUT / 2);
waitForTimeout(TIMEOUT / 2);
driver.navigate().refresh();
assertCurrentUrlStartsWith(testRealmAdminConsolePage); // assert still logged in (within lifespan)
TIME_UNIT.sleep(TIMEOUT / 2 + 2);
waitForTimeout(TIMEOUT / 2 + 2);
driver.navigate().refresh();
log.debug(driver.getCurrentUrl());
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); // assert logged out (lifespan exceeded)
}
private void waitForTimeout (int timeout) throws InterruptedException {
log.info("Wait for timeout: " + timeout + " " + TIME_UNIT);
TIME_UNIT.sleep(timeout);
log.info("Timeout reached");
}
}