Ensure user details form state remains in sync (#19696)
This commit is contained in:
parent
a2eb619e0e
commit
b6c8344fb5
6 changed files with 125 additions and 5 deletions
|
@ -44,7 +44,7 @@ describe.skip("Events tests", () => {
|
|||
const result = await adminClient.createUser(
|
||||
eventsTestUser.userRepresentation
|
||||
);
|
||||
eventsTestUser.eventsTestUserId = result.id;
|
||||
eventsTestUser.eventsTestUserId = result.id!;
|
||||
});
|
||||
|
||||
after(() =>
|
||||
|
|
|
@ -42,7 +42,7 @@ describe("Group test", () => {
|
|||
enabled: true,
|
||||
})
|
||||
.then((user) => {
|
||||
return { id: user.id, username: username + index };
|
||||
return { id: user.id!, username: username + index };
|
||||
});
|
||||
return user;
|
||||
})
|
||||
|
|
80
js/apps/admin-ui/cypress/e2e/users_enable_disable.spec.ts
Normal file
80
js/apps/admin-ui/cypress/e2e/users_enable_disable.spec.ts
Normal file
|
@ -0,0 +1,80 @@
|
|||
import UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
||||
import LoginPage from "../support/pages/LoginPage";
|
||||
import Masthead from "../support/pages/admin-ui/Masthead";
|
||||
import SidebarPage from "../support/pages/admin-ui/SidebarPage";
|
||||
import UsersPage from "../support/pages/admin-ui/manage/users/UsersPage";
|
||||
import UserDetailsPage from "../support/pages/admin-ui/manage/users/user_details/UserDetailsPage";
|
||||
import adminClient from "../support/util/AdminClient";
|
||||
import { keycloakBefore } from "../support/util/keycloak_hooks";
|
||||
|
||||
const loginPage = new LoginPage();
|
||||
const sidebarPage = new SidebarPage();
|
||||
const usersPage = new UsersPage();
|
||||
const userDetailsPage = new UserDetailsPage();
|
||||
const masthead = new Masthead();
|
||||
|
||||
const createUser = (fields: UserRepresentation) =>
|
||||
cy
|
||||
.wrap(null)
|
||||
.then(() =>
|
||||
adminClient.createUser({ username: crypto.randomUUID(), ...fields })
|
||||
);
|
||||
|
||||
const deleteUser = (username: string) =>
|
||||
cy.wrap(null).then(() => adminClient.deleteUser(username));
|
||||
|
||||
describe("User enable/disable", () => {
|
||||
beforeEach(() => {
|
||||
loginPage.logIn();
|
||||
keycloakBefore();
|
||||
sidebarPage.goToUsers();
|
||||
});
|
||||
|
||||
it("disables a user", () => {
|
||||
createUser({ enabled: true }).then(({ username }) => {
|
||||
usersPage.goToUserDetailsPage(username!);
|
||||
userDetailsPage.assertEnabled(username!);
|
||||
|
||||
userDetailsPage.toggleEnabled(username!);
|
||||
masthead.checkNotificationMessage("The user has been saved");
|
||||
cy.wait(1000);
|
||||
userDetailsPage.assertDisabled(username!);
|
||||
|
||||
return deleteUser(username!);
|
||||
});
|
||||
});
|
||||
|
||||
it("enables a user", () => {
|
||||
createUser({ enabled: false }).then(({ username }) => {
|
||||
usersPage.goToUserDetailsPage(username!);
|
||||
userDetailsPage.assertDisabled(username!);
|
||||
|
||||
userDetailsPage.toggleEnabled(username!);
|
||||
masthead.checkNotificationMessage("The user has been saved");
|
||||
cy.wait(1000);
|
||||
userDetailsPage.assertEnabled(username!);
|
||||
|
||||
return deleteUser(username!);
|
||||
});
|
||||
});
|
||||
|
||||
// See: https://github.com/keycloak/keycloak/issues/19647
|
||||
it("ensures submitting doesn't reset the enabled state", () => {
|
||||
createUser({ enabled: true }).then(({ username }) => {
|
||||
usersPage.goToUserDetailsPage(username!);
|
||||
userDetailsPage.assertEnabled(username!);
|
||||
|
||||
userDetailsPage.toggleEnabled(username!);
|
||||
masthead.checkNotificationMessage("The user has been saved");
|
||||
cy.wait(1000);
|
||||
userDetailsPage.assertDisabled(username!);
|
||||
|
||||
userDetailsPage.save();
|
||||
masthead.checkNotificationMessage("The user has been saved");
|
||||
cy.wait(1000);
|
||||
userDetailsPage.assertDisabled(username!);
|
||||
|
||||
return deleteUser(username!);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -69,4 +69,30 @@ export default class UserDetailsPage extends PageObject {
|
|||
cy.findByTestId(this.sessionsTab).click();
|
||||
return this;
|
||||
}
|
||||
|
||||
toggleEnabled(userName: string) {
|
||||
this.#getEnabledSwitch(userName).click({ force: true });
|
||||
}
|
||||
|
||||
assertEnabled(userName: string) {
|
||||
this.#getEnabledSwitchLabel(userName)
|
||||
.scrollIntoView()
|
||||
.contains("Enabled")
|
||||
.should("be.visible");
|
||||
}
|
||||
|
||||
assertDisabled(userName: string) {
|
||||
this.#getEnabledSwitchLabel(userName)
|
||||
.scrollIntoView()
|
||||
.contains("Disabled")
|
||||
.should("be.visible");
|
||||
}
|
||||
|
||||
#getEnabledSwitch(userName: string) {
|
||||
return cy.findByTestId(`${userName}-switch`);
|
||||
}
|
||||
|
||||
#getEnabledSwitchLabel(userName: string) {
|
||||
return this.#getEnabledSwitch(userName).closest("label");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,17 @@ class AdminClient {
|
|||
|
||||
async createUser(user: UserRepresentation) {
|
||||
await this.login();
|
||||
return await this.client.users.create(user);
|
||||
|
||||
const { id } = await this.client.users.create(user);
|
||||
const createdUser = await this.client.users.findOne({ id });
|
||||
|
||||
if (!createdUser) {
|
||||
throw new Error(
|
||||
"Unable to create user, created user could not be found."
|
||||
);
|
||||
}
|
||||
|
||||
return createdUser;
|
||||
}
|
||||
|
||||
async updateUser(id: string, payload: UserRepresentation) {
|
||||
|
|
|
@ -25,8 +25,7 @@ import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
|||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { UserProfileProvider } from "../realm-settings/user-profile/UserProfileContext";
|
||||
import { useParams } from "../utils/useParams";
|
||||
import { toUser, UserParams, UserTab } from "./routes/User";
|
||||
import { toUsers } from "./routes/Users";
|
||||
import { useUpdateEffect } from "../utils/useUpdateEffect";
|
||||
import { UserAttributes } from "./UserAttributes";
|
||||
import { UserConsents } from "./UserConsents";
|
||||
import { UserCredentials } from "./UserCredentials";
|
||||
|
@ -39,6 +38,8 @@ import {
|
|||
} from "./UserProfileFields";
|
||||
import { UserRoleMapping } from "./UserRoleMapping";
|
||||
import { UserSessions } from "./UserSessions";
|
||||
import { UserParams, UserTab, toUser } from "./routes/User";
|
||||
import { toUsers } from "./routes/Users";
|
||||
|
||||
import "./user-section.css";
|
||||
|
||||
|
@ -121,6 +122,9 @@ const EditUserForm = ({ user, bruteForced, refresh }: EditUserFormProps) => {
|
|||
const identityProviderLinksTab = useTab("identity-provider-links");
|
||||
const sessionsTab = useTab("sessions");
|
||||
|
||||
// Ensure the form remains up-to-date when the user is updated.
|
||||
useUpdateEffect(() => userForm.reset(user), [user]);
|
||||
|
||||
const save = async (formUser: UserRepresentation) => {
|
||||
try {
|
||||
await adminClient.users.update(
|
||||
|
|
Loading…
Reference in a new issue