]> source.dussan.org Git - sonarqube.git/blob
f73dbcac56a0c19ef4403ea8ec17ec5e45fbb9d1
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2023 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 import { act, screen } from '@testing-library/react';
22 import userEvent from '@testing-library/user-event';
23 import PermissionsServiceMock from '../../../../../api/mocks/PermissionsServiceMock';
24 import { mockComponent } from '../../../../../helpers/mocks/component';
25 import { mockPermissionGroup, mockPermissionUser } from '../../../../../helpers/mocks/permissions';
26 import {
27   PERMISSIONS_ORDER_FOR_PROJECT_TEMPLATE,
28   PERMISSIONS_ORDER_FOR_VIEW,
29 } from '../../../../../helpers/permissions';
30 import { renderAppWithComponentContext } from '../../../../../helpers/testReactTestingUtils';
31 import { ComponentQualifier, Visibility } from '../../../../../types/component';
32 import { Permissions } from '../../../../../types/permissions';
33 import { Component, PermissionGroup, PermissionUser } from '../../../../../types/types';
34 import { projectPermissionsRoutes } from '../../../routes';
35 import { getPageObject } from '../../../test-utils';
36
37 let serviceMock: PermissionsServiceMock;
38 beforeAll(() => {
39   serviceMock = new PermissionsServiceMock();
40 });
41
42 afterEach(() => {
43   serviceMock.reset();
44 });
45
46 describe('rendering', () => {
47   it.each([
48     [ComponentQualifier.Project, 'roles.page.description2', PERMISSIONS_ORDER_FOR_PROJECT_TEMPLATE],
49     [ComponentQualifier.Portfolio, 'roles.page.description_portfolio', PERMISSIONS_ORDER_FOR_VIEW],
50     [
51       ComponentQualifier.Application,
52       'roles.page.description_application',
53       PERMISSIONS_ORDER_FOR_VIEW,
54     ],
55   ])('should render correctly for %s', async (qualifier, description, permissions) => {
56     const user = userEvent.setup();
57     const ui = getPageObject(user);
58     renderPermissionsProjectApp({ qualifier, visibility: Visibility.Private });
59     await ui.appLoaded();
60
61     expect(screen.getByText(description)).toBeInTheDocument();
62     permissions.forEach((permission) => {
63       expect(ui.projectPermissionCheckbox('johndoe', permission).get()).toBeInTheDocument();
64     });
65   });
66 });
67
68 describe('filtering', () => {
69   it('should allow to filter permission holders', async () => {
70     const user = userEvent.setup();
71     const ui = getPageObject(user);
72     renderPermissionsProjectApp();
73     await ui.appLoaded();
74
75     expect(screen.getByText('sonar-users')).toBeInTheDocument();
76     expect(screen.getByText('johndoe')).toBeInTheDocument();
77
78     await ui.showOnlyUsers();
79     expect(screen.queryByText('sonar-users')).not.toBeInTheDocument();
80     expect(screen.getByText('johndoe')).toBeInTheDocument();
81
82     await ui.showOnlyGroups();
83     expect(screen.getByText('sonar-users')).toBeInTheDocument();
84     expect(screen.queryByText('johndoe')).not.toBeInTheDocument();
85
86     await ui.showAll();
87     expect(screen.getByText('sonar-users')).toBeInTheDocument();
88     expect(screen.getByText('johndoe')).toBeInTheDocument();
89
90     await ui.searchFor('sonar-adm');
91     expect(screen.getByText('sonar-admins')).toBeInTheDocument();
92     expect(screen.queryByText('sonar-users')).not.toBeInTheDocument();
93     expect(screen.queryByText('johndoe')).not.toBeInTheDocument();
94
95     await ui.clearSearch();
96     expect(screen.getByText('sonar-users')).toBeInTheDocument();
97     expect(screen.getByText('johndoe')).toBeInTheDocument();
98   });
99
100   it('should allow to show only permission holders with a specific permission', async () => {
101     const user = userEvent.setup();
102     const ui = getPageObject(user);
103     renderPermissionsProjectApp();
104     await ui.appLoaded();
105
106     expect(screen.getAllByRole('row').length).toBe(7);
107     await ui.toggleFilterByPermission(Permissions.Admin);
108     expect(screen.getAllByRole('row').length).toBe(2);
109     await ui.toggleFilterByPermission(Permissions.Admin);
110     expect(screen.getAllByRole('row').length).toBe(7);
111   });
112 });
113
114 describe('assigning/revoking permissions', () => {
115   it('should allow to apply a permission template', async () => {
116     const user = userEvent.setup();
117     const ui = getPageObject(user);
118     renderPermissionsProjectApp();
119     await ui.appLoaded();
120
121     await ui.openTemplateModal();
122     expect(ui.confirmApplyTemplateBtn.get()).toBeDisabled();
123     await ui.chooseTemplate('Permission Template 2');
124     expect(ui.templateSuccessfullyApplied.get()).toBeInTheDocument();
125     await ui.closeTemplateModal();
126     expect(ui.templateSuccessfullyApplied.query()).not.toBeInTheDocument();
127   });
128
129   it('should allow to turn a public project private (and vice-versa)', async () => {
130     const user = userEvent.setup();
131     const ui = getPageObject(user);
132     renderPermissionsProjectApp();
133     await ui.appLoaded();
134
135     expect(ui.visibilityRadio(Visibility.Public).get()).toBeChecked();
136     expect(
137       ui.projectPermissionCheckbox('sonar-users', Permissions.Browse).query()
138     ).not.toBeInTheDocument();
139     await act(async () => {
140       await ui.turnProjectPrivate();
141     });
142     expect(ui.visibilityRadio(Visibility.Private).get()).toBeChecked();
143     expect(
144       ui.projectPermissionCheckbox('sonar-users', Permissions.Browse).get()
145     ).toBeInTheDocument();
146
147     await ui.turnProjectPublic();
148     expect(ui.makePublicDisclaimer.get()).toBeInTheDocument();
149     await act(async () => {
150       await ui.confirmTurnProjectPublic();
151     });
152     expect(ui.visibilityRadio(Visibility.Public).get()).toBeChecked();
153   });
154
155   it('should add and remove permissions to/from a group', async () => {
156     const user = userEvent.setup();
157     const ui = getPageObject(user);
158     renderPermissionsProjectApp();
159     await ui.appLoaded();
160
161     expect(ui.projectPermissionCheckbox('sonar-users', Permissions.Admin).get()).not.toBeChecked();
162
163     await ui.toggleProjectPermission('sonar-users', Permissions.Admin);
164     await ui.appLoaded();
165     expect(ui.projectPermissionCheckbox('sonar-users', Permissions.Admin).get()).toBeChecked();
166
167     await ui.toggleProjectPermission('sonar-users', Permissions.Admin);
168     await ui.appLoaded();
169     expect(ui.projectPermissionCheckbox('sonar-users', Permissions.Admin).get()).not.toBeChecked();
170   });
171
172   it('should add and remove permissions to/from a user', async () => {
173     const user = userEvent.setup();
174     const ui = getPageObject(user);
175     renderPermissionsProjectApp();
176     await ui.appLoaded();
177
178     expect(ui.projectPermissionCheckbox('johndoe', Permissions.Scan).get()).not.toBeChecked();
179
180     await ui.toggleProjectPermission('johndoe', Permissions.Scan);
181     await ui.appLoaded();
182     expect(ui.projectPermissionCheckbox('johndoe', Permissions.Scan).get()).toBeChecked();
183
184     await ui.toggleProjectPermission('johndoe', Permissions.Scan);
185     await ui.appLoaded();
186     expect(ui.projectPermissionCheckbox('johndoe', Permissions.Scan).get()).not.toBeChecked();
187   });
188
189   it('should handle errors correctly', async () => {
190     serviceMock.setIsAllowedToChangePermissions(false);
191     const user = userEvent.setup();
192     const ui = getPageObject(user);
193     renderPermissionsProjectApp();
194     await ui.appLoaded();
195
196     expect(ui.projectPermissionCheckbox('johndoe', Permissions.Scan).get()).not.toBeChecked();
197     await ui.toggleProjectPermission('johndoe', Permissions.Scan);
198     await ui.appLoaded();
199     expect(ui.projectPermissionCheckbox('johndoe', Permissions.Scan).get()).not.toBeChecked();
200   });
201 });
202
203 it('should correctly handle pagination', async () => {
204   const groups: PermissionGroup[] = [];
205   const users: PermissionUser[] = [];
206   Array.from(Array(20).keys()).forEach((i) => {
207     groups.push(mockPermissionGroup({ name: `Group ${i}` }));
208     users.push(mockPermissionUser({ login: `user-${i}` }));
209   });
210   serviceMock.setGroups(groups);
211   serviceMock.setUsers(users);
212
213   const user = userEvent.setup();
214   const ui = getPageObject(user);
215   renderPermissionsProjectApp();
216   await ui.appLoaded();
217
218   expect(screen.getAllByRole('row').length).toBe(11);
219   await ui.clickLoadMore();
220   expect(screen.getAllByRole('row').length).toBe(21);
221 });
222
223 function renderPermissionsProjectApp(override?: Partial<Component>) {
224   return renderAppWithComponentContext(
225     'project_roles',
226     projectPermissionsRoutes,
227     {},
228     {
229       component: mockComponent({
230         visibility: Visibility.Public,
231         configuration: {
232           canUpdateProjectVisibilityToPrivate: true,
233           canApplyPermissionTemplate: true,
234         },
235         ...override,
236       }),
237     }
238   );
239 }