From: Grégoire Aubert Date: Fri, 3 Aug 2018 08:06:20 +0000 (+0200) Subject: SONAR-11038 Fix project provisioning X-Git-Tag: 7.5~616 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=19db9d08eb0a4aab7909f561992f137b1e7092a9;p=sonarqube.git SONAR-11038 Fix project provisioning --- diff --git a/server/sonar-web/src/main/js/api/alm-integration.ts b/server/sonar-web/src/main/js/api/alm-integration.ts index 798f16e6d89..d35ff9995e0 100644 --- a/server/sonar-web/src/main/js/api/alm-integration.ts +++ b/server/sonar-web/src/main/js/api/alm-integration.ts @@ -31,6 +31,11 @@ export function getRepositories(): Promise<{ return getJSON('/api/alm_integration/list_repositories').catch(throwGlobalError); } -export function provisionProject(data: { repositories: string[] }) { - return postJSON('api/alm_integration/provision_projects', data).catch(throwGlobalError); +export function provisionProject(data: { + installationKeys: string[]; +}): Promise<{ projects: Array<{ projectKey: string }> }> { + return postJSON('/api/alm_integration/provision_projects', { + ...data, + installationKeys: data.installationKeys.join(',') + }).catch(throwGlobalError); } diff --git a/server/sonar-web/src/main/js/app/components/StartupModal.tsx b/server/sonar-web/src/main/js/app/components/StartupModal.tsx index b85885bbcd0..7930a9b7f21 100644 --- a/server/sonar-web/src/main/js/app/components/StartupModal.tsx +++ b/server/sonar-web/src/main/js/app/components/StartupModal.tsx @@ -171,7 +171,9 @@ export class StartupModal extends React.PureComponent { const { currentUser, location } = this.props; if ( currentUser.showOnboardingTutorial && - !['about', 'documentation', 'onboarding'].some(path => location.pathname.startsWith(path)) + !['about', 'documentation', 'onboarding', 'projects/create'].some(path => + location.pathname.startsWith(path) + ) ) { this.setState({ automatic: true }); if (isSonarCloud()) { diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.tsx index d734d6c1401..ccb40acc1f6 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.tsx @@ -18,8 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { Link } from 'react-router'; import * as classNames from 'classnames'; +import { Link } from 'react-router'; import { isLoggedIn, CurrentUser, AppState, Extension } from '../../../types'; import { translate } from '../../../../helpers/l10n'; import { getQualityGatesUrl, getBaseUrl } from '../../../../helpers/urls'; @@ -44,9 +44,13 @@ export default class GlobalNavMenu extends React.PureComponent { return null; } + const active = + this.props.location.pathname.startsWith('projects') && + this.props.location.pathname !== 'projects/create'; + return (
  • - + {isSonarCloud() ? translate('my_projects') : translate('projects.page')}
  • @@ -74,7 +78,7 @@ export default class GlobalNavMenu extends React.PureComponent { return (
  • {translate('my_issues')} @@ -88,7 +92,7 @@ export default class GlobalNavMenu extends React.PureComponent { : { resolved: 'false' }; return (
  • - + {translate('issues.page')}
  • diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.tsx.snap index b886f31dab4..2acadf725f8 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/__snapshots__/GlobalNavMenu-test.tsx.snap @@ -6,7 +6,7 @@ exports[`should show administration menu if the user has the rights 1`] = ` >
  • { const { identityProvider, repository, selected } = this.props; const alreadyImported = Boolean(repository.linkedProjectKey); return ( - - {identityProvider.name} - {this.props.repository.label} - {alreadyImported && ( + <> + + {identityProvider.name} + {this.props.repository.label} + + {repository.linkedProjectKey && ( - {translate('onboarding.create_project.already_imported')} + + {translate('onboarding.create_project.already_imported')} + )} - + ); } } diff --git a/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx b/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx index 078a54d13de..920be163938 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/AutoProjectCreate.tsx @@ -21,20 +21,17 @@ import * as React from 'react'; import AlmRepositoryItem from './AlmRepositoryItem'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; import IdentityProviderLink from '../../../components/ui/IdentityProviderLink'; -import { getIdentityProviders } from '../../../api/users'; import { getRepositories, provisionProject } from '../../../api/alm-integration'; -import { IdentityProvider, LoggedInUser, AlmRepository } from '../../../app/types'; -import { ProjectBase } from '../../../api/components'; +import { IdentityProvider, AlmRepository } from '../../../app/types'; import { SubmitButton } from '../../../components/ui/buttons'; import { translateWithParameters, translate } from '../../../helpers/l10n'; interface Props { - currentUser: LoggedInUser; - onProjectCreate: (project: ProjectBase[]) => void; + identityProvider: IdentityProvider; + onProjectCreate: (projectKeys: string[]) => void; } interface State { - identityProviders: IdentityProvider[]; installationUrl?: string; installed?: boolean; loading: boolean; @@ -46,7 +43,6 @@ interface State { export default class AutoProjectCreate extends React.PureComponent { mounted = false; state: State = { - identityProviders: [], loading: true, repositories: [], selectedRepositories: {}, @@ -55,37 +51,28 @@ export default class AutoProjectCreate extends React.PureComponent componentDidMount() { this.mounted = true; - Promise.all([this.fetchIdentityProviders(), this.fetchRepositories()]).then( - this.stopLoading, - this.stopLoading - ); + this.fetchRepositories(); } componentWillUnmount() { this.mounted = false; } - fetchIdentityProviders = () => { - return getIdentityProviders().then( - ({ identityProviders }) => { + fetchRepositories = () => { + getRepositories().then( + ({ almIntegration, repositories }) => { if (this.mounted) { - this.setState({ identityProviders }); + this.setState({ ...almIntegration, loading: false, repositories }); } }, () => { - return Promise.resolve(); + if (this.mounted) { + this.setState({ loading: false }); + } } ); }; - fetchRepositories = () => { - return getRepositories().then(({ almIntegration, repositories }) => { - if (this.mounted) { - this.setState({ ...almIntegration, repositories }); - } - }); - }; - handleFormSubmit = (event: React.FormEvent) => { event.preventDefault(); @@ -93,15 +80,15 @@ export default class AutoProjectCreate extends React.PureComponent const { selectedRepositories } = this.state; this.setState({ submitting: true }); provisionProject({ - repositories: Object.keys(selectedRepositories).filter(key => + installationKeys: Object.keys(selectedRepositories).filter(key => Boolean(selectedRepositories[key]) ) }).then( - ({ project }) => this.props.onProjectCreate([project]), + ({ projects }) => this.props.onProjectCreate(projects.map(project => project.projectKey)), () => { if (this.mounted) { - this.setState({ submitting: false }); - this.reloadRepositories(); + this.setState({ loading: true, submitting: false }); + this.fetchRepositories(); } } ); @@ -114,17 +101,6 @@ export default class AutoProjectCreate extends React.PureComponent ); }; - reloadRepositories = () => { - this.setState({ loading: true }); - this.fetchRepositories().then(this.stopLoading, this.stopLoading); - }; - - stopLoading = () => { - if (this.mounted) { - this.setState({ loading: false }); - } - }; - toggleRepository = (repository: AlmRepository) => { this.setState(({ selectedRepositories }) => ({ selectedRepositories: { @@ -136,21 +112,57 @@ export default class AutoProjectCreate extends React.PureComponent })); }; - render() { - if (this.state.loading) { - return ; - } - - const { currentUser } = this.props; - const identityProvider = this.state.identityProviders.find( - identityProvider => identityProvider.key === currentUser.externalProvider - ); + renderContent = () => { + const { identityProvider } = this.props; + const { selectedRepositories, submitting } = this.state; - if (!identityProvider) { - return null; + if (this.state.installed) { + return ( +
    +
      + {this.state.repositories.map(repo => ( +
    • + +
    • + ))} +
    + + {translate('create')} + + + + ); } + return ( +
    +

    + {translateWithParameters( + 'onboarding.create_project.install_app_x', + identityProvider.name + )} +

    + + {translateWithParameters( + 'onboarding.create_project.install_app_x.button', + identityProvider.name + )} + +
    + ); + }; - const { selectedRepositories, submitting } = this.state; + render() { + const { identityProvider } = this.props; + const { loading } = this.state; return ( <> @@ -160,45 +172,7 @@ export default class AutoProjectCreate extends React.PureComponent identityProvider.name )}

    - {this.state.installed ? ( -
    -
      - {this.state.repositories.map(repo => ( -
    • - -
    • - ))} -
    - - {translate('onboarding.create_project.create_project')} - - - - ) : ( -
    -

    - {translateWithParameters( - 'onboarding.create_project.install_app_x', - identityProvider.name - )} -

    - - {translateWithParameters( - 'onboarding.create_project.install_app_x.button', - identityProvider.name - )} - -
    - )} + {loading ? : this.renderContent()} ); } diff --git a/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx b/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx index 63224ebacec..a3cdbb510a0 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/CreateProjectPage.tsx @@ -26,18 +26,18 @@ import Helmet from 'react-helmet'; import AutoProjectCreate from './AutoProjectCreate'; import ManualProjectCreate from './ManualProjectCreate'; import { serializeQuery, Query, parseQuery } from './utils'; +import DeferredSpinner from '../../../components/common/DeferredSpinner'; import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; import { getCurrentUser } from '../../../store/rootReducer'; -import { skipOnboarding } from '../../../store/users/actions'; -import { CurrentUser, isLoggedIn } from '../../../app/types'; +import { skipOnboarding as skipOnboardingAction } from '../../../store/users/actions'; +import { CurrentUser, IdentityProvider, isLoggedIn, LoggedInUser } from '../../../app/types'; +import { skipOnboarding, getIdentityProviders } from '../../../api/users'; import { translate } from '../../../helpers/l10n'; -import { ProjectBase } from '../../../api/components'; -import { getProjectUrl, getOrganizationUrl } from '../../../helpers/urls'; +import { getProjectUrl } from '../../../helpers/urls'; import '../../../app/styles/sonarcloud.css'; interface OwnProps { location: Location; - onFinishOnboarding: () => void; router: Pick; } @@ -46,16 +46,24 @@ interface StateProps { } interface DispatchProps { - skipOnboarding: () => void; + skipOnboardingAction: () => void; } -type Props = OwnProps & StateProps & DispatchProps; +interface Props extends OwnProps, StateProps, DispatchProps { + currentUser: LoggedInUser; +} + +interface State { + identityProvider?: IdentityProvider; + loading: boolean; +} -export class CreateProjectPage extends React.PureComponent { +export class CreateProjectPage extends React.PureComponent { mounted = false; constructor(props: Props) { super(props); + this.state = { loading: true }; if (!this.canAutoCreate(props)) { this.updateQuery({ manual: true }); } @@ -76,18 +84,37 @@ export class CreateProjectPage extends React.PureComponent { document.documentElement.classList.remove('white-page'); } - handleProjectCreate = (projects: Pick[], organization?: string) => { - if (projects.length > 1 && organization) { - this.props.router.push(getOrganizationUrl(organization) + '/projects'); - } else if (projects.length === 1) { - this.props.router.push(getProjectUrl(projects[0].key)); + handleProjectCreate = (projectKeys: string[]) => { + skipOnboarding().catch(() => {}); + this.props.skipOnboardingAction(); + if (projectKeys.length > 1) { + this.props.router.push({ pathname: '/projects' }); + } else if (projectKeys.length === 1) { + this.props.router.push(getProjectUrl(projectKeys[0])); } }; canAutoCreate = ({ currentUser } = this.props) => { - return ( - isLoggedIn(currentUser) && - ['bitbucket', 'github'].includes(currentUser.externalProvider || '') + return ['bitbucket', 'github'].includes(currentUser.externalProvider || ''); + }; + + fetchIdentityProviders = () => { + getIdentityProviders().then( + ({ identityProviders }) => { + if (this.mounted) { + this.setState({ + identityProvider: identityProviders.find( + identityProvider => identityProvider.key === this.props.currentUser.externalProvider + ), + loading: false + }); + } + }, + () => { + if (this.mounted) { + this.setState({ loading: false }); + } + } ); }; @@ -110,11 +137,10 @@ export class CreateProjectPage extends React.PureComponent { render() { const { currentUser } = this.props; - if (!isLoggedIn(currentUser)) { - return null; - } + const { identityProvider, loading } = this.state; const displayManual = parseQuery(this.props.location.query).manual; const header = translate('onboarding.create_project.header'); + const hasAutoProvisioning = this.canAutoCreate() && identityProvider; return ( <> @@ -122,48 +148,53 @@ export class CreateProjectPage extends React.PureComponent {

    {header}

    - - {this.canAutoCreate() && ( - - )} - - {displayManual || !this.canAutoCreate() ? ( - + {loading ? ( + ) : ( - + <> + {hasAutoProvisioning && ( + + )} + + {displayManual || !hasAutoProvisioning ? ( + + ) : ( + + )} + )} @@ -177,7 +208,7 @@ const mapStateToProps = (state: any): StateProps => { }; }; -const mapDispatchToProps: DispatchProps = { skipOnboarding }; +const mapDispatchToProps: DispatchProps = { skipOnboardingAction }; export default connect(mapStateToProps, mapDispatchToProps)( CreateProjectPage diff --git a/server/sonar-web/src/main/js/apps/projects/create/ManualProjectCreate.tsx b/server/sonar-web/src/main/js/apps/projects/create/ManualProjectCreate.tsx index 041b09bdd4d..d1df2b59ec0 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/ManualProjectCreate.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/ManualProjectCreate.tsx @@ -27,7 +27,7 @@ import { LoggedInUser, Organization } from '../../../app/types'; import { fetchMyOrganizations } from '../../account/organizations/actions'; import { getMyOrganizations } from '../../../store/rootReducer'; import { translate } from '../../../helpers/l10n'; -import { createProject, ProjectBase } from '../../../api/components'; +import { createProject } from '../../../api/components'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; interface StateProps { @@ -40,7 +40,7 @@ interface DispatchProps { interface OwnProps { currentUser: LoggedInUser; - onProjectCreate: (project: ProjectBase[]) => void; + onProjectCreate: (projectKeys: string[]) => void; } type Props = OwnProps & StateProps & DispatchProps; @@ -91,7 +91,7 @@ export class ManualProjectCreate extends React.PureComponent { name: projectName, organization: selectedOrganization }).then( - ({ project }) => this.props.onProjectCreate([project]), + ({ project }) => this.props.onProjectCreate([project.key]), () => { if (this.mounted) { this.setState({ submitting: false }); @@ -198,7 +198,7 @@ export class ManualProjectCreate extends React.PureComponent { /> - {translate('onboarding.create_project.create_project')} + {translate('create')} diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/AutoProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/projects/create/__tests__/AutoProjectCreate-test.tsx index bfe95430578..91e189f4204 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/AutoProjectCreate-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/AutoProjectCreate-test.tsx @@ -20,24 +20,9 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import AutoProjectCreate from '../AutoProjectCreate'; -import { getIdentityProviders } from '../../../../api/users'; import { getRepositories } from '../../../../api/alm-integration'; -import { LoggedInUser } from '../../../../app/types'; import { waitAndUpdate } from '../../../../helpers/testUtils'; -jest.mock('../../../../api/users', () => ({ - getIdentityProviders: jest.fn().mockResolvedValue({ - identityProviders: [ - { - backgroundColor: 'blue', - iconPath: 'icon/path', - key: 'foo', - name: 'Foo Provider' - } - ] - }) -})); - jest.mock('../../../../api/alm-integration', () => ({ getRepositories: jest.fn().mockResolvedValue({ almIntegration: { @@ -49,7 +34,13 @@ jest.mock('../../../../api/alm-integration', () => ({ provisionProject: jest.fn().mockResolvedValue({ projects: [] }) })); -const user: LoggedInUser = { isLoggedIn: true, login: 'foo', name: 'Foo', externalProvider: 'foo' }; +const identityProvider = { + backgroundColor: 'blue', + iconPath: 'icon/path', + key: 'foo', + name: 'Foo Provider' +}; + const repositories = [ { label: 'Cool Project', @@ -64,14 +55,12 @@ const repositories = [ ]; beforeEach(() => { - (getIdentityProviders as jest.Mock).mockClear(); (getRepositories as jest.Mock).mockClear(); }); it('should display the provider app install button', async () => { const wrapper = getWrapper(); expect(wrapper).toMatchSnapshot(); - expect(getIdentityProviders).toHaveBeenCalled(); expect(getRepositories).toHaveBeenCalled(); await waitAndUpdate(wrapper); @@ -92,5 +81,7 @@ it('should display the list of repositories', async () => { }); function getWrapper(props = {}) { - return shallow(); + return shallow( + + ); } diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx b/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx index 6f995afd252..42f39b9fb61 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/CreateProjectPage-test.tsx @@ -21,8 +21,22 @@ import * as React from 'react'; import { shallow } from 'enzyme'; import { Location } from 'history'; import { CreateProjectPage } from '../CreateProjectPage'; +import { getIdentityProviders } from '../../../../api/users'; import { LoggedInUser } from '../../../../app/types'; -import { click } from '../../../../helpers/testUtils'; +import { click, waitAndUpdate } from '../../../../helpers/testUtils'; + +jest.mock('../../../../api/users', () => ({ + getIdentityProviders: jest.fn().mockResolvedValue({ + identityProviders: [ + { + backgroundColor: 'blue', + iconPath: 'icon/path', + key: 'github', + name: 'GitHub' + } + ] + }) +})); const user: LoggedInUser = { externalProvider: 'github', @@ -31,21 +45,32 @@ const user: LoggedInUser = { name: 'Foo' }; -it('should render correctly', () => { - expect(getWrapper()).toMatchSnapshot(); +beforeEach(() => { + (getIdentityProviders as jest.Mock).mockClear(); +}); + +it('should render correctly', async () => { + const wrapper = getWrapper(); + expect(wrapper).toMatchSnapshot(); + await waitAndUpdate(wrapper); + expect(wrapper).toMatchSnapshot(); }); it('should render with Manual creation only', () => { expect(getWrapper({ currentUser: { ...user, externalProvider: 'microsoft' } })).toMatchSnapshot(); }); -it('should switch tabs', () => { +it('should switch tabs', async () => { const replace = jest.fn(); const wrapper = getWrapper({ router: { replace } }); replace.mockImplementation(location => { wrapper.setProps({ location }).update(); }); + await waitAndUpdate(wrapper); + + expect(wrapper).toMatchSnapshot(); + click(wrapper.find('.js-manual')); expect(wrapper.find('Connect(ManualProjectCreate)').exists()).toBeTruthy(); click(wrapper.find('.js-auto')); @@ -57,9 +82,8 @@ function getWrapper(props = {}) { ); diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx b/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx index b79b4e4ae35..f67db69e464 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/ManualProjectCreate-test.tsx @@ -63,7 +63,7 @@ it('should correctly create a project', async () => { expect(createProject).toBeCalledWith({ project: 'bar', name: 'Bar', organization: 'foo' }); await waitAndUpdate(wrapper); - expect(onProjectCreate).toBeCalledWith([{ key: 'bar', name: 'Bar' }]); + expect(onProjectCreate).toBeCalledWith(['bar']); }); function getWrapper(props = {}) { diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AlmRepositoryItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AlmRepositoryItem-test.tsx.snap index eddcbf0214b..292a0a839c0 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AlmRepositoryItem-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AlmRepositoryItem-test.tsx.snap @@ -1,56 +1,60 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should render correctly 1`] = ` - - Foo Provider - + - Awesome Project - - + Foo Provider + + Awesome Project + + + `; exports[`should render disabled 1`] = ` - - Foo Provider - + - Cool Project - + Foo Provider + + Cool Project + + @@ -58,34 +62,50 @@ exports[`should render disabled 1`] = ` className="little-spacer-right" fill="#00aa00" /> - onboarding.create_project.already_imported + + onboarding.create_project.already_imported + - + `; exports[`should render selected 1`] = ` - - Foo Provider - + - Awesome Project - - + Foo Provider + + Awesome Project + + + `; diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap index 6d6c0398864..7a0c3760929 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/AutoProjectCreate-test.tsx.snap @@ -63,7 +63,7 @@ exports[`should display the list of repositories 1`] = ` - onboarding.create_project.create_project + create + +

    + onboarding.create_project.beta_feature_x.Foo Provider +

    + +
    `; exports[`should display the provider app install button 2`] = ` diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap index 1880a16ba4c..fffc678a6db 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/CreateProjectPage-test.tsx.snap @@ -20,44 +20,73 @@ exports[`should render correctly 1`] = ` onboarding.create_project.header - + + onProjectCreate={[Function]} + /> + `; @@ -82,17 +111,83 @@ exports[`should render with Manual creation only 1`] = ` onboarding.create_project.header - + + onProjectCreate={[Function]} + /> + + + +`; + +exports[`should switch tabs 1`] = ` + + + `; diff --git a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap index fafb751c9bb..8f1ddb22631 100644 --- a/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/create/__tests__/__snapshots__/ManualProjectCreate-test.tsx.snap @@ -4,7 +4,7 @@ exports[`should correctly create a project 1`] = ` - onboarding.create_project.create_project + create `; @@ -12,7 +12,7 @@ exports[`should correctly create a project 2`] = ` - onboarding.create_project.create_project + create `; @@ -113,7 +113,7 @@ exports[`should render correctly 1`] = ` - onboarding.create_project.create_project + create ; personalOrganization?: string; - selection: 'personal' | 'existing' | 'new'; + selection: Selection; } export default class OrganizationStep extends React.PureComponent { @@ -74,9 +76,10 @@ export default class OrganizationStep extends React.PureComponent const personalOrganization = organizationKeys.length === 1 ? organizationKeys[0] : undefined; const existingOrganizations = organizationKeys.length > 1 ? sortBy(organizationKeys) : []; - const selection = personalOrganization - ? 'personal' - : existingOrganizations.length > 0 ? 'existing' : 'new'; + let selection: Selection = 'personal'; + if (!personalOrganization) { + selection = existingOrganizations.length > 0 ? 'existing' : 'new'; + } this.setState({ loading: false, existingOrganizations,