diff --git a/cypress/integration/users_test.spec.ts b/cypress/integration/users_test.spec.ts index 672e964d49..70c1531937 100644 --- a/cypress/integration/users_test.spec.ts +++ b/cypress/integration/users_test.spec.ts @@ -16,7 +16,6 @@ describe("Group creation", () => { const loginPage = new LoginPage(); const masthead = new Masthead(); const sidebarPage = new SidebarPage(); - const listingPage = new ListingPage(); const groupModal = new GroupModal(); beforeEach(function () { @@ -25,33 +24,24 @@ describe("Group creation", () => { sidebarPage.goToGroups(); }); + function createNewGroup() { + groupName += "_" + (Math.random() + 1).toString(36).substring(7); + + groupModal + .open("openCreateGroupModal") + .fillGroupForm(groupName) + .clickCreate(); + + groupsList = [...groupsList, groupName]; + masthead.checkNotificationMessage("Group created"); + + sidebarPage.goToGroups(); + } + it("Add groups to be joined", () => { - groupName += "_" + (Math.random() + 1).toString(36).substring(7); - - groupModal - .open("openCreateGroupModal") - .fillGroupForm(groupName) - .clickCreate(); - - groupsList = [...groupsList, groupName]; - masthead.checkNotificationMessage("Group created"); - - sidebarPage.goToGroups(); - listingPage.searchItem(groupName, false).itemExist(groupName); - - groupName = "group"; - groupName += "_" + (Math.random() + 1).toString(36).substring(7); - - groupModal - .open("openCreateGroupModal") - .fillGroupForm(groupName) - .clickCreate(); - - groupsList = [...groupsList, groupName]; - masthead.checkNotificationMessage("Group created"); - - sidebarPage.goToGroups(); - listingPage.searchItem(groupName, false).itemExist(groupName); + for (let i = 0; i <= 2; i++) { + createNewGroup(); + } }); }); @@ -93,7 +83,21 @@ describe("Users test", () => { createUserPage.goToCreateUser(); - createUserPage.createUser(itemId).save(); + createUserPage.createUser(itemId); + + createUserPage.toggleAddGroupModal(); + + const groupsListCopy = groupsList.slice(0, 1); + + console.log(groupsList); + + groupsListCopy.forEach((element) => { + cy.getId(`${element}-check`).click(); + }); + + createUserPage.joinGroups(); + + createUserPage.save(); masthead.checkNotificationMessage("The user has been created"); @@ -126,15 +130,17 @@ describe("Users test", () => { userGroupsPage.goToGroupsTab(); userGroupsPage.toggleAddGroupModal(); - groupsList.forEach((element) => { + cy.wait(1000); + + const groupsListCopy = groupsList.slice(1, 2); + + groupsListCopy.forEach((element) => { cy.getId(`${element}-check`).click(); }); - userGroupsPage.joinGroup(); + userGroupsPage.joinGroups(); cy.wait(1000); - - listingPage.itemExist(groupName); }); it("Leave group test", function () { @@ -142,7 +148,8 @@ describe("Users test", () => { listingPage.goToItemDetails(itemId); // Go to user groups userGroupsPage.goToGroupsTab(); - cy.getId(`leave-${groupName}`).click(); + cy.wait(1000); + cy.contains("Leave").click(); cy.getId("modalConfirm").click(); }); diff --git a/cypress/support/pages/admin_console/manage/users/CreateUserPage.ts b/cypress/support/pages/admin_console/manage/users/CreateUserPage.ts index c0abe02d6e..4f81ed2970 100644 --- a/cypress/support/pages/admin_console/manage/users/CreateUserPage.ts +++ b/cypress/support/pages/admin_console/manage/users/CreateUserPage.ts @@ -4,6 +4,8 @@ export default class CreateUserPage { emptyStateCreateUserBtn: string; searchPgCreateUserBtn: string; addUserBtn: string; + joinGroupsBtn: string; + joinBtn: string; saveBtn: string; cancelBtn: string; @@ -14,6 +16,8 @@ export default class CreateUserPage { this.emptyStateCreateUserBtn = "empty-primary-action"; this.searchPgCreateUserBtn = "create-new-user"; this.addUserBtn = "add-user"; + this.joinGroupsBtn = "join-groups-button"; + this.joinBtn = "join-button"; this.saveBtn = "create-user"; this.cancelBtn = "cancel-create-user"; } @@ -44,6 +48,18 @@ export default class CreateUserPage { return this; } + toggleAddGroupModal() { + cy.getId(this.joinGroupsBtn).click(); + + return this; + } + + joinGroups() { + cy.getId(this.joinBtn).click(); + + return this; + } + save() { cy.getId(this.saveBtn).click(); diff --git a/cypress/support/pages/admin_console/manage/users/UserGroupsPage.ts b/cypress/support/pages/admin_console/manage/users/UserGroupsPage.ts index e45717772d..e29f1b3e81 100644 --- a/cypress/support/pages/admin_console/manage/users/UserGroupsPage.ts +++ b/cypress/support/pages/admin_console/manage/users/UserGroupsPage.ts @@ -6,7 +6,7 @@ export default class UserGroupsPage { constructor() { this.userGroupsTab = "user-groups-tab"; this.addGroupButton = "add-group-button"; - this.joinGroupButton = "joinGroup"; + this.joinGroupButton = "join-button"; } goToGroupsTab() { @@ -21,7 +21,7 @@ export default class UserGroupsPage { return this; } - joinGroup() { + joinGroups() { cy.getId(this.joinGroupButton).click(); return this; diff --git a/src/user/JoinGroupDialog.tsx b/src/user/JoinGroupDialog.tsx index 2802acd5bd..feaf843e63 100644 --- a/src/user/JoinGroupDialog.tsx +++ b/src/user/JoinGroupDialog.tsx @@ -31,8 +31,9 @@ export type JoinGroupDialogProps = { open: boolean; toggleDialog: () => void; onClose: () => void; - username: string; + username?: string; onConfirm: (newGroups: Group[]) => void; + chips?: any; }; type Group = GroupRepresentation & { @@ -45,6 +46,7 @@ export const JoinGroupDialog = ({ toggleDialog, onConfirm, username, + chips, }: JoinGroupDialogProps) => { const { t } = useTranslation("roles"); const adminClient = useAdminClient(); @@ -65,17 +67,23 @@ export const JoinGroupDialog = ({ () => asyncStateFetch( async () => { - const existingUserGroups = await adminClient.users.listGroups({ id }); const allGroups = await adminClient.groups.find(); if (groupId) { const group = await adminClient.groups.findOne({ id: groupId }); return { group, groups: group.subGroups! }; - } else { + } else if (id) { + const existingUserGroups = await adminClient.users.listGroups({ + id, + }); + return { groups: _.differenceBy(allGroups, existingUserGroups, "id"), }; - } + } else + return { + groups: allGroups, + }; }, async ({ group: selectedGroup, groups }) => { if (selectedGroup) { @@ -85,7 +93,9 @@ export const JoinGroupDialog = ({ groups.forEach((group: Group) => { group.checked = !!selectedRows.find((r) => r.id === group.id); }); - setGroups(groups); + id + ? setGroups(groups) + : setGroups([...groups.filter((row) => !chips.includes(row.name))]); }, errorHandler ), @@ -95,12 +105,14 @@ export const JoinGroupDialog = ({ return ( ; save: (user: UserRepresentation) => void; editMode: boolean; timestamp?: number; + onGroupsUpdate: (groups: GroupRepresentation[]) => void; }; export const UserForm = ({ form: { handleSubmit, register, errors, watch, control, setValue, reset }, save, editMode, + onGroupsUpdate, }: UserFormProps) => { const { t } = useTranslation("users"); const { realm } = useRealm(); @@ -45,6 +54,14 @@ export const UserForm = ({ const watchUsernameInput = watch("username"); const [timestamp, setTimestamp] = useState(null); + const [chips, setChips] = useState<(string | undefined)[]>([]); + const [selectedGroups, setSelectedGroups] = useState( + [] + ); + + const { addAlert } = useAlerts(); + + const [open, setOpen] = useState(false); useEffect(() => { if (editMode) { @@ -56,7 +73,7 @@ export const UserForm = ({ handleError ); } - }, []); + }, [chips]); const setupForm = (user: UserRepresentation) => { reset(); @@ -90,6 +107,50 @@ export const UserForm = ({ setRequiredUserActionsDropdownOpen(false); }; + const deleteItem = (id: string) => { + const copyOfChips = chips; + const copyOfGroups = selectedGroups; + + setChips(copyOfChips.filter((item) => item !== id)); + setSelectedGroups(copyOfGroups.filter((item) => item.name !== id)); + onGroupsUpdate(selectedGroups); + }; + + const addChips = async (groups: GroupRepresentation[]): Promise => { + const newSelectedGroups = groups; + + const newGroupNames: (string | undefined)[] = newSelectedGroups!.map( + (item) => item.name + ); + setChips([...chips!, ...newGroupNames]); + setSelectedGroups([...selectedGroups!, ...newSelectedGroups]); + }; + + onGroupsUpdate(selectedGroups); + + const addGroups = async (groups: GroupRepresentation[]): Promise => { + const newGroups = groups; + + newGroups.forEach(async (group) => { + try { + await adminClient.users.addToGroup({ + id: id, + groupId: group.id!, + }); + addAlert(t("users:addedGroupMembership"), AlertVariant.success); + } catch (error) { + addAlert( + t("users:addedGroupMembershipError", { error }), + AlertVariant.danger + ); + } + }); + }; + + const toggleModal = () => { + setOpen(!open); + }; + return ( + {open && ( + setOpen(!open)} + onConfirm={editMode ? addGroups : addChips} + toggleDialog={() => toggleModal()} + chips={chips} + /> + )} {editMode ? ( <> + {!editMode && ( + + } + > + ( + <> + + + {chips.map((currentChip) => ( + deleteItem(currentChip!)} + > + {currentChip} + + ))} + + + + + )} + /> + + )} +