]> source.dussan.org Git - sonarqube.git/blob
28f49b63b67281890e01fa95758094f6492080c9
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 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 { addGlobalSuccessMessage } from 'design-system/lib';
23 import React from 'react';
24 import { byLabelText, byRole, byText } from '~sonar-aligned/helpers/testSelector';
25 import SystemServiceMock from '../../../../../api/mocks/SystemServiceMock';
26 import * as api from '../../../../../api/system';
27 import { mockEmailConfiguration } from '../../../../../helpers/mocks/system';
28 import { renderComponent } from '../../../../../helpers/testReactTestingUtils';
29 import { AuthMethod } from '../../../../../types/system';
30 import EmailNotification from '../EmailNotification';
31
32 jest.mock('../../../../../api/system');
33 jest.mock('../../../../../api/settings');
34
35 jest.mock('design-system', () => ({
36   ...jest.requireActual('design-system'),
37   addGlobalSuccessMessage: jest.fn(),
38 }));
39
40 const systemHandler = new SystemServiceMock();
41
42 beforeEach(() => {
43   jest.clearAllMocks();
44   systemHandler.reset();
45 });
46
47 const ui = {
48   editSubheading1: byText('email_notification.subheading.1'),
49
50   // common fields
51   selectorBasicAuth: byRole('radio', {
52     name: 'email_notification.form.basic_auth.title email_notification.form.basic_auth.description',
53   }),
54   selectorOAuthAuth: byRole('radio', {
55     name: 'email_notification.form.oauth_auth.title email_notification.form.oauth_auth.description recommended email_notification.form.oauth_auth.recommended_reason',
56   }),
57   host: byRole('textbox', {
58     name: 'email_notification.form.host field_required',
59   }),
60   port: byRole('spinbutton', {
61     name: 'email_notification.form.port field_required',
62   }),
63   securityProtocol: byRole('searchbox', {
64     name: 'email_notification.form.security_protocol field_required',
65   }),
66   fromAddress: byRole('textbox', {
67     name: 'email_notification.form.from_address field_required',
68   }),
69   fromName: byRole('textbox', {
70     name: 'email_notification.form.from_name field_required',
71   }),
72   subjectPrefix: byRole('textbox', {
73     name: 'email_notification.form.subject_prefix field_required',
74   }),
75   username: byRole('textbox', {
76     name: 'email_notification.form.username field_required',
77   }),
78
79   // basic authentication
80   basic_password: byLabelText('email_notification.form.basic_password*'),
81
82   // oauth
83   oauth_auth_host: byRole('textbox', {
84     name: 'email_notification.form.oauth_authentication_host field_required',
85   }),
86   oauth_client_id: byLabelText('email_notification.form.oauth_client_id*'),
87   oauth_client_secret: byLabelText('email_notification.form.oauth_client_secret*'),
88   oauth_tenant: byRole('textbox', { name: 'email_notification.form.oauth_tenant field_required' }),
89
90   save: byRole('button', {
91     name: 'email_notification.form.save_configuration',
92   }),
93 };
94
95 describe('Email Basic Configuration', () => {
96   it('can save the basic configuration', async () => {
97     jest.spyOn(api, 'postEmailConfiguration');
98     const user = userEvent.setup();
99     renderEmailNotifications();
100     expect(await ui.editSubheading1.find()).toBeInTheDocument();
101
102     expect(ui.save.get()).toBeDisabled();
103
104     expect(ui.selectorBasicAuth.get()).toBeChecked();
105     expect(ui.username.get()).toHaveValue('');
106     expect(ui.basic_password.get()).toHaveValue('');
107     expect(ui.host.get()).toHaveValue('');
108     expect(ui.port.get()).toHaveValue(587);
109     expect(ui.securityProtocol.get()).toHaveValue('');
110     expect(ui.fromAddress.get()).toHaveValue('');
111     expect(ui.fromName.get()).toHaveValue('SonarQube');
112     expect(ui.subjectPrefix.get()).toHaveValue('[SonarQube]');
113
114     await user.type(ui.basic_password.get(), 'password');
115     await user.type(ui.host.get(), 'host');
116     await user.clear(ui.port.get());
117     await user.type(ui.port.get(), '1234');
118     await user.click(ui.securityProtocol.get());
119     await user.click(screen.getByText('SSLTLS'));
120     await user.type(ui.fromAddress.get(), 'admin@localhost.com');
121     await user.clear(ui.fromName.get());
122     await user.type(ui.fromName.get(), 'fromName');
123     await user.clear(ui.subjectPrefix.get());
124     await user.type(ui.subjectPrefix.get(), 'prefix');
125     await user.type(ui.username.get(), 'username');
126
127     expect(ui.selectorBasicAuth.get()).toBeChecked();
128     expect(ui.username.get()).toHaveValue('username');
129     expect(ui.basic_password.get()).toHaveValue('password');
130     expect(ui.host.get()).toHaveValue('host');
131     expect(ui.port.get()).toHaveValue(1234);
132     expect(ui.securityProtocol.get()).toHaveValue('SSLTLS');
133     expect(ui.fromAddress.get()).toHaveValue('admin@localhost.com');
134     expect(ui.fromName.get()).toHaveValue('fromName');
135     expect(ui.subjectPrefix.get()).toHaveValue('prefix');
136
137     expect(await ui.save.find()).toBeEnabled();
138     await user.click(ui.save.get());
139
140     expect(api.postEmailConfiguration).toHaveBeenCalledTimes(1);
141     expect(api.postEmailConfiguration).toHaveBeenCalledWith({
142       authMethod: 'BASIC',
143       basicPassword: 'password',
144       fromAddress: 'admin@localhost.com',
145       fromName: 'fromName',
146       host: 'host',
147       port: '1234',
148       securityProtocol: 'SSLTLS',
149       subjectPrefix: 'prefix',
150       username: 'username',
151     });
152
153     expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
154       'email_notification.form.save_configuration.create_success',
155     );
156   });
157
158   it('can edit an existing configuration', async () => {
159     systemHandler.addEmailConfiguration(
160       mockEmailConfiguration(AuthMethod.Basic, { id: 'email-1' }),
161     );
162     jest.spyOn(api, 'patchEmailConfiguration');
163     const user = userEvent.setup();
164     renderEmailNotifications();
165     expect(await ui.editSubheading1.find()).toBeInTheDocument();
166
167     expect(ui.save.get()).toBeDisabled();
168     await user.type(ui.basic_password.get(), 'updated');
169     await user.type(ui.host.get(), '-updated');
170     await user.type(ui.port.get(), '5678');
171     await user.click(ui.securityProtocol.get());
172     await user.click(screen.getByText('STARTTLS'));
173     await user.clear(ui.fromAddress.get());
174     await user.type(ui.fromAddress.get(), 'updated@email.com');
175     await user.type(ui.fromName.get(), '-updated');
176     await user.type(ui.subjectPrefix.get(), '-updated');
177     await user.type(ui.username.get(), '-updated');
178
179     expect(await ui.save.find()).toBeEnabled();
180     await user.click(ui.save.get());
181
182     expect(api.patchEmailConfiguration).toHaveBeenCalledTimes(1);
183     expect(api.patchEmailConfiguration).toHaveBeenCalledWith('email-1', {
184       authMethod: 'BASIC',
185       basicPassword: 'updated',
186       fromAddress: 'updated@email.com',
187       fromName: 'from_name-updated',
188       host: 'host-updated',
189       id: 'email-1',
190       isBasicPasswordSet: true,
191       port: '5678',
192       securityProtocol: 'STARTTLS',
193       subjectPrefix: 'subject_prefix-updated',
194       username: 'username-updated',
195     });
196
197     expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
198       'email_notification.form.save_configuration.update_success',
199     );
200   });
201 });
202
203 describe('Email Oauth Configuration', () => {
204   it('can save the oauth configuration', async () => {
205     jest.spyOn(api, 'postEmailConfiguration');
206     const user = userEvent.setup();
207     renderEmailNotifications();
208     expect(await ui.editSubheading1.find()).toBeInTheDocument();
209     await user.click(ui.selectorOAuthAuth.get());
210
211     expect(ui.save.get()).toBeDisabled();
212
213     expect(ui.selectorOAuthAuth.get()).toBeChecked();
214     expect(ui.oauth_auth_host.get()).toHaveValue('');
215     expect(ui.oauth_client_id.get()).toHaveValue('');
216     expect(ui.oauth_client_secret.get()).toHaveValue('');
217     expect(ui.oauth_tenant.get()).toHaveValue('');
218     expect(ui.host.get()).toHaveValue('');
219     expect(ui.port.get()).toHaveValue(587);
220     expect(ui.securityProtocol.get()).toHaveValue('');
221     expect(ui.fromAddress.get()).toHaveValue('');
222     expect(ui.fromName.get()).toHaveValue('SonarQube');
223     expect(ui.subjectPrefix.get()).toHaveValue('[SonarQube]');
224
225     await user.type(ui.oauth_auth_host.get(), 'oauth_auth_host');
226     await user.type(ui.oauth_client_id.get(), 'oauth_client_id');
227     await user.type(ui.oauth_client_secret.get(), 'oauth_client_secret');
228     await user.type(ui.oauth_tenant.get(), 'oauth_tenant');
229     await user.type(ui.host.get(), 'host');
230     await user.clear(ui.port.get());
231     await user.type(ui.port.get(), '1234');
232     await user.click(ui.securityProtocol.get());
233     await user.click(screen.getByText('SSLTLS'));
234     await user.type(ui.fromAddress.get(), 'admin@localhost.com');
235     await user.clear(ui.fromName.get());
236     await user.type(ui.fromName.get(), 'fromName');
237     await user.clear(ui.subjectPrefix.get());
238     await user.type(ui.subjectPrefix.get(), 'prefix');
239     await user.type(ui.username.get(), 'username');
240
241     expect(ui.selectorOAuthAuth.get()).toBeChecked();
242     expect(ui.username.get()).toHaveValue('username');
243     expect(ui.oauth_auth_host.get()).toHaveValue('oauth_auth_host');
244     expect(ui.oauth_client_id.get()).toHaveValue('oauth_client_id');
245     expect(ui.oauth_client_secret.get()).toHaveValue('oauth_client_secret');
246     expect(ui.oauth_tenant.get()).toHaveValue('oauth_tenant');
247     expect(ui.host.get()).toHaveValue('host');
248     expect(ui.port.get()).toHaveValue(1234);
249     expect(ui.securityProtocol.get()).toHaveValue('SSLTLS');
250     expect(ui.fromAddress.get()).toHaveValue('admin@localhost.com');
251     expect(ui.fromName.get()).toHaveValue('fromName');
252     expect(ui.subjectPrefix.get()).toHaveValue('prefix');
253
254     expect(await ui.save.find()).toBeEnabled();
255     await user.click(ui.save.get());
256
257     expect(api.postEmailConfiguration).toHaveBeenCalledTimes(1);
258     expect(api.postEmailConfiguration).toHaveBeenCalledWith({
259       authMethod: 'OAUTH',
260       basicPassword: '',
261       oauthAuthenticationHost: 'oauth_auth_host',
262       oauthClientId: 'oauth_client_id',
263       oauthClientSecret: 'oauth_client_secret',
264       oauthTenant: 'oauth_tenant',
265       fromAddress: 'admin@localhost.com',
266       fromName: 'fromName',
267       host: 'host',
268       port: '1234',
269       securityProtocol: 'SSLTLS',
270       subjectPrefix: 'prefix',
271       username: 'username',
272     });
273
274     expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
275       'email_notification.form.save_configuration.create_success',
276     );
277   });
278
279   it('can edit the oauth configuration', async () => {
280     systemHandler.addEmailConfiguration(
281       mockEmailConfiguration(AuthMethod.OAuth, { id: 'email-1' }),
282     );
283     jest.spyOn(api, 'patchEmailConfiguration');
284     const user = userEvent.setup();
285     renderEmailNotifications();
286     expect(await ui.editSubheading1.find()).toBeInTheDocument();
287     await user.click(ui.selectorOAuthAuth.get());
288
289     expect(ui.save.get()).toBeDisabled();
290     await user.type(ui.oauth_auth_host.get(), '-updated');
291     await user.type(ui.oauth_client_id.get(), 'updated_id');
292     await user.type(ui.oauth_client_secret.get(), 'updated_secret');
293     await user.type(ui.oauth_tenant.get(), '-updated');
294     await user.type(ui.host.get(), '-updated');
295     await user.type(ui.port.get(), '5678');
296     await user.click(ui.securityProtocol.get());
297     await user.click(screen.getByText('STARTTLS'));
298     await user.clear(ui.fromAddress.get());
299     await user.type(ui.fromAddress.get(), 'updated@email.com');
300     await user.type(ui.fromName.get(), '-updated');
301     await user.type(ui.subjectPrefix.get(), '-updated');
302     await user.type(ui.username.get(), '-updated');
303
304     expect(await ui.save.find()).toBeEnabled();
305     await user.click(ui.save.get());
306
307     expect(api.patchEmailConfiguration).toHaveBeenCalledTimes(1);
308     expect(api.patchEmailConfiguration).toHaveBeenCalledWith('email-1', {
309       authMethod: 'OAUTH',
310       oauthAuthenticationHost: 'oauth_auth_host-updated',
311       oauthClientId: 'updated_id',
312       oauthClientSecret: 'updated_secret',
313       oauthTenant: 'oauth_tenant-updated',
314       fromAddress: 'updated@email.com',
315       fromName: 'from_name-updated',
316       host: 'host-updated',
317       id: 'email-1',
318       isOauthClientIdSet: true,
319       isOauthClientSecretSet: true,
320       port: '5678',
321       securityProtocol: 'STARTTLS',
322       subjectPrefix: 'subject_prefix-updated',
323       username: 'username-updated',
324     });
325
326     expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
327       'email_notification.form.save_configuration.update_success',
328     );
329   });
330 });
331
332 function renderEmailNotifications() {
333   return renderComponent(<EmailNotification />);
334 }