From cae72b1b49abfc394f56e0b5b8df860b669c6083 Mon Sep 17 00:00:00 2001 From: Kevin Silva Date: Wed, 7 Dec 2022 14:51:33 +0100 Subject: [PATCH] SONAR-17740 Add RTL test for 'project/create' bitbucket and gitlab pages and remove the enzyme tests --- .../api/mocks/AlmIntegrationsServiceMock.ts | 209 +++- .../js/api/mocks/AlmSettingsServiceMock.ts | 22 +- .../project/AzurePersonalAccessTokenForm.tsx | 2 +- .../create/project/ManualProjectCreate.tsx | 4 +- .../project/PersonalAccessTokenForm.tsx | 8 +- .../create/project/__tests__/Azure-it.tsx | 133 +++ .../create/project/__tests__/Bitbucket-it.tsx | 162 +++ .../project/__tests__/BitbucketCloud-it.tsx | 212 ++++ .../BitbucketCloudProjectCreate-test.tsx | 181 ---- ...BitbucketCloudProjectCreateRender-test.tsx | 58 -- .../BitbucketCloudSearchForm-test.tsx | 83 -- .../BitbucketImportRepositoryForm-test.tsx | 71 -- .../BitbucketProjectAccordion-test.tsx | 72 -- .../__tests__/BitbucketProjectCreate-test.tsx | 155 --- .../BitbucketProjectCreateRenderer-test.tsx | 67 -- .../__tests__/BitbucketRepositories-test.tsx | 65 -- .../__tests__/BitbucketSearchResults-test.tsx | 55 - .../project/__tests__/CreateProject-it.tsx | 215 ---- .../CreateProjectModeSelection-test.tsx | 159 --- .../__tests__/CreateProjectPage-test.tsx | 116 --- .../create/project/__tests__/GitHub-it.tsx | 86 ++ .../create/project/__tests__/GitLab-it.tsx | 177 ++++ .../__tests__/GitlabProjectCreate-test.tsx | 211 ---- .../GitlabProjectCreateRenderer-test.tsx | 66 -- .../GitlabProjectSelectionForm-test.tsx | 98 -- .../PersonalAccessTokenForm-test.tsx | 144 --- .../__tests__/WrongBindingCountAlert-test.tsx | 35 - .../BitbucketCloudProjectCreate-test.tsx.snap | 54 - ...cketCloudProjectCreateRender-test.tsx.snap | 173 ---- .../BitbucketCloudSearchForm-test.tsx.snap | 482 --------- ...itbucketImportRepositoryForm-test.tsx.snap | 148 --- .../BitbucketProjectAccordion-test.tsx.snap | 455 -------- .../BitbucketProjectCreate-test.tsx.snap | 92 -- ...tbucketProjectCreateRenderer-test.tsx.snap | 477 --------- .../BitbucketRepositories-test.tsx.snap | 248 ----- .../BitbucketSearchResults-test.tsx.snap | 106 -- .../CreateProjectModeSelection-test.tsx.snap | 972 ------------------ .../CreateProjectPage-test.tsx.snap | 355 ------- .../GitlabProjectCreate-test.tsx.snap | 39 - .../GitlabProjectCreateRenderer-test.tsx.snap | 247 ----- .../GitlabProjectSelectionForm-test.tsx.snap | 340 ------ .../PersonalAccessTokenForm-test.tsx.snap | 679 ------------ .../WrongBindingCountAlert-test.tsx.snap | 59 -- .../components/BaselineSettingDays.tsx | 2 +- .../BaselineSettingDays-test.tsx.snap | 6 +- .../home/CreateProfileForm.tsx | 6 +- .../js/components/common/ProjectKeyInput.tsx | 2 +- .../ProjectKeyInput-test.tsx.snap | 14 +- .../components/controls/ValidationInput.tsx | 8 +- .../__tests__/ValidationInput-test.tsx | 4 +- 50 files changed, 1001 insertions(+), 6833 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/Azure-it.tsx create mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx create mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudSearchForm-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketImportRepositoryForm-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectAccordion-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketRepositories-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketSearchResults-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProject-it.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx create mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx create mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreate-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreateRenderer-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectSelectionForm-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/PersonalAccessTokenForm-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/WrongBindingCountAlert-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudSearchForm-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketRepositories-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketSearchResults-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreate-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreateRenderer-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectSelectionForm-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/PersonalAccessTokenForm-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/WrongBindingCountAlert-test.tsx.snap 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 3ab27ae48af..1a3f06b3f5e 100644 --- a/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts @@ -17,31 +17,53 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { cloneDeep } from 'lodash'; +import { cloneDeep, uniqueId } from 'lodash'; import { mockAzureProject, mockAzureRepository, + mockBitbucketCloudRepository, + mockBitbucketProject, + mockBitbucketRepository, mockGitlabProject, } from '../../helpers/mocks/alm-integrations'; -import { AzureProject, AzureRepository, GitlabProject } from '../../types/alm-integration'; +import { + AzureProject, + AzureRepository, + BitbucketCloudRepository, + BitbucketProject, + BitbucketRepository, + GitlabProject, +} from '../../types/alm-integration'; +import { Visibility } from '../../types/component'; import { checkPersonalAccessTokenIsValid, getAzureProjects, getAzureRepositories, + getBitbucketServerProjects, + getBitbucketServerRepositories, getGithubClientId, getGithubOrganizations, getGitlabProjects, importAzureRepository, + importBitbucketCloudRepository, + importBitbucketServerProject, + importGitlabProject, searchAzureRepositories, + searchForBitbucketCloudRepositories, + searchForBitbucketServerRepositories, setAlmPersonalAccessToken, } from '../alm-integrations'; -import { ProjectBase } from '../components'; export default class AlmIntegrationsServiceMock { almInstancePATMap: { [key: string]: boolean } = {}; gitlabProjects: GitlabProject[]; azureProjects: AzureProject[]; azureRepositories: AzureRepository[]; + gitlabPagination; + bitbucketCloudRepositories: BitbucketCloudRepository[]; + bitbucketIsLastPage: boolean; + bitbucketRepositories: BitbucketRepository[]; + bitbucketProjects: BitbucketProject[]; defaultAlmInstancePATMap: { [key: string]: boolean } = { 'conf-final-1': false, 'conf-final-2': true, @@ -49,7 +71,10 @@ export default class AlmIntegrationsServiceMock { 'conf-github-2': true, 'conf-azure-1': false, 'conf-azure-2': true, - 'config-reject': false, + 'conf-bitbucketcloud-1': false, + 'conf-bitbucketcloud-2': true, + 'conf-bitbucketserver-1': false, + 'conf-bitbucketserver-2': true, }; defaultGitlabProjects: GitlabProject[] = [ @@ -63,11 +88,51 @@ export default class AlmIntegrationsServiceMock { mockGitlabProject({ name: 'Gitlab project 3', id: '3' }), ]; + defaultGitlabPagination = { + pageIndex: 1, + pageSize: 30, + total: this.defaultGitlabProjects.length, + }; + defaultAzureProjects: AzureProject[] = [ mockAzureProject({ name: 'Azure project', description: 'Description project 1' }), mockAzureProject({ name: 'Azure project 2', description: 'Description project 2' }), ]; + defaultBitbucketCloudRepositories: BitbucketCloudRepository[] = [ + mockBitbucketCloudRepository({ + uuid: 1000, + name: 'BitbucketCloud Repo 1', + slug: 'bitbucketcloud_repo_1', + sqProjectKey: 'key', + }), + mockBitbucketCloudRepository({ + uuid: 10001, + name: 'BitbucketCloud Repo 2', + slug: 'bitbucketcloud_repo_2', + }), + ]; + + defaultBitbucketRepositories: BitbucketRepository[] = [ + mockBitbucketRepository({ + name: 'Bitbucket Repo 1', + slug: 'bitbucket_repo_1', + projectKey: 'bitbucket_project_1', + sqProjectKey: 'key', + }), + mockBitbucketRepository({ + id: 2, + name: 'Bitbucket Repo 2', + slug: 'bitbucket_repo_2', + projectKey: 'bitbucket_project_1', + }), + ]; + + defaultBitbucketProjects: BitbucketProject[] = [ + mockBitbucketProject({ name: 'Bitbucket Project 1', key: 'bitbucket_project_1' }), + mockBitbucketProject({ name: 'Bitbucket Project 2', key: 'bitbucket_project_2' }), + ]; + defaultAzureRepositories: AzureRepository[] = [ mockAzureRepository({ sqProjectKey: 'random' }), mockAzureRepository({ name: 'Azure repo 2' }), @@ -89,20 +154,38 @@ export default class AlmIntegrationsServiceMock { constructor() { this.almInstancePATMap = cloneDeep(this.defaultAlmInstancePATMap); - this.gitlabProjects = cloneDeep(this.defaultGitlabProjects); this.azureProjects = cloneDeep(this.defaultAzureProjects); this.azureRepositories = cloneDeep(this.defaultAzureRepositories); - (checkPersonalAccessTokenIsValid as jest.Mock).mockImplementation( - this.checkPersonalAccessTokenIsValid - ); - (setAlmPersonalAccessToken as jest.Mock).mockImplementation(this.setAlmPersonalAccessToken); - (getGitlabProjects as jest.Mock).mockImplementation(this.getGitlabProjects); - (getGithubClientId as jest.Mock).mockImplementation(this.getGithubClientId); - (getGithubOrganizations as jest.Mock).mockImplementation(this.getGithubOrganizations); - (getAzureProjects as jest.Mock).mockImplementation(this.getAzureProjects); - (getAzureRepositories as jest.Mock).mockImplementation(this.getAzureRepositories); - (searchAzureRepositories as jest.Mock).mockImplementation(this.searchAzureRepositories); - (importAzureRepository as jest.Mock).mockImplementation(this.importAzureRepository); + this.bitbucketCloudRepositories = cloneDeep(this.defaultBitbucketCloudRepositories); + this.gitlabProjects = cloneDeep(this.defaultGitlabProjects); + this.gitlabPagination = cloneDeep(this.defaultGitlabPagination); + this.bitbucketRepositories = cloneDeep(this.defaultBitbucketRepositories); + this.bitbucketProjects = cloneDeep(this.defaultBitbucketProjects); + this.bitbucketIsLastPage = true; + jest + .mocked(checkPersonalAccessTokenIsValid) + .mockImplementation(this.checkPersonalAccessTokenIsValid); + jest.mocked(setAlmPersonalAccessToken).mockImplementation(this.setAlmPersonalAccessToken); + jest.mocked(getGitlabProjects).mockImplementation(this.getGitlabProjects); + jest.mocked(importGitlabProject).mockImplementation(this.importProject); + jest.mocked(importBitbucketCloudRepository).mockImplementation(this.importProject); + jest.mocked(getGithubClientId).mockImplementation(this.getGithubClientId); + jest.mocked(getGithubOrganizations).mockImplementation(this.getGithubOrganizations); + jest.mocked(getAzureProjects).mockImplementation(this.getAzureProjects); + jest.mocked(getAzureRepositories).mockImplementation(this.getAzureRepositories); + jest.mocked(searchAzureRepositories).mockImplementation(this.searchAzureRepositories); + jest.mocked(importAzureRepository).mockImplementation(this.importAzureRepository); + jest + .mocked(searchForBitbucketCloudRepositories) + .mockImplementation(this.searchForBitbucketCloudRepositories); + jest.mocked(getBitbucketServerProjects).mockImplementation(this.getBitbucketServerProjects); + jest + .mocked(getBitbucketServerRepositories) + .mockImplementation(this.getBitbucketServerRepositories); + jest.mocked(importBitbucketServerProject).mockImplementation(this.importBitbucketServerProject); + jest + .mocked(searchForBitbucketServerRepositories) + .mockImplementation(this.searchForBitbucketServerRepositories); } checkPersonalAccessTokenIsValid = (conf: string) => { @@ -114,17 +197,17 @@ export default class AlmIntegrationsServiceMock { return Promise.resolve(); }; - getAzureProjects = (): Promise<{ projects: AzureProject[] }> => { + getAzureProjects = () => { return Promise.resolve({ projects: this.azureProjects }); }; - getAzureRepositories = (): Promise<{ repositories: AzureRepository[] }> => { + getAzureRepositories = () => { return Promise.resolve({ repositories: this.azureRepositories, }); }; - searchAzureRepositories = (): Promise<{ repositories: AzureRepository[] }> => { + searchAzureRepositories = () => { return Promise.resolve({ repositories: this.azureRepositories, }); @@ -134,32 +217,66 @@ export default class AlmIntegrationsServiceMock { this.azureRepositories = azureRepositories; }; - importAzureRepository = (): Promise<{ project: ProjectBase }> => { + importAzureRepository = () => { return Promise.resolve({ project: { key: 'key', name: 'name', qualifier: 'qualifier', - visibility: 'private', + visibility: Visibility.Private, }, }); }; - setAzureProjects = (azureProjects: AzureProject[]) => { - this.azureProjects = azureProjects; + searchForBitbucketCloudRepositories = () => { + return Promise.resolve({ + isLastPage: this.bitbucketIsLastPage, + repositories: this.bitbucketCloudRepositories, + }); }; + setBitbucketCloudRepositories(bitbucketCloudRepositories: BitbucketCloudRepository[]) { + this.bitbucketCloudRepositories = bitbucketCloudRepositories; + } + getGitlabProjects = () => { return Promise.resolve({ projects: this.gitlabProjects, - projectsPaging: { - pageIndex: 1, - pageSize: 30, - total: this.gitlabProjects.length, + projectsPaging: this.gitlabPagination, + }); + }; + + importProject = () => { + return Promise.resolve({ + project: { + key: 'key', + name: 'name', + qualifier: 'qualifier', + visibility: Visibility.Private, }, }); }; + createRandomGitlabProjectsWithLoadMore(quantity: number, total: number) { + const generatedProjects = Array.from(Array(quantity).keys()).map((index) => { + return mockGitlabProject({ name: `Gitlab project ${index}`, id: uniqueId() }); + }); + this.gitlabProjects = generatedProjects; + this.gitlabPagination = { ...this.defaultGitlabPagination, total }; + } + + createRandomBitbucketCloudProjectsWithLoadMore(quantity: number, total: number) { + const generatedRepositories = Array.from(Array(quantity).keys()).map((index) => { + return mockBitbucketCloudRepository({ + name: `Gitlab project ${index}`, + uuid: Math.floor(Math.random() * 100000), + }); + }); + + this.bitbucketCloudRepositories = generatedRepositories; + this.bitbucketIsLastPage = quantity >= total; + } + setGitlabProjects(gitlabProjects: GitlabProject[]) { this.gitlabProjects = gitlabProjects; } @@ -172,9 +289,47 @@ export default class AlmIntegrationsServiceMock { return Promise.resolve(this.defaultOrganizations); }; + getBitbucketServerProjects = () => { + return Promise.resolve({ projects: this.bitbucketProjects }); + }; + + getBitbucketServerRepositories = () => { + return Promise.resolve({ + isLastPage: this.bitbucketIsLastPage, + repositories: this.bitbucketRepositories, + }); + }; + + setBitbucketServerProjects = (bitbucketProjects: BitbucketProject[]) => { + this.bitbucketProjects = bitbucketProjects; + }; + + importBitbucketServerProject = () => { + return Promise.resolve({ + project: { + key: 'key', + name: 'name', + qualifier: 'qualifier', + visibility: Visibility.Private, + }, + }); + }; + + searchForBitbucketServerRepositories = () => { + return Promise.resolve({ + isLastPage: this.bitbucketIsLastPage, + repositories: this.bitbucketRepositories, + }); + }; + reset = () => { this.almInstancePATMap = cloneDeep(this.defaultAlmInstancePATMap); this.gitlabProjects = cloneDeep(this.defaultGitlabProjects); this.azureRepositories = cloneDeep(this.defaultAzureRepositories); + this.gitlabPagination = cloneDeep(this.defaultGitlabPagination); + this.bitbucketCloudRepositories = cloneDeep(this.defaultBitbucketCloudRepositories); + this.bitbucketRepositories = cloneDeep(this.defaultBitbucketRepositories); + this.bitbucketProjects = cloneDeep(this.defaultBitbucketProjects); + this.bitbucketIsLastPage = true; }; } diff --git a/server/sonar-web/src/main/js/api/mocks/AlmSettingsServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/AlmSettingsServiceMock.ts index c5e32cb41f0..ea2f1f01f8b 100644 --- a/server/sonar-web/src/main/js/api/mocks/AlmSettingsServiceMock.ts +++ b/server/sonar-web/src/main/js/api/mocks/AlmSettingsServiceMock.ts @@ -31,11 +31,31 @@ export default class AlmSettingsServiceMock { mockAlmSettingsInstance({ key: 'conf-github-2', alm: AlmKeys.GitHub, url: 'url' }), mockAlmSettingsInstance({ key: 'conf-azure-1', alm: AlmKeys.Azure, url: 'url' }), mockAlmSettingsInstance({ key: 'conf-azure-2', alm: AlmKeys.Azure, url: 'url' }), + mockAlmSettingsInstance({ + key: 'conf-bitbucketcloud-1', + alm: AlmKeys.BitbucketCloud, + url: 'url', + }), + mockAlmSettingsInstance({ + key: 'conf-bitbucketcloud-2', + alm: AlmKeys.BitbucketCloud, + url: 'url', + }), + mockAlmSettingsInstance({ + key: 'conf-bitbucketserver-1', + alm: AlmKeys.BitbucketServer, + url: 'url', + }), + mockAlmSettingsInstance({ + key: 'conf-bitbucketserver-2', + alm: AlmKeys.BitbucketServer, + url: 'url', + }), ]; constructor() { this.almSettings = cloneDeep(this.defaultSetting); - (getAlmSettings as jest.Mock).mockImplementation(this.getAlmSettingsHandler); + jest.mocked(getAlmSettings).mockImplementation(this.getAlmSettingsHandler); } getAlmSettingsHandler = () => { diff --git a/server/sonar-web/src/main/js/apps/create/project/AzurePersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/AzurePersonalAccessTokenForm.tsx index 1de8de0ac52..c38dd39c971 100644 --- a/server/sonar-web/src/main/js/apps/create/project/AzurePersonalAccessTokenForm.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/AzurePersonalAccessTokenForm.tsx @@ -95,7 +95,7 @@ export default function AzurePersonalAccessTokenForm(props: AzurePersonalAccessT > } error={mainBranchNameError} - id="main-branch-name" + labelHtmlFor="main-branch-name" isInvalid={mainBranchNameIsInvalid} isValid={mainBranchNameIsValid} label={translate('onboarding.create_project.main_branch_name')} diff --git a/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx index d3b501776c0..14258e02b1c 100644 --- a/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx @@ -355,7 +355,7 @@ export default class PersonalAccessTokenForm extends React.PureComponent { + almIntegrationHandler = new AlmIntegrationsServiceMock(); + almSettingsHandler = new AlmSettingsServiceMock(); +}); + +beforeEach(() => { + jest.clearAllMocks(); + almIntegrationHandler.reset(); + almSettingsHandler.reset(); +}); + +it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => { + const user = userEvent.setup(); + renderCreateProject(); + expect(ui.azureCreateProjectButton.get()).toBeInTheDocument(); + + await user.click(ui.azureCreateProjectButton.get()); + + expect(screen.getByText('onboarding.create_project.azure.title')).toBeInTheDocument(); + expect(screen.getByText('alm.configuration.selector.label.alm.azure.long')).toBeInTheDocument(); + + expect(screen.getByText('onboarding.create_project.enter_pat')).toBeInTheDocument(); + expect(screen.getByText('onboarding.create_project.pat_form.title.azure')).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: 'onboarding.create_project.pat_form.list_repositories' }) + ).toBeInTheDocument(); + + await user.click(ui.personalAccessTokenInput.get()); + await user.keyboard('secret'); + await user.click( + screen.getByRole('button', { name: 'onboarding.create_project.pat_form.list_repositories' }) + ); + + expect(screen.getByText('Azure project')).toBeInTheDocument(); + expect(screen.getByText('Azure project 2')).toBeInTheDocument(); + // eslint-disable-next-line jest-dom/prefer-in-document + expect(screen.getAllByText('onboarding.create_project.repository_imported')).toHaveLength(1); +}); + +it('should show import project feature when PAT is already set', async () => { + const user = userEvent.setup(); + renderCreateProject(); + + await act(async () => { + await user.click(ui.azureCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-azure-2/]); + }); + + expect(screen.getByText('Azure project 2')).toBeInTheDocument(); + const importButton = screen.getByText('onboarding.create_project.import_selected_repo'); + const radioButton = screen.getByRole('radio', { name: 'Azure repo 2' }); + + expect(radioButton).toBeInTheDocument(); + expect(importButton).toBeDisabled(); + await user.click(radioButton); + expect(importButton).toBeEnabled(); + await user.click(importButton); + + expect(await screen.findByText('/dashboard?id=key')).toBeInTheDocument(); +}); + +it('should show search filter when PAT is already set', async () => { + const user = userEvent.setup(); + renderCreateProject(); + + await act(async () => { + await user.click(ui.azureCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-azure-2/]); + }); + + // Should search with positive results + const inputSearch = screen.getByPlaceholderText( + 'onboarding.create_project.search_projects_repositories' + ); + await user.click(inputSearch); + await user.keyboard('s'); + + expect(searchAzureRepositories).toHaveBeenCalledWith('conf-azure-2', 's'); + + // Should search with empty results + almIntegrationHandler.setSearchAzureRepositories([]); + await user.keyboard('f'); + expect(screen.getByRole('alert')).toHaveTextContent('onboarding.create_project.azure.no_results'); +}); + +function renderCreateProject(props: Partial = {}) { + renderApp('project/create', ); +} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx new file mode 100644 index 00000000000..9c460d8f324 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx @@ -0,0 +1,162 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { act, screen, within } from '@testing-library/react'; + +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import selectEvent from 'react-select-event'; +import { byLabelText, byRole, byText } from 'testing-library-selector'; +import { searchForBitbucketServerRepositories } from '../../../../api/alm-integrations'; +import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock'; +import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock'; +import { renderApp } from '../../../../helpers/testReactTestingUtils'; +import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage'; + +jest.mock('../../../../api/alm-integrations'); +jest.mock('../../../../api/alm-settings'); + +let almIntegrationHandler: AlmIntegrationsServiceMock; +let almSettingsHandler: AlmSettingsServiceMock; + +const ui = { + bitbucketServerCreateProjectButton: byText('onboarding.create_project.select_method.bitbucket'), + personalAccessTokenInput: byRole('textbox', { + name: /onboarding.create_project.enter_pat/, + }), + instanceSelector: byLabelText(/alm.configuration.selector.label/), +}; + +beforeAll(() => { + almIntegrationHandler = new AlmIntegrationsServiceMock(); + almSettingsHandler = new AlmSettingsServiceMock(); +}); + +beforeEach(() => { + jest.clearAllMocks(); + almIntegrationHandler.reset(); + almSettingsHandler.reset(); +}); + +it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => { + const user = userEvent.setup(); + renderCreateProject(); + expect(ui.bitbucketServerCreateProjectButton.get()).toBeInTheDocument(); + + await user.click(ui.bitbucketServerCreateProjectButton.get()); + expect(screen.getByText('onboarding.create_project.from_bbs')).toBeInTheDocument(); + expect(ui.instanceSelector.get()).toBeInTheDocument(); + + expect( + screen.getByText('onboarding.create_project.pat_form.title.bitbucket') + ).toBeInTheDocument(); + + expect(screen.getByRole('button', { name: 'save' })).toBeDisabled(); + + await user.click( + screen.getByRole('textbox', { + name: /onboarding.create_project.enter_pat/, + }) + ); + + await user.keyboard('password'); + + expect(screen.getByRole('button', { name: 'save' })).toBeEnabled(); + await user.click(screen.getByRole('button', { name: 'save' })); + + expect(screen.getByText('Bitbucket Project 1')).toBeInTheDocument(); + expect(screen.getByText('Bitbucket Project 2')).toBeInTheDocument(); +}); + +it('should show import project feature when PAT is already set', async () => { + const user = userEvent.setup(); + renderCreateProject(); + await act(async () => { + await user.click(ui.bitbucketServerCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketserver-2/]); + }); + + expect(screen.getByText('Bitbucket Project 1')).toBeInTheDocument(); + + await user.click(screen.getByRole('button', { name: 'expand_all' })); + + expect(screen.getByRole('button', { name: 'collapse_all' })).toBeInTheDocument(); + + const projectItem = screen.getByRole('region', { name: /Bitbucket Project 1/ }); + + expect( + within(projectItem).getByText('onboarding.create_project.repository_imported') + ).toBeInTheDocument(); + + expect(within(projectItem).getByRole('link', { name: /Bitbucket Repo 1/ })).toBeInTheDocument(); + expect(within(projectItem).getByRole('link', { name: /Bitbucket Repo 1/ })).toHaveAttribute( + 'href', + '/dashboard?id=key' + ); + + await user.click(projectItem); + const radioButton = within(projectItem).getByRole('radio', { + name: 'Bitbucket Repo 2', + }); + const importButton = screen.getByText('onboarding.create_project.import_selected_repo'); + + expect(radioButton).toBeInTheDocument(); + expect(importButton).toBeDisabled(); + await user.click(radioButton); + expect(importButton).toBeEnabled(); + await user.click(importButton); + expect(await screen.findByText('/dashboard?id=key')).toBeInTheDocument(); +}); + +it('should show search filter when PAT is already set', async () => { + const user = userEvent.setup(); + renderCreateProject(); + + await act(async () => { + await user.click(ui.bitbucketServerCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketserver-2/]); + }); + + const inputSearch = screen.getByRole('searchbox', { + name: 'search_verb', + }); + await user.click(inputSearch); + await user.keyboard('search'); + + expect(searchForBitbucketServerRepositories).toHaveBeenLastCalledWith( + 'conf-bitbucketserver-2', + 'search' + ); +}); + +it('should show no result message when there are no projects', async () => { + const user = userEvent.setup(); + almIntegrationHandler.setBitbucketServerProjects([]); + renderCreateProject(); + await act(async () => { + await user.click(ui.bitbucketServerCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketserver-2/]); + }); + + expect(screen.getByRole('alert')).toHaveTextContent('onboarding.create_project.no_bbs_projects'); +}); + +function renderCreateProject(props: Partial = {}) { + renderApp('project/create', ); +} 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 new file mode 100644 index 00000000000..1398e60f657 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx @@ -0,0 +1,212 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { act, screen, within } from '@testing-library/react'; + +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import selectEvent from 'react-select-event'; +import { byLabelText, byRole, byText } from 'testing-library-selector'; +import { searchForBitbucketCloudRepositories } from '../../../../api/alm-integrations'; +import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock'; +import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock'; +import { renderApp } from '../../../../helpers/testReactTestingUtils'; +import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage'; + +jest.mock('../../../../api/alm-integrations'); +jest.mock('../../../../api/alm-settings'); + +let almIntegrationHandler: AlmIntegrationsServiceMock; +let almSettingsHandler: AlmSettingsServiceMock; + +const ui = { + bitbucketCloudCreateProjectButton: byText( + 'onboarding.create_project.select_method.bitbucketcloud' + ), + personalAccessTokenInput: byRole('textbox', { + name: /onboarding.create_project.enter_pat/, + }), + instanceSelector: byLabelText(/alm.configuration.selector.label/), +}; + +beforeAll(() => { + almIntegrationHandler = new AlmIntegrationsServiceMock(); + almSettingsHandler = new AlmSettingsServiceMock(); +}); + +beforeEach(() => { + jest.clearAllMocks(); + almIntegrationHandler.reset(); + almSettingsHandler.reset(); +}); + +it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => { + const user = userEvent.setup(); + renderCreateProject(); + expect(ui.bitbucketCloudCreateProjectButton.get()).toBeInTheDocument(); + + await user.click(ui.bitbucketCloudCreateProjectButton.get()); + expect( + screen.getByRole('heading', { name: 'onboarding.create_project.bitbucketcloud.title' }) + ).toBeInTheDocument(); + expect(ui.instanceSelector.get()).toBeInTheDocument(); + + expect( + screen.getByText('onboarding.create_project.enter_pat.bitbucketcloud') + ).toBeInTheDocument(); + expect( + screen.getByText( + 'onboarding.create_project.pat_help.instructions_username.bitbucketcloud.title' + ) + ).toBeInTheDocument(); + + expect(screen.getByRole('button', { name: 'save' })).toBeDisabled(); + + await user.click( + screen.getByRole('textbox', { + name: /onboarding.create_project.enter_username/, + }) + ); + + await user.keyboard('username'); + + await user.click( + screen.getByRole('textbox', { + name: /onboarding.create_project.enter_pat.bitbucketcloud/, + }) + ); + + await user.keyboard('password'); + + expect(screen.getByRole('button', { name: 'save' })).toBeEnabled(); + await user.click(screen.getByRole('button', { name: 'save' })); + + expect(screen.getByText('BitbucketCloud Repo 1')).toBeInTheDocument(); + expect(screen.getByText('BitbucketCloud Repo 2')).toBeInTheDocument(); +}); + +it('should show import project feature when PAT is already set', async () => { + const user = userEvent.setup(); + let projectItem; + renderCreateProject(); + await act(async () => { + await user.click(ui.bitbucketCloudCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketcloud-2/]); + }); + + expect(screen.getByText('BitbucketCloud Repo 1')).toBeInTheDocument(); + expect(screen.getByText('BitbucketCloud Repo 2')).toBeInTheDocument(); + + projectItem = screen.getByRole('row', { name: /BitbucketCloud Repo 1/ }); + expect( + within(projectItem).getByText('onboarding.create_project.repository_imported') + ).toBeInTheDocument(); + + expect( + within(projectItem).getByRole('link', { name: /BitbucketCloud Repo 1/ }) + ).toBeInTheDocument(); + expect(within(projectItem).getByRole('link', { name: /BitbucketCloud Repo 1/ })).toHaveAttribute( + 'href', + '/dashboard?id=key' + ); + + projectItem = screen.getByRole('row', { name: /BitbucketCloud Repo 2/ }); + const importProjectButton = within(projectItem).getByRole('button', { + name: 'onboarding.create_project.set_up', + }); + + await user.click(importProjectButton); + expect(await screen.findByText('/dashboard?id=key')).toBeInTheDocument(); +}); + +it('should show search filter when PAT is already set', async () => { + const user = userEvent.setup(); + renderCreateProject(); + + await act(async () => { + await user.click(ui.bitbucketCloudCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketcloud-2/]); + }); + + expect(searchForBitbucketCloudRepositories).toHaveBeenLastCalledWith( + 'conf-bitbucketcloud-2', + '', + 30, + 1 + ); + + const inputSearch = screen.getByRole('searchbox', { + name: 'search_verb', + }); + await user.click(inputSearch); + await user.keyboard('search'); + + expect(searchForBitbucketCloudRepositories).toHaveBeenLastCalledWith( + 'conf-bitbucketcloud-2', + 'search', + 30, + 1 + ); +}); + +it('should show no result message when there are no projects', async () => { + const user = userEvent.setup(); + almIntegrationHandler.setBitbucketCloudRepositories([]); + renderCreateProject(); + await act(async () => { + await user.click(ui.bitbucketCloudCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketcloud-2/]); + }); + + expect(screen.getByRole('alert')).toHaveTextContent( + 'onboarding.create_project.bitbucketcloud.no_projects' + ); +}); + +it('should have load more', async () => { + const user = userEvent.setup(); + almIntegrationHandler.createRandomBitbucketCloudProjectsWithLoadMore(2, 4); + renderCreateProject(); + await act(async () => { + await user.click(ui.bitbucketCloudCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-bitbucketcloud-2/]); + }); + + const loadMore = screen.getByRole('button', { name: 'show_more' }); + expect(loadMore).toBeInTheDocument(); + + /* + * Next api call response will simulate reaching the last page so we can test the + * loadmore button disapperance. + */ + almIntegrationHandler.createRandomBitbucketCloudProjectsWithLoadMore(4, 4); + await user.click(loadMore); + + expect(searchForBitbucketCloudRepositories).toHaveBeenLastCalledWith( + 'conf-bitbucketcloud-2', + '', + 30, + 2 + ); + expect(loadMore).not.toBeInTheDocument(); +}); + +function renderCreateProject(props: Partial = {}) { + renderApp('project/create', ); +} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx deleted file mode 100644 index 4aee42212ca..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreate-test.tsx +++ /dev/null @@ -1,181 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { - importBitbucketCloudRepository, - searchForBitbucketCloudRepositories, -} from '../../../../api/alm-integrations'; -import { mockBitbucketCloudRepository } from '../../../../helpers/mocks/alm-integrations'; -import { mockBitbucketCloudAlmSettingsInstance } from '../../../../helpers/mocks/alm-settings'; -import { mockLocation, mockRouter } from '../../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import BitbucketCloudProjectCreate, { - BITBUCKET_CLOUD_PROJECTS_PAGESIZE, -} from '../BitbucketCloudProjectCreate'; - -jest.mock('../../../../api/alm-integrations', () => { - const { mockProject } = jest.requireActual('../../../../helpers/mocks/projects'); - return { - importBitbucketCloudRepository: jest - .fn() - .mockResolvedValue({ project: mockProject({ key: 'project-key' }) }), - searchForBitbucketCloudRepositories: jest - .fn() - .mockResolvedValue({ isLastPage: true, repositories: [] }), - checkPersonalAccessTokenIsValid: jest.fn().mockResolvedValue({ status: true }), - setAlmPersonalAccessToken: jest.fn().mockResolvedValue(null), - }; -}); - -it('Should render correctly', async () => { - const wrapper = shallowRender({ almInstances: [] }); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); - wrapper.setProps({ almInstances: [mockBitbucketCloudAlmSettingsInstance()] }); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('Setting changeds'); -}); - -it('Should handle app password correctly', async () => { - const wrapper = shallowRender(); - - await waitAndUpdate(wrapper); - await wrapper.instance().handlePersonalAccessTokenCreated(); - expect(wrapper.state().showPersonalAccessTokenForm).toBe(false); -}); - -it('Should handle error correctly', async () => { - (searchForBitbucketCloudRepositories as jest.Mock).mockRejectedValueOnce({}); - - const wrapper = shallowRender(); - wrapper.setState({ - showPersonalAccessTokenForm: false, - repositories: [mockBitbucketCloudRepository()], - projectsPaging: { pageIndex: 2, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE }, - }); - await wrapper.instance().handlePersonalAccessTokenCreated(); - expect(wrapper.state().repositories).toHaveLength(0); - expect(wrapper.state().projectsPaging.pageIndex).toBe(1); - expect(wrapper.state().showPersonalAccessTokenForm).toBe(true); - expect(wrapper.state().resetPat).toBe(true); -}); - -it('Should load repository', async () => { - (searchForBitbucketCloudRepositories as jest.Mock).mockResolvedValueOnce({ - isLastPage: true, - repositories: [ - mockBitbucketCloudRepository(), - mockBitbucketCloudRepository({ sqProjectKey: 'sq-key' }), - ], - }); - - const wrapper = shallowRender(); - await wrapper.instance().handlePersonalAccessTokenCreated(); - expect(wrapper.state().repositories).toHaveLength(2); -}); - -it('Should load more repository', async () => { - (searchForBitbucketCloudRepositories as jest.Mock).mockResolvedValueOnce({ - isLastPage: true, - repositories: [ - mockBitbucketCloudRepository(), - mockBitbucketCloudRepository({ sqProjectKey: 'sq-key' }), - ], - }); - - const wrapper = shallowRender(); - wrapper.setState({ showPersonalAccessTokenForm: false, isLastPage: false }); - wrapper.instance().handleLoadMore(); - await waitAndUpdate(wrapper); - expect(wrapper.state().repositories).toHaveLength(2); - expect(wrapper.state().projectsPaging.pageIndex).toBe(2); -}); - -it('Should handle search repository', async () => { - (searchForBitbucketCloudRepositories as jest.Mock).mockResolvedValueOnce({ - isLastPage: true, - repositories: [ - mockBitbucketCloudRepository(), - mockBitbucketCloudRepository({ sqProjectKey: 'sq-key' }), - ], - }); - - const wrapper = shallowRender(); - wrapper.setState({ - isLastPage: false, - showPersonalAccessTokenForm: false, - projectsPaging: { pageIndex: 2, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE }, - repositories: [mockBitbucketCloudRepository()], - }); - wrapper.instance().handleSearch('test'); - await waitAndUpdate(wrapper); - expect(wrapper.state().repositories).toHaveLength(2); - expect(wrapper.state().projectsPaging.pageIndex).toBe(1); - expect(searchForBitbucketCloudRepositories).toHaveBeenLastCalledWith( - 'key', - 'test', - BITBUCKET_CLOUD_PROJECTS_PAGESIZE, - 1 - ); -}); - -it('Should import repository', async () => { - const onProjectCreate = jest.fn(); - const wrapper = shallowRender({ onProjectCreate }); - wrapper.setState({ - isLastPage: false, - showPersonalAccessTokenForm: false, - projectsPaging: { pageIndex: 1, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE }, - repositories: [mockBitbucketCloudRepository({ slug: 'slug-test' })], - }); - await wrapper.instance().handleImport('slug-test'); - expect(importBitbucketCloudRepository).toHaveBeenCalledWith('key', 'slug-test'); - expect(onProjectCreate).toHaveBeenCalledWith('project-key'); -}); - -it('Should behave correctly when import fail', async () => { - (importBitbucketCloudRepository as jest.Mock).mockRejectedValueOnce({}); - const onProjectCreate = jest.fn(); - const wrapper = shallowRender({ onProjectCreate }); - wrapper.setState({ - isLastPage: false, - showPersonalAccessTokenForm: false, - projectsPaging: { pageIndex: 1, pageSize: BITBUCKET_CLOUD_PROJECTS_PAGESIZE }, - repositories: [mockBitbucketCloudRepository({ slug: 'slug-test' })], - }); - await wrapper.instance().handleImport('slug-test'); - expect(importBitbucketCloudRepository).toHaveBeenCalledWith('key', 'slug-test'); - expect(onProjectCreate).not.toHaveBeenCalled(); -}); - -function shallowRender(props?: Partial) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx deleted file mode 100644 index 43c4f5c6b80..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudProjectCreateRender-test.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { mockBitbucketCloudAlmSettingsInstance } from '../../../../helpers/mocks/alm-settings'; -import BitbucketCloudProjectCreateRenderer, { - BitbucketCloudProjectCreateRendererProps, -} from '../BitbucketCloudProjectCreateRender'; - -it('Should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect(shallowRender({ selectedAlmInstance: undefined })).toMatchSnapshot('Wrong config'); - expect(shallowRender({ loading: true })).toMatchSnapshot('Loading...'); - expect( - shallowRender({ - showPersonalAccessTokenForm: true, - }) - ).toMatchSnapshot('Need App password'); -}); - -function shallowRender(props?: Partial) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudSearchForm-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudSearchForm-test.tsx deleted file mode 100644 index 253442d7b0a..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloudSearchForm-test.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { mockBitbucketCloudRepository } from '../../../../helpers/mocks/alm-integrations'; -import BitbucketCloudSearchForm, { - BitbucketCloudSearchFormProps, -} from '../BitbucketCloudSearchForm'; - -it('Should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect( - shallowRender({ - repositories: [ - mockBitbucketCloudRepository(), - mockBitbucketCloudRepository({ sqProjectKey: 'sq-key' }), - ], - isLastPage: false, - }) - ).toMatchSnapshot('Show more'); - expect( - shallowRender({ - repositories: [mockBitbucketCloudRepository()], - isLastPage: true, - }) - ).toMatchSnapshot('Show no more'); - expect( - shallowRender({ - repositories: [mockBitbucketCloudRepository()], - isLastPage: false, - loadingMore: true, - }) - ).toMatchSnapshot('Loading more'); - expect( - shallowRender({ - repositories: [], - isLastPage: false, - searching: true, - }) - ).toMatchSnapshot('Searching'); - expect( - shallowRender({ - importingSlug: 'import-slug', - repositories: [ - mockBitbucketCloudRepository({ slug: 'import-slug' }), - mockBitbucketCloudRepository({ sqProjectKey: 'sq-key' }), - ], - isLastPage: false, - }) - ).toMatchSnapshot('Importing'); -}); - -function shallowRender(props?: Partial) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketImportRepositoryForm-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketImportRepositoryForm-test.tsx deleted file mode 100644 index ecf054c6f33..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketImportRepositoryForm-test.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import SearchBox from '../../../../components/controls/SearchBox'; -import { - mockBitbucketProject, - mockBitbucketRepository, -} from '../../../../helpers/mocks/alm-integrations'; -import { change } from '../../../../helpers/testUtils'; -import BitbucketImportRepositoryForm, { - BitbucketImportRepositoryFormProps, -} from '../BitbucketImportRepositoryForm'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ projects: undefined })).toMatchSnapshot('no projects'); - expect(shallowRender({ searching: true })).toMatchSnapshot('searching'); - expect(shallowRender({ searchResults: [mockBitbucketRepository()] })).toMatchSnapshot( - 'search results' - ); -}); - -it('should correctly handle search', () => { - const onSearch = jest.fn(); - const wrapper = shallowRender({ onSearch }); - change(wrapper.find(SearchBox), 'foo'); - expect(onSearch).toHaveBeenCalledWith('foo'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectAccordion-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectAccordion-test.tsx deleted file mode 100644 index 1a238bad84a..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectAccordion-test.tsx +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import Radio from '../../../../components/controls/Radio'; -import { - mockBitbucketProject, - mockBitbucketRepository, -} from '../../../../helpers/mocks/alm-integrations'; -import BitbucketProjectAccordion, { - BitbucketProjectAccordionProps, -} from '../BitbucketProjectAccordion'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ disableRepositories: true })).toMatchSnapshot('disable options'); - expect(shallowRender({ open: false })).toMatchSnapshot('closed'); - expect(shallowRender({ onClick: undefined })).toMatchSnapshot('no click handler'); - expect(shallowRender({ repositories: [] })).toMatchSnapshot('no repos'); - expect(shallowRender({ selectedRepository: mockBitbucketRepository() })).toMatchSnapshot( - 'selected repo' - ); - expect(shallowRender({ showingAllRepositories: false })).toMatchSnapshot('not showing all repos'); - expect(shallowRender({ project: undefined })).toMatchSnapshot('no project info'); -}); - -it('should correctly handle selecting repos', () => { - const onSelectRepository = jest.fn(); - const repo = mockBitbucketRepository(); - const wrapper = shallowRender({ - onSelectRepository, - repositories: [repo], - }); - - wrapper.find(Radio).at(0).props().onCheck(''); - expect(onSelectRepository).toHaveBeenCalledWith(repo); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx deleted file mode 100644 index 91a6ea85605..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx +++ /dev/null @@ -1,155 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { - getBitbucketServerProjects, - getBitbucketServerRepositories, - importBitbucketServerProject, - searchForBitbucketServerRepositories, -} from '../../../../api/alm-integrations'; -import { - mockBitbucketProject, - mockBitbucketRepository, -} from '../../../../helpers/mocks/alm-integrations'; -import { mockAlmSettingsInstance } from '../../../../helpers/mocks/alm-settings'; -import { mockLocation, mockRouter } from '../../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import { AlmKeys } from '../../../../types/alm-settings'; -import BitbucketProjectCreate from '../BitbucketProjectCreate'; - -jest.mock('../../../../api/alm-integrations', () => { - const { mockBitbucketProject, mockBitbucketRepository } = jest.requireActual( - '../../../../helpers/mocks/alm-integrations' - ); - return { - getBitbucketServerProjects: jest.fn().mockResolvedValue({ - projects: [ - mockBitbucketProject({ key: 'project1', name: 'Project 1' }), - mockBitbucketProject({ id: 2, key: 'project2' }), - ], - }), - getBitbucketServerRepositories: jest.fn().mockResolvedValue({ - repositories: [ - mockBitbucketRepository({ projectKey: 'project1' }), - mockBitbucketRepository({ id: 2, projectKey: 'project1', slug: 'project__repo2' }), - ], - }), - importBitbucketServerProject: jest.fn().mockResolvedValue({ project: { key: 'baz' } }), - searchForBitbucketServerRepositories: jest.fn().mockResolvedValue({ - repositories: [ - mockBitbucketRepository(), - mockBitbucketRepository({ id: 2, slug: 'project__repo2' }), - ], - }), - }; -}); - -beforeEach(jest.clearAllMocks); - -it('should render correctly', async () => { - expect(shallowRender()).toMatchSnapshot(); - expect(shallowRender({ almInstances: [] })).toMatchSnapshot('No setting'); - - const wrapper = shallowRender(); - (getBitbucketServerRepositories as jest.Mock).mockRejectedValueOnce({}); - await wrapper.instance().handlePersonalAccessTokenCreated(); - expect(wrapper).toMatchSnapshot('No repository'); -}); - -it('should correctly fetch projects and repos', async () => { - const wrapper = shallowRender(); - await wrapper.instance().handlePersonalAccessTokenCreated(); - - // Opens first project on mount. - expect(getBitbucketServerProjects).toHaveBeenCalledWith('foo'); - expect(wrapper.state().projects).toHaveLength(2); - - // Check repos got loaded. - await waitAndUpdate(wrapper); - expect(getBitbucketServerRepositories).toHaveBeenCalledWith('foo', 'Project 1'); - expect(wrapper.state().projectRepositories).toEqual( - expect.objectContaining({ - project1: expect.objectContaining({ - repositories: expect.arrayContaining([ - expect.objectContaining({ id: 1 }), - expect.objectContaining({ id: 2 }), - ]), - }), - }) - ); - expect(wrapper.state().projectRepositories).toBeDefined(); -}); - -it('should correctly import a repo', async () => { - const onProjectCreate = jest.fn(); - const repo = mockBitbucketRepository(); - const wrapper = shallowRender({ onProjectCreate }); - const instance = wrapper.instance(); - - instance.handleSelectRepository(repo); - instance.handleImportRepository(); - expect(importBitbucketServerProject).toHaveBeenCalledWith('foo', repo.projectKey, repo.slug); - await waitAndUpdate(wrapper); - expect(onProjectCreate).toHaveBeenCalledWith('baz'); -}); - -it('should correctly handle search', async () => { - const wrapper = shallowRender(); - const instance = wrapper.instance(); - - // Don't trigger search on empty query. - instance.handleSearch(''); - expect(searchForBitbucketServerRepositories).not.toHaveBeenCalled(); - expect(wrapper.state().searching).toBe(false); - expect(wrapper.state().searchResults).toBeUndefined(); - - instance.handleSearch('bar'); - expect(searchForBitbucketServerRepositories).toHaveBeenCalledWith('foo', 'bar'); - expect(wrapper.state().searching).toBe(true); - await waitAndUpdate(wrapper); - expect(wrapper.state().searching).toBe(false); - expect(wrapper.state().searchResults).toHaveLength(2); -}); - -it('should behave correctly when no setting', async () => { - const wrapper = shallowRender({ almInstances: [] }); - await wrapper.instance().handleSearch(''); - await wrapper.instance().handleImportRepository(); - await wrapper.instance().fetchBitbucketRepositories([mockBitbucketProject()]); - - expect(searchForBitbucketServerRepositories).not.toHaveBeenCalled(); - expect(importBitbucketServerProject).not.toHaveBeenCalled(); - expect(getBitbucketServerRepositories).not.toHaveBeenCalled(); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx deleted file mode 100644 index 41dc80e94e2..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { - mockBitbucketProject, - mockBitbucketRepository, -} from '../../../../helpers/mocks/alm-integrations'; -import { mockAlmSettingsInstance } from '../../../../helpers/mocks/alm-settings'; -import { AlmKeys } from '../../../../types/alm-settings'; -import BitbucketProjectCreateRenderer, { - BitbucketProjectCreateRendererProps, -} from '../BitbucketProjectCreateRenderer'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ showPersonalAccessTokenForm: true })).toMatchSnapshot('pat form'); - expect(shallowRender({ loading: true })).toMatchSnapshot('loading'); - expect(shallowRender({ importing: true })).toMatchSnapshot('importing'); - expect(shallowRender({ selectedRepository: mockBitbucketRepository() })).toMatchSnapshot( - 'selected repo' - ); - expect(shallowRender({ selectedAlmInstance: undefined })).toMatchSnapshot( - 'invalid config, regular user' - ); - expect(shallowRender({ selectedAlmInstance: undefined, canAdmin: true })).toMatchSnapshot( - 'invalid config, admin user' - ); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketRepositories-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketRepositories-test.tsx deleted file mode 100644 index 137468f862b..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketRepositories-test.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { - mockBitbucketProject, - mockBitbucketRepository, -} from '../../../../helpers/mocks/alm-integrations'; -import { click } from '../../../../helpers/testUtils'; -import BitbucketProjectAccordion from '../BitbucketProjectAccordion'; -import BitbucketRepositories, { BitbucketRepositoriesProps } from '../BitbucketRepositories'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ projectRepositories: {} })).toMatchSnapshot('no repos'); - expect(shallowRender({ selectedRepository: mockBitbucketRepository() })).toMatchSnapshot( - 'selected repo' - ); -}); - -it('should correctly handle opening/closing accordions', () => { - const wrapper = shallowRender(); - click(wrapper.find(BitbucketProjectAccordion).at(1)); - expect(wrapper).toMatchSnapshot('2nd opened'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketSearchResults-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketSearchResults-test.tsx deleted file mode 100644 index 2bb40e32c2c..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketSearchResults-test.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { - mockBitbucketProject, - mockBitbucketRepository, -} from '../../../../helpers/mocks/alm-integrations'; -import BitbucketSearchResults, { BitbucketSearchResultsProps } from '../BitbucketSearchResults'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect( - shallowRender({ searching: true, projects: [], searchResults: undefined }) - ).toMatchSnapshot('searching'); - expect(shallowRender({ searchResults: undefined })).toMatchSnapshot('no results'); - expect( - shallowRender({ - searchResults: [ - mockBitbucketRepository(), - mockBitbucketRepository({ projectKey: 'unknown' }), - ], - }) - ).toMatchSnapshot('unknown project in search results'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProject-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProject-it.tsx deleted file mode 100644 index 89c35d0eda4..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProject-it.tsx +++ /dev/null @@ -1,215 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { act, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import * as React from 'react'; -import selectEvent from 'react-select-event'; -import { byLabelText, byRole, byText } from 'testing-library-selector'; -import { searchAzureRepositories } from '../../../../api/alm-integrations'; -import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock'; -import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock'; -import { renderApp } from '../../../../helpers/testReactTestingUtils'; -import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage'; - -jest.mock('../../../../api/alm-integrations'); -jest.mock('../../../../api/alm-settings'); - -const original = window.location; - -let almIntegrationHandler: AlmIntegrationsServiceMock; -let almSettingsHandler: AlmSettingsServiceMock; - -const ui = { - gitlabCreateProjectButton: byText('onboarding.create_project.select_method.gitlab'), - githubCreateProjectButton: byText('onboarding.create_project.select_method.github'), - azureCreateProjectButton: byText('onboarding.create_project.select_method.azure'), - personalAccessTokenInput: byRole('textbox', { - name: 'onboarding.create_project.enter_pat field_required', - }), - instanceSelector: byLabelText(/alm.configuration.selector.label/), -}; - -beforeAll(() => { - Object.defineProperty(window, 'location', { - configurable: true, - value: { replace: jest.fn() }, - }); - almIntegrationHandler = new AlmIntegrationsServiceMock(); - almSettingsHandler = new AlmSettingsServiceMock(); -}); - -beforeEach(() => { - jest.clearAllMocks(); - almIntegrationHandler.reset(); - almSettingsHandler.reset(); -}); - -afterAll(() => { - Object.defineProperty(window, 'location', { configurable: true, value: original }); -}); - -describe('Gitlab onboarding page', () => { - it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => { - const user = userEvent.setup(); - renderCreateProject(); - expect(ui.gitlabCreateProjectButton.get()).toBeInTheDocument(); - - await user.click(ui.gitlabCreateProjectButton.get()); - expect(screen.getByText('onboarding.create_project.gitlab.title')).toBeInTheDocument(); - expect(ui.instanceSelector.get()).toBeInTheDocument(); - - expect(screen.getByText('onboarding.create_project.enter_pat')).toBeInTheDocument(); - expect(screen.getByText('onboarding.create_project.pat_help.title')).toBeInTheDocument(); - expect(screen.getByRole('button', { name: 'save' })).toBeInTheDocument(); - - await user.click(ui.personalAccessTokenInput.get()); - await user.keyboard('secret'); - await user.click(screen.getByRole('button', { name: 'save' })); - - expect(screen.getByText('Gitlab project 1')).toBeInTheDocument(); - expect(screen.getByText('Gitlab project 2')).toBeInTheDocument(); - expect(screen.getAllByText('onboarding.create_project.set_up')).toHaveLength(2); - expect(screen.getByText('onboarding.create_project.repository_imported')).toBeInTheDocument(); - }); - - it('should show import project feature when PAT is already set', async () => { - const user = userEvent.setup(); - renderCreateProject(); - await act(async () => { - await user.click(ui.gitlabCreateProjectButton.get()); - await selectEvent.select(ui.instanceSelector.get(), [/conf-final-2/]); - }); - - expect(screen.getByText('Gitlab project 1')).toBeInTheDocument(); - expect(screen.getByText('Gitlab project 2')).toBeInTheDocument(); - }); - - it('should show no result message when there are no projects', async () => { - const user = userEvent.setup(); - almIntegrationHandler.setGitlabProjects([]); - renderCreateProject(); - await act(async () => { - await user.click(ui.gitlabCreateProjectButton.get()); - await selectEvent.select(ui.instanceSelector.get(), [/conf-final-2/]); - }); - - expect(screen.getByText('onboarding.create_project.gitlab.no_projects')).toBeInTheDocument(); - }); -}); - -describe('Github onboarding page', () => { - it('should redirect to github authorization page when not already authorized', async () => { - const user = userEvent.setup(); - renderCreateProject(); - expect(ui.githubCreateProjectButton.get()).toBeInTheDocument(); - - await user.click(ui.githubCreateProjectButton.get()); - expect(screen.getByText('onboarding.create_project.github.title')).toBeInTheDocument(); - expect(screen.getByText('alm.configuration.selector.placeholder')).toBeInTheDocument(); - expect(ui.instanceSelector.get()).toBeInTheDocument(); - - await selectEvent.select(ui.instanceSelector.get(), [/conf-github-1/]); - - expect(window.location.replace).toHaveBeenCalled(); - expect( - screen.getByText('onboarding.create_project.github.choose_organization') - ).toBeInTheDocument(); - }); -}); - -describe('Azure onboarding page', () => { - it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => { - const user = userEvent.setup(); - renderCreateProject(); - expect(ui.azureCreateProjectButton.get()).toBeInTheDocument(); - - await user.click(ui.azureCreateProjectButton.get()); - - expect(screen.getByText('onboarding.create_project.azure.title')).toBeInTheDocument(); - expect(screen.getByText('alm.configuration.selector.label.alm.azure.long')).toBeInTheDocument(); - - expect(screen.getByText('onboarding.create_project.enter_pat')).toBeInTheDocument(); - expect(screen.getByText('onboarding.create_project.pat_form.title.azure')).toBeInTheDocument(); - expect( - screen.getByRole('button', { name: 'onboarding.create_project.pat_form.list_repositories' }) - ).toBeInTheDocument(); - - await user.click(ui.personalAccessTokenInput.get()); - await user.keyboard('secret'); - await user.click( - screen.getByRole('button', { name: 'onboarding.create_project.pat_form.list_repositories' }) - ); - - expect(screen.getByText('Azure project')).toBeInTheDocument(); - expect(screen.getByText('Azure project 2')).toBeInTheDocument(); - // eslint-disable-next-line jest-dom/prefer-in-document - expect(screen.getAllByText('onboarding.create_project.repository_imported')).toHaveLength(1); - }); - - it('should show import project feature when PAT is already set', async () => { - const user = userEvent.setup(); - renderCreateProject(); - - await act(async () => { - await user.click(ui.azureCreateProjectButton.get()); - await selectEvent.select(ui.instanceSelector.get(), [/conf-azure-2/]); - }); - - expect(screen.getByText('Azure project 2')).toBeInTheDocument(); - const importButton = screen.getByText('onboarding.create_project.import_selected_repo'); - const radioButton = screen.getByRole('radio', { name: 'Azure repo 2' }); - - expect(radioButton).toBeInTheDocument(); - expect(importButton).toBeDisabled(); - await user.click(radioButton); - expect(importButton).toBeEnabled(); - await user.click(importButton); - - expect(await screen.findByText('/dashboard?id=key')).toBeInTheDocument(); - }); - - it('should show search filter when PAT is already set', async () => { - const user = userEvent.setup(); - renderCreateProject(); - - await act(async () => { - await user.click(ui.azureCreateProjectButton.get()); - await selectEvent.select(ui.instanceSelector.get(), [/conf-azure-2/]); - }); - - // Should search with positive results - const inputSearch = screen.getByPlaceholderText( - 'onboarding.create_project.search_projects_repositories' - ); - await user.click(inputSearch); - await user.keyboard('s'); - - expect(searchAzureRepositories).toHaveBeenCalledWith('conf-azure-2', 's'); - - // Should search with empty results - almIntegrationHandler.setSearchAzureRepositories([]); - await user.keyboard('f'); - expect(screen.getByText('onboarding.create_project.azure.no_results')).toBeInTheDocument(); - }); -}); - -function renderCreateProject(props: Partial = {}) { - renderApp('project/create', ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx deleted file mode 100644 index e677e2a580d..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectModeSelection-test.tsx +++ /dev/null @@ -1,159 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { mockAppState } from '../../../../helpers/testMocks'; -import { click } from '../../../../helpers/testUtils'; -import { AlmKeys } from '../../../../types/alm-settings'; -import { - CreateProjectModeSelection, - CreateProjectModeSelectionProps, -} from '../CreateProjectModeSelection'; -import { CreateProjectModes } from '../types'; - -it('should render correctly', () => { - expect(shallowRender({ loadingBindings: true })).toMatchSnapshot('loading instances'); - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({}, { [AlmKeys.BitbucketServer]: 0, [AlmKeys.GitHub]: 2 })).toMatchSnapshot( - 'invalid configs, not admin' - ); - expect( - shallowRender( - { appState: mockAppState({ canAdmin: true }) }, - { [AlmKeys.BitbucketServer]: 0, [AlmKeys.GitHub]: 2 } - ) - ).toMatchSnapshot('invalid configs, admin'); - expect( - shallowRender( - { appState: mockAppState({ canAdmin: true }) }, - { [AlmKeys.BitbucketServer]: 0, [AlmKeys.BitbucketCloud]: 0, [AlmKeys.GitHub]: 2 } - ) - ).toMatchSnapshot('invalid configs, admin'); - expect( - shallowRender( - { appState: mockAppState({ canAdmin: true }) }, - { - [AlmKeys.Azure]: 0, - [AlmKeys.BitbucketCloud]: 0, - [AlmKeys.BitbucketServer]: 0, - [AlmKeys.GitHub]: 0, - [AlmKeys.GitLab]: 0, - } - ) - ).toMatchSnapshot('no alm conf yet, admin'); -}); - -it('should correctly pass the selected mode up', () => { - const onSelectMode = jest.fn(); - let wrapper = shallowRender({ onSelectMode }); - - const almButton = 'button.create-project-mode-type-alm'; - - click(wrapper.find('button.create-project-mode-type-manual')); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.Manual); - onSelectMode.mockClear(); - - click(wrapper.find(almButton).at(0)); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.AzureDevOps); - onSelectMode.mockClear(); - - click(wrapper.find(almButton).at(1)); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.BitbucketServer); - onSelectMode.mockClear(); - - click(wrapper.find(almButton).at(2)); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.BitbucketCloud); - onSelectMode.mockClear(); - - click(wrapper.find(almButton).at(3)); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.GitHub); - onSelectMode.mockClear(); - - click(wrapper.find(almButton).at(4)); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.GitLab); - onSelectMode.mockClear(); - - wrapper = shallowRender( - { onSelectMode }, - { [AlmKeys.BitbucketCloud]: 1, [AlmKeys.BitbucketServer]: 0 } - ); - - click(wrapper.find(almButton).at(2)); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.BitbucketCloud); - onSelectMode.mockClear(); -}); - -it('should call the proper click handler', () => { - const almButton = 'button.create-project-mode-type-alm'; - - const onSelectMode = jest.fn(); - const onConfigMode = jest.fn(); - - let wrapper = shallowRender({ onSelectMode, onConfigMode }, { [AlmKeys.Azure]: 0 }); - - click(wrapper.find(almButton).at(0)); - expect(onConfigMode).not.toHaveBeenCalled(); - expect(onSelectMode).not.toHaveBeenCalled(); - onConfigMode.mockClear(); - onSelectMode.mockClear(); - - wrapper = shallowRender({ onSelectMode, onConfigMode }); - - click(wrapper.find(almButton).at(0)); - expect(onConfigMode).not.toHaveBeenCalled(); - expect(onSelectMode).toHaveBeenCalledWith(CreateProjectModes.AzureDevOps); - onConfigMode.mockClear(); - onSelectMode.mockClear(); - - wrapper = shallowRender( - { onSelectMode, onConfigMode, appState: mockAppState({ canAdmin: true }) }, - { [AlmKeys.Azure]: 0 } - ); - - click(wrapper.find(almButton).at(0)); - expect(onConfigMode).toHaveBeenCalledWith(CreateProjectModes.AzureDevOps); - expect(onSelectMode).not.toHaveBeenCalled(); - onConfigMode.mockClear(); - onSelectMode.mockClear(); -}); - -function shallowRender( - props: Partial = {}, - almCountOverrides = {} -) { - const almCounts = { - [AlmKeys.Azure]: 1, - [AlmKeys.BitbucketCloud]: 1, - [AlmKeys.BitbucketServer]: 1, - [AlmKeys.GitHub]: 1, - [AlmKeys.GitLab]: 1, - ...almCountOverrides, - }; - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx deleted file mode 100644 index 146f6bb91de..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/CreateProjectPage-test.tsx +++ /dev/null @@ -1,116 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { getAlmSettings } from '../../../../api/alm-settings'; -import { mockAppState, mockLocation, mockRouter } from '../../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import { AlmKeys } from '../../../../types/alm-settings'; -import AlmBindingDefinitionForm from '../../../settings/components/almIntegration/AlmBindingDefinitionForm'; -import CreateProjectModeSelection from '../CreateProjectModeSelection'; -import { CreateProjectPage } from '../CreateProjectPage'; -import { CreateProjectModes } from '../types'; - -jest.mock('../../../../api/alm-settings', () => { - const { AlmKeys } = jest.requireActual('../../../../types/alm-settings'); - return { - getAlmSettings: jest.fn().mockResolvedValue([{ alm: AlmKeys.BitbucketServer, key: 'foo' }]), - }; -}); - -beforeEach(jest.clearAllMocks); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); - expect(getAlmSettings).toHaveBeenCalled(); -}); - -it.each([ - [CreateProjectModes.Manual], - [CreateProjectModes.AzureDevOps], - [CreateProjectModes.BitbucketServer], - [CreateProjectModes.BitbucketCloud], - [CreateProjectModes.GitHub], - [CreateProjectModes.GitLab], -])('should render correctly for %s mode', (mode: CreateProjectModes) => { - expect( - shallowRender({ - location: mockLocation({ query: { mode } }), - }) - ).toMatchSnapshot(); -}); - -it('should render alm configuration creation correctly', () => { - const wrapper = shallowRender(); - - wrapper.find(CreateProjectModeSelection).props().onConfigMode(AlmKeys.Azure); - expect(wrapper).toMatchSnapshot(); -}); - -it('should cancel alm configuration creation properly', () => { - const wrapper = shallowRender(); - - wrapper.find(CreateProjectModeSelection).props().onConfigMode(AlmKeys.Azure); - expect(wrapper.state().creatingAlmDefinition).toBe(AlmKeys.Azure); - - wrapper.find(AlmBindingDefinitionForm).props().onCancel(); - expect(wrapper.state().creatingAlmDefinition).toBeUndefined(); -}); - -it('should submit alm configuration creation properly', async () => { - const push = jest.fn(); - const wrapper = shallowRender({ router: mockRouter({ push }) }); - - wrapper.find(CreateProjectModeSelection).props().onConfigMode(AlmKeys.Azure); - expect(wrapper.state().creatingAlmDefinition).toBe(AlmKeys.Azure); - - wrapper.find(AlmBindingDefinitionForm).props().afterSubmit({ key: 'test-key' }); - await waitAndUpdate(wrapper); - expect(wrapper.state().creatingAlmDefinition).toBeUndefined(); - expect(getAlmSettings).toHaveBeenCalled(); - expect(push).toHaveBeenCalledWith({ pathname: '/path', query: { mode: AlmKeys.Azure } }); -}); - -it('should submit alm configuration creation properly for BBC', async () => { - const push = jest.fn(); - const wrapper = shallowRender({ router: mockRouter({ push }) }); - - wrapper.find(CreateProjectModeSelection).props().onConfigMode(AlmKeys.BitbucketServer); - expect(wrapper.state().creatingAlmDefinition).toBe(AlmKeys.BitbucketServer); - - (getAlmSettings as jest.Mock).mockResolvedValueOnce([{ alm: AlmKeys.BitbucketCloud }]); - wrapper.find(AlmBindingDefinitionForm).props().afterSubmit({ key: 'test-key' }); - await waitAndUpdate(wrapper); - expect(wrapper.state().creatingAlmDefinition).toBeUndefined(); - expect(getAlmSettings).toHaveBeenCalled(); - expect(push).toHaveBeenCalledWith({ pathname: '/path', query: { mode: AlmKeys.BitbucketCloud } }); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx new file mode 100644 index 00000000000..63f933ab800 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitHub-it.tsx @@ -0,0 +1,86 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { screen } from '@testing-library/react'; + +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import selectEvent from 'react-select-event'; +import { byLabelText, byRole, byText } from 'testing-library-selector'; +import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock'; +import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock'; +import { renderApp } from '../../../../helpers/testReactTestingUtils'; +import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage'; + +jest.mock('../../../../api/alm-integrations'); +jest.mock('../../../../api/alm-settings'); + +const original = window.location; + +let almIntegrationHandler: AlmIntegrationsServiceMock; +let almSettingsHandler: AlmSettingsServiceMock; + +const ui = { + githubCreateProjectButton: byText('onboarding.create_project.select_method.github'), + personalAccessTokenInput: byRole('textbox', { + name: /onboarding.create_project.enter_pat/, + }), + instanceSelector: byLabelText(/alm.configuration.selector.label/), +}; + +beforeAll(() => { + Object.defineProperty(window, 'location', { + configurable: true, + value: { replace: jest.fn() }, + }); + almIntegrationHandler = new AlmIntegrationsServiceMock(); + almSettingsHandler = new AlmSettingsServiceMock(); +}); + +beforeEach(() => { + jest.clearAllMocks(); + almIntegrationHandler.reset(); + almSettingsHandler.reset(); +}); + +afterAll(() => { + Object.defineProperty(window, 'location', { configurable: true, value: original }); +}); + +it('should redirect to github authorization page when not already authorized', async () => { + const user = userEvent.setup(); + renderCreateProject(); + expect(ui.githubCreateProjectButton.get()).toBeInTheDocument(); + + await user.click(ui.githubCreateProjectButton.get()); + expect(screen.getByText('onboarding.create_project.github.title')).toBeInTheDocument(); + expect(screen.getByText('alm.configuration.selector.placeholder')).toBeInTheDocument(); + expect(ui.instanceSelector.get()).toBeInTheDocument(); + + await selectEvent.select(ui.instanceSelector.get(), [/conf-github-1/]); + + expect(window.location.replace).toHaveBeenCalled(); + expect( + screen.getByText('onboarding.create_project.github.choose_organization') + ).toBeInTheDocument(); +}); + +function renderCreateProject(props: Partial = {}) { + renderApp('project/create', ); +} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx new file mode 100644 index 00000000000..91c3adc4b8e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitLab-it.tsx @@ -0,0 +1,177 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import { act, screen, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; +import selectEvent from 'react-select-event'; +import { byLabelText, byRole, byText } from 'testing-library-selector'; +import { getGitlabProjects } from '../../../../api/alm-integrations'; +import AlmIntegrationsServiceMock from '../../../../api/mocks/AlmIntegrationsServiceMock'; +import AlmSettingsServiceMock from '../../../../api/mocks/AlmSettingsServiceMock'; +import { renderApp } from '../../../../helpers/testReactTestingUtils'; +import CreateProjectPage, { CreateProjectPageProps } from '../CreateProjectPage'; + +jest.mock('../../../../api/alm-integrations'); +jest.mock('../../../../api/alm-settings'); + +let almIntegrationHandler: AlmIntegrationsServiceMock; +let almSettingsHandler: AlmSettingsServiceMock; + +const ui = { + gitlabCreateProjectButton: byText('onboarding.create_project.select_method.gitlab'), + + personalAccessTokenInput: byRole('textbox', { + name: /onboarding.create_project.enter_pat/, + }), + instanceSelector: byLabelText(/alm.configuration.selector.label/), +}; + +beforeAll(() => { + almIntegrationHandler = new AlmIntegrationsServiceMock(); + almSettingsHandler = new AlmSettingsServiceMock(); +}); + +beforeEach(() => { + jest.clearAllMocks(); + almIntegrationHandler.reset(); + almSettingsHandler.reset(); +}); + +it('should ask for PAT when it is not set yet and show the import project feature afterwards', async () => { + const user = userEvent.setup(); + renderCreateProject(); + expect(ui.gitlabCreateProjectButton.get()).toBeInTheDocument(); + + await user.click(ui.gitlabCreateProjectButton.get()); + expect(screen.getByText('onboarding.create_project.gitlab.title')).toBeInTheDocument(); + expect(ui.instanceSelector.get()).toBeInTheDocument(); + + expect(screen.getByText('onboarding.create_project.enter_pat')).toBeInTheDocument(); + expect(screen.getByText('onboarding.create_project.pat_help.title')).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'save' })).toBeInTheDocument(); + + await user.click(ui.personalAccessTokenInput.get()); + await user.keyboard('secret'); + await user.click(screen.getByRole('button', { name: 'save' })); + + expect(screen.getByText('Gitlab project 1')).toBeInTheDocument(); + expect(screen.getByText('Gitlab project 2')).toBeInTheDocument(); + expect(screen.getAllByText('onboarding.create_project.set_up')).toHaveLength(2); + expect(screen.getByText('onboarding.create_project.repository_imported')).toBeInTheDocument(); +}); + +it('should show import project feature when PAT is already set', async () => { + const user = userEvent.setup(); + let projectItem; + renderCreateProject(); + await act(async () => { + await user.click(ui.gitlabCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-final-2/]); + }); + + expect(screen.getByText('Gitlab project 1')).toBeInTheDocument(); + expect(screen.getByText('Gitlab project 2')).toBeInTheDocument(); + + projectItem = screen.getByRole('row', { name: /Gitlab project 1/ }); + expect( + within(projectItem).getByText('onboarding.create_project.repository_imported') + ).toBeInTheDocument(); + expect(within(projectItem).getByRole('link', { name: /Gitlab project 1/ })).toBeInTheDocument(); + expect(within(projectItem).getByRole('link', { name: /Gitlab project 1/ })).toHaveAttribute( + 'href', + '/dashboard?id=key' + ); + + projectItem = screen.getByRole('row', { name: /Gitlab project 2/ }); + const importProjectButton = within(projectItem).getByRole('button', { + name: 'onboarding.create_project.set_up', + }); + + await user.click(importProjectButton); + expect(await screen.findByText('/dashboard?id=key')).toBeInTheDocument(); +}); + +it('should show search filter when PAT is already set', async () => { + const user = userEvent.setup(); + renderCreateProject(); + + await act(async () => { + await user.click(ui.gitlabCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-final-2/]); + }); + + const inputSearch = screen.getByRole('searchbox', { + name: 'search_verb', + }); + await user.click(inputSearch); + await user.keyboard('sea'); + + expect(getGitlabProjects).toHaveBeenLastCalledWith({ + almSetting: 'conf-final-2', + page: 1, + pageSize: 30, + query: 'sea', + }); +}); + +it('should have load more', async () => { + const user = userEvent.setup(); + almIntegrationHandler.createRandomGitlabProjectsWithLoadMore(10, 20); + renderCreateProject(); + await act(async () => { + await user.click(ui.gitlabCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-final-2/]); + }); + const loadMore = screen.getByRole('button', { name: 'show_more' }); + expect(loadMore).toBeInTheDocument(); + + /* + * Next api call response will simulate reaching the last page so we can test the + * loadmore button disapperance. + */ + almIntegrationHandler.createRandomGitlabProjectsWithLoadMore(20, 20); + await user.click(loadMore); + expect(getGitlabProjects).toHaveBeenLastCalledWith({ + almSetting: 'conf-final-2', + page: 2, + pageSize: 30, + query: '', + }); + expect(loadMore).not.toBeInTheDocument(); +}); + +it('should show no result message when there are no projects', async () => { + const user = userEvent.setup(); + almIntegrationHandler.setGitlabProjects([]); + renderCreateProject(); + await act(async () => { + await user.click(ui.gitlabCreateProjectButton.get()); + await selectEvent.select(ui.instanceSelector.get(), [/conf-final-2/]); + }); + + expect(screen.getByRole('alert')).toHaveTextContent( + 'onboarding.create_project.gitlab.no_projects' + ); +}); + +function renderCreateProject(props: Partial = {}) { + renderApp('project/create', ); +} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreate-test.tsx deleted file mode 100644 index 4293a00e936..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreate-test.tsx +++ /dev/null @@ -1,211 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { getGitlabProjects, importGitlabProject } from '../../../../api/alm-integrations'; -import { mockGitlabProject } from '../../../../helpers/mocks/alm-integrations'; -import { mockAlmSettingsInstance } from '../../../../helpers/mocks/alm-settings'; -import { mockLocation, mockRouter } from '../../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import { AlmKeys } from '../../../../types/alm-settings'; -import GitlabProjectCreate from '../GitlabProjectCreate'; - -jest.mock('../../../../api/alm-integrations', () => ({ - getGitlabProjects: jest.fn().mockRejectedValue('error'), - importGitlabProject: jest.fn().mockRejectedValue('error'), -})); - -beforeEach(jest.clearAllMocks); - -const almSettingKey = 'gitlab-setting'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -it('should fetch more projects and preserve search', async () => { - const projects = [ - mockGitlabProject({ id: '1' }), - mockGitlabProject({ id: '2' }), - mockGitlabProject({ id: '3' }), - mockGitlabProject({ id: '4' }), - mockGitlabProject({ id: '5' }), - mockGitlabProject({ id: '6' }), - ]; - (getGitlabProjects as jest.Mock) - .mockResolvedValueOnce({ - projects: projects.slice(0, 5), - projectsPaging: { - pageIndex: 1, - pageSize: 4, - total: 6, - }, - }) - .mockResolvedValueOnce({ - projects: projects.slice(5), - projectsPaging: { - pageIndex: 2, - pageSize: 4, - total: 6, - }, - }); - - const wrapper = shallowRender(); - - await wrapper.instance().handlePersonalAccessTokenCreated(); - wrapper.setState({ searchQuery: 'query' }); - - wrapper.instance().handleLoadMore(); - expect(wrapper.state().loadingMore).toBe(true); - - await waitAndUpdate(wrapper); - expect(wrapper.state().loadingMore).toBe(false); - expect(wrapper.state().projects).toEqual(projects); - - expect(getGitlabProjects).toHaveBeenCalledWith(expect.objectContaining({ query: 'query' })); -}); - -it('should search for projects', async () => { - const projects = [ - mockGitlabProject({ id: '1' }), - mockGitlabProject({ id: '2' }), - mockGitlabProject({ id: '3' }), - mockGitlabProject({ id: '4' }), - mockGitlabProject({ id: '5' }), - mockGitlabProject({ id: '6' }), - ]; - (getGitlabProjects as jest.Mock) - .mockResolvedValueOnce({ - projects, - projectsPaging: { - pageIndex: 1, - pageSize: 6, - total: 6, - }, - }) - .mockResolvedValueOnce({ - projects: projects.slice(3, 5), - projectsPaging: { - pageIndex: 1, - pageSize: 6, - total: 2, - }, - }); - const query = 'query'; - - const wrapper = shallowRender(); - await wrapper.instance().handlePersonalAccessTokenCreated(); - - wrapper.instance().handleSearch(query); - expect(wrapper.state().searching).toBe(true); - await waitAndUpdate(wrapper); - expect(wrapper.state().searching).toBe(false); - expect(wrapper.state().searchQuery).toBe(query); - expect(wrapper.state().projects).toEqual([projects[3], projects[4]]); - - expect(getGitlabProjects).toHaveBeenCalledWith(expect.objectContaining({ query })); -}); - -it('should import', async () => { - const projects = [mockGitlabProject({ id: '1' }), mockGitlabProject({ id: '2' })]; - (getGitlabProjects as jest.Mock).mockResolvedValueOnce({ - projects, - projectsPaging: { - pageIndex: 1, - pageSize: 6, - total: 2, - }, - }); - const createdProjectkey = 'imported_project_key'; - - (importGitlabProject as jest.Mock).mockResolvedValueOnce({ - project: { key: createdProjectkey }, - }); - - const onProjectCreate = jest.fn(); - - const wrapper = shallowRender({ onProjectCreate }); - await wrapper.instance().handlePersonalAccessTokenCreated(); - - wrapper.instance().handleImport(projects[1].id); - expect(wrapper.state().importingGitlabProjectId).toBe(projects[1].id); - - await waitAndUpdate(wrapper); - - expect(wrapper.state().importingGitlabProjectId).toBeUndefined(); - expect(onProjectCreate).toHaveBeenCalledWith(createdProjectkey); -}); - -it('should do nothing with missing settings', async () => { - const wrapper = shallowRender({ almInstances: [] }); - - await wrapper.instance().handleLoadMore(); - await wrapper.instance().handleSearch('whatever'); - await wrapper.instance().handlePersonalAccessTokenCreated(); - await wrapper.instance().handleImport('gitlab project id'); - - expect(getGitlabProjects).not.toHaveBeenCalled(); - expect(importGitlabProject).not.toHaveBeenCalled(); -}); - -it('should handle errors when fetching projects', async () => { - (getGitlabProjects as jest.Mock).mockRejectedValueOnce({}); - - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - await wrapper.instance().handlePersonalAccessTokenCreated(); - - expect(wrapper.state().resetPat).toBe(true); - expect(wrapper.state().showPersonalAccessTokenForm).toBe(true); -}); - -it('should handle errors when importing a project', async () => { - (importGitlabProject as jest.Mock).mockRejectedValueOnce({}); - (getGitlabProjects as jest.Mock).mockResolvedValueOnce({ - projects: [mockGitlabProject()], - projectsPaging: { - pageIndex: 1, - pageSize: 10, - total: 1, - }, - }); - - const wrapper = shallowRender(); - await wrapper.instance().handlePersonalAccessTokenCreated(); - - await wrapper.instance().handleImport('gitlabId'); - await waitAndUpdate(wrapper); - - expect(wrapper.state().showPersonalAccessTokenForm).toBe(true); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreateRenderer-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreateRenderer-test.tsx deleted file mode 100644 index 3422a875696..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectCreateRenderer-test.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { mockAlmSettingsInstance } from '../../../../helpers/mocks/alm-settings'; -import { AlmKeys } from '../../../../types/alm-settings'; -import GitlabProjectCreateRenderer, { - GitlabProjectCreateRendererProps, -} from '../GitlabProjectCreateRenderer'; - -it('should render correctly', () => { - expect(shallowRender({ loading: true })).toMatchSnapshot('loading'); - expect(shallowRender({ almInstances: undefined })).toMatchSnapshot('invalid settings'); - expect(shallowRender({ almInstances: undefined })).toMatchSnapshot( - 'invalid settings, admin user' - ); - expect(shallowRender()).toMatchSnapshot('pat form'); - expect(shallowRender({ showPersonalAccessTokenForm: false })).toMatchSnapshot( - 'project selection form' - ); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectSelectionForm-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectSelectionForm-test.tsx deleted file mode 100644 index b464e947bc0..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/GitlabProjectSelectionForm-test.tsx +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { Button } from '../../../../components/controls/buttons'; -import ListFooter from '../../../../components/controls/ListFooter'; -import SearchBox from '../../../../components/controls/SearchBox'; -import { mockGitlabProject } from '../../../../helpers/mocks/alm-integrations'; -import GitlabProjectSelectionForm, { - GitlabProjectSelectionFormProps, -} from '../GitlabProjectSelectionForm'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('projects'); - - expect(shallowRender({ projects: undefined, projectsPaging: mockPaging() })).toMatchSnapshot( - 'undefined projects' - ); - expect(shallowRender({ projects: [], projectsPaging: mockPaging() })).toMatchSnapshot( - 'no projects' - ); - expect( - shallowRender({ projects: [], projectsPaging: mockPaging(), searchQuery: 'findme' }) - ).toMatchSnapshot('no projects when searching'); - - expect(shallowRender({ importingGitlabProjectId: '2' })).toMatchSnapshot('importing'); -}); - -describe('appropriate callback', () => { - const onImport = jest.fn(); - const onLoadMore = jest.fn(); - const onSearch = jest.fn(); - const wrapper = shallowRender({ onImport, onLoadMore, onSearch }); - - it('should be called when clicking to import', () => { - wrapper.find(Button).first().simulate('click'); - - expect(onImport).toHaveBeenCalled(); - }); - - it('should be assigned to the list footer', () => { - const { loadMore } = wrapper.find(ListFooter).first().props(); - - expect(loadMore).toBe(onLoadMore); - }); - - it('should be assigned to the search box', () => { - const { onChange } = wrapper.find(SearchBox).first().props(); - - expect(onChange).toBe(onSearch); - }); -}); - -function shallowRender(props: Partial = {}) { - const projects = [ - mockGitlabProject(), - mockGitlabProject({ - id: '2', - sqProjectKey: 'already-imported', - sqProjectName: 'Already Imported', - }), - ]; - - return shallow( - - ); -} - -function mockPaging(total = 0) { - return { total, pageIndex: 1, pageSize: 30 }; -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/PersonalAccessTokenForm-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/PersonalAccessTokenForm-test.tsx deleted file mode 100644 index 5ab0fec34d5..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/PersonalAccessTokenForm-test.tsx +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { - checkPersonalAccessTokenIsValid, - setAlmPersonalAccessToken, -} from '../../../../api/alm-integrations'; -import { SubmitButton } from '../../../../components/controls/buttons'; -import { - mockAlmSettingsInstance, - mockBitbucketCloudAlmSettingsInstance, -} from '../../../../helpers/mocks/alm-settings'; -import { change, submit, waitAndUpdate } from '../../../../helpers/testUtils'; -import { AlmKeys } from '../../../../types/alm-settings'; -import PersonalAccessTokenForm from '../PersonalAccessTokenForm'; - -jest.mock('../../../../api/alm-integrations', () => ({ - checkPersonalAccessTokenIsValid: jest.fn().mockResolvedValue({ status: true }), - setAlmPersonalAccessToken: jest.fn().mockResolvedValue({}), -})); - -it('should render correctly', async () => { - expect(shallowRender()).toMatchSnapshot('no token needed'); - - (checkPersonalAccessTokenIsValid as jest.Mock).mockResolvedValueOnce({ status: false }); - let wrapper = shallowRender(); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('bitbucket'); - - (checkPersonalAccessTokenIsValid as jest.Mock).mockResolvedValueOnce({ status: false }); - wrapper = shallowRender({ almSetting: mockBitbucketCloudAlmSettingsInstance() }); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('bitbucket cloud'); - - (checkPersonalAccessTokenIsValid as jest.Mock).mockResolvedValueOnce({ status: false }); - wrapper = shallowRender({ - almSetting: mockAlmSettingsInstance({ alm: AlmKeys.GitLab, url: 'https://gitlab.com/api/v4' }), - }); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('gitlab'); - - (checkPersonalAccessTokenIsValid as jest.Mock).mockResolvedValueOnce({ status: false }); - wrapper = shallowRender({ - almSetting: mockAlmSettingsInstance({ - alm: AlmKeys.GitLab, - url: 'https://gitlabapi.unexpectedurl.org', - }), - }); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('gitlab with non-standard api path'); -}); - -it('should correctly handle form interactions', async () => { - const onPersonalAccessTokenCreated = jest.fn(); - const wrapper = shallowRender({ onPersonalAccessTokenCreated }); - - await waitAndUpdate(wrapper); - // Submit button disabled by default. - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); - - // Submit button enabled if there's a value. - change(wrapper.find('input'), 'token'); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(false); - - // Expect correct calls to be made when submitting. - submit(wrapper.find('form')); - expect(onPersonalAccessTokenCreated).toHaveBeenCalled(); - expect(setAlmPersonalAccessToken).toHaveBeenCalledWith('key', 'token', undefined); -}); - -it('should correctly handle form for bitbucket interactions', async () => { - const onPersonalAccessTokenCreated = jest.fn(); - const wrapper = shallowRender({ - almSetting: mockBitbucketCloudAlmSettingsInstance(), - onPersonalAccessTokenCreated, - }); - - await waitAndUpdate(wrapper); - // Submit button disabled by default. - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); - - change(wrapper.find('input#personal_access_token_validation'), 'token'); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); - - // Submit button enabled if there's a value. - change(wrapper.find('#username'), 'username'); - expect(wrapper.find(SubmitButton).prop('disabled')).toBe(false); - - // Expect correct calls to be made when submitting. - submit(wrapper.find('form')); - expect(onPersonalAccessTokenCreated).toHaveBeenCalled(); - expect(setAlmPersonalAccessToken).toHaveBeenCalledWith('key', 'token', 'username'); -}); - -it('should show error when issue', async () => { - (checkPersonalAccessTokenIsValid as jest.Mock).mockRejectedValueOnce({}); - const wrapper = shallowRender({ - almSetting: mockBitbucketCloudAlmSettingsInstance(), - }); - - await waitAndUpdate(wrapper); - - (checkPersonalAccessTokenIsValid as jest.Mock).mockRejectedValueOnce({}); - - change(wrapper.find('input#personal_access_token_validation'), 'token'); - change(wrapper.find('#username'), 'username'); - - // Expect correct calls to be made when submitting. - submit(wrapper.find('form')); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('issue submitting token'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/WrongBindingCountAlert-test.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/WrongBindingCountAlert-test.tsx deleted file mode 100644 index 5d9b687841f..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/WrongBindingCountAlert-test.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { shallow } from 'enzyme'; -import * as React from 'react'; -import { AlmKeys } from '../../../../types/alm-settings'; -import WrongBindingCountAlert, { WrongBindingCountAlertProps } from '../WrongBindingCountAlert'; - -it('should render correctly', () => { - expect(shallowRender({ canAdmin: true })).toMatchSnapshot('for admin'); - expect(shallowRender({ alm: AlmKeys.BitbucketServer })).toMatchSnapshot('bitbucket'); - expect(shallowRender({ alm: AlmKeys.GitLab })).toMatchSnapshot('gitlab'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap deleted file mode 100644 index efaf694bc72..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreate-test.tsx.snap +++ /dev/null @@ -1,54 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly 1`] = ` - -`; - -exports[`Should render correctly: Setting changeds 1`] = ` - -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap deleted file mode 100644 index d5d68483133..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudProjectCreateRender-test.tsx.snap +++ /dev/null @@ -1,173 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly 1`] = ` - - - - onboarding.create_project.bitbucketcloud.title - - } - /> - - - -`; - -exports[`Should render correctly: Loading... 1`] = ` - - - - onboarding.create_project.bitbucketcloud.title - - } - /> - - - -`; - -exports[`Should render correctly: Need App password 1`] = ` - - - - onboarding.create_project.bitbucketcloud.title - - } - /> - - - -`; - -exports[`Should render correctly: Wrong config 1`] = ` - - - - onboarding.create_project.bitbucketcloud.title - - } - /> - - - -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudSearchForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudSearchForm-test.tsx.snap deleted file mode 100644 index a788d858535..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketCloudSearchForm-test.tsx.snap +++ /dev/null @@ -1,482 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly 1`] = ` - - - onboarding.create_project.update_your_token - , - } - } - /> - -`; - -exports[`Should render correctly: Importing 1`] = ` -
- -
- - - - - - - - - - - - - -
- - - Repo - - -
- - - project - - -
- - onboarding.create_project.bitbucketcloud.link - - - -
- - - - - Repo - - - -
- - - project - - -
- - onboarding.create_project.bitbucketcloud.link - - - - - onboarding.create_project.repository_imported - -
-
- -
-
-`; - -exports[`Should render correctly: Loading more 1`] = ` -
- -
- - - - - - - - -
- - - Repo - - -
- - - project - - -
- - onboarding.create_project.bitbucketcloud.link - - - -
-
- - -
-
-`; - -exports[`Should render correctly: Searching 1`] = ` -
- -
-
- no_results -
-
- -
-
-`; - -exports[`Should render correctly: Show more 1`] = ` -
- -
- - - - - - - - - - - - - -
- - - Repo - - -
- - - project - - -
- - onboarding.create_project.bitbucketcloud.link - - - -
- - - - - Repo - - - -
- - - project - - -
- - onboarding.create_project.bitbucketcloud.link - - - - - onboarding.create_project.repository_imported - -
-
- -
-
-`; - -exports[`Should render correctly: Show no more 1`] = ` -
- -
- - - - - - - - -
- - - Repo - - -
- - - project - - -
- - onboarding.create_project.bitbucketcloud.link - - - -
-
- x_of_y_shown.1.1 -
-
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap deleted file mode 100644 index 8292bfe2bba..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap +++ /dev/null @@ -1,148 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` -
- - -
-`; - -exports[`should render correctly: no projects 1`] = ` - - - onboarding.create_project.update_your_token - , - } - } - /> - -`; - -exports[`should render correctly: search results 1`] = ` -
- - -
-`; - -exports[`should render correctly: searching 1`] = ` -
- - -
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap deleted file mode 100644 index 5c21a64e4e9..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap +++ /dev/null @@ -1,455 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: closed 1`] = ` - - Project - - } -/> -`; - -exports[`should render correctly: default 1`] = ` - - Project - - } -> -
- - - Repo - - -
- -
-
- - - Bar - - -
- - onboarding.create_project.repository_imported - -
-
-
-
-`; - -exports[`should render correctly: disable options 1`] = ` - - Project - - } -> -
- - - Repo - - -
- -
-
- - - Bar - - -
- - onboarding.create_project.repository_imported - -
-
-
-
-`; - -exports[`should render correctly: no click handler 1`] = ` - - Project - - } -> -
- - - Repo - - -
- -
-
- - - Bar - - -
- - onboarding.create_project.repository_imported - -
-
-
-
-`; - -exports[`should render correctly: no project info 1`] = ` - - search_results - - } -> -
- - - Repo - - -
- -
-
- - - Bar - - -
- - onboarding.create_project.repository_imported - -
-
-
-
-`; - -exports[`should render correctly: no repos 1`] = ` - - Project - - } -> -
- - - onboarding.create_project.update_your_token - , - } - } - /> - -
-
-`; - -exports[`should render correctly: not showing all repos 1`] = ` - - Project - - } -> -
- - - Repo - - -
- -
-
- - - Bar - - -
- - onboarding.create_project.repository_imported - -
-
-
- - onboarding.create_project.only_showing_X_first_repos.2 - -
-`; - -exports[`should render correctly: selected repo 1`] = ` - - Project - - } -> -
- - - Repo - - -
- -
-
- - - Bar - - -
- - onboarding.create_project.repository_imported - -
-
-
-
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap deleted file mode 100644 index e168e70e45b..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap +++ /dev/null @@ -1,92 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; - -exports[`should render correctly: No repository 1`] = ` - -`; - -exports[`should render correctly: No setting 1`] = ` - -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap deleted file mode 100644 index 6047821c001..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap +++ /dev/null @@ -1,477 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` - - - - - - } - title={ - - - onboarding.create_project.from_bbs - - } - /> - - - -`; - -exports[`should render correctly: importing 1`] = ` - - - - - - } - title={ - - - onboarding.create_project.from_bbs - - } - /> - - - -`; - -exports[`should render correctly: invalid config, admin user 1`] = ` - - - - - - } - title={ - - - onboarding.create_project.from_bbs - - } - /> - - - -`; - -exports[`should render correctly: invalid config, regular user 1`] = ` - - - - - - } - title={ - - - onboarding.create_project.from_bbs - - } - /> - - - -`; - -exports[`should render correctly: loading 1`] = ` - - - - - - } - title={ - - - onboarding.create_project.from_bbs - - } - /> - - - -`; - -exports[`should render correctly: pat form 1`] = ` - - - - onboarding.create_project.from_bbs - - } - /> - - - -`; - -exports[`should render correctly: selected repo 1`] = ` - - - - - - } - title={ - - - onboarding.create_project.from_bbs - - } - /> - - - -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketRepositories-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketRepositories-test.tsx.snap deleted file mode 100644 index 44c85577219..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketRepositories-test.tsx.snap +++ /dev/null @@ -1,248 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should correctly handle opening/closing accordions: 2nd opened 1`] = ` - -
- - collapse_all - -
- - -
-`; - -exports[`should render correctly: default 1`] = ` - -
- - expand_all - -
- - -
-`; - -exports[`should render correctly: no repos 1`] = ` - -
- - expand_all - -
- - -
-`; - -exports[`should render correctly: selected repo 1`] = ` - -
- - expand_all - -
- - -
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketSearchResults-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketSearchResults-test.tsx.snap deleted file mode 100644 index b9f80fb1ed6..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketSearchResults-test.tsx.snap +++ /dev/null @@ -1,106 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` -
- - - -
-`; - -exports[`should render correctly: no results 1`] = ` - - onboarding.create_project.no_bbs_repos.filter - -`; - -exports[`should render correctly: searching 1`] = ` -
- -
-`; - -exports[`should render correctly: unknown project in search results 1`] = ` -
- - - - -
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap deleted file mode 100644 index 36a8a852f6b..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectModeSelection-test.tsx.snap +++ /dev/null @@ -1,972 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` - -

- onboarding.create_project.select_method -

-

- onboarding.create_project.select_method.devops_platform -

-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

- onboarding.create_project.select_method.manually -

- -
-`; - -exports[`should render correctly: invalid configs, admin 1`] = ` - -

- onboarding.create_project.select_method -

-

- onboarding.create_project.select_method.devops_platform -

-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

- onboarding.create_project.select_method.manually -

- -
-`; - -exports[`should render correctly: invalid configs, admin 2`] = ` - -

- onboarding.create_project.select_method -

-

- onboarding.create_project.select_method.devops_platform -

-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

- onboarding.create_project.select_method.manually -

- -
-`; - -exports[`should render correctly: invalid configs, not admin 1`] = ` - -

- onboarding.create_project.select_method -

-

- onboarding.create_project.select_method.devops_platform -

-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

- onboarding.create_project.select_method.manually -

- -
-`; - -exports[`should render correctly: loading instances 1`] = ` - -

- onboarding.create_project.select_method -

-

- onboarding.create_project.select_method.devops_platform -

-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

- onboarding.create_project.select_method.manually -

- -
-`; - -exports[`should render correctly: no alm conf yet, admin 1`] = ` - -

- onboarding.create_project.select_method -

-

- onboarding.create_project.select_method.devops_platform -

-

- onboarding.create_project.select_method.no_alm_yet.admin -

-
-
- -
-
- -
-
- -
-
- -
-
- -
-
-

- onboarding.create_project.select_method.manually -

- -
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap deleted file mode 100644 index 6ec13628e53..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap +++ /dev/null @@ -1,355 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render alm configuration creation correctly 1`] = ` - - - -
- - -
-
-`; - -exports[`should render correctly 1`] = ` - - - -
- -
-
-`; - -exports[`should render correctly for azure mode 1`] = ` - - - -
- -
-
-`; - -exports[`should render correctly for bitbucket mode 1`] = ` - - - -
- -
-
-`; - -exports[`should render correctly for bitbucketcloud mode 1`] = ` - - - -
- -
-
-`; - -exports[`should render correctly for github mode 1`] = ` - - - -
- -
-
-`; - -exports[`should render correctly for gitlab mode 1`] = ` - - - -
- -
-
-`; - -exports[`should render correctly for manual mode 1`] = ` - - - -
- -
-
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreate-test.tsx.snap deleted file mode 100644 index 1fe927da52e..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreate-test.tsx.snap +++ /dev/null @@ -1,39 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` - -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreateRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreateRenderer-test.tsx.snap deleted file mode 100644 index 6f4f4831744..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectCreateRenderer-test.tsx.snap +++ /dev/null @@ -1,247 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: invalid settings 1`] = ` - - - - onboarding.create_project.gitlab.title - - } - /> - - - -`; - -exports[`should render correctly: invalid settings, admin user 1`] = ` - - - - onboarding.create_project.gitlab.title - - } - /> - - - -`; - -exports[`should render correctly: loading 1`] = ` - - - - onboarding.create_project.gitlab.title - - } - /> - - - -`; - -exports[`should render correctly: pat form 1`] = ` - - - - onboarding.create_project.gitlab.title - - } - /> - - - -`; - -exports[`should render correctly: project selection form 1`] = ` - - - - onboarding.create_project.gitlab.title - - } - /> - - - -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectSelectionForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectSelectionForm-test.tsx.snap deleted file mode 100644 index 35a35f027d0..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/GitlabProjectSelectionForm-test.tsx.snap +++ /dev/null @@ -1,340 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: importing 1`] = ` -
- -
- - - - - - - - - - - - - -
- - - Awesome Project ! - - -
- - - Company / Best Projects - - -
- - onboarding.create_project.gitlab.link - - - -
- - - - - Already Imported - - - -
- - - Company / Best Projects - - -
- - onboarding.create_project.gitlab.link - - - - - onboarding.create_project.repository_imported - -
- -
-`; - -exports[`should render correctly: no projects 1`] = ` - - - onboarding.create_project.update_your_token - , - } - } - /> - -`; - -exports[`should render correctly: no projects when searching 1`] = ` -
- -
-
- no_results -
- -
-`; - -exports[`should render correctly: projects 1`] = ` -
- -
- - - - - - - - - - - - - -
- - - Awesome Project ! - - -
- - - Company / Best Projects - - -
- - onboarding.create_project.gitlab.link - - - -
- - - - - Already Imported - - - -
- - - Company / Best Projects - - -
- - onboarding.create_project.gitlab.link - - - - - onboarding.create_project.repository_imported - -
- -
-`; - -exports[`should render correctly: undefined projects 1`] = ` - - - onboarding.create_project.update_your_token - , - } - } - /> - -`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/PersonalAccessTokenForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/PersonalAccessTokenForm-test.tsx.snap deleted file mode 100644 index d569b0fb97b..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/PersonalAccessTokenForm-test.tsx.snap +++ /dev/null @@ -1,679 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: bitbucket 1`] = ` -
-
-

- onboarding.create_project.pat_form.title.bitbucket -

-

- onboarding.create_project.pat_form.help.bitbucket -

- - - - - - save - - - -
- -

- onboarding.create_project.pat_help.title -

-

- - onboarding.create_project.pat_help.bitbucket.instructions.button - , - "menu": - onboarding.create_project.pat_help.bitbucket.instructions.menu - , - } - } - /> -

- -

- onboarding.create_project.pat_help.instructions2.bitbucket -

-
    -
  • - - onboarding.create_project.pat_help.read_permission - , - } - } - /> -
  • -
  • - - onboarding.create_project.pat_help.read_permission - , - } - } - /> -
  • -
-
-
-`; - -exports[`should render correctly: bitbucket cloud 1`] = ` -
-
-

- onboarding.create_project.pat_form.title.bitbucketcloud -

-

- onboarding.create_project.pat_form.help.bitbucketcloud -

- - - - - - - - - save - - - -
- -

- onboarding.create_project.pat_help.instructions_username.bitbucketcloud.title -

-

- onboarding.create_project.pat_help.instructions_username.bitbucketcloud -

- -

- onboarding.create_project.pat_help.bitbucketcloud.title -

-

- -

- -

- onboarding.create_project.pat_help.instructions2.bitbucketcloud -

-
    -
  • - - onboarding.create_project.pat_help.read_permission - , - } - } - /> -
  • -
-
-
-`; - -exports[`should render correctly: gitlab 1`] = ` -
-
-

- onboarding.create_project.pat_form.title.gitlab -

-

- onboarding.create_project.pat_form.help.gitlab -

- - - - - - save - - - -
- -

- onboarding.create_project.pat_help.title -

-

- -

- -

- onboarding.create_project.pat_help.instructions2.gitlab -

-
    -
  • - - onboarding.create_project.pat_help.gitlab.read_api_permission - -
  • -
-
-
-`; - -exports[`should render correctly: gitlab with non-standard api path 1`] = ` -
-
-

- onboarding.create_project.pat_form.title.gitlab -

-

- onboarding.create_project.pat_form.help.gitlab -

- - - - - - save - - - -
- -

- onboarding.create_project.pat_help.title -

-

- -

- -

- onboarding.create_project.pat_help.instructions2.gitlab -

-
    -
  • - - onboarding.create_project.pat_help.gitlab.read_api_permission - -
  • -
-
-
-`; - -exports[`should render correctly: no token needed 1`] = ` - -`; - -exports[`should show error when issue: issue submitting token 1`] = ` -
-
-

- onboarding.create_project.pat_form.title.bitbucketcloud -

-

- onboarding.create_project.pat_form.help.bitbucketcloud -

- - - - - - - - - save - - - -
- -

- onboarding.create_project.pat_help.instructions_username.bitbucketcloud.title -

-

- onboarding.create_project.pat_help.instructions_username.bitbucketcloud -

- -

- onboarding.create_project.pat_help.bitbucketcloud.title -

-

- -

- -

- onboarding.create_project.pat_help.instructions2.bitbucketcloud -

-
    -
  • - - onboarding.create_project.pat_help.read_permission - , - } - } - /> -
  • -
-
-
-`; diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/WrongBindingCountAlert-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/WrongBindingCountAlert-test.tsx.snap deleted file mode 100644 index a1b89ceab0e..00000000000 --- a/server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/WrongBindingCountAlert-test.tsx.snap +++ /dev/null @@ -1,59 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: bitbucket 1`] = ` - - - -`; - -exports[`should render correctly: for admin 1`] = ` - - - settings.page - , - } - } - /> - -`; - -exports[`should render correctly: gitlab 1`] = ` - - - -`; diff --git a/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingDays.tsx b/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingDays.tsx index b4fa182eca3..c982f37b95c 100644 --- a/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingDays.tsx +++ b/server/sonar-web/src/main/js/apps/projectBaseline/components/BaselineSettingDays.tsx @@ -53,7 +53,7 @@ export default function BaselineSettingDays(props: Props) { {action !== undefined && ( )} - {id && label && ( -