]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14405 Add monorepo checkbox for Gitlab bindings
authorPhilippe Perrin <philippe.perrin@sonarsource.com>
Thu, 28 Jan 2021 16:58:17 +0000 (17:58 +0100)
committersonartech <sonartech@sonarsource.com>
Tue, 2 Feb 2021 20:07:49 +0000 (20:07 +0000)
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/AlmSpecificForm.tsx
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/PRDecorationBinding.tsx
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/PRDecorationBinding-test.tsx
server/sonar-web/src/main/js/apps/settings/components/pullRequestDecorationBinding/__tests__/__snapshots__/AlmSpecificForm-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/__tests__/__snapshots__/TutorialSelectionRenderer-test.tsx.snap
server/sonar-web/src/main/js/helpers/mocks/alm-settings.ts
server/sonar-web/src/main/js/types/alm-settings.ts

index 6aac532900742f4e6419aa12d97ecd87872c6260..1fc2a7e95b4245985ccf83a1cef2e3f65d6c1938 100644 (file)
@@ -151,6 +151,15 @@ export default function AlmSpecificForm(props: AlmSpecificFormProps) {
     monorepoEnabled
   } = props;
 
+  const renderMonoRepoFieldWithDocLink = (docLink: string) => {
+    return renderMonoRepoField({
+      monorepoEnabled,
+      value: monorepo,
+      docLink,
+      onFieldChange: props.onFieldChange
+    });
+  };
+
   switch (alm) {
     case AlmKeys.Azure:
       return (
@@ -169,12 +178,7 @@ export default function AlmSpecificForm(props: AlmSpecificFormProps) {
             propKey: 'repository',
             value: repository || ''
           })}
-          {renderMonoRepoField({
-            monorepoEnabled,
-            value: monorepo,
-            docLink: '/documentation/analysis/azuredevops-integration/',
-            onFieldChange: props.onFieldChange
-          })}
+          {renderMonoRepoFieldWithDocLink('/documentation/analysis/azuredevops-integration/')}
         </>
       );
     case AlmKeys.Bitbucket:
@@ -212,12 +216,7 @@ export default function AlmSpecificForm(props: AlmSpecificFormProps) {
             propKey: 'slug',
             value: slug || ''
           })}
-          {renderMonoRepoField({
-            monorepoEnabled,
-            value: monorepo,
-            docLink: '/documentation/analysis/bitbucket-integration/',
-            onFieldChange: props.onFieldChange
-          })}
+          {renderMonoRepoFieldWithDocLink('/documentation/analysis/bitbucket-integration/')}
         </>
       );
     case AlmKeys.GitHub:
@@ -238,21 +237,21 @@ export default function AlmSpecificForm(props: AlmSpecificFormProps) {
             propKey: 'summaryCommentEnabled',
             value: summaryCommentEnabled === undefined ? true : summaryCommentEnabled
           })}
-          {renderMonoRepoField({
-            monorepoEnabled,
-            value: monorepo,
-            docLink: '/documentation/analysis/github-integration/',
-            onFieldChange: props.onFieldChange
-          })}
+          {renderMonoRepoFieldWithDocLink('/documentation/analysis/github-integration/')}
         </>
       );
     case AlmKeys.GitLab:
-      return renderField({
-        id: 'gitlab.repository',
-        onFieldChange: props.onFieldChange,
-        propKey: 'repository',
-        value: repository || ''
-      });
+      return (
+        <>
+          {renderField({
+            id: 'gitlab.repository',
+            onFieldChange: props.onFieldChange,
+            propKey: 'repository',
+            value: repository || ''
+          })}
+          {renderMonoRepoFieldWithDocLink('/documentation/analysis/gitlab-integration/')}
+        </>
+      );
     default:
       return null;
   }
index 3d2368ed24b691e1dee38a76c8629e83fffc7560..3d9a226923e5788a0474681681fb46506dec9422 100644 (file)
@@ -163,27 +163,24 @@ export class PRDecorationBinding extends React.PureComponent<Props & StateProps,
   ): Promise<void> {
     const almSetting = key;
     const project = this.props.component.key;
+    const repository = almSpecificFields?.repository;
+    const slug = almSpecificFields?.slug;
+    const monorepo = almSpecificFields?.monorepo ?? false;
 
     switch (alm) {
       case AlmKeys.Azure: {
-        const projectName = almSpecificFields?.slug;
-        const repositoryName = almSpecificFields?.repository;
-        const monorepo = almSpecificFields?.monorepo ?? false;
-        if (!projectName || !repositoryName) {
+        if (!slug || !repository) {
           return Promise.reject();
         }
         return setProjectAzureBinding({
           almSetting,
           project,
-          projectName,
-          repositoryName,
+          projectName: slug,
+          repositoryName: repository,
           monorepo
         });
       }
       case AlmKeys.Bitbucket: {
-        const repository = almSpecificFields?.repository;
-        const slug = almSpecificFields?.slug;
-        const monorepo = almSpecificFields?.monorepo ?? false;
         if (!repository || !slug) {
           return Promise.reject();
         }
@@ -196,13 +193,11 @@ export class PRDecorationBinding extends React.PureComponent<Props & StateProps,
         });
       }
       case AlmKeys.GitHub: {
-        const repository = almSpecificFields?.repository;
         // By default it must remain true.
         const summaryCommentEnabled =
           almSpecificFields?.summaryCommentEnabled === undefined
             ? true
             : almSpecificFields?.summaryCommentEnabled;
-        const monorepo = almSpecificFields?.monorepo ?? false;
         if (!repository) {
           return Promise.reject();
         }
@@ -216,11 +211,14 @@ export class PRDecorationBinding extends React.PureComponent<Props & StateProps,
       }
 
       case AlmKeys.GitLab: {
-        const repository = almSpecificFields && almSpecificFields.repository;
+        if (!repository) {
+          return Promise.reject();
+        }
         return setProjectGitlabBinding({
           almSetting,
           project,
-          repository
+          repository,
+          monorepo
         });
       }
 
index 53e7289bf8cb2c08ba8abb51b8dfbef692d8a0e5..6d9c7e4dd6548da9fcbc2753225b92fb5e266ad4 100644 (file)
@@ -26,7 +26,8 @@ import {
   getProjectAlmBinding,
   setProjectAzureBinding,
   setProjectBitbucketBinding,
-  setProjectGithubBinding
+  setProjectGithubBinding,
+  setProjectGitlabBinding
 } from '../../../../../api/alm-settings';
 import { mockComponent } from '../../../../../helpers/testMocks';
 import { AlmKeys, AlmSettingsInstance } from '../../../../../types/alm-settings';
@@ -38,6 +39,7 @@ jest.mock('../../../../../api/alm-settings', () => ({
   setProjectAzureBinding: jest.fn().mockResolvedValue(undefined),
   setProjectBitbucketBinding: jest.fn().mockResolvedValue(undefined),
   setProjectGithubBinding: jest.fn().mockResolvedValue(undefined),
+  setProjectGitlabBinding: jest.fn().mockResolvedValue(undefined),
   deleteProjectAlmBinding: jest.fn().mockResolvedValue(undefined)
 }));
 
@@ -91,7 +93,8 @@ describe('handleSubmit', () => {
   const instances: AlmSettingsInstance[] = [
     { key: 'github', alm: AlmKeys.GitHub },
     { key: 'azure', alm: AlmKeys.Azure },
-    { key: 'bitbucket', alm: AlmKeys.Bitbucket }
+    { key: 'bitbucket', alm: AlmKeys.Bitbucket },
+    { key: 'gitlab', alm: AlmKeys.GitLab }
   ];
 
   it('should work for github', async () => {
@@ -162,6 +165,28 @@ describe('handleSubmit', () => {
     });
     expect(wrapper.state().success).toBe(true);
   });
+
+  it('should work for gitlab', async () => {
+    const wrapper = shallowRender();
+    await waitAndUpdate(wrapper);
+    const gitlabKey = 'gitlab';
+    const repository = 'repo';
+    const monorepo = true;
+    wrapper.setState({
+      formData: { key: gitlabKey, repository, monorepo },
+      instances
+    });
+    wrapper.instance().handleSubmit();
+    await waitAndUpdate(wrapper);
+
+    expect(setProjectGitlabBinding).toBeCalledWith({
+      almSetting: gitlabKey,
+      project: PROJECT_KEY,
+      repository,
+      monorepo
+    });
+    expect(wrapper.state().success).toBe(true);
+  });
 });
 
 describe.each([[500], [404]])('For status %i', status => {
@@ -234,107 +259,32 @@ it('should handle field changes', async () => {
   });
 });
 
-it('should reject submitted azure settings', async () => {
-  const wrapper = shallowRender();
-
-  expect.assertions(2);
-  await expect(
-    wrapper.instance().submitProjectAlmBinding(AlmKeys.Azure, 'azure-binding', { slug: 'project' })
-  ).rejects.toBeUndefined();
-  await expect(
-    wrapper
-      .instance()
-      .submitProjectAlmBinding(AlmKeys.Azure, 'azure-binding', { repository: 'repo' })
-  ).rejects.toBeUndefined();
-});
-
-it('should accept submit azure settings', async () => {
-  const wrapper = shallowRender();
-  await wrapper
-    .instance()
-    .submitProjectAlmBinding(AlmKeys.Azure, 'azure', { repository: 'az-repo', slug: 'az-project' });
-  expect(setProjectAzureBinding).toHaveBeenCalledWith({
-    almSetting: 'azure',
-    project: PROJECT_KEY,
-    repositoryName: 'az-repo',
-    projectName: 'az-project',
-    monorepo: false
-  });
-});
-
-it('should reject submitted bbs settings', async () => {
-  const wrapper = shallowRender();
-
-  expect.assertions(2);
-  await expect(
-    wrapper
-      .instance()
-      .submitProjectAlmBinding(AlmKeys.Bitbucket, 'bbs-binding', { slug: 'project' })
-  ).rejects.toBeUndefined();
-  await expect(
-    wrapper
-      .instance()
-      .submitProjectAlmBinding(AlmKeys.Bitbucket, 'bbs-binding', { repository: 'repo' })
-  ).rejects.toBeUndefined();
-});
-
-it('should accept submit bbs settings', async () => {
-  const wrapper = shallowRender();
-  await wrapper.instance().submitProjectAlmBinding(AlmKeys.Bitbucket, 'bbs', {
-    repository: 'bbs-repo',
-    slug: 'bbs-project'
-  });
-  expect(setProjectBitbucketBinding).toHaveBeenCalledWith({
-    almSetting: 'bbs',
-    project: PROJECT_KEY,
-    repository: 'bbs-repo',
-    slug: 'bbs-project',
-    monorepo: false
-  });
-});
-
-it('should reject submit github settings', async () => {
+it.each([
+  [AlmKeys.Azure, {}],
+  [AlmKeys.Azure, { slug: 'test' }],
+  [AlmKeys.Azure, { repository: 'test' }],
+  [AlmKeys.Bitbucket, {}],
+  [AlmKeys.Bitbucket, { slug: 'test' }],
+  [AlmKeys.Bitbucket, { repository: 'test' }],
+  [AlmKeys.GitHub, {}],
+  [AlmKeys.GitLab, {}]
+])('should properly reject promise for %s & %s', async (almKey: AlmKeys, params: {}) => {
   const wrapper = shallowRender();
 
   expect.assertions(1);
   await expect(
-    wrapper.instance().submitProjectAlmBinding(AlmKeys.GitHub, 'github-binding', {})
+    wrapper.instance().submitProjectAlmBinding(almKey, 'binding', params)
   ).rejects.toBeUndefined();
 });
 
-it('should accept submit github settings', async () => {
-  (setProjectGithubBinding as jest.Mock).mockRestore();
-  const wrapper = shallowRender();
-  await wrapper
-    .instance()
-    .submitProjectAlmBinding(AlmKeys.GitHub, 'github-binding', { repository: 'foo' });
-  expect(setProjectGithubBinding).toHaveBeenCalledWith({
-    almSetting: 'github-binding',
-    project: PROJECT_KEY,
-    repository: 'foo',
-    summaryCommentEnabled: true,
-    monorepo: false
-  });
-
-  await wrapper.instance().submitProjectAlmBinding(AlmKeys.GitHub, 'github-binding', {
-    repository: 'foo',
-    summaryCommentEnabled: true
-  });
-  expect(setProjectGithubBinding).toHaveBeenCalledWith({
-    almSetting: 'github-binding',
-    project: PROJECT_KEY,
-    repository: 'foo',
-    summaryCommentEnabled: true,
-    monorepo: false
-  });
-});
-
 it('should validate form', async () => {
   const wrapper = shallowRender();
   await waitAndUpdate(wrapper);
 
-  expect(wrapper.instance().validateForm({ key: '', repository: '' })).toBe(false);
-  expect(wrapper.instance().validateForm({ key: '', repository: 'c' })).toBe(false);
+  const validateMethod = wrapper.instance().validateForm;
+
+  expect(validateMethod({ key: '', repository: '' })).toBe(false);
+  expect(validateMethod({ key: '', repository: 'c' })).toBe(false);
 
   wrapper.setState({
     instances: [
@@ -345,24 +295,19 @@ it('should validate form', async () => {
     ]
   });
 
-  expect(wrapper.instance().validateForm({ key: 'azure', repository: 'rep' })).toBe(false);
-  expect(wrapper.instance().validateForm({ key: 'azure', slug: 'project' })).toBe(false);
-  expect(
-    wrapper
-      .instance()
-      .validateForm({ key: 'azure', repository: 'repo', slug: 'project', monorepo: true })
-  ).toBe(true);
-
-  expect(wrapper.instance().validateForm({ key: 'github', repository: '' })).toBe(false);
-  expect(wrapper.instance().validateForm({ key: 'github', repository: 'asdf' })).toBe(true);
-
-  expect(wrapper.instance().validateForm({ key: 'bitbucket', repository: 'key' })).toBe(false);
-  expect(
-    wrapper.instance().validateForm({ key: 'bitbucket', repository: 'key', slug: 'slug' })
-  ).toBe(true);
-
-  expect(wrapper.instance().validateForm({ key: 'gitlab' })).toBe(false);
-  expect(wrapper.instance().validateForm({ key: 'gitlab', repository: 'key' })).toBe(true);
+  [
+    { values: { key: 'azure', repository: 'rep' }, result: false },
+    { values: { key: 'azure', slug: 'project' }, result: false },
+    { values: { key: 'azure', repository: 'repo', slug: 'project' }, result: true },
+    { values: { key: 'github', repository: '' }, result: false },
+    { values: { key: 'github', repository: 'asdf' }, result: true },
+    { values: { key: 'bitbucket', repository: 'key' }, result: false },
+    { values: { key: 'bitbucket', repository: 'key', slug: 'slug' }, result: true },
+    { values: { key: 'gitlab' }, result: false },
+    { values: { key: 'gitlab', repository: 'key' }, result: true }
+  ].forEach(({ values, result }) => {
+    expect(validateMethod(values)).toBe(result);
+  });
 });
 
 function shallowRender(props: Partial<PRDecorationBinding['props']> = {}) {
index cc9dadc14c0c48035ef549a83cc1b696aed29bf7..64af693dfb7ef7b80ed0ed76733a018eca2d78bf 100644 (file)
@@ -617,57 +617,103 @@ exports[`it should render correctly for github and monorepo=true 1`] = `
 `;
 
 exports[`it should render correctly for gitlab and monorepo=false 1`] = `
-<div
-  className="form-field"
->
-  <label
-    className="display-flex-center"
-    htmlFor="gitlab.repository"
+<Fragment>
+  <div
+    className="form-field"
   >
-    settings.pr_decoration.binding.form.gitlab.repository
-    <em
-      className="mandatory"
+    <label
+      className="display-flex-center"
+      htmlFor="gitlab.repository"
     >
-      *
-    </em>
-  </label>
-  <input
-    className="input-super-large"
-    id="gitlab.repository"
-    maxLength={256}
-    name="gitlab.repository"
-    onChange={[Function]}
-    type="text"
-    value=""
-  />
-</div>
+      settings.pr_decoration.binding.form.gitlab.repository
+      <em
+        className="mandatory"
+      >
+        *
+      </em>
+    </label>
+    <input
+      className="input-super-large"
+      id="gitlab.repository"
+      maxLength={256}
+      name="gitlab.repository"
+      onChange={[Function]}
+      type="text"
+      value=""
+    />
+  </div>
+</Fragment>
 `;
 
 exports[`it should render correctly for gitlab and monorepo=true 1`] = `
-<div
-  className="form-field"
->
-  <label
-    className="display-flex-center"
-    htmlFor="gitlab.repository"
+<Fragment>
+  <div
+    className="form-field"
   >
-    settings.pr_decoration.binding.form.gitlab.repository
-    <em
-      className="mandatory"
+    <label
+      className="display-flex-center"
+      htmlFor="gitlab.repository"
     >
-      *
-    </em>
-  </label>
-  <input
-    className="input-super-large"
-    id="gitlab.repository"
-    maxLength={256}
-    name="gitlab.repository"
-    onChange={[Function]}
-    type="text"
-    value=""
-  />
-</div>
+      settings.pr_decoration.binding.form.gitlab.repository
+      <em
+        className="mandatory"
+      >
+        *
+      </em>
+    </label>
+    <input
+      className="input-super-large"
+      id="gitlab.repository"
+      maxLength={256}
+      name="gitlab.repository"
+      onChange={[Function]}
+      type="text"
+      value=""
+    />
+  </div>
+  <div
+    className="form-field"
+  >
+    <label
+      className="display-flex-center"
+      htmlFor="monorepo"
+    >
+      settings.pr_decoration.binding.form.monorepo
+      <HelpTooltip
+        className="spacer-left"
+        overlay={
+          <FormattedMessage
+            defaultMessage="settings.pr_decoration.binding.form.monorepo.help"
+            id="settings.pr_decoration.binding.form.monorepo.help"
+            values={
+              Object {
+                "doc_link": <Link
+                  onlyActiveOnIndex={false}
+                  style={Object {}}
+                  target="_blank"
+                  to="/documentation/analysis/gitlab-integration/"
+                >
+                  learn_more
+                </Link>,
+              }
+            }
+          />
+        }
+        placement="right"
+      />
+    </label>
+    <div
+      className="display-flex-center"
+    >
+      <InputForBoolean
+        isDefault={true}
+        name="monorepo"
+        onChange={[Function]}
+        value={false}
+      />
+    </div>
+  </div>
+</Fragment>
 `;
 
 exports[`should render an alert for azure when the monorepo option is activated 1`] = `
index c43527dccbd274d988e540dfe265a95868821899..bdc9b40712c00292eca6be42f9c399c8019992f8 100644 (file)
@@ -86,6 +86,7 @@ exports[`should render correctly: gitlab tutorial 1`] = `
       Object {
         "alm": "gitlab",
         "key": "foo",
+        "monorepo": true,
         "repository": "PROJECT_KEY",
         "url": "https://gitlab.com/api/v4",
       }
index a1f23453a5623ea2ba7f60befbffdbfa661cfdeb..5e48a2c263c08d69eebbca67b7368b0872fc0c0a 100644 (file)
@@ -131,6 +131,7 @@ export function mockProjectGitLabBindingResponse(
     key: 'foo',
     repository: 'PROJECT_KEY',
     url: 'https://gitlab.com/api/v4',
+    monorepo: true,
     ...overrides
   };
 }
index 08d1416635938a8ab03321248cf602414dcc2383..ce3c5a0cb90dc7ec0e5c1c4f82ae64da185dfa63 100644 (file)
@@ -86,6 +86,7 @@ export interface ProjectGitLabBindingResponse extends ProjectAlmBindingResponse
   alm: AlmKeys.GitLab;
   repository: string;
   url: string;
+  monorepo: boolean;
 }
 
 export interface ProjectAlmBindingParams {
@@ -113,6 +114,7 @@ export interface GithubProjectAlmBindingParams extends ProjectAlmBindingParams {
 
 export interface GitlabProjectAlmBindingParams extends ProjectAlmBindingParams {
   repository?: string;
+  monorepo: boolean;
 }
 
 export interface AlmSettingsInstance {