]> source.dussan.org Git - sonarqube.git/blob
6d9c7e4dd6548da9fcbc2753225b92fb5e266ad4
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2021 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 { shallow } from 'enzyme';
21 import * as React from 'react';
22 import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
23 import {
24   deleteProjectAlmBinding,
25   getAlmSettings,
26   getProjectAlmBinding,
27   setProjectAzureBinding,
28   setProjectBitbucketBinding,
29   setProjectGithubBinding,
30   setProjectGitlabBinding
31 } from '../../../../../api/alm-settings';
32 import { mockComponent } from '../../../../../helpers/testMocks';
33 import { AlmKeys, AlmSettingsInstance } from '../../../../../types/alm-settings';
34 import { PRDecorationBinding } from '../PRDecorationBinding';
35
36 jest.mock('../../../../../api/alm-settings', () => ({
37   getAlmSettings: jest.fn().mockResolvedValue([]),
38   getProjectAlmBinding: jest.fn().mockResolvedValue(undefined),
39   setProjectAzureBinding: jest.fn().mockResolvedValue(undefined),
40   setProjectBitbucketBinding: jest.fn().mockResolvedValue(undefined),
41   setProjectGithubBinding: jest.fn().mockResolvedValue(undefined),
42   setProjectGitlabBinding: jest.fn().mockResolvedValue(undefined),
43   deleteProjectAlmBinding: jest.fn().mockResolvedValue(undefined)
44 }));
45
46 const PROJECT_KEY = 'project-key';
47
48 beforeEach(() => {
49   jest.clearAllMocks();
50 });
51
52 it('should render correctly', () => {
53   expect(shallowRender()).toMatchSnapshot();
54 });
55
56 it('should fill selects and fill formdata', async () => {
57   const url = 'github.com';
58   const instances = [{ key: 'instance1', url, alm: AlmKeys.GitHub }];
59   const formdata = {
60     key: 'instance1',
61     repository: 'account/repo'
62   };
63   (getAlmSettings as jest.Mock).mockResolvedValueOnce(instances);
64   (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce(formdata);
65
66   const wrapper = shallowRender();
67   await waitAndUpdate(wrapper);
68
69   expect(wrapper.state().loading).toBe(false);
70   expect(wrapper.state().formData).toEqual(formdata);
71   expect(wrapper.state().isChanged).toBe(false);
72 });
73
74 it('should handle reset', async () => {
75   const wrapper = shallowRender();
76   await waitAndUpdate(wrapper);
77   wrapper.setState({
78     formData: {
79       key: 'whatever',
80       repository: 'something/else'
81     }
82   });
83
84   wrapper.instance().handleReset();
85   await waitAndUpdate(wrapper);
86
87   expect(deleteProjectAlmBinding).toBeCalledWith(PROJECT_KEY);
88   expect(wrapper.state().formData).toEqual({ key: '', repository: '', slug: '' });
89   expect(wrapper.state().isChanged).toBe(false);
90 });
91
92 describe('handleSubmit', () => {
93   const instances: AlmSettingsInstance[] = [
94     { key: 'github', alm: AlmKeys.GitHub },
95     { key: 'azure', alm: AlmKeys.Azure },
96     { key: 'bitbucket', alm: AlmKeys.Bitbucket },
97     { key: 'gitlab', alm: AlmKeys.GitLab }
98   ];
99
100   it('should work for github', async () => {
101     const wrapper = shallowRender();
102     await waitAndUpdate(wrapper);
103     const githubKey = 'github';
104     const repository = 'repo/path';
105     const summaryCommentEnabled = true;
106     const monorepo = true;
107     wrapper.setState({
108       formData: { key: githubKey, repository, summaryCommentEnabled, monorepo },
109       instances
110     });
111     wrapper.instance().handleSubmit();
112     await waitAndUpdate(wrapper);
113
114     expect(setProjectGithubBinding).toBeCalledWith({
115       almSetting: githubKey,
116       project: PROJECT_KEY,
117       repository,
118       summaryCommentEnabled,
119       monorepo
120     });
121     expect(wrapper.state().success).toBe(true);
122   });
123
124   it('should work for azure', async () => {
125     const wrapper = shallowRender();
126     await waitAndUpdate(wrapper);
127     const azureKey = 'azure';
128     const repository = 'az-rep';
129     const slug = 'az-project';
130     const monorepo = true;
131     wrapper.setState({
132       formData: { key: azureKey, repository, slug, monorepo },
133       instances
134     });
135     wrapper.instance().handleSubmit();
136     await waitAndUpdate(wrapper);
137
138     expect(setProjectAzureBinding).toBeCalledWith({
139       almSetting: azureKey,
140       project: PROJECT_KEY,
141       projectName: slug,
142       repositoryName: repository,
143       monorepo
144     });
145     expect(wrapper.state().success).toBe(true);
146   });
147
148   it('should work for bitbucket', async () => {
149     const wrapper = shallowRender();
150     await waitAndUpdate(wrapper);
151     const bitbucketKey = 'bitbucket';
152     const repository = 'repoKey';
153     const slug = 'repoSlug';
154     const monorepo = true;
155     wrapper.setState({ formData: { key: bitbucketKey, repository, slug, monorepo }, instances });
156     wrapper.instance().handleSubmit();
157     await waitAndUpdate(wrapper);
158
159     expect(setProjectBitbucketBinding).toBeCalledWith({
160       almSetting: bitbucketKey,
161       project: PROJECT_KEY,
162       repository,
163       slug,
164       monorepo
165     });
166     expect(wrapper.state().success).toBe(true);
167   });
168
169   it('should work for gitlab', async () => {
170     const wrapper = shallowRender();
171     await waitAndUpdate(wrapper);
172     const gitlabKey = 'gitlab';
173     const repository = 'repo';
174     const monorepo = true;
175     wrapper.setState({
176       formData: { key: gitlabKey, repository, monorepo },
177       instances
178     });
179     wrapper.instance().handleSubmit();
180     await waitAndUpdate(wrapper);
181
182     expect(setProjectGitlabBinding).toBeCalledWith({
183       almSetting: gitlabKey,
184       project: PROJECT_KEY,
185       repository,
186       monorepo
187     });
188     expect(wrapper.state().success).toBe(true);
189   });
190 });
191
192 describe.each([[500], [404]])('For status %i', status => {
193   it('should handle failures gracefully', async () => {
194     const newFormData = {
195       key: 'whatever',
196       repository: 'something/else'
197     };
198
199     (getProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status });
200     (setProjectGithubBinding as jest.Mock).mockRejectedValueOnce({ status });
201     (deleteProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status });
202
203     const wrapper = shallowRender();
204     await waitAndUpdate(wrapper);
205     wrapper.setState({
206       formData: newFormData,
207       orignalData: undefined
208     });
209
210     wrapper.instance().handleSubmit();
211     await waitAndUpdate(wrapper);
212     expect(wrapper.instance().state.orignalData).toBeUndefined();
213     wrapper.instance().handleReset();
214     await waitAndUpdate(wrapper);
215     expect(wrapper.instance().state.formData).toEqual(newFormData);
216   });
217 });
218
219 it('should handle field changes', async () => {
220   const url = 'git.enterprise.com';
221   const repository = 'my/repo';
222   const instances: AlmSettingsInstance[] = [
223     { key: 'instance1', url, alm: AlmKeys.GitHub },
224     { key: 'instance2', url, alm: AlmKeys.GitHub },
225     { key: 'instance3', url: 'otherurl', alm: AlmKeys.GitHub }
226   ];
227   (getAlmSettings as jest.Mock).mockResolvedValueOnce(instances);
228   const wrapper = shallowRender();
229   await waitAndUpdate(wrapper);
230
231   wrapper.instance().handleFieldChange('key', 'instance2');
232   await waitAndUpdate(wrapper);
233   expect(wrapper.state().formData).toEqual({
234     key: 'instance2'
235   });
236
237   wrapper.instance().handleFieldChange('repository', repository);
238   await waitAndUpdate(wrapper);
239   expect(wrapper.state().formData).toEqual({
240     key: 'instance2',
241     repository
242   });
243
244   wrapper.instance().handleFieldChange('summaryCommentEnabled', true);
245   await waitAndUpdate(wrapper);
246   expect(wrapper.state().formData).toEqual({
247     key: 'instance2',
248     repository,
249     summaryCommentEnabled: true
250   });
251
252   wrapper.instance().handleFieldChange('monorepo', true);
253   await waitAndUpdate(wrapper);
254   expect(wrapper.state().formData).toEqual({
255     key: 'instance2',
256     repository,
257     summaryCommentEnabled: true,
258     monorepo: true
259   });
260 });
261
262 it.each([
263   [AlmKeys.Azure, {}],
264   [AlmKeys.Azure, { slug: 'test' }],
265   [AlmKeys.Azure, { repository: 'test' }],
266   [AlmKeys.Bitbucket, {}],
267   [AlmKeys.Bitbucket, { slug: 'test' }],
268   [AlmKeys.Bitbucket, { repository: 'test' }],
269   [AlmKeys.GitHub, {}],
270   [AlmKeys.GitLab, {}]
271 ])('should properly reject promise for %s & %s', async (almKey: AlmKeys, params: {}) => {
272   const wrapper = shallowRender();
273
274   expect.assertions(1);
275   await expect(
276     wrapper.instance().submitProjectAlmBinding(almKey, 'binding', params)
277   ).rejects.toBeUndefined();
278 });
279
280 it('should validate form', async () => {
281   const wrapper = shallowRender();
282   await waitAndUpdate(wrapper);
283
284   const validateMethod = wrapper.instance().validateForm;
285
286   expect(validateMethod({ key: '', repository: '' })).toBe(false);
287   expect(validateMethod({ key: '', repository: 'c' })).toBe(false);
288
289   wrapper.setState({
290     instances: [
291       { key: 'azure', alm: AlmKeys.Azure },
292       { key: 'bitbucket', alm: AlmKeys.Bitbucket },
293       { key: 'github', alm: AlmKeys.GitHub },
294       { key: 'gitlab', alm: AlmKeys.GitLab }
295     ]
296   });
297
298   [
299     { values: { key: 'azure', repository: 'rep' }, result: false },
300     { values: { key: 'azure', slug: 'project' }, result: false },
301     { values: { key: 'azure', repository: 'repo', slug: 'project' }, result: true },
302     { values: { key: 'github', repository: '' }, result: false },
303     { values: { key: 'github', repository: 'asdf' }, result: true },
304     { values: { key: 'bitbucket', repository: 'key' }, result: false },
305     { values: { key: 'bitbucket', repository: 'key', slug: 'slug' }, result: true },
306     { values: { key: 'gitlab' }, result: false },
307     { values: { key: 'gitlab', repository: 'key' }, result: true }
308   ].forEach(({ values, result }) => {
309     expect(validateMethod(values)).toBe(result);
310   });
311 });
312
313 function shallowRender(props: Partial<PRDecorationBinding['props']> = {}) {
314   return shallow<PRDecorationBinding>(
315     <PRDecorationBinding
316       component={mockComponent({ key: PROJECT_KEY })}
317       monorepoEnabled={false}
318       {...props}
319     />
320   );
321 }