21224: moved openuserattributes to resolve circular dep Arvados-DCO-1.1-Signed-off...
[arvados.git] / services / workbench2 / cypress / e2e / details-card.cy.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 describe('User Details Card tests', function () {
6     let activeUser;
7     let adminUser;
8
9     before(function () {
10         // Only set up common users once. These aren't set up as aliases because
11         // aliases are cleaned up after every test. Also it doesn't make sense
12         // to set the same users on beforeEach() over and over again, so we
13         // separate a little from Cypress' 'Best Practices' here.
14         cy.getUser('admin', 'Admin', 'User', true, true)
15             .as('adminUser')
16             .then(function () {
17                 adminUser = this.adminUser;
18             });
19         cy.getUser('activeUser1', 'Active', 'User', false, true)
20             .as('activeUser')
21             .then(function () {
22                 activeUser = this.activeUser;
23             });
24         cy.on('uncaught:exception', (err, runnable) => {
25             console.error(err);
26         });
27     });
28
29     beforeEach(function () {
30         cy.clearCookies();
31         cy.clearLocalStorage();
32     });
33
34     it('should display the user details card', () => {
35         cy.loginAs(adminUser);
36
37         cy.get('[data-cy=user-details-card]').should('be.visible');
38         cy.get('[data-cy=user-details-card]').contains(adminUser.user.full_name).should('be.visible');
39     });
40
41     it('shows the appropriate buttons in the multiselect toolbar', () => {
42         const msButtonTooltips = ['API Details', 'Attributes', 'User account'];
43
44         cy.loginAs(activeUser);
45
46         cy.get('[data-cy=multiselect-button]').should('have.length', msButtonTooltips.length);
47
48         for (let i = 0; i < msButtonTooltips.length; i++) {
49             cy.get('[data-cy=multiselect-button]').eq(i).trigger('mouseover');
50             cy.get('body').contains(msButtonTooltips[i]).should('exist');
51             cy.get('[data-cy=multiselect-button]').eq(i).trigger('mouseout');
52         }
53     });
54 });
55
56 describe('Project Details Card tests', function () {
57     let activeUser;
58     let adminUser;
59
60     before(function () {
61         // Only set up common users once. These aren't set up as aliases because
62         // aliases are cleaned up after every test. Also it doesn't make sense
63         // to set the same users on beforeEach() over and over again, so we
64         // separate a little from Cypress' 'Best Practices' here.
65         cy.getUser('admin', 'Admin', 'User', true, true)
66             .as('adminUser')
67             .then(function () {
68                 adminUser = this.adminUser;
69             });
70         cy.getUser('activeUser1', 'Active', 'User', false, true)
71             .as('activeUser')
72             .then(function () {
73                 activeUser = this.activeUser;
74             });
75         cy.on('uncaught:exception', (err, runnable) => {
76             console.error(err);
77         });
78     });
79
80     beforeEach(function () {
81         cy.clearCookies();
82         cy.clearLocalStorage();
83     });
84
85     it('should display the project details card', () => {
86         const projName = `Test project (${Math.floor(999999 * Math.random())})`;
87         cy.loginAs(adminUser);
88
89         // Create project
90         cy.get('[data-cy=side-panel-button]').click();
91         cy.get('[data-cy=side-panel-new-project]').click();
92         cy.get('[data-cy=form-dialog]')
93             .should('contain', 'New Project')
94             .within(() => {
95                 cy.get('[data-cy=name-field]').within(() => {
96                     cy.get('input').type(projName);
97                 });
98             });
99         cy.get('[data-cy=form-submit-btn]').click();
100         cy.get('[data-cy=form-dialog]').should('not.exist');
101
102         cy.get('[data-cy=project-details-card]').should('be.visible');
103         cy.get('[data-cy=project-details-card]').contains(projName).should('be.visible');
104     });
105
106     it('shows the appropriate buttons in the multiselect toolbar', () => {
107         const msButtonTooltips = ['View details', 'Open in new tab', 'Copy link to clipboard'];
108
109         const msOverflowMenuButtonTooltips = [
110             'Open with 3rd party client',
111             'API Details',
112             'Share',
113             'New project',
114             'Edit project',
115             'Move to',
116             'Move to trash',
117             'Freeze project',
118             'Add to favorites',
119         ];
120
121         const projName = `Test project (${Math.floor(999999 * Math.random())})`;
122         cy.loginAs(activeUser);
123
124         // Create project
125         cy.get('[data-cy=side-panel-button]').click();
126         cy.get('[data-cy=side-panel-new-project]').click();
127         cy.get('[data-cy=form-dialog]')
128             .should('contain', 'New Project')
129             .within(() => {
130                 cy.get('[data-cy=name-field]').within(() => {
131                     cy.get('input').type(projName);
132                 });
133             });
134         cy.get('[data-cy=form-submit-btn]').click();
135         cy.get('[data-cy=form-dialog]').should('not.exist');
136
137         for (let i = 0; i < msButtonTooltips.length; i++) {
138             cy.get('[data-cy=multiselect-button]').eq(i).should('exist');
139             cy.get('[data-cy=multiselect-button]').eq(i).trigger('mouseover');
140             cy.waitForDom()
141             cy.get('body').within(() => {
142                 cy.contains(msButtonTooltips[i]).should('exist');
143             });
144             cy.get('[data-cy=multiselect-button]').eq(i).trigger('mouseout');
145         }
146
147         cy.get('[data-cy=overflow-menu-button]').click();
148         cy.get('[data-cy=overflow-menu]')
149             .should('be.visible')
150             .within(() => {
151                 cy.get('[data-cy=multiselect-button]').should('exist');
152
153                 for (let i = 0; i < msOverflowMenuButtonTooltips.length; i++) {
154                     cy.get('li')
155                         .eq(i)
156                         .within(() => {
157                             cy.get(`span`).should('have.prop', 'title', msOverflowMenuButtonTooltips[i]);
158                         });
159                 }
160             });
161     });
162
163     it('should toggle description display', () => {
164         const projName = `Test project (${Math.floor(999999 * Math.random())})`;
165         //must be long enough to require a 2nd line
166         const projDescription =
167             'Science! true daughter of Old Time thou art! Who alterest all things with thy peering eyes. Why preyest thou thus upon the poet’s heart, Vulture, whose wings are dull realities? '
168         cy.loginAs(adminUser);
169
170         // Create project
171         cy.get('[data-cy=side-panel-button]').click();
172         cy.get('[data-cy=side-panel-new-project]').click();
173         cy.get('[data-cy=form-dialog]')
174             .should('contain', 'New Project')
175             .within(() => {
176                 cy.get('[data-cy=name-field]').within(() => {
177                     cy.get('input').type(projName);
178                 });
179             });
180         cy.get('[data-cy=form-submit-btn]').click();
181
182         //check for no description
183         cy.get('[data-cy=no-description').should('be.visible');
184
185         //add description
186         cy.get('[data-cy=side-panel-tree]').contains('Home Projects').click();
187         cy.get('[data-cy=project-panel] tbody tr').contains(projName).rightclick({ force: true });
188         cy.get('[data-cy=context-menu]').contains('Edit').click();
189         cy.get('[data-cy=form-dialog]').within(() => {
190             cy.get('div[contenteditable=true]').click().type(projDescription);
191             cy.get('[data-cy=form-submit-btn]').click();
192         });
193         cy.get('[data-cy=project-panel] tbody tr').contains(projName).click({ force: true });
194         cy.get('[data-cy=project-details-card]').contains(projName).should('be.visible');
195
196         //toggle description
197         //description is always visible, even when collapsed
198         cy.get('[data-cy=project-details-card]').contains(projDescription).should('be.visible');
199         cy.get('[data-cy=project-details-card]').invoke('height').should('be.lt', 90);
200         cy.get('[data-cy=toggle-description]').click();
201         cy.waitForDom();
202         cy.get('[data-cy=project-details-card]').invoke('height').should('be.gt', 91);
203         cy.get('[data-cy=toggle-description]').click();
204         cy.waitForDom();
205         cy.get('[data-cy=project-details-card]').invoke('height').should('be.lt', 90);
206     });
207
208     it('should display key/value pairs', () => {
209         const projName = `Test project (${Math.floor(999999 * Math.random())})`;
210         cy.loginAs(adminUser);
211
212         // Create project wih key/value pairs
213         cy.get('[data-cy=side-panel-button]').click();
214         cy.get('[data-cy=side-panel-new-project]').click();
215         cy.get('[data-cy=form-dialog]')
216             .should('contain', 'New Project')
217             .within(() => {
218                 cy.get('[data-cy=name-field]').within(() => {
219                     cy.get('input').type(projName);
220                 });
221             });
222
223         cy.get('[data-cy=key-input]').should('be.visible').click().type('Animal');
224         cy.get('[data-cy=value-input]').should('be.visible').click().type('Dog');
225         cy.get('[data-cy=property-add-btn]').should('be.visible').click();
226
227         cy.get('[data-cy=key-input]').should('be.visible').click().type('Importance');
228         cy.get('[data-cy=value-input]').should('be.visible').click().type('Critical');
229         cy.get('[data-cy=property-add-btn]').should('be.visible').click();
230
231         cy.get('[data-cy=form-submit-btn]').click();
232
233         //toggle chips
234         cy.get('[data-cy=project-details-card]').invoke('height').should('be.lt', 100);
235         cy.get('[data-cy=toggle-chips]').click();
236         cy.waitForDom();
237         cy.get('[data-cy=project-details-card]').invoke('height').should('be.gt', 101);
238         cy.get('[data-cy=toggle-chips').click();
239         cy.waitForDom();
240         cy.get('[data-cy=project-details-card]').invoke('height').should('be.lt', 100);
241
242         //check for key/value pairs in project details card
243         cy.get('[data-cy=project-details-card]').contains('Animal').should('be.visible');
244         cy.get('[data-cy=project-details-card]').contains('Importance').should('be.visible').click();
245         cy.waitForDom();
246         cy.window().then((win) => {
247             win.navigator.clipboard.readText().then((text) => {
248                 //wait is necessary due to known issue with cypress@13.7.1
249                 cy.wait(1000)
250                 expect(text).to.match(new RegExp(`Importance: Critical`));
251                 })
252             }
253         );
254     });
255 });