mirror of
https://github.com/keycloak/keycloak.git
synced 2026-06-03 13:58:36 -04:00
Signed-off-by: Yike Gao <yikegao8@gmail.com>
This commit is contained in:
parent
2a79636bbe
commit
4aff9a43ce
6 changed files with 540 additions and 128 deletions
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* 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.testframework.ui.page;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.NoSuchElementException;
|
||||
import org.openqa.selenium.StaleElementReferenceException;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
public class LoginUpdateProfilePage extends AbstractLoginPage {
|
||||
|
||||
@FindBy(id = "username")
|
||||
private WebElement usernameInput;
|
||||
|
||||
@FindBy(name = "firstName")
|
||||
private WebElement firstNameInput;
|
||||
|
||||
@FindBy(name = "lastName")
|
||||
private WebElement lastNameInput;
|
||||
|
||||
@FindBy(name = "email")
|
||||
private WebElement emailInput;
|
||||
|
||||
@FindBy(name = "department")
|
||||
private WebElement departmentInput;
|
||||
|
||||
@FindBy(css = "input[type=\"submit\"]")
|
||||
private WebElement submitButton;
|
||||
|
||||
@FindBy(name = "cancel-aia")
|
||||
private WebElement cancelAIAButton;
|
||||
|
||||
@FindBy(css = "div[class^='pf-v5-c-alert'], div[class^='alert-error']")
|
||||
private WebElement loginAlertErrorMessage;
|
||||
|
||||
private final UpdateProfileErrors errorsPage;
|
||||
|
||||
public LoginUpdateProfilePage(ManagedWebDriver driver) {
|
||||
super(driver);
|
||||
this.errorsPage = new UpdateProfileErrors(driver);
|
||||
}
|
||||
|
||||
public void update(String firstName, String lastName) {
|
||||
prepareUpdate().firstName(firstName).lastName(lastName).submit();
|
||||
}
|
||||
|
||||
public void update(String firstName, String lastName, String email) {
|
||||
prepareUpdate().firstName(firstName).lastName(lastName).email(email).submit();
|
||||
}
|
||||
|
||||
public void update(Map<String, String> attributes) {
|
||||
prepareUpdate().otherProfileAttribute(attributes).submit();
|
||||
}
|
||||
|
||||
public Update prepareUpdate() {
|
||||
return new Update(this);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
cancelAIAButton.click();
|
||||
}
|
||||
|
||||
public String getAlertError() {
|
||||
try {
|
||||
return loginAlertErrorMessage.getText();
|
||||
} catch (NoSuchElementException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return readValue(By.id("username"));
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return readValue(By.name("firstName"));
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return readValue(By.name("lastName"));
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return readValue(By.name("email"));
|
||||
}
|
||||
|
||||
public String getDepartment() {
|
||||
return readValue(By.name("department"));
|
||||
}
|
||||
|
||||
private String readValue(By locator) {
|
||||
return driver.waiting().until(d -> {
|
||||
try {
|
||||
return d.findElement(locator).getAttribute("value");
|
||||
} catch (StaleElementReferenceException e) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isDepartmentEnabled() {
|
||||
return departmentInput.isEnabled();
|
||||
}
|
||||
|
||||
public UpdateProfileErrors getInputErrors() {
|
||||
return errorsPage;
|
||||
}
|
||||
|
||||
public String getLabelForField(String fieldId) {
|
||||
return driver.findElement(By.cssSelector("label[for=" + fieldId + "]")).getText().replaceAll("\\s\\*$", "");
|
||||
}
|
||||
|
||||
public WebElement getElementById(String fieldId) {
|
||||
try {
|
||||
return driver.findElement(By.id(fieldId));
|
||||
} catch (NoSuchElementException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUsernamePresent() {
|
||||
try {
|
||||
return usernameInput.isDisplayed();
|
||||
} catch (NoSuchElementException nse) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmailInputPresent() {
|
||||
try {
|
||||
return emailInput.isDisplayed();
|
||||
} catch (NoSuchElementException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDepartmentPresent() {
|
||||
try {
|
||||
return departmentInput.isDisplayed();
|
||||
} catch (NoSuchElementException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCancelDisplayed() {
|
||||
try {
|
||||
return cancelAIAButton.isDisplayed();
|
||||
} catch (NoSuchElementException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttribute(String elementId, String value) {
|
||||
WebElement element = getElementById(elementId);
|
||||
|
||||
if (element != null) {
|
||||
element.clear();
|
||||
element.sendKeys(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void clickAddAttributeValue(String elementId) {
|
||||
WebElement element = getElementById("kc-add-" + elementId);
|
||||
|
||||
if (element != null) {
|
||||
element.click();
|
||||
}
|
||||
}
|
||||
|
||||
public void clickRemoveAttributeValue(String elementId) {
|
||||
WebElement element = getElementById("kc-remove-" + elementId);
|
||||
|
||||
if (element != null) {
|
||||
element.click();
|
||||
}
|
||||
}
|
||||
|
||||
public String getAttribute(String elementId) {
|
||||
WebElement element = getElementById(elementId);
|
||||
|
||||
if (element != null) {
|
||||
return element.getAttribute("value");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExpectedPageId() {
|
||||
return "login-login-update-profile";
|
||||
}
|
||||
|
||||
public static class Update {
|
||||
private final LoginUpdateProfilePage page;
|
||||
private String username;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String department;
|
||||
private String email;
|
||||
private final Map<String, String> other = new LinkedHashMap<>();
|
||||
|
||||
protected Update(LoginUpdateProfilePage page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public Update username(String username) {
|
||||
this.username = username;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Update firstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Update lastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Update department(String department) {
|
||||
this.department = department;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Update email(String email) {
|
||||
this.email = email;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Update otherProfileAttribute(Map<String, String> attributes) {
|
||||
other.putAll(attributes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void submit() {
|
||||
if (username != null) {
|
||||
page.usernameInput.clear();
|
||||
page.usernameInput.sendKeys(username);
|
||||
}
|
||||
if (firstName != null) {
|
||||
page.firstNameInput.clear();
|
||||
page.firstNameInput.sendKeys(firstName);
|
||||
}
|
||||
if (lastName != null) {
|
||||
page.lastNameInput.clear();
|
||||
page.lastNameInput.sendKeys(lastName);
|
||||
}
|
||||
|
||||
if (department != null) {
|
||||
page.departmentInput.clear();
|
||||
page.departmentInput.sendKeys(department);
|
||||
}
|
||||
|
||||
if (email != null) {
|
||||
page.emailInput.clear();
|
||||
page.emailInput.sendKeys(email);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : other.entrySet()) {
|
||||
WebElement el = page.driver.findElement(By.id(entry.getKey()));
|
||||
if (el != null) {
|
||||
el.clear();
|
||||
el.sendKeys(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
page.submitButton.submit();
|
||||
}
|
||||
}
|
||||
|
||||
// For managing input errors
|
||||
public static class UpdateProfileErrors {
|
||||
|
||||
private final ManagedWebDriver driver;
|
||||
|
||||
public UpdateProfileErrors(ManagedWebDriver driver) {
|
||||
this.driver = driver;
|
||||
}
|
||||
|
||||
private String getTextById(String id) {
|
||||
try {
|
||||
return driver.findElement(By.id(id)).getText();
|
||||
} catch (NoSuchElementException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getFirstNameError() {
|
||||
String text = getTextById("input-error-firstname");
|
||||
if (text != null) {
|
||||
return text;
|
||||
}
|
||||
return getTextById("input-error-firstName");
|
||||
}
|
||||
|
||||
public String getLastNameError() {
|
||||
String text = getTextById("input-error-lastname");
|
||||
if (text != null) {
|
||||
return text;
|
||||
}
|
||||
return getTextById("input-error-lastName");
|
||||
}
|
||||
|
||||
public String getEmailError() {
|
||||
return getTextById("input-error-email");
|
||||
}
|
||||
|
||||
public String getUsernameError() {
|
||||
return getTextById("input-error-username");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.actions;
|
||||
|
||||
package org.keycloak.tests.actions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -29,116 +30,114 @@ import org.keycloak.admin.client.resource.UserResource;
|
|||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.EventRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.userprofile.config.UPAttribute;
|
||||
import org.keycloak.representations.userprofile.config.UPAttributePermissions;
|
||||
import org.keycloak.representations.userprofile.config.UPConfig;
|
||||
import org.keycloak.testframework.annotations.InjectEvents;
|
||||
import org.keycloak.testframework.annotations.InjectRealm;
|
||||
import org.keycloak.testframework.annotations.InjectUser;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.events.EventAssertion;
|
||||
import org.keycloak.testframework.events.Events;
|
||||
import org.keycloak.testframework.injection.LifeCycle;
|
||||
import org.keycloak.testframework.oauth.OAuthClient;
|
||||
import org.keycloak.testframework.oauth.annotations.InjectOAuthClient;
|
||||
import org.keycloak.testframework.realm.ManagedRealm;
|
||||
import org.keycloak.testframework.realm.ManagedUser;
|
||||
import org.keycloak.testframework.realm.RealmBuilder;
|
||||
import org.keycloak.testframework.realm.RealmConfig;
|
||||
import org.keycloak.testframework.realm.UserBuilder;
|
||||
import org.keycloak.testsuite.AbstractChangeImportedUserPasswordsTest;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.admin.AdminApiUtil;
|
||||
import org.keycloak.testsuite.arquillian.annotation.IgnoreBrowserDriver;
|
||||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.AppPage.RequestType;
|
||||
import org.keycloak.testsuite.pages.ErrorPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.LoginUpdateProfileEditUsernameAllowedPage;
|
||||
import org.keycloak.testframework.realm.UserConfig;
|
||||
import org.keycloak.testframework.ui.annotations.InjectPage;
|
||||
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
|
||||
import org.keycloak.testframework.ui.page.ErrorPage;
|
||||
import org.keycloak.testframework.ui.page.LoginPage;
|
||||
import org.keycloak.testframework.ui.page.LoginUpdateProfilePage;
|
||||
import org.keycloak.testframework.ui.webdriver.BrowserType;
|
||||
import org.keycloak.testframework.ui.webdriver.ManagedWebDriver;
|
||||
import org.keycloak.tests.suites.DatabaseTest;
|
||||
import org.keycloak.tests.utils.PasswordGenerateUtil;
|
||||
import org.keycloak.tests.utils.admin.AdminApiUtil;
|
||||
import org.keycloak.userprofile.UserProfileContext;
|
||||
import org.keycloak.utils.StringUtil;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openqa.selenium.ElementClickInterceptedException;
|
||||
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
|
||||
|
||||
import static org.keycloak.userprofile.config.UPConfigUtils.ROLE_ADMIN;
|
||||
import static org.keycloak.userprofile.config.UPConfigUtils.ROLE_USER;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserPasswordsTest {
|
||||
@KeycloakIntegrationTest
|
||||
@DatabaseTest
|
||||
public class RequiredActionUpdateProfileTest {
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
private static final String PASSWORD = PasswordGenerateUtil.generatePassword();
|
||||
|
||||
@Page
|
||||
protected AppPage appPage;
|
||||
@InjectRealm(config = RequiredActionUpdateProfileRealmConfig.class)
|
||||
ManagedRealm realm;
|
||||
|
||||
@Page
|
||||
@InjectWebDriver
|
||||
ManagedWebDriver driver;
|
||||
|
||||
@InjectOAuthClient
|
||||
OAuthClient oauth;
|
||||
|
||||
@InjectEvents
|
||||
Events events;
|
||||
|
||||
@InjectUser(ref = "testUser", config = TestUserConfig.class, lifecycle = LifeCycle.METHOD)
|
||||
ManagedUser testUser;
|
||||
|
||||
@InjectUser(ref = "johnDoh", config = JohnDohUserConfig.class, lifecycle = LifeCycle.METHOD)
|
||||
ManagedUser johnDohUser;
|
||||
|
||||
@InjectPage
|
||||
protected LoginPage loginPage;
|
||||
|
||||
@Page
|
||||
protected LoginUpdateProfileEditUsernameAllowedPage updateProfilePage;
|
||||
@InjectPage
|
||||
protected LoginUpdateProfilePage updateProfilePage;
|
||||
|
||||
@Page
|
||||
@InjectPage
|
||||
protected ErrorPage errorPage;
|
||||
|
||||
@Override
|
||||
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||
super.configureTestRealm(testRealm);
|
||||
ActionUtil.addRequiredActionForUser(testRealm, "test-user@localhost", UserModel.RequiredAction.UPDATE_PROFILE.name());
|
||||
ActionUtil.addRequiredActionForUser(testRealm, "john-doh@localhost", UserModel.RequiredAction.UPDATE_PROFILE.name());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeTest() {
|
||||
AdminApiUtil.removeUserByUsername(managedRealm.admin(), "test-user@localhost");
|
||||
UserRepresentation user = UserBuilder.create().enabled(true)
|
||||
.username("test-user@localhost")
|
||||
.email("test-user@localhost")
|
||||
.firstName("Tom")
|
||||
.lastName("Brady")
|
||||
.emailVerified(true)
|
||||
.requiredActions(UserModel.RequiredAction.UPDATE_PROFILE.name()).build();
|
||||
AdminApiUtil.createUserAndResetPasswordWithAdminClient(managedRealm.admin(), user, generatePassword("test-user@localhost"));
|
||||
|
||||
AdminApiUtil.removeUserByUsername(managedRealm.admin(), "john-doh@localhost");
|
||||
user = UserBuilder.create().enabled(true)
|
||||
.username("john-doh@localhost")
|
||||
.email("john-doh@localhost")
|
||||
.firstName("John")
|
||||
.lastName("Doh")
|
||||
.emailVerified(true)
|
||||
.requiredActions(UserModel.RequiredAction.UPDATE_PROFILE.name()).build();
|
||||
AdminApiUtil.createUserAndResetPasswordWithAdminClient(managedRealm.admin(), user, generatePassword("john-doh@localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfile() {
|
||||
oauth.openLoginForm();
|
||||
UserRepresentation user = ActionUtil.findUserWithAdminClient(adminClient, "test-user@localhost");
|
||||
user.setEmailVerified(true);
|
||||
adminClient.realm("test").users().get(user.getId()).update(user);
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
assertFalse(updateProfilePage.isCancelDisplayed());
|
||||
|
||||
updateProfilePage.prepareUpdate().username("test-user@localhost").firstName("New first").lastName("New last").email("new@email.com").submit();
|
||||
|
||||
events.expectRequiredAction(EventType.UPDATE_PROFILE).detail(Details.PREVIOUS_FIRST_NAME, "Tom").detail(Details.UPDATED_FIRST_NAME, "New first")
|
||||
.detail(Details.PREVIOUS_LAST_NAME, "Brady").detail(Details.UPDATED_LAST_NAME, "New last")
|
||||
.detail(Details.PREVIOUS_EMAIL, "test-user@localhost").detail(Details.UPDATED_EMAIL, "new@email.com")
|
||||
.assertEvent();
|
||||
Assertions.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
EventAssertion.assertSuccess(pollEvent())
|
||||
.type(EventType.UPDATE_PROFILE)
|
||||
.details(Details.PREVIOUS_FIRST_NAME, "Tom")
|
||||
.details(Details.UPDATED_FIRST_NAME, "New first")
|
||||
.details(Details.PREVIOUS_LAST_NAME, "Brady")
|
||||
.details(Details.UPDATED_LAST_NAME, "New last")
|
||||
.details(Details.PREVIOUS_EMAIL, "test-user@localhost")
|
||||
.details(Details.UPDATED_EMAIL, "new@email.com");
|
||||
assertThat(oauth.parseLoginResponse().getCode(), notNullValue());
|
||||
|
||||
EventAssertion.expectLoginSuccess(events.poll());
|
||||
EventAssertion.expectLoginSuccess(pollEvent());
|
||||
|
||||
// assert user is really updated in persistent store
|
||||
user = ActionUtil.findUserWithAdminClient(adminClient, "test-user@localhost");
|
||||
UserRepresentation user = testUser.admin().toRepresentation();
|
||||
Assertions.assertEquals("New first", user.getFirstName());
|
||||
Assertions.assertEquals("New last", user.getLastName());
|
||||
Assertions.assertEquals("new@email.com", user.getEmail());
|
||||
|
|
@ -151,15 +150,16 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
public void updateUsername() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("john-doh@localhost", getPassword("john-doh@localhost"));
|
||||
loginPage.fillLogin("john-doh@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
String userId = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost").getId();
|
||||
String userId = johnDohUser.getId();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
updateProfilePage.prepareUpdate().username("new").firstName("New first").lastName("New last").email("john-doh@localhost").submit();
|
||||
|
||||
EventAssertion.assertSuccess(events.poll())
|
||||
EventAssertion.assertSuccess(pollEvent())
|
||||
.type(EventType.UPDATE_PROFILE)
|
||||
.isCodeId()
|
||||
.sessionId(null)
|
||||
|
|
@ -169,26 +169,26 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
.details(Details.UPDATED_LAST_NAME, "New last")
|
||||
.withoutDetails(Details.CONSENT);
|
||||
|
||||
Assertions.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
assertThat(oauth.parseLoginResponse().getCode(), notNullValue());
|
||||
|
||||
EventAssertion.expectLoginSuccess(events.poll()).details(Details.USERNAME, "john-doh@localhost").userId(userId);
|
||||
EventAssertion.expectLoginSuccess(pollEvent()).details(Details.USERNAME, "john-doh@localhost").userId(userId);
|
||||
|
||||
// assert user is really updated in persistent store
|
||||
UserRepresentation user = ActionUtil.findUserWithAdminClient(adminClient, "new");
|
||||
UserRepresentation user = johnDohUser.admin().toRepresentation();
|
||||
Assertions.assertEquals("New first", user.getFirstName());
|
||||
Assertions.assertEquals("New last", user.getLastName());
|
||||
Assertions.assertEquals("john-doh@localhost", user.getEmail());
|
||||
Assertions.assertEquals("new", user.getUsername());
|
||||
// email not changed so verify that emailVerified flag is NOT reset
|
||||
Assertions.assertEquals(true, user.isEmailVerified());
|
||||
getCleanup().addUserId(user.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileMissingFirstName() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -202,14 +202,15 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
Assertions.assertEquals("new@email.com", updateProfilePage.getEmail());
|
||||
Assertions.assertEquals("Please specify this field.", updateProfilePage.getInputErrors().getFirstNameError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileMissingLastName() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -224,14 +225,15 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
Assertions.assertEquals("Please specify this field.", updateProfilePage.getInputErrors().getLastNameError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileMissingEmail() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -250,19 +252,20 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
containsString("Please specify this field")
|
||||
));
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileInvalidEmail() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
updateProfilePage.prepareUpdate().username("invalid").firstName("New first").lastName("New last")
|
||||
.email("invalidemail").submit();
|
||||
.email("invalidemail").submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -273,14 +276,15 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
Assertions.assertEquals("Invalid email address.", updateProfilePage.getInputErrors().getEmailError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileMissingUsername() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("john-doh@localhost", getPassword("john-doh@localhost"));
|
||||
loginPage.fillLogin("john-doh@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -296,14 +300,15 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
Assertions.assertEquals("Please specify username.", updateProfilePage.getInputErrors().getUsernameError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileDuplicateUsername() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("john-doh@localhost", getPassword("john-doh@localhost"));
|
||||
loginPage.fillLogin("john-doh@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -319,14 +324,15 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
Assertions.assertEquals("Username already exists.", updateProfilePage.getInputErrors().getUsernameError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileDuplicatedEmail() {
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -342,16 +348,18 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
Assertions.assertEquals("Email already exists.", updateProfilePage.getInputErrors().getEmailError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileDuplicateUsernameWithEmail() {
|
||||
getCleanup().addUserId(createUser(TEST_REALM_NAME, "user1@local.com", generatePassword("user1@local.com"), "user1", "user1", "user1@local.org"));
|
||||
String userId = createUser("user1@local.com", "user1", "user1", "user1@local.org");
|
||||
realm.cleanup().add(r -> r.users().get(userId).remove());
|
||||
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("john-doh@localhost", getPassword("john-doh@localhost"));
|
||||
loginPage.fillLogin("john-doh@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -367,16 +375,18 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
Assertions.assertEquals("Username already exists.", updateProfilePage.getInputErrors().getUsernameError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileDuplicatedEmailWithUsername() {
|
||||
getCleanup().addUserId(createUser(TEST_REALM_NAME, "user1@local.com", generatePassword("user1@local.com"), "user1", "user1", "user1@local.org"));
|
||||
String userId = createUser("user1@local.com", "user1", "user1", "user1@local.org");
|
||||
realm.cleanup().add(r -> r.users().get(userId).remove());
|
||||
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
|
|
@ -392,38 +402,34 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
Assertions.assertEquals("Email already exists.", updateProfilePage.getInputErrors().getEmailError());
|
||||
|
||||
events.assertEmpty();
|
||||
assertNoMoreEvents();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileExpiredCookies() {
|
||||
oauth.openLoginForm();
|
||||
loginPage.login("john-doh@localhost", getPassword("john-doh@localhost"));
|
||||
loginPage.fillLogin("john-doh@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
// Expire cookies and assert the page with "back to application" link present
|
||||
driver.manage().deleteAllCookies();
|
||||
driver.cookies().deleteAll();
|
||||
|
||||
updateProfilePage.prepareUpdate().username("test-user@localhost").firstName("New first").lastName("New last").email("keycloak-user@localhost").submit();
|
||||
errorPage.assertCurrent();
|
||||
|
||||
String backToAppLink = errorPage.getBackToApplicationLink();
|
||||
|
||||
ClientRepresentation client = AdminApiUtil.findClientByClientId(adminClient.realm("test"), "test-app").toRepresentation();
|
||||
Assertions.assertEquals(backToAppLink, client.getBaseUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateProfileWithoutRemoveCustomAttributes() {
|
||||
UserProfileResource upResource = adminClient.realm("test").users().userProfile();
|
||||
UserProfileResource upResource = realm.admin().users().userProfile();
|
||||
UPConfig upConfig = upResource.getConfiguration();
|
||||
upConfig.setUnmanagedAttributePolicy(UPConfig.UnmanagedAttributePolicy.ADMIN_EDIT);
|
||||
upResource.update(upConfig);
|
||||
|
||||
try {
|
||||
UserRepresentation userRep = ActionUtil.findUserWithAdminClient(adminClient, "test-user@localhost");
|
||||
UserResource user = adminClient.realm("test").users().get(userRep.getId());
|
||||
UserResource user = testUser.admin();
|
||||
UserRepresentation userRep = user.toRepresentation();
|
||||
|
||||
userRep.setAttributes(new HashMap<>());
|
||||
userRep.getAttributes().put("custom", Arrays.asList("custom"));
|
||||
|
|
@ -432,21 +438,26 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
|
||||
oauth.openLoginForm();
|
||||
|
||||
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
|
||||
loginPage.fillLogin("test-user@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
|
||||
updateProfilePage.assertCurrent();
|
||||
assertFalse(updateProfilePage.isCancelDisplayed());
|
||||
|
||||
updateProfilePage.prepareUpdate().username("test-user@localhost").firstName("New first").lastName("New last").email("new@email.com").submit();
|
||||
|
||||
events.expectRequiredAction(EventType.UPDATE_PROFILE).detail(Details.CONTEXT, UserProfileContext.UPDATE_PROFILE.name()).detail(Details.PREVIOUS_EMAIL, "test-user@localhost").detail(Details.UPDATED_EMAIL, "new@email.com").assertEvent();
|
||||
EventAssertion.assertSuccess(pollEvent())
|
||||
.type(EventType.UPDATE_PROFILE)
|
||||
.details(Details.CONTEXT, UserProfileContext.UPDATE_PROFILE.name())
|
||||
.details(Details.PREVIOUS_EMAIL, "test-user@localhost")
|
||||
.details(Details.UPDATED_EMAIL, "new@email.com");
|
||||
|
||||
Assertions.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
assertThat(oauth.parseLoginResponse().getCode(), notNullValue());
|
||||
|
||||
EventAssertion.expectLoginSuccess(events.poll());
|
||||
EventAssertion.expectLoginSuccess(pollEvent());
|
||||
|
||||
// assert user is really updated in persistent store
|
||||
userRep = ActionUtil.findUserWithAdminClient(adminClient, "test-user@localhost");
|
||||
userRep = testUser.admin().toRepresentation();
|
||||
Assertions.assertEquals("New first", userRep.getFirstName());
|
||||
Assertions.assertEquals("New last", userRep.getLastName());
|
||||
Assertions.assertEquals("new@email.com", userRep.getEmail());
|
||||
|
|
@ -460,9 +471,10 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
}
|
||||
|
||||
@Test
|
||||
@IgnoreBrowserDriver(HtmlUnitDriver.class) // we can't yet run modern JavaScript using HtmlUnit
|
||||
public void testMultivaluedAttributes() {
|
||||
UserProfileResource userProfile = managedRealm.admin().users().userProfile();
|
||||
Assumptions.assumeFalse(driver.getBrowserType().equals(BrowserType.HTML_UNIT)); // we can't yet run modern JavaScript using HtmlUnit
|
||||
|
||||
UserProfileResource userProfile = realm.admin().users().userProfile();
|
||||
UPConfig configuration = userProfile.getConfiguration();
|
||||
|
||||
try {
|
||||
|
|
@ -480,7 +492,8 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
userProfile.update(testUpConfig);
|
||||
|
||||
oauth.openLoginForm();
|
||||
loginPage.login("john-doh@localhost", getPassword("john-doh@localhost"));
|
||||
loginPage.fillLogin("john-doh@localhost", PASSWORD);
|
||||
loginPage.submit();
|
||||
updateProfilePage.assertCurrent();
|
||||
|
||||
for (String attribute : attributes) {
|
||||
|
|
@ -493,12 +506,13 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
updateProfilePage.clickAddAttributeValue(elementId);
|
||||
}
|
||||
updateProfilePage.update("f", "l", "e@keycloak.org");
|
||||
UserRepresentation userRep = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost");
|
||||
driver.waiting().waitForOAuthCallback();
|
||||
UserRepresentation userRep = johnDohUser.admin().toRepresentation();
|
||||
assertThat(userRep.getAttributes().get(attribute), Matchers.containsInAnyOrder(values.toArray()));
|
||||
|
||||
// make sure multiple values are properly rendered
|
||||
userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PROFILE.name()));
|
||||
managedRealm.admin().users().get(userRep.getId()).update(userRep);
|
||||
johnDohUser.admin().update(userRep);
|
||||
oauth.openLoginForm();
|
||||
assertThat(IntStream.range(0, 5).mapToObj(value -> updateProfilePage.getAttribute(attribute + "-" + value)).collect(Collectors.toSet()), Matchers.equalTo(valuesSet));
|
||||
|
||||
|
|
@ -515,13 +529,14 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
}
|
||||
}
|
||||
updateProfilePage.update("f", "l", "e@keycloak.org");
|
||||
userRep = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost");
|
||||
driver.waiting().waitForOAuthCallback();
|
||||
userRep = johnDohUser.admin().toRepresentation();
|
||||
assertThat(userRep.getAttributes().get(attribute), Matchers.hasSize(1));
|
||||
assertThat(userRep.getAttributes().get(attribute).get(0), Matchers.in(values));
|
||||
|
||||
// make sure adding/removing within the same context works
|
||||
userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PROFILE.name()));
|
||||
managedRealm.admin().users().get(userRep.getId()).update(userRep);
|
||||
johnDohUser.admin().update(userRep);
|
||||
oauth.openLoginForm();
|
||||
for (String value : values) {
|
||||
String elementId = attribute + "-" + value;
|
||||
|
|
@ -545,13 +560,14 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
updateProfilePage.setAttribute(attribute + "-0", lastValue);
|
||||
}
|
||||
updateProfilePage.update("f", "l", "e@keycloak.org");
|
||||
userRep = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost");
|
||||
driver.waiting().waitForOAuthCallback();
|
||||
userRep = johnDohUser.admin().toRepresentation();
|
||||
assertThat(userRep.getAttributes().get(attribute), Matchers.hasSize(1));
|
||||
assertThat(userRep.getAttributes().get(attribute).get(0), Matchers.in(values));
|
||||
|
||||
// at the end the attribute is set with multiple values
|
||||
userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PROFILE.name()));
|
||||
managedRealm.admin().users().get(userRep.getId()).update(userRep);
|
||||
johnDohUser.admin().update(userRep);
|
||||
oauth.openLoginForm();
|
||||
for (String value : values) {
|
||||
String elementId = attribute + "-" + value;
|
||||
|
|
@ -559,15 +575,16 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
updateProfilePage.clickAddAttributeValue(elementId);
|
||||
}
|
||||
updateProfilePage.update("f", "l", "e@keycloak.org");
|
||||
driver.waiting().waitForOAuthCallback();
|
||||
|
||||
// restart the update profile flow
|
||||
userRep = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost");
|
||||
userRep = johnDohUser.admin().toRepresentation();
|
||||
userRep.setRequiredActions(List.of(UserModel.RequiredAction.UPDATE_PROFILE.name()));
|
||||
managedRealm.admin().users().get(userRep.getId()).update(userRep);
|
||||
johnDohUser.admin().update(userRep);
|
||||
oauth.openLoginForm();
|
||||
}
|
||||
|
||||
UserRepresentation userRep = ActionUtil.findUserWithAdminClient(adminClient, "john-doh@localhost");
|
||||
UserRepresentation userRep = johnDohUser.admin().toRepresentation();
|
||||
|
||||
// all attributes should be set with multiple values
|
||||
for (String attribute : attributes) {
|
||||
|
|
@ -578,4 +595,64 @@ public class RequiredActionUpdateProfileTest extends AbstractChangeImportedUserP
|
|||
}
|
||||
}
|
||||
|
||||
private String createUser(String username, String firstName, String lastName, String email) {
|
||||
UserRepresentation user = UserBuilder.create().enabled(true)
|
||||
.username(username)
|
||||
.email(email)
|
||||
.firstName(firstName)
|
||||
.lastName(lastName)
|
||||
.emailVerified(true)
|
||||
.build();
|
||||
return AdminApiUtil.createUserAndResetPasswordWithAdminClient(realm.admin(), user, PASSWORD);
|
||||
}
|
||||
|
||||
private void assertNoMoreEvents() {
|
||||
EventRepresentation event = events.poll();
|
||||
assertNull(event, "Expected no more events but got: " + (event != null ? event.getType() : null));
|
||||
}
|
||||
|
||||
private EventRepresentation pollEvent() {
|
||||
return driver.waiting().until(d -> events.poll());
|
||||
}
|
||||
|
||||
public static class RequiredActionUpdateProfileRealmConfig implements RealmConfig {
|
||||
|
||||
@Override
|
||||
public RealmBuilder configure(RealmBuilder realm) {
|
||||
realm.editUsernameAllowed(true);
|
||||
realm.users(UserBuilder.create("keycloak-user@localhost")
|
||||
.email("keycloak-user@localhost")
|
||||
.name("keycloak", "User")
|
||||
.password(PASSWORD)
|
||||
.emailVerified(true));
|
||||
return realm;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestUserConfig implements UserConfig {
|
||||
|
||||
@Override
|
||||
public UserBuilder configure(UserBuilder user) {
|
||||
return user.username("test-user@localhost")
|
||||
.email("test-user@localhost")
|
||||
.name("Tom", "Brady")
|
||||
.password(PASSWORD)
|
||||
.emailVerified(true)
|
||||
.requiredActions(UserModel.RequiredAction.UPDATE_PROFILE.name());
|
||||
}
|
||||
}
|
||||
|
||||
public static class JohnDohUserConfig implements UserConfig {
|
||||
|
||||
@Override
|
||||
public UserBuilder configure(UserBuilder user) {
|
||||
return user.username("john-doh@localhost")
|
||||
.email("john-doh@localhost")
|
||||
.name("John", "Doh")
|
||||
.password(PASSWORD)
|
||||
.emailVerified(true)
|
||||
.requiredActions(UserModel.RequiredAction.UPDATE_PROFILE.name());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import org.junit.platform.suite.api.Suite;
|
|||
@Suite
|
||||
@SelectPackages({
|
||||
"org.keycloak.tests.account",
|
||||
"org.keycloak.tests.actions",
|
||||
"org.keycloak.tests.authz",
|
||||
"org.keycloak.tests.broker",
|
||||
"org.keycloak.tests.client",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.keycloak.tests.suites;
|
||||
|
||||
import org.keycloak.tests.actions.RequiredActionUpdateProfileTest;
|
||||
import org.keycloak.tests.i18n.LoginPageTest;
|
||||
|
||||
import org.junit.platform.suite.api.SelectClasses;
|
||||
|
|
@ -8,7 +9,8 @@ import org.junit.platform.suite.api.Suite;
|
|||
@Suite
|
||||
// TODO: Select relevant test classes or packages once they have been migrated
|
||||
@SelectClasses({
|
||||
LoginPageTest.class
|
||||
LoginPageTest.class,
|
||||
RequiredActionUpdateProfileTest.class
|
||||
})
|
||||
public class FormsTestSuite {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ ExportImportTest
|
|||
KcOidcBrokerTest
|
||||
LDAPUserLoginTest
|
||||
LoginTest
|
||||
RequiredActionUpdateProfileTest
|
||||
SamlClientTest
|
||||
UserProfileTest
|
||||
OidcAdvancedClaimToGroupMapperTest
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
org.keycloak.testsuite.forms.**
|
||||
org.keycloak.testsuite.actions.RequiredActionUpdateProfileTest
|
||||
org.keycloak.testsuite.actions.TermsAndConditionsTest
|
||||
|
|
|
|||
Loading…
Reference in a new issue