]> source.dussan.org Git - sonarqube.git/blob
22abab10298cbe0692d2d21e78ba01ab819ff770
[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 userEvent from '@testing-library/user-event';
21 import React from 'react';
22 import selectEvent from 'react-select-event';
23 import { byRole, byText } from '~sonar-aligned/helpers/testSelector';
24 import AlmSettingsServiceMock from '../../../../../api/mocks/AlmSettingsServiceMock';
25 import CurrentUserContextProvider from '../../../../../app/components/current-user/CurrentUserContextProvider';
26 import { mockComponent } from '../../../../../helpers/mocks/component';
27 import { mockCurrentUser } from '../../../../../helpers/testMocks';
28 import { renderComponent } from '../../../../../helpers/testReactTestingUtils';
29 import {
30   AlmKeys,
31   ProjectAlmBindingConfigurationErrorScope,
32 } from '../../../../../types/alm-settings';
33 import { Component } from '../../../../../types/types';
34 import { CurrentUser } from '../../../../../types/users';
35 import PRDecorationBinding from '../PRDecorationBinding';
36
37 let almSettings: AlmSettingsServiceMock;
38
39 beforeAll(() => {
40   almSettings = new AlmSettingsServiceMock();
41 });
42
43 afterEach(() => {
44   almSettings.reset();
45 });
46
47 const inputsList = {
48   [AlmKeys.GitLab]: { 'gitlab.repository': 'Repository', monorepo: false },
49   [AlmKeys.GitHub]: {
50     'github.repository': 'Repository',
51     'github.summary_comment_setting': false,
52     monorepo: false,
53   },
54   [AlmKeys.Azure]: {
55     'azure.repository': 'Repository',
56     'azure.project': 'Project',
57     monorepo: false,
58   },
59   [AlmKeys.BitbucketCloud]: { 'bitbucketcloud.repository': 'Repository', monorepo: false },
60   [AlmKeys.BitbucketServer]: {
61     'bitbucket.repository': 'Repository',
62     'bitbucket.slug': 'Slug',
63     monorepo: false,
64   },
65 };
66
67 it.each([
68   {
69     key: 'conf-final-1',
70     alm: AlmKeys.GitLab,
71   },
72   {
73     key: 'conf-github-1',
74     alm: AlmKeys.GitHub,
75   },
76   {
77     key: 'conf-azure-1',
78     alm: AlmKeys.Azure,
79   },
80   {
81     key: 'conf-bitbucketcloud-1',
82     alm: AlmKeys.BitbucketCloud,
83   },
84   {
85     key: 'conf-bitbucketserver-1',
86     alm: AlmKeys.BitbucketServer,
87   },
88 ])(
89   'should get, set, delete and validate binding for $alm',
90   async ({ key, alm }: { alm: AlmKeys; key: string }) => {
91     const { ui, user } = getPageObjects();
92     almSettings.setProjectBindingConfigurationErrors({
93       scope: ProjectAlmBindingConfigurationErrorScope.Global,
94       errors: [{ msg: 'cute error' }],
95     });
96     const { rerender } = renderPRDecorationBinding();
97     expect(await ui.mainTitle.find()).toBeInTheDocument();
98
99     // Set form data
100     await selectEvent.select(ui.input('name', 'combobox').get(), (content) =>
101       content.includes(key),
102     );
103
104     const list = inputsList[alm];
105     for (const [inputId, value] of Object.entries(list)) {
106       // eslint-disable-next-line no-await-in-loop
107       await ui.setInput(inputId, value);
108     }
109     // Save form and check for errors
110     await user.click(ui.saveButton.get());
111     expect(await ui.validationMsg('cute error').find()).toBeInTheDocument();
112
113     // Check validation with errors
114     await user.click(ui.validateButton.get());
115     expect(ui.validationMsg('cute error').get()).toBeInTheDocument();
116
117     // Save form and check for errors
118     almSettings.setProjectBindingConfigurationErrors(undefined);
119     await ui.setInput(
120       Object.keys(list).find((key) => key.endsWith('.repository')) as string,
121       'Anything',
122     );
123     await user.click(ui.saveButton.get());
124     expect(
125       await ui.validationMsg('settings.pr_decoration.binding.check_configuration.success').find(),
126     ).toBeInTheDocument();
127
128     await user.click(ui.validateButton.get());
129     expect(
130       ui.validationMsg('settings.pr_decoration.binding.check_configuration.success').get(),
131     ).toBeInTheDocument();
132
133     // Rerender and verify that validation is done for binding
134     rerender(
135       <MockedPRDecorationBinding component={mockComponent()} currentUser={mockCurrentUser()} />,
136     );
137     expect(
138       await ui.validationMsg('settings.pr_decoration.binding.check_configuration.success').find(),
139     ).toBeInTheDocument();
140     expect(ui.saveButton.query()).not.toBeInTheDocument();
141
142     // Reset binding
143     await user.click(ui.resetButton.get());
144     expect(ui.input('', 'textbox').query()).not.toBeInTheDocument();
145     expect(ui.input('', 'switch').query()).not.toBeInTheDocument();
146   },
147 );
148
149 function getPageObjects() {
150   const user = userEvent.setup();
151
152   async function setInput(inputId: string, value: string | boolean) {
153     if (typeof value === 'boolean') {
154       if (value) {
155         await user.click(ui.input(inputId, 'switch').get());
156       }
157     } else {
158       const input = ui.input(inputId, 'textbox').get();
159       await user.clear(input);
160       await user.type(input, value);
161     }
162   }
163
164   const ui = {
165     mainTitle: byRole('heading', { name: 'settings.pr_decoration.binding.title' }),
166     input: (id: string, role: 'combobox' | 'switch' | 'textbox') =>
167       byRole(role, { name: new RegExp(`settings.pr_decoration.binding.form.${id}`) }),
168     saveButton: byRole('button', { name: 'save' }),
169     resetButton: byRole('button', { name: 'reset_verb' }),
170     validateButton: byRole('button', {
171       name: 'settings.pr_decoration.binding.check_configuration',
172     }),
173     validationMsg: (text: string) => byText(text),
174     setInput,
175   };
176
177   return {
178     ui,
179     user,
180   };
181 }
182
183 function MockedPRDecorationBinding({
184   component,
185   currentUser,
186 }: {
187   component: Component;
188   currentUser: CurrentUser;
189 }) {
190   return (
191     <CurrentUserContextProvider currentUser={currentUser}>
192       <PRDecorationBinding component={component} />
193     </CurrentUserContextProvider>
194   );
195 }
196
197 function renderPRDecorationBinding(
198   component: Component = mockComponent(),
199   currentUser: CurrentUser = mockCurrentUser(),
200 ) {
201   return renderComponent(
202     <MockedPRDecorationBinding component={component} currentUser={currentUser} />,
203   );
204 }