]> source.dussan.org Git - sonarqube.git/blob
1070420b649f04ce829b00f9f76ab701bd6f5d2d
[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 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';
31
32 jest.mock('../../../../../api/settings');
33
34 const mockDefinitionFields = [
35   mockDefinition({
36     key: 'test1',
37     category: 'authentication',
38     subCategory: 'saml',
39     name: 'test1',
40     description: 'desc1',
41   }),
42   mockDefinition({
43     key: 'test2',
44     category: 'authentication',
45     subCategory: 'saml',
46     name: 'test2',
47     description: 'desc2',
48   }),
49   mockDefinition({
50     key: 'sonar.auth.saml.certificate.secured',
51     category: 'authentication',
52     subCategory: 'saml',
53     name: 'Certificate',
54     description: 'Secured certificate',
55     type: SettingType.PASSWORD,
56   }),
57   mockDefinition({
58     key: 'sonar.auth.saml.enabled',
59     category: 'authentication',
60     subCategory: 'saml',
61     name: 'Enabled',
62     description: 'To enable the flag',
63     type: SettingType.BOOLEAN,
64   }),
65 ];
66
67 let handler: AuthenticationServiceMock;
68
69 beforeEach(() => {
70   handler = new AuthenticationServiceMock();
71 });
72
73 afterEach(() => handler.resetValues());
74
75 const ui = {
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' }),
82 };
83
84 it('should render tabs and allow navigation', async () => {
85   const user = userEvent.setup();
86   renderAuthentication([]);
87
88   expect(screen.getAllByRole('tab')).toHaveLength(4);
89
90   expect(screen.getByRole('tab', { name: 'SAML' })).toHaveAttribute('aria-selected', 'true');
91
92   await user.click(screen.getByRole('tab', { name: 'github GitHub' }));
93
94   expect(screen.getByRole('tab', { name: 'SAML' })).toHaveAttribute('aria-selected', 'false');
95   expect(screen.getByRole('tab', { name: 'github GitHub' })).toHaveAttribute(
96     'aria-selected',
97     'true'
98   );
99 });
100
101 describe('SAML tab', () => {
102   it('should allow user to test the configuration', async () => {
103     const user = userEvent.setup();
104
105     const definitions = [
106       mockDefinition({
107         key: 'sonar.auth.saml.certificate.secured',
108         category: 'authentication',
109         subCategory: 'saml',
110         name: 'Certificate',
111         description: 'Secured certificate',
112         type: SettingType.PASSWORD,
113       }),
114       mockDefinition({
115         key: 'sonar.auth.saml.enabled',
116         category: 'authentication',
117         subCategory: 'saml',
118         name: 'Enabled',
119         description: 'To enable the flag',
120         type: SettingType.BOOLEAN,
121       }),
122     ];
123
124     renderAuthentication(definitions);
125
126     await user.click(await screen.findByText('settings.almintegration.form.secret.update_field'));
127
128     await user.click(screen.getByRole('textbox', { name: 'Certificate' }));
129     await user.keyboard('new certificate');
130
131     expect(ui.testButton.get()).toHaveClass('disabled');
132
133     await user.click(ui.saveButton.get());
134
135     expect(ui.testButton.get()).not.toHaveClass('disabled');
136   });
137
138   it('should allow user to edit fields and save configuration', async () => {
139     const user = userEvent.setup();
140     const definitions = mockDefinitionFields;
141     renderAuthentication(definitions);
142
143     expect(ui.enabledToggle.get()).toHaveAttribute('aria-disabled', 'true');
144     // update fields
145     await user.click(ui.textbox1.get());
146     await user.keyboard('new test1');
147
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');
152
153     // reset value
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');
158
159     await user.click(ui.textbox2.get());
160     await user.keyboard('new test2');
161     expect(ui.enabledToggle.get()).toHaveAttribute('aria-disabled', 'false');
162
163     expect(
164       screen.getByRole('button', { name: 'settings.almintegration.form.secret.update_field' })
165     ).toBeInTheDocument();
166     await user.click(
167       screen.getByRole('button', { name: 'settings.almintegration.form.secret.update_field' })
168     );
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();
176
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' }));
182
183     expect(screen.getByRole('button', { name: 'on' })).toBeInTheDocument();
184   });
185
186   it('should handle and show errors to the user', async () => {
187     const user = userEvent.setup();
188     const definitions = mockDefinitionFields;
189     renderAuthentication(definitions);
190
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();
197   });
198
199   it('should not display the login message feature info box', () => {
200     renderAuthentication([]);
201
202     expect(ui.customMessageInformation.query()).not.toBeInTheDocument();
203   });
204
205   it('should display the login message feature info box', () => {
206     renderAuthentication([], [Feature.LoginMessage]);
207
208     expect(ui.customMessageInformation.get()).toBeInTheDocument();
209   });
210 });
211
212 function renderAuthentication(definitions: ExtendedSettingDefinition[], features: Feature[] = []) {
213   renderComponent(
214     <AvailableFeaturesContext.Provider value={features}>
215       <Authentication definitions={definitions} />
216     </AvailableFeaturesContext.Provider>
217   );
218 }