3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 import { within } from '@testing-library/react';
21 import userEvent from '@testing-library/user-event';
22 import React from 'react';
23 import { byRole, byText } from '~sonar-aligned/helpers/testSelector';
24 import ComputeEngineServiceMock from '../../../../../api/mocks/ComputeEngineServiceMock';
25 import GitlabProvisioningServiceMock from '../../../../../api/mocks/GitlabProvisioningServiceMock';
26 import SettingsServiceMock from '../../../../../api/mocks/SettingsServiceMock';
27 import SystemServiceMock from '../../../../../api/mocks/SystemServiceMock';
28 import { AvailableFeaturesContext } from '../../../../../app/components/available-features/AvailableFeaturesContext';
29 import { mockGitlabConfiguration } from '../../../../../helpers/mocks/alm-integrations';
30 import { definitions } from '../../../../../helpers/mocks/definitions-list';
31 import { renderComponent } from '../../../../../helpers/testReactTestingUtils';
32 import { AlmKeys } from '../../../../../types/alm-settings';
33 import { Feature } from '../../../../../types/features';
34 import { ProvisioningType } from '../../../../../types/provisioning';
35 import { TaskStatuses, TaskTypes } from '../../../../../types/tasks';
36 import Authentication from '../Authentication';
38 let handler: GitlabProvisioningServiceMock;
39 let system: SystemServiceMock;
40 let settingsHandler: SettingsServiceMock;
41 let computeEngineHandler: ComputeEngineServiceMock;
44 handler = new GitlabProvisioningServiceMock();
45 system = new SystemServiceMock();
46 settingsHandler = new SettingsServiceMock();
47 computeEngineHandler = new ComputeEngineServiceMock();
52 settingsHandler.reset();
54 computeEngineHandler.reset();
57 const glContainer = byRole('tabpanel', { name: 'gitlab GitLab' });
60 noGitlabConfiguration: glContainer.byText('settings.authentication.gitlab.form.not_configured'),
61 createConfigButton: glContainer.byRole('button', {
62 name: 'settings.authentication.form.create',
64 editConfigButton: glContainer.byRole('button', {
65 name: 'settings.authentication.form.edit',
67 editMappingButton: glContainer.byRole('button', {
68 name: 'settings.authentication.configuration.roles_mapping.button_label',
70 deleteConfigButton: glContainer.byRole('button', {
71 name: 'settings.authentication.form.delete',
73 enableConfigButton: glContainer.byRole('button', {
74 name: 'settings.authentication.form.enable',
76 disableConfigButton: glContainer.byRole('button', {
77 name: 'settings.authentication.form.disable',
79 createDialog: byRole('dialog', {
80 name: 'settings.authentication.gitlab.form.create',
82 editDialog: byRole('dialog', {
83 name: 'settings.authentication.gitlab.form.edit',
85 applicationId: byRole('textbox', {
86 name: 'property.applicationId.name',
88 url: byRole('textbox', { name: 'property.url.name' }),
89 secret: byRole('textbox', {
90 name: 'property.secret.name',
92 synchronizeGroups: byRole('switch', {
93 name: 'property.synchronizeGroups.name',
95 saveConfigButton: byRole('button', { name: 'settings.almintegration.form.save' }),
96 jitProvisioningRadioButton: glContainer.byRole('radio', {
97 name: /settings.authentication.gitlab.provisioning_at_login/,
99 autoProvisioningRadioButton: glContainer.byRole('radio', {
100 name: /settings.authentication.gitlab.form.provisioning_with_gitlab/,
102 jitAllowUsersToSignUpToggle: byRole('switch', { name: 'property.allowUsersToSignUp.name' }),
103 autoProvisioningToken: byRole('textbox', {
104 name: 'property.provisioningToken.name',
106 autoProvisioningUpdateTokenButton: byRole('button', {
107 name: 'settings.almintegration.form.secret.update_field',
109 groups: byRole('textbox', {
110 name: 'property.allowedGroups.name',
112 deleteGroupButton: byRole('button', { name: /delete_value/ }),
113 removeProvisioniongGroup: byRole('button', {
114 name: /settings.definition.delete_value.property.allowedGroups.name./,
116 saveProvisioning: glContainer.byRole('button', { name: 'save' }),
117 cancelProvisioningChanges: glContainer.byRole('button', { name: 'cancel' }),
118 confirmAutoProvisioningDialog: byRole('dialog', {
119 name: 'settings.authentication.gitlab.confirm.AUTO_PROVISIONING',
121 confirmJitProvisioningDialog: byRole('alertdialog', {
122 name: 'settings.authentication.gitlab.confirm.JIT',
124 confirmInsecureProvisioningDialog: byRole('alertdialog', {
125 name: 'settings.authentication.gitlab.confirm.insecure',
127 confirmProvisioningChange: byRole('button', {
128 name: 'settings.authentication.gitlab.provisioning_change.confirm_changes',
130 syncSummary: glContainer.byText(/Test summary/),
131 syncWarning: glContainer.byText(/Warning/),
132 gitlabProvisioningPending: glContainer
135 .byText(/synchronization_pending/),
136 gitlabProvisioningInProgress: glContainer
139 .byText(/synchronization_in_progress/),
140 gitlabProvisioningSuccess: glContainer.byText(/synchronization_successful/),
141 gitlabProvisioningAlert: glContainer.byText(/synchronization_failed/),
142 gitlabConfigurationStatus: glContainer.byRole('status', {
143 name: /settings.authentication.gitlab.configuration/,
145 gitlabMissingSecretErrorMessage: byText(
146 'settings.authentication.gitlab.form.secret.required_for_url_change',
148 testConfiguration: glContainer.byRole('button', {
149 name: 'settings.authentication.configuration.test',
151 continueAutoButton: byRole('button', {
152 name: 'settings.authentication.confirm_auto_provisioning.continue',
154 switchJitButton: byRole('button', {
155 name: 'settings.authentication.confirm_auto_provisioning.switch_jit',
157 consentDialog: byRole('dialog', {
158 name: 'settings.authentication.confirm_auto_provisioning.header',
160 mappingRow: byRole('dialog', {
161 name: 'settings.authentication.configuration.roles_mapping.dialog.title.alm.gitlab',
163 mappingCheckbox: byRole('checkbox'),
164 mappingDialogClose: byRole('dialog', {
165 name: 'settings.authentication.configuration.roles_mapping.dialog.title.alm.gitlab',
166 }).byRole('button', {
169 getMappingRowByRole: (text: string) =>
170 ui.mappingRow.getAll().find((row) => within(row).queryByText(text) !== null),
173 it('should create a Gitlab configuration and disable it with proper validation', async () => {
174 handler.setGitlabConfigurations([]);
175 renderAuthentication();
176 const user = userEvent.setup();
178 expect(await ui.noGitlabConfiguration.find()).toBeInTheDocument();
179 expect(ui.createConfigButton.get()).toBeInTheDocument();
181 await user.click(ui.createConfigButton.get());
182 expect(await ui.createDialog.find()).toBeInTheDocument();
183 await user.type(ui.applicationId.get(), '123');
184 expect(ui.saveConfigButton.get()).toBeDisabled();
185 await user.type(ui.url.get(), 'https://company.ui.com');
186 await user.type(ui.secret.get(), '123');
187 expect(ui.saveConfigButton.get()).toBeEnabled();
188 await user.click(ui.synchronizeGroups.get());
189 await user.click(ui.saveConfigButton.get());
191 expect(await ui.editConfigButton.find()).toBeInTheDocument();
192 expect(ui.noGitlabConfiguration.query()).not.toBeInTheDocument();
193 expect(glContainer.get()).toHaveTextContent('https://company.ui.com');
195 expect(ui.disableConfigButton.get()).toBeInTheDocument();
196 await user.click(ui.disableConfigButton.get());
197 expect(ui.enableConfigButton.get()).toBeInTheDocument();
198 expect(ui.disableConfigButton.query()).not.toBeInTheDocument();
201 it('should edit a configuration with proper validation and delete it', async () => {
202 const user = userEvent.setup();
203 renderAuthentication();
205 expect(await ui.editConfigButton.find()).toBeInTheDocument();
206 expect(glContainer.get()).toHaveTextContent('URL');
207 expect(ui.disableConfigButton.get()).toBeInTheDocument();
208 expect(ui.deleteConfigButton.get()).toBeInTheDocument();
209 expect(ui.deleteConfigButton.get()).toBeDisabled();
211 await user.click(ui.editConfigButton.get());
212 expect(await ui.editDialog.find()).toBeInTheDocument();
213 expect(ui.url.get()).toHaveValue('URL');
214 expect(ui.applicationId.get()).toBeInTheDocument();
215 expect(ui.secret.query()).not.toBeInTheDocument();
216 expect(ui.synchronizeGroups.get()).toBeChecked();
218 expect(ui.applicationId.get()).toBeInTheDocument();
219 await user.clear(ui.applicationId.get());
220 expect(ui.saveConfigButton.get()).toBeDisabled();
221 await user.type(ui.applicationId.get(), '456');
222 expect(ui.saveConfigButton.get()).toBeEnabled();
224 expect(ui.url.get()).toBeInTheDocument();
225 await user.clear(ui.url.get());
226 expect(ui.saveConfigButton.get()).toBeDisabled();
227 await user.type(ui.url.get(), 'www.internet.com');
228 expect(ui.saveConfigButton.get()).toBeDisabled();
229 expect(ui.gitlabMissingSecretErrorMessage.get()).toBeInTheDocument();
230 await user.click(ui.autoProvisioningUpdateTokenButton.get());
231 await user.type(ui.secret.get(), '123');
232 expect(ui.gitlabMissingSecretErrorMessage.query()).not.toBeInTheDocument();
233 expect(ui.saveConfigButton.get()).toBeEnabled();
234 await user.click(ui.saveConfigButton.get());
236 expect(glContainer.get()).not.toHaveTextContent('URL');
237 expect(glContainer.get()).toHaveTextContent('www.internet.com');
239 expect(ui.disableConfigButton.get()).toBeInTheDocument();
240 await user.click(ui.disableConfigButton.get());
241 expect(await ui.enableConfigButton.find()).toBeInTheDocument();
242 expect(ui.deleteConfigButton.get()).toBeEnabled();
243 await user.click(ui.deleteConfigButton.get());
244 expect(await ui.noGitlabConfiguration.find()).toBeInTheDocument();
245 expect(ui.editConfigButton.query()).not.toBeInTheDocument();
248 it('should be able to save just-in-time with no organizations', async () => {
249 const user = userEvent.setup();
250 renderAuthentication([Feature.GitlabProvisioning]);
252 expect(await ui.jitProvisioningRadioButton.find()).toBeChecked();
254 expect(ui.groups.get()).toHaveValue('Cypress Hill');
255 expect(await ui.saveProvisioning.find()).toBeDisabled();
256 await user.click(ui.deleteGroupButton.get());
257 expect(await ui.saveProvisioning.find()).toBeEnabled();
260 it('should not be able to save Auto provisioning with no organizations', async () => {
261 const user = userEvent.setup();
262 handler.setGitlabConfigurations([
263 mockGitlabConfiguration({
264 allowUsersToSignUp: false,
266 provisioningType: ProvisioningType.auto,
267 allowedGroups: ['D12'],
268 isProvisioningTokenSet: true,
271 renderAuthentication([Feature.GitlabProvisioning]);
273 expect(await ui.autoProvisioningRadioButton.find()).toBeChecked();
275 expect(ui.groups.get()).toHaveValue('D12');
276 expect(ui.saveProvisioning.get()).toBeDisabled();
277 await user.click(ui.deleteGroupButton.get());
278 expect(await ui.saveProvisioning.find()).toBeDisabled();
281 it('should change from just-in-time to Auto Provisioning if auto was never set before', async () => {
282 const user = userEvent.setup();
283 handler.setGitlabConfigurations([
284 mockGitlabConfiguration({
285 allowUsersToSignUp: false,
287 provisioningType: ProvisioningType.jit,
289 isProvisioningTokenSet: false,
292 renderAuthentication([Feature.GitlabProvisioning]);
294 expect(await ui.editConfigButton.find()).toBeInTheDocument();
295 expect(ui.jitProvisioningRadioButton.get()).toBeChecked();
297 await user.click(ui.autoProvisioningRadioButton.get());
298 expect(await ui.autoProvisioningRadioButton.find()).toBeEnabled();
299 expect(ui.saveProvisioning.get()).toBeDisabled();
301 await user.type(ui.autoProvisioningToken.get(), 'JRR Tolkien');
302 expect(await ui.saveProvisioning.find()).toBeDisabled();
304 await user.type(ui.groups.get(), 'Run DMC');
305 expect(await ui.saveProvisioning.find()).toBeEnabled();
306 await user.click(ui.deleteGroupButton.get());
307 expect(await ui.saveProvisioning.find()).toBeDisabled();
309 await user.type(ui.groups.get(), 'Public Enemy');
310 expect(await ui.saveProvisioning.find()).toBeEnabled();
313 it('should change from just-in-time to Auto Provisioning if auto was set before', async () => {
314 handler.setGitlabConfigurations([
315 mockGitlabConfiguration({
316 allowUsersToSignUp: false,
318 provisioningType: ProvisioningType.jit,
319 allowedGroups: ['D12'],
320 isProvisioningTokenSet: true,
323 const user = userEvent.setup();
324 renderAuthentication([Feature.GitlabProvisioning]);
326 expect(await ui.editConfigButton.find()).toBeInTheDocument();
327 expect(ui.jitProvisioningRadioButton.get()).toBeChecked();
329 user.click(ui.autoProvisioningRadioButton.get());
330 expect(await ui.autoProvisioningRadioButton.find()).toBeEnabled();
331 expect(await ui.saveProvisioning.find()).toBeEnabled();
333 expect(ui.groups.get()).toHaveValue('D12');
334 await user.click(ui.deleteGroupButton.get());
335 expect(await ui.saveProvisioning.find()).toBeDisabled();
336 await user.type(ui.groups.get(), 'Wu Tang Clan');
338 expect(ui.saveProvisioning.get()).toBeEnabled();
341 it('should change from auto provisioning to JIT with proper validation', async () => {
342 handler.setGitlabConfigurations([
343 mockGitlabConfiguration({
344 allowUsersToSignUp: false,
346 provisioningType: ProvisioningType.auto,
347 allowedGroups: ['D12'],
348 isProvisioningTokenSet: true,
351 const user = userEvent.setup();
352 renderAuthentication([Feature.GitlabProvisioning]);
354 expect(await ui.editConfigButton.find()).toBeInTheDocument();
356 expect(ui.jitProvisioningRadioButton.get()).not.toBeChecked();
357 expect(ui.autoProvisioningRadioButton.get()).toBeChecked();
359 expect(ui.autoProvisioningToken.query()).not.toBeInTheDocument();
360 expect(ui.autoProvisioningUpdateTokenButton.get()).toBeInTheDocument();
362 await user.click(ui.jitProvisioningRadioButton.get());
363 expect(await ui.jitProvisioningRadioButton.find()).toBeChecked();
365 expect(await ui.saveProvisioning.find()).toBeEnabled();
367 await user.click(ui.jitAllowUsersToSignUpToggle.get());
368 await user.click(ui.deleteGroupButton.get());
370 await user.click(ui.saveProvisioning.get());
372 ui.confirmJitProvisioningDialog
373 .byText('settings.authentication.gitlab.provisioning_change.insecure_config')
375 ).toBeInTheDocument();
376 await user.click(ui.confirmProvisioningChange.get());
377 expect(ui.confirmJitProvisioningDialog.query()).not.toBeInTheDocument();
379 expect(ui.jitProvisioningRadioButton.get()).toBeChecked();
380 expect(await ui.saveProvisioning.find()).toBeDisabled();
383 it('should show configuration warning with jit provisioning and no groups', async () => {
384 handler.setGitlabConfigurations([
385 mockGitlabConfiguration({
386 allowUsersToSignUp: false,
388 provisioningType: ProvisioningType.jit,
390 isProvisioningTokenSet: true,
393 const user = userEvent.setup();
394 renderAuthentication([Feature.GitlabProvisioning]);
396 expect(await ui.editConfigButton.find()).toBeInTheDocument();
398 await user.click(ui.jitAllowUsersToSignUpToggle.get());
399 await user.click(ui.saveProvisioning.get());
402 ui.confirmInsecureProvisioningDialog
403 .byText('settings.authentication.gitlab.provisioning_change.insecure_config')
405 ).toBeInTheDocument();
407 await user.click(ui.confirmProvisioningChange.get());
408 expect(ui.confirmJitProvisioningDialog.query()).not.toBeInTheDocument();
410 expect(ui.jitProvisioningRadioButton.get()).toBeChecked();
411 expect(await ui.saveProvisioning.find()).toBeDisabled();
414 it('should be able to allow user to sign up for JIT with proper validation', async () => {
415 handler.setGitlabConfigurations([
416 mockGitlabConfiguration({
417 allowUsersToSignUp: false,
419 provisioningType: ProvisioningType.jit,
422 const user = userEvent.setup();
423 renderAuthentication([Feature.GitlabProvisioning]);
425 expect(await ui.editConfigButton.find()).toBeInTheDocument();
427 expect(ui.jitProvisioningRadioButton.get()).toBeChecked();
428 expect(ui.autoProvisioningRadioButton.get()).not.toBeChecked();
430 expect(ui.jitAllowUsersToSignUpToggle.get()).not.toBeChecked();
432 expect(ui.saveProvisioning.get()).toBeDisabled();
433 await user.click(ui.jitAllowUsersToSignUpToggle.get());
434 expect(ui.saveProvisioning.get()).toBeEnabled();
435 await user.click(ui.jitAllowUsersToSignUpToggle.get());
436 expect(ui.saveProvisioning.get()).toBeDisabled();
437 await user.click(ui.jitAllowUsersToSignUpToggle.get());
439 await user.click(ui.saveProvisioning.get());
441 expect(ui.jitProvisioningRadioButton.get()).toBeChecked();
442 expect(ui.jitAllowUsersToSignUpToggle.get()).toBeChecked();
443 expect(await ui.saveProvisioning.find()).toBeDisabled();
446 it('should be able to edit token for Auto provisioning with proper validation', async () => {
447 handler.setGitlabConfigurations([
448 mockGitlabConfiguration({
449 allowUsersToSignUp: false,
451 provisioningType: ProvisioningType.auto,
452 allowedGroups: ['Cypress Hill', 'Public Enemy'],
453 isProvisioningTokenSet: true,
456 const user = userEvent.setup();
457 renderAuthentication([Feature.GitlabProvisioning]);
459 expect(await ui.autoProvisioningRadioButton.find()).toBeChecked();
460 expect(ui.autoProvisioningUpdateTokenButton.get()).toBeInTheDocument();
462 expect(ui.saveProvisioning.get()).toBeDisabled();
464 // Changing the Provisioning token should enable save
465 await user.click(ui.autoProvisioningUpdateTokenButton.get());
466 expect(ui.saveProvisioning.get()).toBeDisabled();
467 await user.click(ui.cancelProvisioningChanges.get());
468 expect(ui.saveProvisioning.get()).toBeDisabled();
471 it('should be able to reset Auto Provisioning changes', async () => {
472 handler.setGitlabConfigurations([
473 mockGitlabConfiguration({
474 allowUsersToSignUp: false,
476 provisioningType: ProvisioningType.auto,
477 allowedGroups: ['Cypress Hill', 'Public Enemy'],
478 isProvisioningTokenSet: true,
481 const user = userEvent.setup();
482 renderAuthentication([Feature.GitlabProvisioning]);
484 expect(await ui.autoProvisioningRadioButton.find()).toBeChecked();
486 await user.click(ui.autoProvisioningUpdateTokenButton.get());
487 await user.type(ui.autoProvisioningToken.get(), 'ToToken!');
488 expect(ui.saveProvisioning.get()).toBeEnabled();
489 await user.click(ui.cancelProvisioningChanges.get());
490 expect(ui.saveProvisioning.get()).toBeDisabled();
493 describe('Gitlab Provisioning', () => {
497 now: new Date('2022-02-04T12:00:59Z'),
499 handler.setGitlabConfigurations([
500 mockGitlabConfiguration({
502 provisioningType: ProvisioningType.auto,
503 allowedGroups: ['Test'],
509 jest.runOnlyPendingTimers();
510 jest.useRealTimers();
513 it('should display a success status when the synchronisation is a success', async () => {
514 computeEngineHandler.addTask({
515 status: TaskStatuses.Success,
516 executedAt: '2022-02-03T11:45:35+0200',
517 infoMessages: ['Test summary'],
518 type: TaskTypes.GitlabProvisioning,
521 renderAuthentication([Feature.GitlabProvisioning]);
522 expect(await ui.gitlabProvisioningSuccess.find()).toBeInTheDocument();
523 expect(ui.syncSummary.get()).toBeInTheDocument();
526 it('should display a success status even when another task is pending', async () => {
527 computeEngineHandler.addTask({
528 status: TaskStatuses.Pending,
529 executedAt: '2022-02-03T11:55:35+0200',
530 type: TaskTypes.GitlabProvisioning,
532 computeEngineHandler.addTask({
533 status: TaskStatuses.Success,
534 executedAt: '2022-02-03T11:45:35+0200',
535 type: TaskTypes.GitlabProvisioning,
537 renderAuthentication([Feature.GitlabProvisioning]);
538 expect(await ui.gitlabProvisioningSuccess.find()).toBeInTheDocument();
539 expect(ui.gitlabProvisioningPending.get()).toBeInTheDocument();
542 it('should display an error alert when the synchronisation failed', async () => {
543 computeEngineHandler.addTask({
544 status: TaskStatuses.Failed,
545 executedAt: '2022-02-03T11:45:35+0200',
546 errorMessage: "T'es mauvais Jacques",
547 type: TaskTypes.GitlabProvisioning,
549 renderAuthentication([Feature.GitlabProvisioning]);
550 expect(await ui.gitlabProvisioningAlert.find()).toBeInTheDocument();
551 expect(glContainer.get()).toHaveTextContent("T'es mauvais Jacques");
552 expect(ui.gitlabProvisioningSuccess.query()).not.toBeInTheDocument();
555 it('should display an error alert even when another task is in progress', async () => {
556 computeEngineHandler.addTask({
557 status: TaskStatuses.InProgress,
558 executedAt: '2022-02-03T11:55:35+0200',
559 type: TaskTypes.GitlabProvisioning,
561 computeEngineHandler.addTask({
562 status: TaskStatuses.Failed,
563 executedAt: '2022-02-03T11:45:35+0200',
564 errorMessage: "T'es mauvais Jacques",
565 type: TaskTypes.GitlabProvisioning,
567 renderAuthentication([Feature.GitlabProvisioning]);
568 expect(await ui.gitlabProvisioningAlert.find()).toBeInTheDocument();
569 expect(glContainer.get()).toHaveTextContent("T'es mauvais Jacques");
570 expect(ui.gitlabProvisioningSuccess.query()).not.toBeInTheDocument();
571 expect(ui.gitlabProvisioningInProgress.get()).toBeInTheDocument();
574 it('should show warning', async () => {
575 computeEngineHandler.addTask({
576 status: TaskStatuses.Success,
577 warnings: ['Warning'],
578 infoMessages: ['Test summary'],
579 type: TaskTypes.GitlabProvisioning,
581 renderAuthentication([Feature.GitlabProvisioning]);
583 expect(await ui.syncWarning.find()).toBeInTheDocument();
584 expect(ui.syncSummary.get()).toBeInTheDocument();
587 it('should show configuration validity', async () => {
588 const user = userEvent.setup();
589 renderAuthentication([Feature.GitlabProvisioning]);
591 expect(await ui.gitlabConfigurationStatus.find()).toHaveTextContent(
592 'settings.authentication.gitlab.configuration.valid.AUTO_PROVISIONING',
594 await user.click(ui.jitProvisioningRadioButton.get());
595 await user.click(ui.saveProvisioning.get());
596 await user.click(ui.confirmProvisioningChange.get());
597 expect(ui.gitlabConfigurationStatus.get()).toHaveTextContent(
598 'settings.authentication.gitlab.configuration.valid.JIT',
600 handler.setGitlabConfigurations([
601 mockGitlabConfiguration({ ...handler.gitlabConfigurations[0], errorMessage: 'ERROR' }),
603 await user.click(ui.testConfiguration.get());
604 expect(glContainer.get()).toHaveTextContent('ERROR');
605 await user.click(ui.disableConfigButton.get());
606 expect(ui.gitlabConfigurationStatus.query()).not.toBeInTheDocument();
609 it('should display a modal if user was already using auto and continue using auto provisioning', async () => {
610 const user = userEvent.setup();
612 settingsHandler.set('sonar.auth.gitlab.userConsentForPermissionProvisioningRequired', '');
613 handler.setGitlabConfigurations([
614 mockGitlabConfiguration({
615 allowUsersToSignUp: false,
617 provisioningType: ProvisioningType.auto,
618 allowedGroups: ['D12'],
619 isProvisioningTokenSet: true,
622 renderAuthentication([Feature.GitlabProvisioning]);
624 expect(await ui.consentDialog.find()).toBeInTheDocument();
625 await user.click(ui.continueAutoButton.get());
627 expect(await ui.autoProvisioningRadioButton.find()).toBeChecked();
628 expect(ui.consentDialog.query()).not.toBeInTheDocument();
631 it('should display a modal if user was already using auto and switch to JIT', async () => {
632 const user = userEvent.setup();
634 settingsHandler.set('sonar.auth.gitlab.userConsentForPermissionProvisioningRequired', '');
635 handler.setGitlabConfigurations([
636 mockGitlabConfiguration({
637 allowUsersToSignUp: false,
639 provisioningType: ProvisioningType.auto,
640 allowedGroups: ['D12'],
641 isProvisioningTokenSet: true,
644 renderAuthentication([Feature.GitlabProvisioning]);
646 expect(await ui.consentDialog.find()).toBeInTheDocument();
647 await user.click(ui.switchJitButton.get());
649 expect(await ui.jitProvisioningRadioButton.find()).toBeChecked();
650 expect(ui.consentDialog.query()).not.toBeInTheDocument();
653 it('should sort mapping rows', async () => {
654 const user = userEvent.setup();
655 handler.setGitlabConfigurations([
656 mockGitlabConfiguration({
657 allowUsersToSignUp: false,
659 provisioningType: ProvisioningType.auto,
660 allowedGroups: ['D12'],
661 isProvisioningTokenSet: true,
664 renderAuthentication([Feature.GitlabProvisioning]);
666 expect(await ui.editMappingButton.find()).toBeInTheDocument();
667 await user.click(ui.editMappingButton.get());
669 const rows = (await ui.mappingRow.findAll()).filter(
670 (row) => within(row).queryAllByRole('checkbox').length > 0,
673 expect(rows).toHaveLength(5);
675 expect(rows[0]).toHaveTextContent('guest');
676 expect(rows[1]).toHaveTextContent('reporter');
677 expect(rows[2]).toHaveTextContent('developer');
678 expect(rows[3]).toHaveTextContent('maintainer');
679 expect(rows[4]).toHaveTextContent('owner');
682 it('should apply new mapping and new provisioning type at the same time', async () => {
683 const user = userEvent.setup();
684 handler.setGitlabConfigurations([
685 mockGitlabConfiguration({
686 allowUsersToSignUp: false,
688 provisioningType: ProvisioningType.jit,
689 allowedGroups: ['D12'],
690 isProvisioningTokenSet: true,
693 renderAuthentication([Feature.GitlabProvisioning]);
695 expect(await ui.jitProvisioningRadioButton.find()).toBeChecked();
696 expect(ui.editMappingButton.query()).not.toBeInTheDocument();
697 await user.click(ui.autoProvisioningRadioButton.get());
698 expect(await ui.editMappingButton.find()).toBeInTheDocument();
699 await user.click(ui.editMappingButton.get());
701 expect(await ui.mappingRow.findAll()).toHaveLength(6);
703 let guestCheckboxes = ui.mappingCheckbox.getAll(ui.getMappingRowByRole('guest'));
704 let ownerCheckboxes = ui.mappingCheckbox.getAll(ui.getMappingRowByRole('owner'));
706 expect(guestCheckboxes[0]).toBeChecked();
707 expect(guestCheckboxes[1]).toBeChecked();
708 expect(guestCheckboxes[2]).not.toBeChecked();
709 expect(guestCheckboxes[3]).not.toBeChecked();
710 expect(guestCheckboxes[4]).not.toBeChecked();
711 expect(guestCheckboxes[5]).not.toBeChecked();
712 expect(ownerCheckboxes[0]).toBeChecked();
713 expect(ownerCheckboxes[1]).toBeChecked();
714 expect(ownerCheckboxes[2]).toBeChecked();
715 expect(ownerCheckboxes[3]).toBeChecked();
716 expect(ownerCheckboxes[4]).toBeChecked();
717 expect(ownerCheckboxes[5]).toBeChecked();
719 await user.click(guestCheckboxes[0]);
720 await user.click(guestCheckboxes[5]);
721 await user.click(ownerCheckboxes[5]);
722 await user.click(ui.mappingDialogClose.get());
724 await user.click(ui.saveProvisioning.get());
725 await user.click(ui.confirmProvisioningChange.get());
727 // Clean local mapping state
728 await user.click(ui.jitProvisioningRadioButton.get());
729 await user.click(ui.autoProvisioningRadioButton.get());
731 await user.click(ui.editMappingButton.get());
732 guestCheckboxes = ui.mappingCheckbox.getAll(ui.getMappingRowByRole('guest'));
733 ownerCheckboxes = ui.mappingCheckbox.getAll(ui.getMappingRowByRole('owner'));
735 expect(guestCheckboxes[0]).not.toBeChecked();
736 expect(guestCheckboxes[5]).toBeChecked();
737 expect(ownerCheckboxes[5]).not.toBeChecked();
738 await user.click(ui.mappingDialogClose.get());
742 function renderAuthentication(features: Feature[] = []) {
744 <AvailableFeaturesContext.Provider value={features}>
745 <Authentication definitions={definitions} />
746 </AvailableFeaturesContext.Provider>,
747 `?tab=${AlmKeys.GitLab}`,