KEYCLOAK-7925 Initial tests for the new Account Console
This commit is contained in:
parent
c56e171f3a
commit
bd8510f4da
30 changed files with 1791 additions and 115 deletions
|
@ -16,13 +16,13 @@
|
|||
*/
|
||||
package org.keycloak.testsuite.auth.page.account.fragment;
|
||||
|
||||
import org.keycloak.testsuite.page.AbstractAlert;
|
||||
import org.keycloak.testsuite.page.AbstractPatternFlyAlert;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class AccountManagementAlert extends AbstractAlert {
|
||||
public class AccountManagementPatternFlyAlert extends AbstractPatternFlyAlert {
|
||||
|
||||
public boolean isError() {
|
||||
return checkAlertType("error");
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||
import org.keycloak.testsuite.page.PatternFlyClosableAlert;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public abstract class AbstractAccountPage extends AuthRealm {
|
||||
@Page
|
||||
private PatternFlyClosableAlert alert;
|
||||
|
||||
public AbstractAccountPage() {
|
||||
setAuthRealm(TEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Account Console is based on hash routing, e.g. [server_root]/auth/realms/test/account/#/password.
|
||||
* All page objects for Account Console need to specify their "hash path" using this method.
|
||||
*
|
||||
* @return the hash path
|
||||
*/
|
||||
protected abstract List<String> createHashPath();
|
||||
|
||||
@Override
|
||||
public UriBuilder createUriBuilder() {
|
||||
String fragment = null;
|
||||
final List<String> hashPath = createHashPath();
|
||||
if (hashPath != null) {
|
||||
fragment = "/" + String.join("/", hashPath);
|
||||
}
|
||||
|
||||
return super.createUriBuilder().path("account/").fragment(fragment);
|
||||
}
|
||||
|
||||
public PatternFlyClosableAlert alert() {
|
||||
return alert;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.VerticalNavBar;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public abstract class AbstractLoggedInPage extends AbstractAccountPage {
|
||||
@Page
|
||||
protected WelcomeScreen welcomeScreen;
|
||||
|
||||
@FindBy(className = "nav-pf-vertical nav-pf-vertical-with-badges")
|
||||
private VerticalNavBar verticalNavBar;
|
||||
|
||||
@FindBy(id = "pageTitle")
|
||||
protected WebElement pageTitle;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should simulate a user navigating to this page using links in the nav bar. It assume that user is logged in
|
||||
* and at some Account Console page (not Welcome Screen), i.e. that the nav bar is visible.
|
||||
*/
|
||||
public abstract void navigateToUsingNavBar();
|
||||
|
||||
public VerticalNavBar verticalNavBar() {
|
||||
return verticalNavBar;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class ApplicationsPage extends AbstractLoggedInPage {
|
||||
@Page
|
||||
private ApplicationsCard applicationsCard;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
List<String> hashPath = super.createHashPath();
|
||||
hashPath.add("applications");
|
||||
return hashPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateToUsingNavBar() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && applicationsCard.isVisible();
|
||||
}
|
||||
|
||||
public ApplicationsCard applications() {
|
||||
return applicationsCard;
|
||||
}
|
||||
|
||||
public class ApplicationsCard extends Card {
|
||||
@FindBy(className = "card-pf-application")
|
||||
private WebElement cardRoot;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(cardRoot);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class AuthenticatorPage extends AbstractLoggedInPage {
|
||||
@Page
|
||||
private YourAuthenticatorsCard yourAuthenticatorsCard;
|
||||
@Page
|
||||
private AddAuthenticatorCard addAuthenticatorCard;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
List<String> hashPath = super.createHashPath();
|
||||
hashPath.add("authenticator");
|
||||
return hashPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateToUsingNavBar() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && yourAuthenticators().isVisible() && addAuthenticator().isVisible();
|
||||
}
|
||||
|
||||
public YourAuthenticatorsCard yourAuthenticators() {
|
||||
return yourAuthenticatorsCard;
|
||||
}
|
||||
|
||||
public AddAuthenticatorCard addAuthenticator() {
|
||||
return addAuthenticatorCard;
|
||||
}
|
||||
|
||||
public class YourAuthenticatorsCard extends Card {
|
||||
@FindBy(id = "authenticatorFinishSetUpTitle")
|
||||
private WebElement yourAuthenticatorsTitle;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(yourAuthenticatorsTitle);
|
||||
}
|
||||
}
|
||||
|
||||
public class AddAuthenticatorCard extends Card {
|
||||
@FindBy(id = "authenticatorSubTitle")
|
||||
private WebElement addAuthenticatorTitle;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(addAuthenticatorTitle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.clickBtnAndWaitForAlert;
|
||||
import static org.keycloak.testsuite.util.UIUtils.getTextFromElement;
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
import static org.keycloak.testsuite.util.UIUtils.setTextInputValue;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class ChangePasswordPage extends AbstractLoggedInPage {
|
||||
@Page
|
||||
private UpdatePasswordCard updatePasswordCard;
|
||||
@Page
|
||||
private PasswordLastUpdateCard passwordLastUpdateCard;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
List<String> hashPath = super.createHashPath();
|
||||
hashPath.add("password");
|
||||
return hashPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateToUsingNavBar() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && updatePassword().isVisible();
|
||||
}
|
||||
|
||||
public PasswordLastUpdateCard passwordLastUpdate() {
|
||||
return passwordLastUpdateCard;
|
||||
}
|
||||
|
||||
public UpdatePasswordCard updatePassword() {
|
||||
return updatePasswordCard;
|
||||
}
|
||||
|
||||
public class PasswordLastUpdateCard extends Card {
|
||||
@FindBy(id = "passwordLastUpdate")
|
||||
private WebElement cardRoot;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(cardRoot);
|
||||
}
|
||||
|
||||
public String getTextDateTime() {
|
||||
return getTextFromElement(cardRoot.findElement(By.tagName("strong")));
|
||||
}
|
||||
|
||||
public LocalDateTime getDateTime() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d, yyyy, h:m:s a"); // e.g. Aug 31, 2018, 5:41:24 PM
|
||||
return LocalDateTime.from(formatter.parse(getTextDateTime()));
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdatePasswordCard extends Card {
|
||||
@FindBy(id = "updatePasswordSubTitle")
|
||||
private WebElement updatePasswordSubTitle;
|
||||
@FindBy(id = "password")
|
||||
private WebElement currentPassword;
|
||||
@FindBy(id = "newPassword")
|
||||
private WebElement newPassword;
|
||||
@FindBy(id = "confirmation")
|
||||
private WebElement confirmPassword;
|
||||
@FindBy(name = "submitAction")
|
||||
private WebElement submitBtn;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(updatePasswordSubTitle);
|
||||
}
|
||||
|
||||
public void setCurrentPassword(String value) {
|
||||
setTextInputValue(currentPassword, value);
|
||||
}
|
||||
|
||||
public void setNewPassword(String value) {
|
||||
setTextInputValue(newPassword, value);
|
||||
}
|
||||
|
||||
public void setConfirmPassword(String value) {
|
||||
setTextInputValue(confirmPassword, value);
|
||||
}
|
||||
|
||||
public boolean isSaveDisabled() {
|
||||
return submitBtn.getAttribute("disabled") != null;
|
||||
}
|
||||
|
||||
public void clickSave() {
|
||||
clickBtnAndWaitForAlert(submitBtn);
|
||||
}
|
||||
|
||||
public void setPasswords(String currentPassword, String newPassword) {
|
||||
setCurrentPassword(currentPassword);
|
||||
setNewPassword(newPassword);
|
||||
setConfirmPassword(newPassword);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class DeviceActivityPage extends AbstractLoggedInPage {
|
||||
@Page
|
||||
private SignedInDevicesCard signedInDevicesCard;
|
||||
@Page
|
||||
private RecentlyUsedDevicesCard recentlyUsedDevicesCard;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
List<String> hashPath = super.createHashPath();
|
||||
hashPath.add("device-activity");
|
||||
return hashPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateToUsingNavBar() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && signedInDevices().isVisible() && recentlyUsedDevices().isVisible();
|
||||
}
|
||||
|
||||
public SignedInDevicesCard signedInDevices() {
|
||||
return signedInDevicesCard;
|
||||
}
|
||||
|
||||
public RecentlyUsedDevicesCard recentlyUsedDevices() {
|
||||
return recentlyUsedDevicesCard;
|
||||
}
|
||||
|
||||
public class SignedInDevicesCard extends Card {
|
||||
@FindBy(id = "signedInDevicesTitle")
|
||||
private WebElement signedInDevicesTitle;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(signedInDevicesTitle);
|
||||
}
|
||||
}
|
||||
|
||||
public class RecentlyUsedDevicesCard extends Card {
|
||||
@FindBy(id = "recentlyUsedDevicesTitle")
|
||||
private WebElement recentlyUsedDevicesTitle;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(recentlyUsedDevicesTitle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class LinkedAccountsPage extends AbstractLoggedInPage {
|
||||
@Page
|
||||
private AuthorizedProvidersCard authorizedProvidersCard;
|
||||
@Page
|
||||
private AvailableProvidersCard availableProvidersCard;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
List<String> hashPath = super.createHashPath();
|
||||
hashPath.add("linked-accounts");
|
||||
return hashPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateToUsingNavBar() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && authorizedProviders().isVisible() && availableProviders().isVisible();
|
||||
}
|
||||
|
||||
public AuthorizedProvidersCard authorizedProviders() {
|
||||
return authorizedProvidersCard;
|
||||
}
|
||||
|
||||
public AvailableProvidersCard availableProviders() {
|
||||
return availableProvidersCard;
|
||||
}
|
||||
|
||||
public class AuthorizedProvidersCard extends Card {
|
||||
@FindBy(id = "authorizedProvidersSubTitle")
|
||||
private WebElement authorizedProvidersTitle;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(authorizedProvidersTitle);
|
||||
}
|
||||
}
|
||||
|
||||
public class AvailableProvidersCard extends Card {
|
||||
@FindBy(id = "identityProviderSubTitle")
|
||||
private WebElement availableProvidersTitle;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(availableProvidersTitle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.clickBtnAndWaitForAlert;
|
||||
import static org.keycloak.testsuite.util.UIUtils.getTextInputValue;
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
import static org.keycloak.testsuite.util.UIUtils.setTextInputValue;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class PersonalInfoPage extends AbstractLoggedInPage {
|
||||
@Page
|
||||
private PersonalInfoCard personalInfoCard;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
List<String> hashPath = super.createHashPath();
|
||||
hashPath.add("account");
|
||||
return hashPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateToUsingNavBar() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && personalInfo().isVisible();
|
||||
}
|
||||
|
||||
public PersonalInfoCard personalInfo() {
|
||||
return personalInfoCard;
|
||||
}
|
||||
|
||||
public class PersonalInfoCard extends Card {
|
||||
@FindBy(id = "personalSubTitle")
|
||||
private WebElement personalSubTitle;
|
||||
@FindBy(id = "username")
|
||||
private WebElement username;
|
||||
@FindBy(id = "email")
|
||||
private WebElement email;
|
||||
@FindBy(id = "firstName")
|
||||
private WebElement firstName;
|
||||
@FindBy(id = "lastName")
|
||||
private WebElement lastName;
|
||||
@FindBy(name = "submitAction")
|
||||
private WebElement submitBtn;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(personalSubTitle);
|
||||
}
|
||||
|
||||
public boolean isUsernameDisabled() {
|
||||
return !username.getTagName().equals("input"); // <div> for disabled
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return getTextInputValue(username);
|
||||
}
|
||||
|
||||
public void setUsername(String value) {
|
||||
setTextInputValue(username, value);
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return getTextInputValue(email);
|
||||
}
|
||||
|
||||
public void setEmail(String value) {
|
||||
setTextInputValue(email, value);
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return getTextInputValue(firstName);
|
||||
}
|
||||
|
||||
public void setFirstName(String value) {
|
||||
setTextInputValue(firstName, value);
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return getTextInputValue(lastName);
|
||||
}
|
||||
|
||||
public void setLastName(String value) {
|
||||
setTextInputValue(lastName, value);
|
||||
}
|
||||
|
||||
public boolean isSaveDisabled() {
|
||||
return submitBtn.getAttribute("disabled") != null;
|
||||
}
|
||||
|
||||
public void clickSave() {
|
||||
clickBtnAndWaitForAlert(submitBtn);
|
||||
}
|
||||
|
||||
public void setValues(UserRepresentation user) {
|
||||
if (!isUsernameDisabled()) {setUsername(user.getUsername());}
|
||||
setEmail(user.getEmail());
|
||||
setFirstName(user.getFirstName());
|
||||
setLastName(user.getLastName());
|
||||
}
|
||||
|
||||
public boolean valuesEqual(UserRepresentation user) {
|
||||
return user.getUsername().equals(getUsername())
|
||||
&& user.getEmail().equals(getEmail())
|
||||
&& user.getFirstName().equals(getFirstName())
|
||||
&& user.getLastName().equals(getLastName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class ResourcesPage extends AbstractLoggedInPage {
|
||||
@Page
|
||||
private ResourcesListCard resourcesListCard;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
List<String> hashPath = super.createHashPath();
|
||||
hashPath.add("my-resources");
|
||||
return hashPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigateToUsingNavBar() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return super.isCurrent() && resourcesListCard.isVisible();
|
||||
}
|
||||
|
||||
public ResourcesListCard resourcesList() {
|
||||
return resourcesListCard;
|
||||
}
|
||||
|
||||
public class ResourcesListCard extends Card {
|
||||
@FindBy(className = "resources-list")
|
||||
private WebElement cardRoot;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(cardRoot);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.keycloak.testsuite.auth.page.account2.fragment.Card;
|
||||
import org.keycloak.testsuite.util.URLUtils;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.clickLink;
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class WelcomeScreen extends AbstractAccountPage {
|
||||
@Page
|
||||
private PersonalInfoCard personalInfo;
|
||||
@Page
|
||||
private AccountSecurityCard accountSecurityCard;
|
||||
@Page
|
||||
private ApplicationsCard applicationsCard;
|
||||
@Page
|
||||
private MyResourcesCard myResourcesCard;
|
||||
@FindBy(id = "welcomeMsg")
|
||||
private WebElement welcomeMsg;
|
||||
@FindBy(id = "signInButton")
|
||||
private WebElement signInBtn;
|
||||
|
||||
@Override
|
||||
protected List<String> createHashPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() {
|
||||
return URLUtils.currentUrlEquals(toString() + "#/") && isElementVisible(welcomeMsg); // the hash will be eventually added after the page is loaded
|
||||
}
|
||||
|
||||
public PersonalInfoCard personalInfo() {
|
||||
return personalInfo;
|
||||
}
|
||||
|
||||
public AccountSecurityCard accountSecurityCard() {
|
||||
return accountSecurityCard;
|
||||
}
|
||||
|
||||
public ApplicationsCard applicationsCard() {
|
||||
return applicationsCard;
|
||||
}
|
||||
|
||||
public MyResourcesCard myResourcesCard() {
|
||||
return myResourcesCard;
|
||||
}
|
||||
|
||||
public void clickLoginBtn() {
|
||||
clickLink(signInBtn);
|
||||
}
|
||||
|
||||
public boolean isLoginBtnVisible() {
|
||||
return isElementVisible(signInBtn);
|
||||
}
|
||||
|
||||
public class PersonalInfoCard extends Card {
|
||||
@FindBy(id = "personalInfoCard")
|
||||
private WebElement personalInfoCard;
|
||||
@FindBy(id = "personalInfoLink")
|
||||
private WebElement personalInfoLink;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(personalInfoCard);
|
||||
}
|
||||
|
||||
public void clickPersonalInfo() {
|
||||
clickLink(personalInfoLink);
|
||||
}
|
||||
}
|
||||
|
||||
public class AccountSecurityCard extends Card {
|
||||
@FindBy(id = "accountSecurityCard")
|
||||
private WebElement accountSecurityCard;
|
||||
@FindBy(id = "changePasswordLink")
|
||||
private WebElement changePasswordLink;
|
||||
@FindBy(id = "authenticatorLink")
|
||||
private WebElement authenticatorLink;
|
||||
@FindBy(id = "deviceActivityLink")
|
||||
private WebElement deviceActivityLink;
|
||||
@FindBy(id = "linkedAccountsLink")
|
||||
private WebElement linkedAccountsLink;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(accountSecurityCard);
|
||||
}
|
||||
|
||||
public void clickChangePassword() {
|
||||
clickLink(changePasswordLink);
|
||||
}
|
||||
|
||||
public void clickAuthenticator() {
|
||||
clickLink(authenticatorLink);
|
||||
}
|
||||
|
||||
public void clickDeviceActivity() {
|
||||
clickLink(deviceActivityLink);
|
||||
}
|
||||
|
||||
public void clickLinkedAccounts() {
|
||||
clickLink(linkedAccountsLink);
|
||||
}
|
||||
|
||||
public boolean isLinkedAccountsVisible() {
|
||||
return isElementVisible(linkedAccountsLink);
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationsCard extends Card {
|
||||
@FindBy(id = "applicationsCard")
|
||||
private WebElement applicationsCard;
|
||||
@FindBy(id = "applicationsLink")
|
||||
private WebElement applicationsLink;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(applicationsCard);
|
||||
}
|
||||
|
||||
public void clickApplicationsLink() {
|
||||
clickLink(applicationsLink);
|
||||
}
|
||||
}
|
||||
|
||||
public class MyResourcesCard extends Card {
|
||||
@FindBy(id = "myResourcesCard")
|
||||
private WebElement myResourcesCard;
|
||||
@FindBy(id = "myResourcesLink")
|
||||
private WebElement myResourcesLink;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return isElementVisible(myResourcesCard);
|
||||
}
|
||||
|
||||
public void clickMyResources() {
|
||||
clickLink(myResourcesLink);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2.fragment;
|
||||
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public abstract class Card {
|
||||
@Drone
|
||||
private WebDriver driver;
|
||||
|
||||
public abstract boolean isVisible();
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.auth.page.account2.fragment;
|
||||
|
||||
import org.jboss.arquillian.graphene.fragment.Root;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import static org.keycloak.testsuite.util.UIUtils.clickLink;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
// TODO rewrite this (blocked by KEYCLOAK-8217)
|
||||
public class VerticalNavBar {
|
||||
@Root
|
||||
private WebElement navBarRoot;
|
||||
|
||||
public void clickNavLinkByIndex(int i) {
|
||||
clickLink(getNavLinkByIndex(i));
|
||||
}
|
||||
|
||||
public void clickSubNavLinkByIndex(int i1, int i2) {
|
||||
clickLink(getNavLinkByIndex(i1));
|
||||
clickLink(getSubNavLinkByIndex(i1, i2));
|
||||
}
|
||||
|
||||
public boolean isNavLinkActive(int i) {
|
||||
return isNavLinkActive(getNavLinkByIndex(i));
|
||||
}
|
||||
|
||||
public boolean isSubNavLinkActive(int i1, int i2) {
|
||||
return isNavLinkActive(getSubNavLinkByIndex(i1, i2));
|
||||
}
|
||||
|
||||
private WebElement getNavLinkByIndex(int i) {
|
||||
return navBarRoot.findElement(By.xpath(String.format("./ul/li[%d]", i)));
|
||||
}
|
||||
|
||||
private WebElement getSubNavLinkByIndex(int i1, int i2) {
|
||||
return navBarRoot.findElement(By.xpath(String.format("./ul/li[%d]/div[contains(@class,'nav-pf-secondary-nav')]/ul/li[%d]", i1, i2)));
|
||||
}
|
||||
|
||||
private boolean isNavLinkActive(WebElement navLink) {
|
||||
return navLink.getAttribute("class").contains("active");
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.page;
|
||||
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.jboss.arquillian.graphene.fragment.Root;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
import org.openqa.selenium.TimeoutException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public abstract class AbstractAlert {
|
||||
|
||||
protected final Logger log = Logger.getLogger(this.getClass());
|
||||
|
||||
@Root
|
||||
protected WebElement root;
|
||||
|
||||
@Drone
|
||||
protected WebDriver driver;
|
||||
|
||||
public String getText() {
|
||||
return root.getText();
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
log.debug("Alert.isSuccess()");
|
||||
return checkAlertType("success");
|
||||
}
|
||||
|
||||
protected boolean checkAlertType(String type) {
|
||||
WaitUtils.waitForPageToLoad();
|
||||
try {
|
||||
(new WebDriverWait(driver, 1)).until(ExpectedConditions.attributeContains(root, "class", "alert-" + type));
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.page;
|
||||
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.TimeoutException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.util.DroneUtils.getCurrentDriver;
|
||||
import static org.keycloak.testsuite.util.UIUtils.getTextFromElement;
|
||||
import static org.keycloak.testsuite.util.UIUtils.isElementVisible;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.PAGELOAD_TIMEOUT_MILLIS;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public abstract class AbstractPatternFlyAlert {
|
||||
public static final String ALERT_CLASS_NAME = "alert";
|
||||
|
||||
protected final Logger log = Logger.getLogger(this.getClass());
|
||||
|
||||
@FindBy(className = ALERT_CLASS_NAME)
|
||||
protected WebElement alertRoot;
|
||||
|
||||
@Drone
|
||||
protected WebDriver driver;
|
||||
|
||||
public boolean isDisplayed() {
|
||||
return isElementVisible(alertRoot);
|
||||
}
|
||||
|
||||
public static void waitUntilDisplayed() {
|
||||
new WebDriverWait(getCurrentDriver(), PAGELOAD_TIMEOUT_MILLIS / 1000).until(
|
||||
ExpectedConditions.visibilityOfElementLocated(By.className(ALERT_CLASS_NAME))
|
||||
);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return getTextFromElement(alertRoot);
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return checkAlertType("success");
|
||||
}
|
||||
|
||||
public void assertDisplayed() {
|
||||
assertTrue("Alert should displayed", isDisplayed());
|
||||
}
|
||||
|
||||
public void assertNotDisplayed() {
|
||||
assertFalse("Alert shouldn't be displayed", isDisplayed());
|
||||
}
|
||||
|
||||
public void assertSuccess() {
|
||||
assertSuccess(null);
|
||||
}
|
||||
|
||||
public void assertSuccess(String expectedText) {
|
||||
assertDisplayed();
|
||||
assertTrue("Alert type should be success", isSuccess());
|
||||
if (expectedText != null) assertEquals(expectedText, getText());
|
||||
}
|
||||
|
||||
protected boolean checkAlertType(String type) {
|
||||
try {
|
||||
new WebDriverWait(driver, 1).until(ExpectedConditions.attributeContains(alertRoot, "class", "alert-" + type));
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -14,20 +14,21 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.console.page.fragment;
|
||||
package org.keycloak.testsuite.page;
|
||||
|
||||
import org.jboss.arquillian.graphene.fragment.Root;
|
||||
import org.keycloak.testsuite.page.AbstractAlert;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Petr Mensik
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
public class AdminConsoleAlert extends AbstractAlert {
|
||||
public class PatternFlyClosableAlert extends AbstractPatternFlyAlert {
|
||||
|
||||
@FindBy(xpath = ".//button[@class='close']")
|
||||
protected WebElement closeButton;
|
||||
|
@ -44,6 +45,45 @@ public class AdminConsoleAlert extends AbstractAlert {
|
|||
return checkAlertType("danger");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertSuccess(String expectedText) {
|
||||
super.assertSuccess(expectedText);
|
||||
close();
|
||||
}
|
||||
|
||||
public void assertInfo() {
|
||||
assertInfo(null);
|
||||
}
|
||||
|
||||
public void assertInfo(String expectedText) {
|
||||
assertDisplayed();
|
||||
assertTrue("Alert type should be info", isInfo());
|
||||
if (expectedText != null) assertEquals(expectedText, getText());
|
||||
close();
|
||||
}
|
||||
|
||||
public void assertWarning() {
|
||||
assertWarning(null);
|
||||
}
|
||||
|
||||
public void assertWarning(String expectedText) {
|
||||
assertDisplayed();
|
||||
assertTrue("Alert type should be warning", isWarning());
|
||||
if (expectedText != null) assertEquals(expectedText, getText());
|
||||
close();
|
||||
}
|
||||
|
||||
public void assertDanger() {
|
||||
assertDanger(null);
|
||||
}
|
||||
|
||||
public void assertDanger(String expectedText) {
|
||||
assertDisplayed();
|
||||
assertTrue("Alert type should be danger", isDanger());
|
||||
if (expectedText != null) assertEquals(expectedText, getText());
|
||||
close();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
closeButton.click();
|
||||
WaitUtils.pause(500); // Sometimes, when a test is too fast,
|
|
@ -1,7 +1,12 @@
|
|||
package org.keycloak.testsuite.util;
|
||||
|
||||
import io.appium.java_client.android.AndroidDriver;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.keycloak.testsuite.page.AbstractPatternFlyAlert;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.JavascriptExecutor;
|
||||
import org.openqa.selenium.Keys;
|
||||
import org.openqa.selenium.NoSuchElementException;
|
||||
import org.openqa.selenium.TimeoutException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
@ -19,6 +24,7 @@ import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
|||
public final class UIUtils {
|
||||
|
||||
public static final String VALUE_ATTR_NAME = "value";
|
||||
public static final short EXPECTED_UI_LAYOUT = Short.parseShort(System.getProperty("testsuite.ui.layout")); // 0 == desktop layout, 1 == smartphone layout, 2 == tablet layout
|
||||
|
||||
public static boolean selectContainsOption(Select select, String optionText) {
|
||||
for (WebElement option : select.getOptions()) {
|
||||
|
@ -55,6 +61,18 @@ public final class UIUtils {
|
|||
performOperationWithPageReload(element::click);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is as an alternative for {@link #clickLink(WebElement)} and should be used in situations where we can't use
|
||||
* {@link WaitUtils#waitForPageToLoad()}. This is because {@link WaitUtils#waitForPageToLoad()} would wait until the
|
||||
* alert would disappeared itself (timeout).
|
||||
*
|
||||
* @param button to click on
|
||||
*/
|
||||
public static void clickBtnAndWaitForAlert(WebElement button) {
|
||||
button.click();
|
||||
AbstractPatternFlyAlert.waitUntilDisplayed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to a link directly instead of clicking on it.
|
||||
* Some browsers are sometimes having problems with clicking on links, so this should be used only in that cases,
|
||||
|
@ -93,9 +111,13 @@ public final class UIUtils {
|
|||
public static void setTextInputValue(WebElement input, String value) {
|
||||
input.click();
|
||||
input.clear();
|
||||
if (value != null) {
|
||||
if (!StringUtils.isEmpty(value)) { // setting new input
|
||||
input.sendKeys(value);
|
||||
}
|
||||
else { // just clearing the input; input.clear() may not fire all JS events so we need to let the page know that something's changed
|
||||
input.sendKeys("a");
|
||||
input.sendKeys(Keys.BACK_SPACE);
|
||||
}
|
||||
|
||||
WebDriver driver = getCurrentDriver();
|
||||
if (driver instanceof AndroidDriver) {
|
||||
|
@ -117,4 +139,21 @@ public final class UIUtils {
|
|||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be used solely with {@link org.jboss.arquillian.graphene.GrapheneElement}, i.e. all elements annotated by
|
||||
* {@link org.openqa.selenium.support.FindBy}. CANNOT be used with elements found directly using
|
||||
* {@link WebDriver#findElement(By)} and similar.
|
||||
*
|
||||
* @param element
|
||||
* @return true if element is present and visible
|
||||
*/
|
||||
public static boolean isElementVisible(WebElement element) {
|
||||
try {
|
||||
return element.isDisplayed();
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,21 +16,25 @@
|
|||
*/
|
||||
package org.keycloak.testsuite.util;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.jboss.arquillian.graphene.wait.ElementBuilder;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.TimeoutException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
|
||||
import org.openqa.selenium.support.ui.ExpectedCondition;
|
||||
import org.openqa.selenium.support.ui.FluentWait;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.jboss.arquillian.graphene.Graphene.waitGui;
|
||||
import static org.keycloak.testsuite.util.DroneUtils.getCurrentDriver;
|
||||
import static org.openqa.selenium.support.ui.ExpectedConditions.*;
|
||||
import static org.openqa.selenium.support.ui.ExpectedConditions.javaScriptThrowsNoExceptions;
|
||||
import static org.openqa.selenium.support.ui.ExpectedConditions.not;
|
||||
import static org.openqa.selenium.support.ui.ExpectedConditions.urlToBe;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -97,9 +101,11 @@ public final class WaitUtils {
|
|||
return; // not needed
|
||||
}
|
||||
|
||||
String currentUrl = null;
|
||||
|
||||
// Ensure the URL is "stable", i.e. is not changing anymore; if it'd changing, some redirects are probably still in progress
|
||||
for (int maxRedirects = 2; maxRedirects > 0; maxRedirects--) {
|
||||
String currentUrl = driver.getCurrentUrl();
|
||||
for (int maxRedirects = 4; maxRedirects > 0; maxRedirects--) {
|
||||
currentUrl = driver.getCurrentUrl();
|
||||
FluentWait<WebDriver> wait = new FluentWait<>(driver).withTimeout(Duration.ofMillis(250));
|
||||
try {
|
||||
wait.until(not(urlToBe(currentUrl)));
|
||||
|
@ -113,19 +119,34 @@ public final class WaitUtils {
|
|||
}
|
||||
|
||||
WebDriverWait wait = new WebDriverWait(getCurrentDriver(), PAGELOAD_TIMEOUT_MILLIS / 1000);
|
||||
ExpectedCondition waitCondition = null;
|
||||
|
||||
try {
|
||||
// Checks if the document is ready and asks AngularJS, if present, whether there are any REST API requests
|
||||
// in progress
|
||||
wait.until(javaScriptThrowsNoExceptions(
|
||||
// Different wait strategies for Admin and Account Consoles
|
||||
if (currentUrl.matches("^[^\\/]+:\\/\\/[^\\/]+\\/auth\\/admin\\/.*$")) { // Admin Console
|
||||
// Checks if the document is ready and asks AngularJS, if present, whether there are any REST API requests in progress
|
||||
waitCondition = javaScriptThrowsNoExceptions(
|
||||
"if (document.readyState !== 'complete' "
|
||||
+ "|| (typeof angular !== 'undefined' && angular.element(document.body).injector().get('$http').pendingRequests.length !== 0)) {"
|
||||
+ "throw \"Not ready\";"
|
||||
+ "}"));
|
||||
} catch (TimeoutException e) {
|
||||
// Sometimes, for no obvious reason, the browser/JS doesn't set document.readyState to 'complete' correctly
|
||||
// but that's no reason to let the test fail; after the timeout the page is surely fully loaded
|
||||
log.warn("waitForPageToLoad time exceeded!");
|
||||
+ "}");
|
||||
}
|
||||
else if (
|
||||
currentUrl.matches("^[^\\/]+:\\/\\/[^\\/]+\\/auth\\/realms\\/[^\\/]+\\/account\\/.*$") // check for Account Console URL
|
||||
&& driver.getPageSource().contains("patternfly-ng") // check for new Account Console (don't use this strategy with the old one)
|
||||
) {
|
||||
waitCondition = javaScriptThrowsNoExceptions(
|
||||
"if (!window.getAngularTestability(document.querySelector('app-root')).isStable()) {" +
|
||||
"throw 'Not ready';" +
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
if (waitCondition != null) {
|
||||
try {
|
||||
wait.until(waitCondition);
|
||||
} catch (TimeoutException e) {
|
||||
log.warn("waitForPageToLoad time exceeded!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
|
|||
deleteAllSessionsInRealm(testRealmAccountPage.getAuthRealm());
|
||||
}
|
||||
|
||||
private void resetTestRealmSession() {
|
||||
protected void resetTestRealmSession() {
|
||||
resetRealmSession(testRealmAccountPage.getAuthRealm());
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,7 @@ import org.jboss.arquillian.graphene.page.Page;
|
|||
import org.junit.Before;
|
||||
import org.keycloak.testsuite.AbstractAuthTest;
|
||||
import org.keycloak.testsuite.auth.page.account.AccountManagement;
|
||||
import org.keycloak.testsuite.auth.page.account.fragment.AccountManagementAlert;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import org.keycloak.testsuite.auth.page.account.fragment.AccountManagementPatternFlyAlert;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
|
@ -36,8 +35,8 @@ public abstract class AbstractAccountManagementTest extends AbstractAuthTest {
|
|||
@Page
|
||||
protected AccountManagement testRealmAccountManagementPage;
|
||||
|
||||
@FindBy(className = "alert")
|
||||
protected AccountManagementAlert alert;
|
||||
@Page
|
||||
protected AccountManagementPatternFlyAlert alert;
|
||||
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
|
|
|
@ -17,16 +17,16 @@
|
|||
|
||||
package org.keycloak.testsuite.ui;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractAuthTest;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
|
@ -34,14 +34,9 @@ public abstract class AbstractUiTest extends AbstractAuthTest {
|
|||
public static final String LOCALIZED_THEME = "localized-theme";
|
||||
public static final String CUSTOM_LOCALE_NAME = "Přísný jazyk";
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation testRealmRep = new RealmRepresentation();
|
||||
testRealmRep.setId(TEST);
|
||||
testRealmRep.setRealm(TEST);
|
||||
testRealmRep.setEnabled(true);
|
||||
configureInternationalizationForRealm(testRealmRep);
|
||||
testRealms.add(testRealmRep);
|
||||
@Before
|
||||
public void addTestUser() {
|
||||
createTestUserWithAdminClient(false);
|
||||
}
|
||||
|
||||
protected void configureInternationalizationForRealm(RealmRepresentation realm) {
|
||||
|
@ -58,4 +53,12 @@ public abstract class AbstractUiTest extends AbstractAuthTest {
|
|||
realm.setAccountTheme(LOCALIZED_THEME);
|
||||
realm.setEmailTheme(LOCALIZED_THEME);
|
||||
}
|
||||
|
||||
protected IdentityProviderRepresentation createIdentityProviderRepresentation(String alias, String providerId) {
|
||||
IdentityProviderRepresentation idpRep = new IdentityProviderRepresentation();
|
||||
idpRep.setProviderId(providerId);
|
||||
idpRep.setAlias(alias);
|
||||
idpRep.setConfig(new HashMap<>());
|
||||
return idpRep;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.ui.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.auth.page.account2.WelcomeScreen;
|
||||
import org.keycloak.testsuite.ui.AbstractUiTest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public abstract class AbstractAccountTest extends AbstractUiTest {
|
||||
public static final String ACCOUNT_THEME_NAME = "keycloak-preview";
|
||||
|
||||
@Page
|
||||
protected WelcomeScreen accountWelcomeScreen;
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
super.addTestRealms(testRealms);
|
||||
RealmRepresentation testRealmRep = testRealms.get(0);
|
||||
testRealmRep.setAccountTheme(ACCOUNT_THEME_NAME);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void enabled() {
|
||||
ProfileAssume.assumeFeatureEnabled(Profile.Feature.ACCOUNT2);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeAccountTest() {
|
||||
accountWelcomeScreen.navigateTo();
|
||||
}
|
||||
|
||||
protected void loginToAccount() {
|
||||
assertCurrentUrlStartsWithLoginUrlOf(accountWelcomeScreen);
|
||||
loginPage.form().login(testUser);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.ui.account2;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.auth.page.account2.AbstractLoggedInPage;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public abstract class BaseAccountPageTest extends AbstractAccountTest {
|
||||
protected abstract AbstractLoggedInPage getAccountPage();
|
||||
|
||||
@Before
|
||||
public void beforeBaseAccountPageTest() {
|
||||
getAccountPage().navigateTo();
|
||||
loginToAccount();
|
||||
getAccountPage().assertCurrent();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO, blocked by KEYCLOAK-8217
|
||||
public void navigationTest() {
|
||||
getAccountPage().navigateToUsingNavBar();
|
||||
getAccountPage().assertCurrent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.ui.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.auth.page.account2.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.ChangePasswordPage;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.admin.Users.getPasswordOf;
|
||||
import static org.keycloak.testsuite.admin.Users.setPasswordFor;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class ChangePasswordTest extends BaseAccountPageTest {
|
||||
@Page
|
||||
private ChangePasswordPage changePasswordPage;
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
super.addTestRealms(testRealms);
|
||||
RealmRepresentation realm = testRealms.get(0);
|
||||
realm.setPasswordPolicy("length(3)");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractLoggedInPage getAccountPage() {
|
||||
return changePasswordPage;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changePassword() {
|
||||
final LocalDateTime testStartTime = LocalDateTime.now();
|
||||
|
||||
final String oldPwd = getPasswordOf(testUser);
|
||||
final String newPwd = "nějaké nové heslo s háčky a čárkami";
|
||||
setPasswordFor(testUser, newPwd);
|
||||
|
||||
assertTrue("The current password should be older than the start time of this test",
|
||||
testStartTime.isAfter(changePasswordPage.passwordLastUpdate().getDateTime()));
|
||||
|
||||
changePasswordPage.updatePassword().setPasswords(oldPwd, newPwd);
|
||||
changePasswordPage.updatePassword().clickSave();
|
||||
changePasswordPage.alert().assertSuccess();
|
||||
|
||||
// try the new password
|
||||
deleteAllSessionsInTestRealm(); // logout
|
||||
changePasswordPage.navigateTo();
|
||||
loginToAccount();
|
||||
changePasswordPage.assertCurrent();
|
||||
|
||||
assertTrue("The new password should be newer than the start time of this test",
|
||||
testStartTime.isBefore(changePasswordPage.passwordLastUpdate().getDateTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formValidationTest() {
|
||||
assertTrue(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
changePasswordPage.updatePassword().setPasswords("abc", "def");
|
||||
assertFalse(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
|
||||
// clear current password
|
||||
changePasswordPage.updatePassword().setCurrentPassword("");
|
||||
assertTrue(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
changePasswordPage.updatePassword().setCurrentPassword("abc");
|
||||
assertFalse(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
|
||||
// clear new password
|
||||
changePasswordPage.updatePassword().setNewPassword("");
|
||||
assertTrue(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
changePasswordPage.updatePassword().setNewPassword("def");
|
||||
assertFalse(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
|
||||
// clear confirm password
|
||||
changePasswordPage.updatePassword().setConfirmPassword("");
|
||||
assertTrue(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
changePasswordPage.updatePassword().setConfirmPassword("def");
|
||||
assertFalse(changePasswordPage.updatePassword().isSaveDisabled());
|
||||
|
||||
// invalid current password
|
||||
changePasswordPage.updatePassword().setPasswords("invalid", "ab");
|
||||
changePasswordPage.updatePassword().clickSave();
|
||||
changePasswordPage.alert().assertDanger("Invalid existing password.");
|
||||
|
||||
// non-matching passwords
|
||||
changePasswordPage.updatePassword().setPasswords(getPasswordOf(testUser), "ab");
|
||||
changePasswordPage.updatePassword().setConfirmPassword("no match");
|
||||
changePasswordPage.updatePassword().clickSave();
|
||||
changePasswordPage.alert().assertDanger("Passwords don't match.");
|
||||
|
||||
// password policy
|
||||
changePasswordPage.updatePassword().setPasswords(getPasswordOf(testUser), "ab");
|
||||
changePasswordPage.updatePassword().clickSave();
|
||||
changePasswordPage.alert().assertDanger("Invalid password: minimum length 3.");
|
||||
|
||||
// check the password is not changed
|
||||
deleteAllSessionsInTestRealm();
|
||||
changePasswordPage.navigateTo();
|
||||
loginToAccount();
|
||||
changePasswordPage.assertCurrent();
|
||||
}
|
||||
|
||||
// TODO test the last update timestamp when the password was never updated (blocked by KEYCLOAK-8193)
|
||||
// TODO test internationalization for last update timestamp (blocked by KEYCLOAK-8194)
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.ui.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.auth.page.account2.AbstractLoggedInPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.PersonalInfoPage;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class PersonalInfoTest extends BaseAccountPageTest {
|
||||
private UserRepresentation testUser2;
|
||||
@Page
|
||||
private PersonalInfoPage personalInfoPage;
|
||||
|
||||
@Before
|
||||
public void setTestUser() {
|
||||
testUser2 = new UserRepresentation();
|
||||
testUser2.setUsername("vmuzikar");
|
||||
testUser2.setEmail("vmuzikar@redhat.com");
|
||||
testUser2.setFirstName("Václav");
|
||||
testUser2.setLastName("Muzikář");
|
||||
ApiUtil.removeUserByUsername(testRealmResource(), testUser2.getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractLoggedInPage getAccountPage() {
|
||||
return personalInfoPage;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateUserInfo() {
|
||||
setEditUsernameAllowed(true);
|
||||
|
||||
assertTrue(personalInfoPage.personalInfo().valuesEqual(testUser));
|
||||
assertFalse(personalInfoPage.personalInfo().isUsernameDisabled());
|
||||
assertTrue(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
|
||||
personalInfoPage.personalInfo().setValues(testUser2);
|
||||
assertTrue(personalInfoPage.personalInfo().valuesEqual(testUser2));
|
||||
assertFalse(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
personalInfoPage.personalInfo().clickSave();
|
||||
personalInfoPage.alert().assertSuccess();
|
||||
|
||||
personalInfoPage.navigateTo();
|
||||
personalInfoPage.personalInfo().valuesEqual(testUser2);
|
||||
|
||||
// change just first and last name
|
||||
testUser2.setFirstName("Another");
|
||||
testUser2.setLastName("Name");
|
||||
personalInfoPage.personalInfo().setValues(testUser2);
|
||||
personalInfoPage.personalInfo().clickSave();
|
||||
personalInfoPage.alert().assertSuccess();
|
||||
personalInfoPage.navigateTo();
|
||||
personalInfoPage.personalInfo().valuesEqual(testUser2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formValidationTest() {
|
||||
setEditUsernameAllowed(true);
|
||||
|
||||
// clear username
|
||||
personalInfoPage.personalInfo().setUsername("");
|
||||
assertTrue(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
personalInfoPage.personalInfo().setUsername("abc");
|
||||
assertFalse(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
|
||||
// clear email
|
||||
personalInfoPage.personalInfo().setEmail("");
|
||||
assertTrue(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
personalInfoPage.personalInfo().setEmail("vmuzikar@redhat.com");
|
||||
assertFalse(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
|
||||
// TODO test email validation (blocked by KEYCLOAK-8098)
|
||||
|
||||
// clear first name
|
||||
personalInfoPage.personalInfo().setFirstName("");
|
||||
assertTrue(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
personalInfoPage.personalInfo().setFirstName("abc");
|
||||
assertFalse(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
|
||||
// clear last name
|
||||
personalInfoPage.personalInfo().setLastName("");
|
||||
assertTrue(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
personalInfoPage.personalInfo().setLastName("abc");
|
||||
assertFalse(personalInfoPage.personalInfo().isSaveDisabled());
|
||||
|
||||
// duplicity tests
|
||||
ApiUtil.createUserWithAdminClient(testRealmResource(), testUser2);
|
||||
// duplicate username
|
||||
personalInfoPage.personalInfo().setUsername(testUser2.getUsername());
|
||||
personalInfoPage.personalInfo().clickSave();
|
||||
personalInfoPage.alert().assertDanger("Username already exists.");
|
||||
personalInfoPage.personalInfo().setUsername(testUser.getUsername());
|
||||
// duplicate email
|
||||
personalInfoPage.personalInfo().setEmail(testUser2.getEmail());
|
||||
personalInfoPage.personalInfo().clickSave();
|
||||
personalInfoPage.alert().assertDanger("Email already exists.");
|
||||
// check no changes were saved
|
||||
personalInfoPage.navigateTo();
|
||||
personalInfoPage.personalInfo().valuesEqual(testUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disabledEditUsername() {
|
||||
setEditUsernameAllowed(false);
|
||||
|
||||
assertTrue(personalInfoPage.personalInfo().isUsernameDisabled());
|
||||
personalInfoPage.personalInfo().setValues(testUser2);
|
||||
personalInfoPage.personalInfo().clickSave();
|
||||
personalInfoPage.alert().assertSuccess();
|
||||
|
||||
testUser2.setUsername(testUser.getUsername()); // the username should remain the same
|
||||
personalInfoPage.navigateTo();
|
||||
personalInfoPage.personalInfo().valuesEqual(testUser2);
|
||||
}
|
||||
|
||||
private void setEditUsernameAllowed(boolean value) {
|
||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||
realm.setEditUsernameAllowed(value);
|
||||
testRealmResource().update(realm);
|
||||
personalInfoPage.navigateTo();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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.ui.account2;
|
||||
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.auth.page.account2.ApplicationsPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.AuthenticatorPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.ChangePasswordPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.DeviceActivityPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.LinkedAccountsPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.PersonalInfoPage;
|
||||
import org.keycloak.testsuite.auth.page.account2.ResourcesPage;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public class WelcomeScreenTest extends AbstractAccountTest {
|
||||
@Page
|
||||
private PersonalInfoPage personalInfoPage;
|
||||
@Page
|
||||
private ChangePasswordPage changePasswordPage;
|
||||
@Page
|
||||
private AuthenticatorPage authenticatorPage;
|
||||
@Page
|
||||
private DeviceActivityPage deviceActivityPage;
|
||||
@Page
|
||||
private LinkedAccountsPage linkedAccountsPage;
|
||||
@Page
|
||||
private ApplicationsPage applicationsPage;
|
||||
@Page
|
||||
private ResourcesPage resourcesPage;
|
||||
|
||||
@Test
|
||||
public void loginTest() {
|
||||
accountWelcomeScreen.assertCurrent();
|
||||
assertTrue(accountWelcomeScreen.isLoginBtnVisible());
|
||||
|
||||
// login
|
||||
accountWelcomeScreen.clickLoginBtn();
|
||||
loginToAccount();
|
||||
accountWelcomeScreen.assertCurrent();
|
||||
assertFalse(accountWelcomeScreen.isLoginBtnVisible());
|
||||
|
||||
// TODO logout test (blocked by KEYCLOAK-8084)
|
||||
}
|
||||
|
||||
@Test
|
||||
public void personalInfoTest() {
|
||||
assertTrue(accountWelcomeScreen.personalInfo().isVisible());
|
||||
accountWelcomeScreen.personalInfo().clickPersonalInfo();
|
||||
loginToAccount();
|
||||
personalInfoPage.assertCurrent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void accountSecurityTest() {
|
||||
assertTrue(accountWelcomeScreen.accountSecurityCard().isVisible());
|
||||
|
||||
// change password link
|
||||
accountWelcomeScreen.accountSecurityCard().clickChangePassword();
|
||||
loginToAccount();
|
||||
changePasswordPage.assertCurrent();
|
||||
|
||||
// authenticator link
|
||||
accountWelcomeScreen.navigateTo();
|
||||
accountWelcomeScreen.accountSecurityCard().clickAuthenticator();
|
||||
authenticatorPage.assertCurrent();
|
||||
|
||||
// device activity link
|
||||
accountWelcomeScreen.navigateTo();
|
||||
accountWelcomeScreen.accountSecurityCard().clickDeviceActivity();
|
||||
deviceActivityPage.assertCurrent();
|
||||
|
||||
// linked accounts link
|
||||
accountWelcomeScreen.navigateTo();
|
||||
assertFalse(accountWelcomeScreen.accountSecurityCard().isLinkedAccountsVisible());
|
||||
// add simple IdP
|
||||
testRealmResource().identityProviders().create(createIdentityProviderRepresentation("test-idp", "test-provider"));
|
||||
// test link appeared
|
||||
accountWelcomeScreen.navigateTo();
|
||||
accountWelcomeScreen.accountSecurityCard().clickLinkedAccounts();
|
||||
linkedAccountsPage.assertCurrent();
|
||||
// no need to remove the IdP
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationsTest() {
|
||||
assertTrue(accountWelcomeScreen.applicationsCard().isVisible());
|
||||
accountWelcomeScreen.applicationsCard().clickApplicationsLink();
|
||||
loginToAccount();
|
||||
applicationsPage.assertCurrent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourcesTest() {
|
||||
assertFalse(accountWelcomeScreen.myResourcesCard().isVisible());
|
||||
|
||||
// set user managed access
|
||||
RealmRepresentation testRealm = testRealmResource().toRepresentation();
|
||||
testRealm.setUserManagedAccessAllowed(true);
|
||||
testRealmResource().update(testRealm);
|
||||
|
||||
// test my resources appeared
|
||||
accountWelcomeScreen.navigateTo();
|
||||
assertTrue(accountWelcomeScreen.myResourcesCard().isVisible());
|
||||
accountWelcomeScreen.myResourcesCard().clickMyResources();
|
||||
loginToAccount();
|
||||
resourcesPage.assertCurrent();
|
||||
// no need to disable user managed access
|
||||
}
|
||||
}
|
|
@ -17,9 +17,11 @@
|
|||
|
||||
package org.keycloak.testsuite.ui.login;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.ui.AbstractUiTest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
|
||||
|
@ -29,9 +31,11 @@ import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
|||
* @author Vaclav Muzikar <vmuzikar@redhat.com>
|
||||
*/
|
||||
public abstract class AbstractLoginTest extends AbstractUiTest {
|
||||
@Before
|
||||
public void addTestUser() {
|
||||
createTestUserWithAdminClient(false);
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
super.addTestRealms(testRealms);
|
||||
RealmRepresentation testRealmRep = testRealms.get(0);
|
||||
configureInternationalizationForRealm(testRealmRep);
|
||||
}
|
||||
|
||||
protected void assertLoginFailed(String message) {
|
||||
|
|
|
@ -26,8 +26,8 @@ import org.keycloak.testsuite.console.page.AdminConsole;
|
|||
import org.keycloak.testsuite.console.page.AdminConsoleRealm;
|
||||
import org.keycloak.testsuite.console.page.AdminConsoleRealm.ConfigureMenu;
|
||||
import org.keycloak.testsuite.console.page.AdminConsoleRealm.ManageMenu;
|
||||
import org.keycloak.testsuite.console.page.fragment.AdminConsoleAlert;
|
||||
import org.keycloak.testsuite.console.page.fragment.ModalDialog;
|
||||
import org.keycloak.testsuite.page.PatternFlyClosableAlert;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -53,8 +53,8 @@ public abstract class AbstractConsoleTest extends AbstractAuthTest {
|
|||
@FindBy(xpath = "//div[@class='modal-dialog']")
|
||||
protected ModalDialog modalDialog;
|
||||
|
||||
@FindBy(className = "alert")
|
||||
protected AdminConsoleAlert alert;
|
||||
@Page
|
||||
protected PatternFlyClosableAlert alert;
|
||||
|
||||
protected boolean adminLoggedIn = false;
|
||||
|
||||
|
@ -111,13 +111,11 @@ public abstract class AbstractConsoleTest extends AbstractAuthTest {
|
|||
}
|
||||
|
||||
public void assertAlertSuccess() {
|
||||
assertTrue("Alert is not success", alert.isSuccess());
|
||||
alert.close();
|
||||
alert.assertSuccess();
|
||||
}
|
||||
|
||||
public void assertAlertDanger() {
|
||||
assertTrue("Alert is not danger", alert.isDanger());
|
||||
alert.close();
|
||||
alert.assertDanger();
|
||||
}
|
||||
|
||||
public ConfigureMenu configure() {
|
||||
|
|
|
@ -167,6 +167,7 @@
|
|||
<backends.console.output>true</backends.console.output>
|
||||
|
||||
<testsuite.constants>${project.build.directory}/dependency/test-constants.properties</testsuite.constants>
|
||||
<testsuite.ui.layout>0</testsuite.ui.layout> <!-- this is to tell the UI tests what type of layout to expect (doesn't setup the layout, just what to expect); 0 == desktop layout, 1 == smartphone layout, 2 == tablet layout -->
|
||||
|
||||
<skip.add.user.json>false</skip.add.user.json>
|
||||
<skip.clean.second.cache>true</skip.clean.second.cache>
|
||||
|
@ -461,6 +462,7 @@
|
|||
<kie.maven.settings>${kie.maven.settings}</kie.maven.settings>
|
||||
|
||||
<testsuite.constants>${testsuite.constants}</testsuite.constants>
|
||||
<testsuite.ui.layout>${testsuite.ui.layout}</testsuite.ui.layout>
|
||||
<cli.log.output>${cli.log.output}</cli.log.output>
|
||||
<test.intermittent>${test.intermittent}</test.intermittent>
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@
|
|||
<h2>${msg("accountSecurityTitle")}</h2>
|
||||
<p class="card-pf-content-intro">${msg("accountSecurityIntroMessage")}</p>
|
||||
<h3 id="changePasswordLink"><a href="${baseUrl}/#/password">${msg("changePasswordHtmlTitle")}</a></h3>
|
||||
<h3 id="authenticatiorLink"><a href="${baseUrl}/#/authenticator">${msg("authenticatorTitle")}</a></h3>
|
||||
<h3 id="authenticatorLink"><a href="${baseUrl}/#/authenticator">${msg("authenticatorTitle")}</a></h3>
|
||||
<h3 id="deviceActivityLink"><a href="${baseUrl}/#/device-activity">${msg("deviceActivityHtmlTitle")}</a></h3>
|
||||
<h3 id="linkedAccountsLink"><a href="${baseUrl}/#/linked-accounts">${msg("linkedAccountsHtmlTitle")}</a></h3>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue