22132: Display scheduling status in logs panel
[arvados.git] / services / workbench2 / cypress / e2e / user-profile.cy.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 describe('User profile tests', function() {
6     let activeUser;
7     let adminUser;
8     const roleGroupName = `Test role group (${Math.floor(999999 * Math.random())})`;
9     const projectGroupName = `Test project group (${Math.floor(999999 * Math.random())})`;
10
11     before(function() {
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;
19             }
20         );
21         cy.getUser('user', 'Active', 'User', false, true)
22             .as('activeUser').then(function() {
23                 activeUser = this.activeUser;
24             }
25         );
26     });
27
28     function assertProfileValues({
29         firstName,
30         lastName,
31         email,
32         username,
33         org,
34         org_email,
35         role,
36         website,
37     }) {
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);
42
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);
47     }
48
49     function enterProfileValues({
50         org,
51         org_email,
52         role,
53         website,
54     }) {
55         cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').clear();
56         if (org) {
57             cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').type(org);
58         }
59         cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').clear();
60         if (org_email) {
61             cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').type(org_email);
62         }
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();
65         if (website) {
66             cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').type(website);
67         }
68     }
69
70     function assertContextMenuItems({
71         account,
72         activate,
73         deactivate,
74         login,
75         setup
76     }) {
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');
80
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');
86         });
87         //de-select the context menu
88         cy.get('body').click();
89     }
90
91     beforeEach(function() {
92         cy.updateResource(adminUser.token, 'users', adminUser.user.uuid, {
93             prefs: {
94                 profile: {
95                     organization: '',
96                     organization_email: '',
97                     role: '',
98                     website_url: '',
99                 },
100             },
101         });
102         cy.updateResource(adminUser.token, 'users', activeUser.user.uuid, {
103             prefs: {
104                 profile: {
105                     organization: '',
106                     organization_email: '',
107                     role: '',
108                     website_url: '',
109                 },
110             },
111         });
112     });
113
114     it('non-admin can edit own profile', function() {
115         cy.loginAs(activeUser);
116
117         cy.get('header button[aria-label="Account Management"]').click();
118         cy.get('#account-menu').contains('My account').click();
119
120         // Admin actions should be hidden, no account menu
121         assertContextMenuItems({
122             account: false,
123             activate: false,
124             deactivate: false,
125             login: false,
126             setup: false,
127         });
128
129         // Check initial values
130         assertProfileValues({
131             firstName: 'Active',
132             lastName: 'User',
133             email: 'user@example.local',
134             username: 'user',
135             org: '',
136             org_email: '',
137             role: '',
138             website: '',
139         });
140
141         // Change values
142         enterProfileValues({
143             org: 'Org name',
144             org_email: 'email@example.com',
145             role: 'Data Scientist',
146             website: 'example.com',
147         });
148
149         cy.get('[data-cy=profile-form] button[type="submit"]').should('not.be.disabled');
150
151         // Submit
152         cy.get('[data-cy=profile-form] button[type="submit"]').click();
153
154         // Check new values
155         assertProfileValues({
156             firstName: 'Active',
157             lastName: 'User',
158             email: 'user@example.local',
159             username: 'user',
160             org: 'Org name',
161             org_email: 'email@example.com',
162             role: 'Data Scientist',
163             website: 'example.com',
164         });
165
166         // if it worked, the save button should be disabled.
167         cy.get('[data-cy=profile-form] button[type="submit"]').should('be.disabled');
168     });
169
170     it('non-admin cannot edit other profile', function() {
171         cy.loginAs(activeUser);
172         cy.goToPath('/user/' + adminUser.user.uuid);
173
174         assertProfileValues({
175             firstName: 'Admin',
176             lastName: 'User',
177             email: 'admin@example.local',
178             username: 'admin',
179             org: '',
180             org_email: '',
181             role: '',
182             website: '',
183         });
184
185         // Inputs should be disabled
186         cy.get('[data-cy=profile-form] input[name="prefs.profile.organization"]').should('be.disabled');
187         cy.get('[data-cy=profile-form] input[name="prefs.profile.organization_email"]').should('be.disabled');
188         cy.get('[data-cy=profile-form] select[name="prefs.profile.role"]').should('be.disabled');
189         cy.get('[data-cy=profile-form] input[name="prefs.profile.website_url"]').should('be.disabled');
190
191         // Submit should be disabled
192         cy.get('[data-cy=profile-form] button[type="submit"]').should('be.disabled');
193
194         // Admin actions should be hidden, no account menu
195         assertContextMenuItems({
196             account: false,
197             activate: false,
198             deactivate: false,
199             login: false,
200             setup: false,
201         });
202     });
203
204     it('admin can edit own profile', function() {
205         cy.loginAs(adminUser);
206
207         cy.get('header button[aria-label="Account Management"]').click();
208         cy.get('#account-menu').contains('My account').click();
209
210         // Admin actions should be visible, no account menu
211         assertContextMenuItems({
212             account: false,
213             activate: false,
214             deactivate: true,
215             login: false,
216             setup: false,
217         });
218
219         // Check initial values
220         assertProfileValues({
221             firstName: 'Admin',
222             lastName: 'User',
223             email: 'admin@example.local',
224             username: 'admin',
225             org: '',
226             org_email: '',
227             role: '',
228             website: '',
229         });
230
231         // Change values
232         enterProfileValues({
233             org: 'Admin org name',
234             org_email: 'admin@example.com',
235             role: 'Researcher',
236             website: 'admin.local',
237         });
238         cy.get('[data-cy=profile-form] button[type="submit"]').click();
239
240         // Check new values
241         assertProfileValues({
242             firstName: 'Admin',
243             lastName: 'User',
244             email: 'admin@example.local',
245             username: 'admin',
246             org: 'Admin org name',
247             org_email: 'admin@example.com',
248             role: 'Researcher',
249             website: 'admin.local',
250         });
251     });
252
253     it('admin can edit other profile', function() {
254         cy.loginAs(adminUser);
255         cy.goToPath('/user/' + activeUser.user.uuid);
256
257         // Check new values
258         assertProfileValues({
259             firstName: 'Active',
260             lastName: 'User',
261             email: 'user@example.local',
262             username: 'user',
263             org: '',
264             org_email: '',
265             role: '',
266             website: '',
267         });
268
269         enterProfileValues({
270             org: 'Changed org name',
271             org_email: 'changed@example.com',
272             role: 'Researcher',
273             website: 'changed.local',
274         });
275         cy.get('[data-cy=profile-form] button[type="submit"]').click();
276
277         // Check new values
278         assertProfileValues({
279             firstName: 'Active',
280             lastName: 'User',
281             email: 'user@example.local',
282             username: 'user',
283             org: 'Changed org name',
284             org_email: 'changed@example.com',
285             role: 'Researcher',
286             website: 'changed.local',
287         });
288
289         // Admin actions should be visible, no account menu
290         assertContextMenuItems({
291             account: false,
292             activate: false,
293             deactivate: true,
294             login: true,
295             setup: false,
296         });
297     });
298
299     it('displays role groups on user profile', function() {
300         cy.loginAs(adminUser);
301
302         cy.createGroup(adminUser.token, {
303             name: roleGroupName,
304             group_class: 'role',
305         }).as('roleGroup').then(function() {
306             cy.createLink(adminUser.token, {
307                 name: 'can_write',
308                 link_class: 'permission',
309                 head_uuid: this.roleGroup.uuid,
310                 tail_uuid: adminUser.user.uuid
311             });
312             cy.createLink(adminUser.token, {
313                 name: 'can_write',
314                 link_class: 'permission',
315                 head_uuid: this.roleGroup.uuid,
316                 tail_uuid: activeUser.user.uuid
317             });
318         });
319
320         cy.createGroup(adminUser.token, {
321             name: projectGroupName,
322             group_class: 'project',
323         }).as('projectGroup').then(function() {
324             cy.createLink(adminUser.token, {
325                 name: 'can_write',
326                 link_class: 'permission',
327                 head_uuid: this.projectGroup.uuid,
328                 tail_uuid: adminUser.user.uuid
329             });
330             cy.createLink(adminUser.token, {
331                 name: 'can_write',
332                 link_class: 'permission',
333                 head_uuid: this.projectGroup.uuid,
334                 tail_uuid: activeUser.user.uuid
335             });
336         });
337
338         cy.goToPath('/user/' + activeUser.user.uuid);
339         cy.get('div [role="tab"]').contains('GROUPS').click();
340         cy.get('[data-cy=user-profile-groups-data-explorer]').contains(roleGroupName);
341         cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', projectGroupName);
342
343         cy.goToPath('/user/' + adminUser.user.uuid);
344         cy.get('div [role="tab"]').contains('GROUPS').click();
345         cy.get('[data-cy=user-profile-groups-data-explorer]').contains(roleGroupName);
346         cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', projectGroupName);
347     });
348
349     it('allows performing admin functions', function() {
350         cy.loginAs(adminUser);
351         cy.goToPath('/user/' + activeUser.user.uuid);
352
353         // Check that user is active
354         cy.get('[data-cy=account-status]').contains('Active');
355         cy.get('div [role="tab"]').contains('GROUPS').click();
356         cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
357         cy.get('div [role="tab"]').contains('PROFILE').click();
358         assertContextMenuItems({
359             account: false,
360             activate: false,
361             deactivate: true,
362             login: true,
363             setup: false,
364         });
365
366         // Deactivate user
367         cy.get('[data-cy=user-profile-panel-options-btn]').click();
368         cy.get('[data-cy=context-menu]').contains('Deactivate user').click();
369         cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
370
371         // Check that user is deactivated
372         cy.get('[data-cy=account-status]').contains('Inactive');
373         cy.get('div [role="tab"]').contains('GROUPS').click();
374         cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', 'All users');
375         cy.get('div [role="tab"]').contains('PROFILE').click();
376         assertContextMenuItems({
377             account: false,
378             activate: true,
379             deactivate: false,
380             login: true,
381             setup: true,
382         });
383
384         // Setup user
385         cy.get('[data-cy=user-profile-panel-options-btn]').click();
386         cy.get('[data-cy=context-menu]').contains('Setup user').click();
387         cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
388
389         // Check that user is setup
390         cy.get('[data-cy=account-status]').contains('Setup');
391         cy.get('div [role="tab"]').contains('GROUPS').click();
392         cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
393         cy.get('div [role="tab"]').contains('PROFILE').click();
394         assertContextMenuItems({
395             account: false,
396             activate: true,
397             deactivate: true,
398             login: true,
399             setup: false,
400         });
401
402         // Activate user
403         cy.get('[data-cy=user-profile-panel-options-btn]').click();
404         cy.get('[data-cy=context-menu]').contains('Activate user').click();
405         cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
406
407         // Check that user is active
408         cy.get('[data-cy=account-status]').contains('Active');
409         cy.get('div [role="tab"]').contains('GROUPS').click();
410         cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
411         cy.get('div [role="tab"]').contains('PROFILE').click();
412         assertContextMenuItems({
413             account: false,
414             activate: false,
415             deactivate: true,
416             login: true,
417             setup: false,
418         });
419
420         // Deactivate and activate user skipping setup
421         cy.get('[data-cy=user-profile-panel-options-btn]').click();
422         cy.get('[data-cy=context-menu]').contains('Deactivate user').click();
423         cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
424         // Check
425         cy.get('[data-cy=account-status]').contains('Inactive');
426         cy.get('div [role="tab"]').contains('GROUPS').click();
427         cy.get('[data-cy=user-profile-groups-data-explorer]').should('not.contain', 'All users');
428         cy.get('div [role="tab"]').contains('PROFILE').click();
429         assertContextMenuItems({
430             account: false,
431             activate: true,
432             deactivate: false,
433             login: true,
434             setup: true,
435         });
436         // reactivate
437         cy.get('[data-cy=user-profile-panel-options-btn]').click();
438         cy.get('[data-cy=context-menu]').contains('Activate user').click();
439         cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
440
441         // Check that user is active
442         cy.get('[data-cy=account-status]').contains('Active');
443         cy.get('div [role="tab"]').contains('GROUPS').click();
444         cy.get('[data-cy=user-profile-groups-data-explorer]').should('contain', 'All users');
445         cy.get('div [role="tab"]').contains('PROFILE').click();
446         assertContextMenuItems({
447             account: false,
448             activate: false,
449             deactivate: true,
450             login: true,
451             setup: false,
452         });
453     });
454
455 });