18559: Update user profile cypress tests and fix minor issues
authorStephen Smith <stephen@curii.com>
Thu, 31 Mar 2022 05:39:05 +0000 (01:39 -0400)
committerStephen Smith <stephen@curii.com>
Thu, 31 Mar 2022 05:39:05 +0000 (01:39 -0400)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

cypress/integration/user-profile.spec.js
src/store/user-profile/user-profile-actions.ts
src/views-components/context-menu/action-sets/user-action-set.ts
src/views-components/data-explorer/renderers.tsx
src/views/user-profile-panel/user-profile-panel-root.tsx

index 325f38c7871c753d6216ba8b8e789a3c1ab03d7c..2af2a144ecdbab6e83ee6da02be49b9f0dc90a84 100644 (file)
@@ -35,8 +35,8 @@ describe('User profile tests', function() {
         role,
         website,
     }) {
-        cy.get('[data-cy=profile-form] [data-cy=firstName] [data-cy=value]').contains(firstName);
-        cy.get('[data-cy=profile-form] [data-cy=lastName] [data-cy=value]').contains(lastName);
+        cy.get('[data-cy=profile-form] input[name="firstName"]').invoke('val').should('equal', firstName);
+        cy.get('[data-cy=profile-form] input[name="lastName"]').invoke('val').should('equal', lastName);
         cy.get('[data-cy=profile-form] [data-cy=email] [data-cy=value]').contains(email);
         cy.get('[data-cy=profile-form] [data-cy=username] [data-cy=value]').contains(username);
 
@@ -76,7 +76,12 @@ describe('User profile tests', function() {
             role: '',
             website: '',
         });
-        cy.get('[data-cy=profile-form] button[type="submit"]').click({force: true});
+        cy.get('[data-cy=profile-form] button[type="submit"]').then((btn) => {
+            if (!btn.is(':disabled')) {
+                btn.click();
+            }
+        });
+
 
         cy.goToPath('/user/' + activeUser.user.uuid);
         enterProfileValues({
@@ -85,7 +90,11 @@ describe('User profile tests', function() {
             role: '',
             website: '',
         });
-        cy.get('[data-cy=profile-form] button[type="submit"]').click({force: true});
+        cy.get('[data-cy=profile-form] button[type="submit"]').then((btn) => {
+            if (!btn.is(':disabled')) {
+                btn.click();
+            }
+        });
     });
 
     it('non-admin can edit own profile', function() {
@@ -157,8 +166,15 @@ describe('User profile tests', function() {
         // Submit should be disabled
         cy.get('[data-cy=profile-form] button[type="submit"]').should('be.disabled');
 
-        // Admin tab should be hidden
-        cy.get('div [role="tab"]').should('not.contain', 'ADMIN');
+        // Admin context items should be hidden
+        cy.get('[data-cy=user-profile-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').within(() => {
+            cy.get('[role=button]').should('not.contain', 'Activate User')
+            cy.get('[role=button]').should('not.contain', 'Deactivate User')
+            cy.get('[role=button]').should('not.contain', 'Login As User')
+            cy.get('[role=button]').should('not.contain', 'Setup User');
+        });
+        cy.get('div[role=presentation]').click();
     });
 
     it('admin can edit own profile', function() {
@@ -167,8 +183,15 @@ describe('User profile tests', function() {
         cy.get('header button[title="Account Management"]').click();
         cy.get('#account-menu').contains('My account').click();
 
-        // Admin tab should be visible
-        cy.get('div [role="tab"]').should('contain', 'ADMIN');
+        // Admin context items should be visible
+        cy.get('[data-cy=user-profile-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').within(() => {
+            cy.get('[role=button]').contains('Activate User')
+            cy.get('[role=button]').contains('Deactivate User')
+            cy.get('[role=button]').contains('Login As User')
+            cy.get('[role=button]').contains('Setup User');
+        });
+        cy.get('div[role=presentation]').click();
 
         // Check initial values
         assertProfileValues({
@@ -291,4 +314,67 @@ describe('User profile tests', function() {
         cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', projectGroupName);
     });
 
+    it('allows performing admin functions', function() {
+        cy.loginAs(adminUser);
+        cy.goToPath('/user/' + activeUser.user.uuid);
+
+        // Check that user is active
+        cy.get('[data-cy=account-status]').contains('Active');
+        cy.get('div [role="tab"]').contains('GROUPS').click();
+        cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
+        cy.get('div [role="tab"]').contains('PROFILE').click();
+
+        // Deactivate user
+        cy.get('[data-cy=user-profile-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').contains('Deactivate User').click();
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+
+        // Check that user is deactivated
+        cy.get('[data-cy=account-status]').contains('Inactive');
+        cy.get('div [role="tab"]').contains('GROUPS').click();
+        cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', 'All users');
+        cy.get('div [role="tab"]').contains('PROFILE').click();
+
+        // Setup user
+        cy.get('[data-cy=user-profile-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').contains('Setup User').click();
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+
+        // Check that user is setup
+        cy.get('[data-cy=account-status]').contains('Setup');
+        cy.get('div [role="tab"]').contains('GROUPS').click();
+        cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
+        cy.get('div [role="tab"]').contains('PROFILE').click();
+
+        // Activate user
+        cy.get('[data-cy=user-profile-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').contains('Activate User').click();
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+
+        // Check that user is active
+        cy.get('[data-cy=account-status]').contains('Active');
+        cy.get('div [role="tab"]').contains('GROUPS').click();
+        cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
+        cy.get('div [role="tab"]').contains('PROFILE').click();
+
+        // Deactivate and activate user skipping setup
+        cy.get('[data-cy=user-profile-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').contains('Deactivate User').click();
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+        //
+        cy.get('[data-cy=account-status]').contains('Inactive');
+        cy.get('div [role="tab"]').contains('GROUPS').click();
+        cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', 'All users');
+        cy.get('div [role="tab"]').contains('PROFILE').click();
+        //
+        cy.get('[data-cy=user-profile-panel-options-btn]').click();
+        cy.get('[data-cy=context-menu]').contains('Activate User').click();
+        cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
+
+        // Check that user is active
+        cy.get('[data-cy=account-status]').contains('Active');
+        cy.get('div [role="tab"]').contains('GROUPS').click();
+        cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
+    });
+
 });
index 4d3d34aaf24969bfe7371b7cfff8f9545c1341a6..9935518b98286e083ca29df33f8390a03e5e23b8 100644 (file)
@@ -114,6 +114,10 @@ export const setup = (uuid: string) =>
     try {
       const resources = await services.userService.setup(uuid);
       dispatch(updateResources(resources.items));
+
+      // Refresh data explorer
+      dispatch(UserProfileGroupsActions.REQUEST_ITEMS());
+
       dispatch(snackbarActions.OPEN_SNACKBAR({ message: "User has been setup", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
     } catch (e) {
       dispatch(snackbarActions.OPEN_SNACKBAR({ message: e.message, hideDuration: 2000, kind: SnackbarKind.ERROR }));
@@ -127,6 +131,10 @@ export const activate = (uuid: string) =>
     try {
       const user = await services.userService.activate(uuid);
       dispatch(updateResources([user]));
+
+      // Refresh data explorer
+      dispatch(UserProfileGroupsActions.REQUEST_ITEMS());
+
       dispatch(snackbarActions.OPEN_SNACKBAR({ message: "User has been activated", hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
     } catch (e) {
       dispatch(snackbarActions.OPEN_SNACKBAR({ message: e.message, hideDuration: 2000, kind: SnackbarKind.ERROR }));
@@ -152,6 +160,9 @@ export const deactivate = (uuid: string) =>
       // Remove all users membership locally
       dispatch<any>(deleteResources(memberships.map(link => link.uuid)));
 
+      // Refresh data explorer
+      dispatch(UserProfileGroupsActions.REQUEST_ITEMS());
+
       dispatch(snackbarActions.OPEN_SNACKBAR({
         message: "User has been deactivated.",
         hideDuration: 2000,
index b01516e2dfed1be235a4027004e9040b09589941..6511b9a052bfb76ee5ea005399a8242394c8fff0 100644 (file)
@@ -44,6 +44,7 @@ export const userActionSet: ContextMenuActionSet = [[{
     }
 },], [{
     name: "Activate User",
+    adminOnly: true,
     icon: ActiveIcon,
     execute: (dispatch, { uuid }) => {
         dispatch<any>(openActivateDialog(uuid));
index 8b29b24d274cfcf0798441d51c3004c1d900bea7..e854da0ee6caeebfdfd41af58dc8a081b58ecf0e 100644 (file)
@@ -220,7 +220,7 @@ enum UserAccountStatus {
 }
 
 const renderAccountStatus = (props: {status: UserAccountStatus}) =>
-    <Grid container alignItems="center" wrap="nowrap" spacing={8}>
+    <Grid container alignItems="center" wrap="nowrap" spacing={8} data-cy="account-status">
         <Grid item>
             {(() => {
                 switch(props.status) {
index 445f15e83a6828e65b0dff6a6fb82d2756f37bc2..1c8b1da74c65e8ef5daf087acaba3dd04e9660e6 100644 (file)
@@ -217,7 +217,7 @@ export const UserProfilePanelRoot = withStyles(styles)(
                                         <Grid item>
                                             <Tooltip title="Actions" disableFocusListener>
                                                 <IconButton
-                                                    data-cy='collection-panel-options-btn'
+                                                    data-cy='user-profile-panel-options-btn'
                                                     aria-label="Actions"
                                                     onClick={(event) => this.handleContextMenu(event, this.props.userUuid)}>
                                                     <MoreOptionsIcon />