3 * Copyright (C) 2009-2023 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 { screen } from '@testing-library/react';
21 import userEvent from '@testing-library/user-event';
22 import React from 'react';
23 import { byRole, byText } from 'testing-library-selector';
24 import AuthenticationServiceMock from '../../../../../api/mocks/AuthenticationServiceMock';
25 import { AvailableFeaturesContext } from '../../../../../app/components/available-features/AvailableFeaturesContext';
26 import { mockDefinition } from '../../../../../helpers/mocks/settings';
27 import { renderComponent } from '../../../../../helpers/testReactTestingUtils';
28 import { Feature } from '../../../../../types/features';
29 import { ExtendedSettingDefinition, SettingType } from '../../../../../types/settings';
30 import Authentication from '../Authentication';
32 jest.mock('../../../../../api/settings');
34 const mockDefinitionFields = [
37 category: 'authentication',
44 category: 'authentication',
50 key: 'sonar.auth.saml.certificate.secured',
51 category: 'authentication',
54 description: 'Secured certificate',
55 type: SettingType.PASSWORD,
58 key: 'sonar.auth.saml.enabled',
59 category: 'authentication',
62 description: 'To enable the flag',
63 type: SettingType.BOOLEAN,
67 let handler: AuthenticationServiceMock;
70 handler = new AuthenticationServiceMock();
73 afterEach(() => handler.resetValues());
76 saveButton: byRole('button', { name: 'settings.authentication.saml.form.save' }),
77 customMessageInformation: byText('settings.authentication.custom_message_information'),
78 enabledToggle: byRole('button', { name: 'off' }),
79 testButton: byText('settings.authentication.saml.form.test'),
80 textbox1: byRole('textbox', { name: 'test1' }),
81 textbox2: byRole('textbox', { name: 'test2' }),
84 it('should render tabs and allow navigation', async () => {
85 const user = userEvent.setup();
86 renderAuthentication([]);
88 expect(screen.getAllByRole('tab')).toHaveLength(4);
90 expect(screen.getByRole('tab', { name: 'SAML' })).toHaveAttribute('aria-selected', 'true');
92 await user.click(screen.getByRole('tab', { name: 'github GitHub' }));
94 expect(screen.getByRole('tab', { name: 'SAML' })).toHaveAttribute('aria-selected', 'false');
95 expect(screen.getByRole('tab', { name: 'github GitHub' })).toHaveAttribute(
101 describe('SAML tab', () => {
102 it('should allow user to test the configuration', async () => {
103 const user = userEvent.setup();
105 const definitions = [
107 key: 'sonar.auth.saml.certificate.secured',
108 category: 'authentication',
111 description: 'Secured certificate',
112 type: SettingType.PASSWORD,
115 key: 'sonar.auth.saml.enabled',
116 category: 'authentication',
119 description: 'To enable the flag',
120 type: SettingType.BOOLEAN,
124 renderAuthentication(definitions);
126 await user.click(await screen.findByText('settings.almintegration.form.secret.update_field'));
128 await user.click(screen.getByRole('textbox', { name: 'Certificate' }));
129 await user.keyboard('new certificate');
131 expect(ui.testButton.get()).toHaveClass('disabled');
133 await user.click(ui.saveButton.get());
135 expect(ui.testButton.get()).not.toHaveClass('disabled');
138 it('should allow user to edit fields and save configuration', async () => {
139 const user = userEvent.setup();
140 const definitions = mockDefinitionFields;
141 renderAuthentication(definitions);
143 expect(ui.enabledToggle.get()).toHaveAttribute('aria-disabled', 'true');
145 await user.click(ui.textbox1.get());
146 await user.keyboard('new test1');
148 await user.click(ui.textbox2.get());
149 await user.keyboard('new test2');
150 // check if enable is allowed after updating
151 expect(ui.enabledToggle.get()).toHaveAttribute('aria-disabled', 'false');
154 await user.click(ui.textbox2.get());
155 await user.keyboard('{Control>}a{/Control}{Backspace}');
156 await user.click(ui.saveButton.get());
157 expect(ui.enabledToggle.get()).toHaveAttribute('aria-disabled', 'true');
159 await user.click(ui.textbox2.get());
160 await user.keyboard('new test2');
161 expect(ui.enabledToggle.get()).toHaveAttribute('aria-disabled', 'false');
164 screen.getByRole('button', { name: 'settings.almintegration.form.secret.update_field' })
165 ).toBeInTheDocument();
167 screen.getByRole('button', { name: 'settings.almintegration.form.secret.update_field' })
169 // check for secure fields
170 expect(screen.getByRole('textbox', { name: 'Certificate' })).toBeInTheDocument();
171 await user.click(screen.getByRole('textbox', { name: 'Certificate' }));
172 await user.keyboard('new certificate');
173 // enable the configuration
174 await user.click(ui.enabledToggle.get());
175 expect(screen.getByRole('button', { name: 'on' })).toBeInTheDocument();
177 await user.click(ui.saveButton.get());
178 expect(screen.getByText('settings.authentication.saml.form.save_success')).toBeInTheDocument();
179 // check after switching tab that the flag is still enabled
180 await user.click(screen.getByRole('tab', { name: 'github GitHub' }));
181 await user.click(screen.getByRole('tab', { name: 'SAML' }));
183 expect(screen.getByRole('button', { name: 'on' })).toBeInTheDocument();
186 it('should handle and show errors to the user', async () => {
187 const user = userEvent.setup();
188 const definitions = mockDefinitionFields;
189 renderAuthentication(definitions);
191 await user.click(ui.textbox1.get());
192 await user.keyboard('value');
193 await user.click(ui.textbox2.get());
194 await user.keyboard('{Control>}a{/Control}error');
195 await user.click(ui.saveButton.get());
196 expect(screen.getByText('settings.authentication.saml.form.save_partial')).toBeInTheDocument();
199 it('should not display the login message feature info box', () => {
200 renderAuthentication([]);
202 expect(ui.customMessageInformation.query()).not.toBeInTheDocument();
205 it('should display the login message feature info box', () => {
206 renderAuthentication([], [Feature.LoginMessage]);
208 expect(ui.customMessageInformation.get()).toBeInTheDocument();
212 function renderAuthentication(definitions: ExtendedSettingDefinition[], features: Feature[] = []) {
214 <AvailableFeaturesContext.Provider value={features}>
215 <Authentication definitions={definitions} />
216 </AvailableFeaturesContext.Provider>