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