From 815cf53518e591b48b8af46f9840e4cc54c4bb65 Mon Sep 17 00:00:00 2001 From: Philippe Perrin Date: Fri, 9 Jun 2023 17:21:05 +0200 Subject: [PATCH] SONAR-19457 New code definition is made part of Bitbucket Cloud project onboarding --- .../src/main/js/api/alm-integrations.ts | 23 +- .../api/mocks/AlmIntegrationsServiceMock.ts | 2 + .../BitbucketCloudProjectCreate.tsx | 34 +-- .../BitbucketCloudProjectCreateRender.tsx | 3 - .../BitbucketCloudSearchForm.tsx | 197 ++++++++---------- .../apps/create/project/CreateProjectPage.tsx | 2 +- .../project/__tests__/BitbucketCloud-it.tsx | 24 ++- 7 files changed, 135 insertions(+), 150 deletions(-) diff --git a/server/sonar-web/src/main/js/api/alm-integrations.ts b/server/sonar-web/src/main/js/api/alm-integrations.ts index 7e81ff101ba..f33562053c0 100644 --- a/server/sonar-web/src/main/js/api/alm-integrations.ts +++ b/server/sonar-web/src/main/js/api/alm-integrations.ts @@ -173,14 +173,21 @@ export function getGithubClientId(almSetting: string): Promise<{ clientId?: stri return getJSON('/api/alm_integrations/get_github_client_id', { almSetting }); } -export function importBitbucketCloudRepository( - almSetting: string, - repositorySlug: string -): Promise<{ project: ProjectBase }> { - return postJSON('/api/alm_integrations/import_bitbucketcloud_repo', { - almSetting, - repositorySlug, - }).catch(throwGlobalError); +export function setupBitbucketCloudProjectCreation(data: { + almSetting: string; + repositorySlug: string; +}) { + return (newCodeDefinitionType?: string, newCodeDefinitionValue?: string) => + importBitbucketCloudRepository({ ...data, newCodeDefinitionType, newCodeDefinitionValue }); +} + +export function importBitbucketCloudRepository(data: { + almSetting: string; + repositorySlug: string; + newCodeDefinitionType?: string; + newCodeDefinitionValue?: string; +}): Promise<{ project: ProjectBase }> { + return postJSON('/api/alm_integrations/import_bitbucketcloud_repo', data).catch(throwGlobalError); } export function importGithubRepository( diff --git a/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts index 05a6d32f6b8..59c1c9b3011 100644 --- a/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts @@ -58,6 +58,7 @@ import { searchForBitbucketServerRepositories, setAlmPersonalAccessToken, setupAzureProjectCreation, + setupBitbucketCloudProjectCreation, setupBitbucketServerProjectCreation, } from '../alm-integrations'; @@ -187,6 +188,7 @@ export default class AlmIntegrationsServiceMock { jest.mocked(setAlmPersonalAccessToken).mockImplementation(this.setAlmPersonalAccessToken); jest.mocked(getGitlabProjects).mockImplementation(this.getGitlabProjects); jest.mocked(importGitlabProject).mockImplementation(this.importProject); + jest.mocked(setupBitbucketCloudProjectCreation).mockReturnValue(() => this.importProject()); jest.mocked(importBitbucketCloudRepository).mockImplementation(this.importProject); jest.mocked(getGithubClientId).mockImplementation(this.getGithubClientId); jest.mocked(getGithubOrganizations).mockImplementation(this.getGithubOrganizations); diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx index 41adf4c9baa..0a4a2baf20c 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx @@ -19,26 +19,26 @@ */ import * as React from 'react'; import { - importBitbucketCloudRepository, searchForBitbucketCloudRepositories, + setupBitbucketCloudProjectCreation, } from '../../../../api/alm-integrations'; import { Location, Router } from '../../../../components/hoc/withRouter'; import { BitbucketCloudRepository } from '../../../../types/alm-integration'; import { AlmSettingsInstance } from '../../../../types/alm-settings'; import { Paging } from '../../../../types/types'; +import { CreateProjectApiCallback } from '../types'; import BitbucketCloudProjectCreateRenderer from './BitbucketCloudProjectCreateRender'; interface Props { canAdmin: boolean; almInstances: AlmSettingsInstance[]; loadingBindings: boolean; - onProjectCreate: (projectKey: string) => void; location: Location; router: Router; + onProjectSetupDone: (createProject: CreateProjectApiCallback) => void; } interface State { - importingSlug?: string; isLastPage?: boolean; loading: boolean; loadingMore: boolean; @@ -189,26 +189,16 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent { + handleImport = (repositorySlug: string) => { const { selectedAlmInstance } = this.state; - if (!selectedAlmInstance) { - return; - } - - this.setState({ importingSlug: repositorySlug }); - - const result = await importBitbucketCloudRepository( - selectedAlmInstance.key, - repositorySlug - ).catch(() => undefined); - - if (this.mounted) { - this.setState({ importingSlug: undefined }); - - if (result) { - this.props.onProjectCreate(result.project.key); - } + if (selectedAlmInstance) { + this.props.onProjectSetupDone( + setupBitbucketCloudProjectCreation({ + almSetting: selectedAlmInstance.key, + repositorySlug, + }) + ); } }; @@ -226,7 +216,6 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent ) : ( void; @@ -53,14 +51,7 @@ function getRepositoryUrl(workspace: string, slug: string) { } export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchFormProps) { - const { - importingSlug, - isLastPage, - loadingMore, - repositories = [], - searching, - searchQuery, - } = props; + const { isLastPage, loadingMore, repositories = [], searching, searchQuery } = props; if (repositories.length === 0 && searchQuery.length === 0 && !searching) { return ( @@ -86,109 +77,101 @@ export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchForm } return ( - <> - -
- +
+ -
+
- {repositories.length === 0 ? ( -
{translate('no_results')}
- ) : ( - - - {repositories.map((repository) => ( - + {repositories.length === 0 ? ( +
{translate('no_results')}
+ ) : ( +
+ + {repositories.map((repository) => ( + + + + {repository.sqProjectKey ? ( - - {repository.sqProjectKey ? ( - - ) : ( - - )} - - ))} - -
+ + + {repository.sqProjectKey ? ( + + + {repository.name} + + ) : ( + repository.name + )} + + +
+ + + {repository.projectKey} + + +
+ + {translate('onboarding.create_project.bitbucketcloud.link')} + + - - - {repository.sqProjectKey ? ( - - - {repository.name} - - ) : ( - repository.name - )} - - -
- - - {repository.projectKey} - - + + + {translate('onboarding.create_project.repository_imported')} +
- + - - - {translate('onboarding.create_project.repository_imported')} - - - -
- )} -
- {isLastPage && - translateWithParameters( - 'x_of_y_shown', - formatMeasure(repositories.length, MetricType.Integer, null), - formatMeasure(repositories.length, MetricType.Integer, null) - )} - {!isLastPage && ( - + )} + + ))} + + + )} +
+ {isLastPage && + translateWithParameters( + 'x_of_y_shown', + formatMeasure(repositories.length, MetricType.Integer, null), + formatMeasure(repositories.length, MetricType.Integer, null) )} - -
-
- + {!isLastPage && ( + + )} + + +
); } diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx index 2f0734b6481..fe3e7e1dda0 100644 --- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx @@ -231,7 +231,7 @@ export class CreateProjectPage extends React.PureComponent diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx index ee4792f5d19..376024a2e44 100644 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx @@ -124,9 +124,7 @@ it('should show import project feature when PAT is already set', async () => { expect(screen.getByText('BitbucketCloud Repo 1')).toBeInTheDocument(); expect(screen.getByText('BitbucketCloud Repo 2')).toBeInTheDocument(); - projectItem = screen.getByRole('row', { - name: 'qualifier.TRK BitbucketCloud Repo 1 project opens_in_new_window onboarding.create_project.bitbucketcloud.link onboarding.create_project.repository_imported', - }); + projectItem = screen.getByRole('row', { name: /BitbucketCloud Repo 1/ }); expect( within(projectItem).getByText('onboarding.create_project.repository_imported') ).toBeInTheDocument(); @@ -139,14 +137,24 @@ it('should show import project feature when PAT is already set', async () => { '/dashboard?id=key' ); - projectItem = screen.getByRole('row', { - name: 'BitbucketCloud Repo 2 project opens_in_new_window onboarding.create_project.bitbucketcloud.link onboarding.create_project.set_up', - }); - const importProjectButton = within(projectItem).getByRole('button', { + projectItem = screen.getByRole('row', { name: /BitbucketCloud Repo 2/ }); + const setupButton = within(projectItem).getByRole('button', { name: 'onboarding.create_project.set_up', }); - await user.click(importProjectButton); + await user.click(setupButton); + + expect( + screen.getByRole('heading', { name: 'onboarding.create_project.new_code_definition.title' }) + ).toBeInTheDocument(); + + await user.click(screen.getByRole('radio', { name: 'new_code_definition.global_setting' })); + await user.click( + screen.getByRole('button', { + name: 'onboarding.create_project.new_code_definition.create_project', + }) + ); + expect(await screen.findByText('/dashboard?id=key')).toBeInTheDocument(); }); -- 2.39.5