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 { 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';
32 jest.mock('../../../../../api/system');
33 jest.mock('../../../../../api/settings');
35 jest.mock('design-system', () => ({
36 ...jest.requireActual('design-system'),
37 addGlobalSuccessMessage: jest.fn(),
40 const systemHandler = new SystemServiceMock();
44 systemHandler.reset();
48 editSubheading1: byText('email_notification.subheading.1'),
51 selectorBasicAuth: byRole('radio', {
52 name: 'email_notification.form.basic_auth.title email_notification.form.basic_auth.description',
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',
57 host: byRole('textbox', {
58 name: 'email_notification.form.host field_required',
60 port: byRole('spinbutton', {
61 name: 'email_notification.form.port field_required',
63 securityProtocol: byRole('searchbox', {
64 name: 'email_notification.form.security_protocol field_required',
66 fromAddress: byRole('textbox', {
67 name: 'email_notification.form.from_address field_required',
69 fromName: byRole('textbox', {
70 name: 'email_notification.form.from_name field_required',
72 subjectPrefix: byRole('textbox', {
73 name: 'email_notification.form.subject_prefix field_required',
75 username: byRole('textbox', {
76 name: 'email_notification.form.username field_required',
79 // basic authentication
80 basic_password: byLabelText('email_notification.form.basic_password*'),
83 oauth_auth_host: byRole('textbox', {
84 name: 'email_notification.form.oauth_authentication_host field_required',
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' }),
90 save: byRole('button', {
91 name: 'email_notification.form.save_configuration',
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();
102 expect(ui.save.get()).toBeDisabled();
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]');
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');
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');
137 expect(await ui.save.find()).toBeEnabled();
138 await user.click(ui.save.get());
140 expect(api.postEmailConfiguration).toHaveBeenCalledTimes(1);
141 expect(api.postEmailConfiguration).toHaveBeenCalledWith({
143 basicPassword: 'password',
144 fromAddress: 'admin@localhost.com',
145 fromName: 'fromName',
148 securityProtocol: 'SSLTLS',
149 subjectPrefix: 'prefix',
150 username: 'username',
153 expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
154 'email_notification.form.save_configuration.create_success',
158 it('can edit an existing configuration', async () => {
159 systemHandler.addEmailConfiguration(
160 mockEmailConfiguration(AuthMethod.Basic, { id: 'email-1' }),
162 jest.spyOn(api, 'patchEmailConfiguration');
163 const user = userEvent.setup();
164 renderEmailNotifications();
165 expect(await ui.editSubheading1.find()).toBeInTheDocument();
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');
179 expect(await ui.save.find()).toBeEnabled();
180 await user.click(ui.save.get());
182 expect(api.patchEmailConfiguration).toHaveBeenCalledTimes(1);
183 expect(api.patchEmailConfiguration).toHaveBeenCalledWith('email-1', {
185 basicPassword: 'updated',
186 fromAddress: 'updated@email.com',
187 fromName: 'from_name-updated',
188 host: 'host-updated',
190 isBasicPasswordSet: true,
192 securityProtocol: 'STARTTLS',
193 subjectPrefix: 'subject_prefix-updated',
194 username: 'username-updated',
197 expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
198 'email_notification.form.save_configuration.update_success',
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());
211 expect(ui.save.get()).toBeDisabled();
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]');
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');
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');
254 expect(await ui.save.find()).toBeEnabled();
255 await user.click(ui.save.get());
257 expect(api.postEmailConfiguration).toHaveBeenCalledTimes(1);
258 expect(api.postEmailConfiguration).toHaveBeenCalledWith({
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',
269 securityProtocol: 'SSLTLS',
270 subjectPrefix: 'prefix',
271 username: 'username',
274 expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
275 'email_notification.form.save_configuration.create_success',
279 it('can edit the oauth configuration', async () => {
280 systemHandler.addEmailConfiguration(
281 mockEmailConfiguration(AuthMethod.OAuth, { id: 'email-1' }),
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());
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');
304 expect(await ui.save.find()).toBeEnabled();
305 await user.click(ui.save.get());
307 expect(api.patchEmailConfiguration).toHaveBeenCalledTimes(1);
308 expect(api.patchEmailConfiguration).toHaveBeenCalledWith('email-1', {
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',
318 isOauthClientIdSet: true,
319 isOauthClientSecretSet: true,
321 securityProtocol: 'STARTTLS',
322 subjectPrefix: 'subject_prefix-updated',
323 username: 'username-updated',
326 expect(addGlobalSuccessMessage).toHaveBeenCalledWith(
327 'email_notification.form.save_configuration.update_success',
332 function renderEmailNotifications() {
333 return renderComponent(<EmailNotification />);