1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 describe('User profile tests', function() {
8 const roleGroupName = `Test role group (${Math.floor(999999 * Math.random())})`;
9 const projectGroupName = `Test project group (${Math.floor(999999 * Math.random())})`;
12 // Only set up common users once. These aren't set up as aliases because
13 // aliases are cleaned up after every test. Also it doesn't make sense
14 // to set the same users on beforeEach() over and over again, so we
15 // separate a little from Cypress' 'Best Practices' here.
16 cy.getUser('admin', 'Admin', 'User', true, true)
17 .as('adminUser').then(function() {
18 adminUser = this.adminUser;
21 cy.getUser('user', 'Active', 'User', false, true)
22 .as('activeUser').then(function() {
23 activeUser = this.activeUser;
28 function assertProfileValues({
38 cy.get('[data-cy=profile-form] input[name="firstName"]').invoke('val').should('equal', firstName);
39 cy.get('[data-cy=profile-form] input[name="lastName"]').invoke('val').should('equal', lastName);
40 cy.get('[data-cy=profile-form] [data-cy=email] [data-cy=value]').contains(email);
41 cy.get('[data-cy=profile-form] [data-cy=username] [data-cy=value]').contains(username);
43 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').invoke('val').should('equal', org);
44 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').invoke('val').should('equal', org_email);
45 cy.get('[data-cy=profile-form] select[name="prefs.profile.role"]').invoke('val').should('equal', role);
46 cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').invoke('val').should('equal', website);
49 function enterProfileValues({
55 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').clear();
57 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').type(org);
59 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').clear();
61 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').type(org_email);
63 cy.get('[data-cy=profile-form] select[name="prefs.profile.role"]').select(role);
64 cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').clear();
66 cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').type(website);
70 function assertContextMenuItems({
77 cy.get('[data-cy=user-profile-panel-options-btn]').click();
78 cy.get('[data-cy=context-menu]').within(() => {
79 cy.get('[role=button]').contains('API Details');
81 cy.get('[role=button]').should(account ? 'contain' : 'not.contain', 'Account Settings');
82 cy.get('[role=button]').should(activate ? 'contain' : 'not.contain', 'Activate user');
83 cy.get('[role=button]').should(deactivate ? 'contain' : 'not.contain', 'Deactivate user');
84 cy.get('[role=button]').should(login ? 'contain' : 'not.contain', 'Login as user');
85 cy.get('[role=button]').should(setup ? 'contain' : 'not.contain', 'Setup user');
87 cy.get('div[role=presentation]').click();
90 beforeEach(function() {
91 cy.updateResource(adminUser.token, 'users', adminUser.user.uuid, {
95 organization_email: '',
101 cy.updateResource(adminUser.token, 'users', activeUser.user.uuid, {
105 organization_email: '',
113 it('non-admin can edit own profile', function() {
114 cy.loginAs(activeUser);
116 cy.get('header button[title="Account Management"]').click();
117 cy.get('#account-menu').contains('My account').click();
119 // Admin actions should be hidden, no account menu
120 assertContextMenuItems({
128 // Check initial values
129 assertProfileValues({
132 email: 'user@example.local',
143 org_email: 'email@example.com',
144 role: 'Data Scientist',
145 website: 'example.com',
148 cy.get('[data-cy=profile-form] button[type="submit"]').should('not.be.disabled');
151 cy.get('[data-cy=profile-form] button[type="submit"]').click();
154 assertProfileValues({
157 email: 'user@example.local',
160 org_email: 'email@example.com',
161 role: 'Data Scientist',
162 website: 'example.com',
165 // if it worked, the save button should be disabled.
166 cy.get('[data-cy=profile-form] button[type="submit"]').should('be.disabled');
169 it('non-admin cannot edit other profile', function() {
170 cy.loginAs(activeUser);
171 cy.goToPath('/user/' + adminUser.user.uuid);
173 assertProfileValues({
176 email: 'admin@example.local',
184 // Inputs should be disabled
185 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').should('be.disabled');
186 cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').should('be.disabled');
187 cy.get('[data-cy=profile-form] select[name="prefs.profile.role"]').should('be.disabled');
188 cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').should('be.disabled');
190 // Submit should be disabled
191 cy.get('[data-cy=profile-form] button[type="submit"]').should('be.disabled');
193 // Admin actions should be hidden, no account menu
194 assertContextMenuItems({
203 it('admin can edit own profile', function() {
204 cy.loginAs(adminUser);
206 cy.get('header button[title="Account Management"]').click();
207 cy.get('#account-menu').contains('My account').click();
209 // Admin actions should be visible, no account menu
210 assertContextMenuItems({
218 // Check initial values
219 assertProfileValues({
222 email: 'admin@example.local',
232 org: 'Admin org name',
233 org_email: 'admin@example.com',
235 website: 'admin.local',
237 cy.get('[data-cy=profile-form] button[type="submit"]').click();
240 assertProfileValues({
243 email: 'admin@example.local',
245 org: 'Admin org name',
246 org_email: 'admin@example.com',
248 website: 'admin.local',
252 it('admin can edit other profile', function() {
253 cy.loginAs(adminUser);
254 cy.goToPath('/user/' + activeUser.user.uuid);
257 assertProfileValues({
260 email: 'user@example.local',
269 org: 'Changed org name',
270 org_email: 'changed@example.com',
272 website: 'changed.local',
274 cy.get('[data-cy=profile-form] button[type="submit"]').click();
277 assertProfileValues({
280 email: 'user@example.local',
282 org: 'Changed org name',
283 org_email: 'changed@example.com',
285 website: 'changed.local',
288 // Admin actions should be visible, no account menu
289 assertContextMenuItems({
298 it('displays role groups on user profile', function() {
299 cy.loginAs(adminUser);
301 cy.createGroup(adminUser.token, {
304 }).as('roleGroup').then(function() {
305 cy.createLink(adminUser.token, {
307 link_class: 'permission',
308 head_uuid: this.roleGroup.uuid,
309 tail_uuid: adminUser.user.uuid
311 cy.createLink(adminUser.token, {
313 link_class: 'permission',
314 head_uuid: this.roleGroup.uuid,
315 tail_uuid: activeUser.user.uuid
319 cy.createGroup(adminUser.token, {
320 name: projectGroupName,
321 group_class: 'project',
322 }).as('projectGroup').then(function() {
323 cy.createLink(adminUser.token, {
325 link_class: 'permission',
326 head_uuid: this.projectGroup.uuid,
327 tail_uuid: adminUser.user.uuid
329 cy.createLink(adminUser.token, {
331 link_class: 'permission',
332 head_uuid: this.projectGroup.uuid,
333 tail_uuid: activeUser.user.uuid
337 cy.goToPath('/user/' + activeUser.user.uuid);
338 cy.get('div [role="tab"]').contains('GROUPS').click();
339 cy.get('[data-cy=user-profile-groups-data-explorer]').contains(roleGroupName);
340 cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', projectGroupName);
342 cy.goToPath('/user/' + adminUser.user.uuid);
343 cy.get('div [role="tab"]').contains('GROUPS').click();
344 cy.get('[data-cy=user-profile-groups-data-explorer]').contains(roleGroupName);
345 cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', projectGroupName);
348 it('allows performing admin functions', function() {
349 cy.loginAs(adminUser);
350 cy.goToPath('/user/' + activeUser.user.uuid);
352 // Check that user is active
353 cy.get('[data-cy=account-status]').contains('Active');
354 cy.get('div [role="tab"]').contains('GROUPS').click();
355 cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
356 cy.get('div [role="tab"]').contains('PROFILE').click();
357 assertContextMenuItems({
366 cy.get('[data-cy=user-profile-panel-options-btn]').click();
367 cy.get('[data-cy=context-menu]').contains('Deactivate user').click();
368 cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
370 // Check that user is deactivated
371 cy.get('[data-cy=account-status]').contains('Inactive');
372 cy.get('div [role="tab"]').contains('GROUPS').click();
373 cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', 'All users');
374 cy.get('div [role="tab"]').contains('PROFILE').click();
375 assertContextMenuItems({
384 cy.get('[data-cy=user-profile-panel-options-btn]').click();
385 cy.get('[data-cy=context-menu]').contains('Setup user').click();
386 cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
388 // Check that user is setup
389 cy.get('[data-cy=account-status]').contains('Setup');
390 cy.get('div [role="tab"]').contains('GROUPS').click();
391 cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
392 cy.get('div [role="tab"]').contains('PROFILE').click();
393 assertContextMenuItems({
402 cy.get('[data-cy=user-profile-panel-options-btn]').click();
403 cy.get('[data-cy=context-menu]').contains('Activate user').click();
404 cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
406 // Check that user is active
407 cy.get('[data-cy=account-status]').contains('Active');
408 cy.get('div [role="tab"]').contains('GROUPS').click();
409 cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
410 cy.get('div [role="tab"]').contains('PROFILE').click();
411 assertContextMenuItems({
419 // Deactivate and activate user skipping setup
420 cy.get('[data-cy=user-profile-panel-options-btn]').click();
421 cy.get('[data-cy=context-menu]').contains('Deactivate user').click();
422 cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
424 cy.get('[data-cy=account-status]').contains('Inactive');
425 cy.get('div [role="tab"]').contains('GROUPS').click();
426 cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', 'All users');
427 cy.get('div [role="tab"]').contains('PROFILE').click();
428 assertContextMenuItems({
436 cy.get('[data-cy=user-profile-panel-options-btn]').click();
437 cy.get('[data-cy=context-menu]').contains('Activate user').click();
438 cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
440 // Check that user is active
441 cy.get('[data-cy=account-status]').contains('Active');
442 cy.get('div [role="tab"]').contains('GROUPS').click();
443 cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
444 cy.get('div [role="tab"]').contains('PROFILE').click();
445 assertContextMenuItems({