3 * Copyright (C) 2009-2021 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 { shallow } from 'enzyme';
21 import * as React from 'react';
22 import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
24 deleteProjectAlmBinding,
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';
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)
46 const PROJECT_KEY = 'project-key';
52 it('should render correctly', () => {
53 expect(shallowRender()).toMatchSnapshot();
56 it('should fill selects and fill formdata', async () => {
57 const url = 'github.com';
58 const instances = [{ key: 'instance1', url, alm: AlmKeys.GitHub }];
61 repository: 'account/repo'
63 (getAlmSettings as jest.Mock).mockResolvedValueOnce(instances);
64 (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce(formdata);
66 const wrapper = shallowRender();
67 await waitAndUpdate(wrapper);
69 expect(wrapper.state().loading).toBe(false);
70 expect(wrapper.state().formData).toEqual(formdata);
71 expect(wrapper.state().isChanged).toBe(false);
74 it('should handle reset', async () => {
75 const wrapper = shallowRender();
76 await waitAndUpdate(wrapper);
80 repository: 'something/else'
84 wrapper.instance().handleReset();
85 await waitAndUpdate(wrapper);
87 expect(deleteProjectAlmBinding).toBeCalledWith(PROJECT_KEY);
88 expect(wrapper.state().formData).toEqual({ key: '', repository: '', slug: '' });
89 expect(wrapper.state().isChanged).toBe(false);
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 }
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;
108 formData: { key: githubKey, repository, summaryCommentEnabled, monorepo },
111 wrapper.instance().handleSubmit();
112 await waitAndUpdate(wrapper);
114 expect(setProjectGithubBinding).toBeCalledWith({
115 almSetting: githubKey,
116 project: PROJECT_KEY,
118 summaryCommentEnabled,
121 expect(wrapper.state().success).toBe(true);
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;
132 formData: { key: azureKey, repository, slug, monorepo },
135 wrapper.instance().handleSubmit();
136 await waitAndUpdate(wrapper);
138 expect(setProjectAzureBinding).toBeCalledWith({
139 almSetting: azureKey,
140 project: PROJECT_KEY,
142 repositoryName: repository,
145 expect(wrapper.state().success).toBe(true);
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);
159 expect(setProjectBitbucketBinding).toBeCalledWith({
160 almSetting: bitbucketKey,
161 project: PROJECT_KEY,
166 expect(wrapper.state().success).toBe(true);
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;
176 formData: { key: gitlabKey, repository, monorepo },
179 wrapper.instance().handleSubmit();
180 await waitAndUpdate(wrapper);
182 expect(setProjectGitlabBinding).toBeCalledWith({
183 almSetting: gitlabKey,
184 project: PROJECT_KEY,
188 expect(wrapper.state().success).toBe(true);
192 describe.each([[500], [404]])('For status %i', status => {
193 it('should handle failures gracefully', async () => {
194 const newFormData = {
196 repository: 'something/else'
199 (getProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status });
200 (setProjectGithubBinding as jest.Mock).mockRejectedValueOnce({ status });
201 (deleteProjectAlmBinding as jest.Mock).mockRejectedValueOnce({ status });
203 const wrapper = shallowRender();
204 await waitAndUpdate(wrapper);
206 formData: newFormData,
207 orignalData: undefined
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);
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 }
227 (getAlmSettings as jest.Mock).mockResolvedValueOnce(instances);
228 const wrapper = shallowRender();
229 await waitAndUpdate(wrapper);
231 wrapper.instance().handleFieldChange('key', 'instance2');
232 await waitAndUpdate(wrapper);
233 expect(wrapper.state().formData).toEqual({
237 wrapper.instance().handleFieldChange('repository', repository);
238 await waitAndUpdate(wrapper);
239 expect(wrapper.state().formData).toEqual({
244 wrapper.instance().handleFieldChange('summaryCommentEnabled', true);
245 await waitAndUpdate(wrapper);
246 expect(wrapper.state().formData).toEqual({
249 summaryCommentEnabled: true
252 wrapper.instance().handleFieldChange('monorepo', true);
253 await waitAndUpdate(wrapper);
254 expect(wrapper.state().formData).toEqual({
257 summaryCommentEnabled: true,
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, {}],
271 ])('should properly reject promise for %s & %s', async (almKey: AlmKeys, params: {}) => {
272 const wrapper = shallowRender();
274 expect.assertions(1);
276 wrapper.instance().submitProjectAlmBinding(almKey, 'binding', params)
277 ).rejects.toBeUndefined();
280 it('should validate form', async () => {
281 const wrapper = shallowRender();
282 await waitAndUpdate(wrapper);
284 const validateMethod = wrapper.instance().validateForm;
286 expect(validateMethod({ key: '', repository: '' })).toBe(false);
287 expect(validateMethod({ key: '', repository: 'c' })).toBe(false);
291 { key: 'azure', alm: AlmKeys.Azure },
292 { key: 'bitbucket', alm: AlmKeys.Bitbucket },
293 { key: 'github', alm: AlmKeys.GitHub },
294 { key: 'gitlab', alm: AlmKeys.GitLab }
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);
313 function shallowRender(props: Partial<PRDecorationBinding['props']> = {}) {
314 return shallow<PRDecorationBinding>(
316 component={mockComponent({ key: PROJECT_KEY })}
317 monorepoEnabled={false}