--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+describe('User profile tests', function() {
+ let activeUser;
+ let adminUser;
+ const roleGroupName = `Test role group (${Math.floor(999999 * Math.random())})`;
+ const projectGroupName = `Test project group (${Math.floor(999999 * Math.random())})`;
+
+ before(function() {
+ // Only set up common users once. These aren't set up as aliases because
+ // aliases are cleaned up after every test. Also it doesn't make sense
+ // to set the same users on beforeEach() over and over again, so we
+ // separate a little from Cypress' 'Best Practices' here.
+ cy.getUser('admin', 'Admin', 'User', true, true)
+ .as('adminUser').then(function() {
+ adminUser = this.adminUser;
+ }
+ );
+ cy.getUser('user', 'Active', 'User', false, true)
+ .as('activeUser').then(function() {
+ activeUser = this.activeUser;
+ }
+ );
+ });
+
+ function assertProfileValues({
+ firstName,
+ lastName,
+ email,
+ username,
+ org,
+ org_email,
+ role,
+ website,
+ }) {
+ 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);
+
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').invoke('val').should('equal', org);
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').invoke('val').should('equal', org_email);
+ cy.get('[data-cy=profile-form] select[name="prefs.profile.role"]').invoke('val').should('equal', role);
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').invoke('val').should('equal', website);
+ }
+
+ function enterProfileValues({
+ org,
+ org_email,
+ role,
+ website,
+ }) {
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').clear();
+ if (org) {
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').type(org);
+ }
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').clear();
+ if (org_email) {
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').type(org_email);
+ }
+ cy.get('[data-cy=profile-form] select[name="prefs.profile.role"]').select(role);
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').clear();
+ if (website) {
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').type(website);
+ }
+ }
+
+ function assertContextMenuItems({
+ account,
+ activate,
+ deactivate,
+ login,
+ setup
+ }) {
+ cy.get('[data-cy=user-profile-panel-options-btn]').click();
+ cy.get('[data-cy=context-menu]').within(() => {
+ cy.get('[role=button]').contains('Advanced');
+
+ cy.get('[role=button]').should(account ? 'contain' : 'not.contain', 'Account Settings');
+ cy.get('[role=button]').should(activate ? 'contain' : 'not.contain', 'Activate User');
+ cy.get('[role=button]').should(deactivate ? 'contain' : 'not.contain', 'Deactivate User');
+ cy.get('[role=button]').should(login ? 'contain' : 'not.contain', 'Login As User');
+ cy.get('[role=button]').should(setup ? 'contain' : 'not.contain', 'Setup User');
+ });
+ cy.get('div[role=presentation]').click();
+ }
+
+ beforeEach(function() {
+ cy.updateResource(adminUser.token, 'users', adminUser.user.uuid, {
+ prefs: {
+ profile: {
+ organization: '',
+ organization_email: '',
+ role: '',
+ website_url: '',
+ },
+ },
+ });
+ cy.updateResource(adminUser.token, 'users', activeUser.user.uuid, {
+ prefs: {
+ profile: {
+ organization: '',
+ organization_email: '',
+ role: '',
+ website_url: '',
+ },
+ },
+ });
+ });
+
+ it('non-admin can edit own profile', function() {
+ cy.loginAs(activeUser);
+
+ cy.get('header button[title="Account Management"]').click();
+ cy.get('#account-menu').contains('My account').click();
+
+ // Admin actions should be hidden, no account menu
+ assertContextMenuItems({
+ account: false,
+ activate: false,
+ deactivate: false,
+ login: false,
+ setup: false,
+ });
+
+ // Check initial values
+ assertProfileValues({
+ firstName: 'Active',
+ lastName: 'User',
+ email: 'user@example.local',
+ username: 'user',
+ org: '',
+ org_email: '',
+ role: '',
+ website: '',
+ });
+
+ // Change values
+ enterProfileValues({
+ org: 'Org name',
+ org_email: 'email@example.com',
+ role: 'Data Scientist',
+ website: 'example.com',
+ });
+
+ // Submit
+ cy.get('[data-cy=profile-form] button[type="submit"]').click();
+
+ // Check new values
+ assertProfileValues({
+ firstName: 'Active',
+ lastName: 'User',
+ email: 'user@example.local',
+ username: 'user',
+ org: 'Org name',
+ org_email: 'email@example.com',
+ role: 'Data Scientist',
+ website: 'example.com',
+ });
+ });
+
+ it('non-admin cannot edit other profile', function() {
+ cy.loginAs(activeUser);
+ cy.goToPath('/user/' + adminUser.user.uuid);
+
+ assertProfileValues({
+ firstName: 'Admin',
+ lastName: 'User',
+ email: 'admin@example.local',
+ username: 'admin',
+ org: '',
+ org_email: '',
+ role: '',
+ website: '',
+ });
+
+ // Inputs should be disabled
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').should('be.disabled');
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').should('be.disabled');
+ cy.get('[data-cy=profile-form] select[name="prefs.profile.role"]').should('be.disabled');
+ cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').should('be.disabled');
+
+ // Submit should be disabled
+ cy.get('[data-cy=profile-form] button[type="submit"]').should('be.disabled');
+
+ // Admin actions should be hidden, no account menu
+ assertContextMenuItems({
+ account: false,
+ activate: false,
+ deactivate: false,
+ login: false,
+ setup: false,
+ });
+ });
+
+ it('admin can edit own profile', function() {
+ cy.loginAs(adminUser);
+
+ cy.get('header button[title="Account Management"]').click();
+ cy.get('#account-menu').contains('My account').click();
+
+ // Admin actions should be visible, no account menu
+ assertContextMenuItems({
+ account: false,
+ activate: false,
+ deactivate: true,
+ login: false,
+ setup: false,
+ });
+
+ // Check initial values
+ assertProfileValues({
+ firstName: 'Admin',
+ lastName: 'User',
+ email: 'admin@example.local',
+ username: 'admin',
+ org: '',
+ org_email: '',
+ role: '',
+ website: '',
+ });
+
+ // Change values
+ enterProfileValues({
+ org: 'Admin org name',
+ org_email: 'admin@example.com',
+ role: 'Researcher',
+ website: 'admin.local',
+ });
+ cy.get('[data-cy=profile-form] button[type="submit"]').click();
+
+ // Check new values
+ assertProfileValues({
+ firstName: 'Admin',
+ lastName: 'User',
+ email: 'admin@example.local',
+ username: 'admin',
+ org: 'Admin org name',
+ org_email: 'admin@example.com',
+ role: 'Researcher',
+ website: 'admin.local',
+ });
+ });
+
+ it('admin can edit other profile', function() {
+ cy.loginAs(adminUser);
+ cy.goToPath('/user/' + activeUser.user.uuid);
+
+ // Check new values
+ assertProfileValues({
+ firstName: 'Active',
+ lastName: 'User',
+ email: 'user@example.local',
+ username: 'user',
+ org: '',
+ org_email: '',
+ role: '',
+ website: '',
+ });
+
+ enterProfileValues({
+ org: 'Changed org name',
+ org_email: 'changed@example.com',
+ role: 'Researcher',
+ website: 'changed.local',
+ });
+ cy.get('[data-cy=profile-form] button[type="submit"]').click();
+
+ // Check new values
+ assertProfileValues({
+ firstName: 'Active',
+ lastName: 'User',
+ email: 'user@example.local',
+ username: 'user',
+ org: 'Changed org name',
+ org_email: 'changed@example.com',
+ role: 'Researcher',
+ website: 'changed.local',
+ });
+
+ // Admin actions should be visible, no account menu
+ assertContextMenuItems({
+ account: false,
+ activate: false,
+ deactivate: true,
+ login: true,
+ setup: false,
+ });
+ });
+
+ it('displays role groups on user profile', function() {
+ cy.loginAs(adminUser);
+
+ cy.createGroup(adminUser.token, {
+ name: roleGroupName,
+ group_class: 'role',
+ }).as('roleGroup').then(function() {
+ cy.createLink(adminUser.token, {
+ name: 'can_write',
+ link_class: 'permission',
+ head_uuid: this.roleGroup.uuid,
+ tail_uuid: adminUser.user.uuid
+ });
+ cy.createLink(adminUser.token, {
+ name: 'can_write',
+ link_class: 'permission',
+ head_uuid: this.roleGroup.uuid,
+ tail_uuid: activeUser.user.uuid
+ });
+ });
+
+ cy.createGroup(adminUser.token, {
+ name: projectGroupName,
+ group_class: 'project',
+ }).as('projectGroup').then(function() {
+ cy.createLink(adminUser.token, {
+ name: 'can_write',
+ link_class: 'permission',
+ head_uuid: this.projectGroup.uuid,
+ tail_uuid: adminUser.user.uuid
+ });
+ cy.createLink(adminUser.token, {
+ name: 'can_write',
+ link_class: 'permission',
+ head_uuid: this.projectGroup.uuid,
+ tail_uuid: activeUser.user.uuid
+ });
+ });
+
+ cy.goToPath('/user/' + activeUser.user.uuid);
+ cy.get('div [role="tab"]').contains('GROUPS').click();
+ cy.get('[data-cy=user-profile-groups-data-explorer]').contains(roleGroupName);
+ cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', projectGroupName);
+
+ cy.goToPath('/user/' + adminUser.user.uuid);
+ cy.get('div [role="tab"]').contains('GROUPS').click();
+ cy.get('[data-cy=user-profile-groups-data-explorer]').contains(roleGroupName);
+ 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();
+ assertContextMenuItems({
+ account: false,
+ activate: false,
+ deactivate: true,
+ login: true,
+ setup: false,
+ });
+
+ // 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();
+ assertContextMenuItems({
+ account: false,
+ activate: true,
+ deactivate: false,
+ login: true,
+ setup: true,
+ });
+
+ // 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();
+ assertContextMenuItems({
+ account: false,
+ activate: true,
+ deactivate: true,
+ login: true,
+ setup: false,
+ });
+
+ // 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();
+ assertContextMenuItems({
+ account: false,
+ activate: false,
+ deactivate: true,
+ login: true,
+ setup: false,
+ });
+
+ // 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();
+ // Check
+ 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();
+ assertContextMenuItems({
+ account: false,
+ activate: true,
+ deactivate: false,
+ login: true,
+ setup: true,
+ });
+ // reactivate
+ 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();
+ assertContextMenuItems({
+ account: false,
+ activate: false,
+ deactivate: true,
+ login: true,
+ setup: false,
+ });
+ });
+
+});