aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/create/organization
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2020-09-22 14:20:28 +0200
committersonartech <sonartech@sonarsource.com>2020-09-28 20:07:23 +0000
commit71cc0592365fc7ff36694c726c1a8ca4e1fcc6cd (patch)
tree79f66251286871397c898aca6ccb050c5f102f23 /server/sonar-web/src/main/js/apps/create/organization
parent7d546a463731e1410ba34225e2e1aa5d9586a3b2 (diff)
downloadsonarqube-71cc0592365fc7ff36694c726c1a8ca4e1fcc6cd.tar.gz
sonarqube-71cc0592365fc7ff36694c726c1a8ca4e1fcc6cd.zip
SONAR-13880 internationalize tooltips
Diffstat (limited to 'server/sonar-web/src/main/js/apps/create/organization')
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx43
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationBind.tsx115
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx215
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx456
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/ManualOrganizationCreate.tsx76
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsForm.tsx205
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx63
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/PlanSelect.tsx81
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/PlanStep.tsx165
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/RemoteOrganizationChoose.tsx204
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/AlmApplicationInstalling-test.tsx27
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationBind-test.tsx52
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx128
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx342
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/ManualOrganizationCreate-test.tsx59
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsForm-test.tsx84
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsStep-test.tsx56
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanSelect-test.tsx62
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanStep-test.tsx93
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/RemoteOrganizationChoose-test.tsx77
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AlmApplicationInstalling-test.tsx.snap47
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationBind-test.tsx.snap50
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap216
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap489
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ManualOrganizationCreate-test.tsx.snap84
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsForm-test.tsx.snap107
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsStep-test.tsx.snap28
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanSelect-test.tsx.snap47
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanStep-test.tsx.snap163
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/RemoteOrganizationChoose-test.tsx.snap195
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/actions-test.ts79
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/utils-test.tsx32
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/actions.ts40
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/utils.ts80
34 files changed, 0 insertions, 4260 deletions
diff --git a/server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx b/server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx
deleted file mode 100644
index d6b9dcebf01..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
-import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
-import { sanitizeAlmId } from '../../../helpers/almIntegrations';
-
-export default function AlmApplicationInstalling({ almKey }: { almKey?: string }) {
- return (
- <DeferredSpinner
- customSpinner={
- <div className="sonarcloud page page-limited">
- <div className="huge-spacer-top text-center">
- <i className="spinner" />
- <p className="big-spacer-top">
- {translateWithParameters(
- 'onboarding.import_organization.installing',
- almKey ? translate(sanitizeAlmId(almKey)) : 'ALM'
- )}
- </p>
- </div>
- </div>
- }
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationBind.tsx b/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationBind.tsx
deleted file mode 100644
index 38d3862aa7d..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationBind.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { Link } from 'react-router';
-import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';
-import { Alert } from 'sonar-ui-common/components/ui/Alert';
-import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
-import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
-import { isGithub } from '../../../helpers/almIntegrations';
-import OrganizationSelect from '../components/OrganizationSelect';
-
-interface Props {
- almKey: string;
- onBindOrganization: (organization: string) => Promise<void>;
- unboundOrganizations: T.Organization[];
-}
-
-interface State {
- organization: string;
- submitting: boolean;
-}
-
-export default class AutoOrganizationBind extends React.PureComponent<Props, State> {
- mounted = false;
-
- constructor(props: Props) {
- super(props);
- this.state = { organization: this.getInitialSelectedOrganization(props), submitting: false };
- }
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- getInitialSelectedOrganization(props: Props) {
- if (props.unboundOrganizations.length === 1) {
- return props.unboundOrganizations[0].key;
- }
- return '';
- }
-
- handleChange = ({ key }: T.Organization) => {
- this.setState({ organization: key });
- };
-
- handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
- event.preventDefault();
- const { organization } = this.state;
- if (organization) {
- this.setState({ submitting: true });
- this.props.onBindOrganization(organization).then(this.stopSubmitting, this.stopSubmitting);
- }
- };
-
- stopSubmitting = () => {
- if (this.mounted) {
- this.setState({ submitting: false });
- }
- };
-
- render() {
- const { almKey } = this.props;
- const { organization, submitting } = this.state;
- return (
- <form id="bind-organization-form" onSubmit={this.handleSubmit}>
- <OrganizationSelect
- onChange={this.handleChange}
- organization={organization}
- organizations={this.props.unboundOrganizations}
- />
- {isGithub(almKey) && (
- <Alert className="abs-width-400 big-spacer-top" display="block" variant="info">
- {translateWithParameters(
- 'onboarding.import_organization.bind_members_not_sync_info_x',
- translate('organization', almKey)
- )}
- <Link
- className="spacer-left"
- target="_blank"
- to={{ pathname: '/documentation/organizations/manage-team/' }}>
- {translate('learn_more')}
- </Link>
- </Alert>
- )}
- <div className="display-flex-center big-spacer-top">
- <SubmitButton disabled={submitting || !organization}>
- {translate('onboarding.import_organization.bind')}
- </SubmitButton>
- {submitting && <DeferredSpinner className="spacer-left" />}
- </div>
- </form>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx b/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx
deleted file mode 100644
index 1f0542b429c..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { ClearButton } from 'sonar-ui-common/components/controls/buttons';
-import RadioToggle from 'sonar-ui-common/components/controls/RadioToggle';
-import { Alert } from 'sonar-ui-common/components/ui/Alert';
-import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
-import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
-import { bindAlmOrganization } from '../../../api/alm-integration';
-import { getAlmMembersUrl, isGithub, sanitizeAlmId } from '../../../helpers/almIntegrations';
-import AutoOrganizationBind from './AutoOrganizationBind';
-import OrganizationDetailsForm from './OrganizationDetailsForm';
-import OrganizationDetailsStep from './OrganizationDetailsStep';
-import PlanStep from './PlanStep';
-import { Step } from './utils';
-
-enum Filters {
- Bind = 'bind',
- Create = 'create'
-}
-
-interface Props {
- almApplication: T.AlmApplication;
- almInstallId: string;
- almOrganization: T.AlmOrganization;
- className?: string;
- createOrganization: (
- organization: T.Organization & { installationId?: string }
- ) => Promise<string>;
- handleCancelImport: () => void;
- handleOrgDetailsFinish: (organization: T.Organization) => Promise<void>;
- handleOrgDetailsStepOpen: () => void;
- onDone: () => void;
- onOrgCreated: (organization: string) => void;
- onUpgradeFail: () => void;
- organization?: T.Organization;
- step: Step;
- subscriptionPlans?: T.SubscriptionPlan[];
- unboundOrganizations: T.Organization[];
-}
-
-interface State {
- filter?: Filters;
-}
-
-export default class AutoOrganizationCreate extends React.PureComponent<Props, State> {
- constructor(props: Props) {
- super(props);
- this.state = {
- filter: props.unboundOrganizations.length === 0 ? Filters.Create : undefined
- };
- }
-
- handleBindOrganization = (organization: string) => {
- return bindAlmOrganization({
- organization,
- installationId: this.props.almInstallId
- }).then(() => this.props.onOrgCreated(organization));
- };
-
- handleCreateOrganization = () => {
- const { almApplication, almOrganization, organization } = this.props;
- if (!organization) {
- return Promise.reject();
- }
- return this.props.createOrganization({
- ...organization,
- alm: {
- key: almApplication.key,
- membersSync: true,
- personal: almOrganization.personal,
- url: almOrganization.almUrl
- },
- installationId: this.props.almInstallId
- });
- };
-
- handleOptionChange = (filter: Filters) => {
- this.setState({ filter });
- };
-
- render() {
- const {
- almApplication,
- almOrganization,
- className,
- organization,
- step,
- subscriptionPlans,
- unboundOrganizations
- } = this.props;
- const { filter } = this.state;
- const hasUnboundOrgs = unboundOrganizations.length > 0;
- const almKey = sanitizeAlmId(almApplication.key);
- return (
- <div className={className}>
- <OrganizationDetailsStep
- finished={organization !== undefined}
- onOpen={this.props.handleOrgDetailsStepOpen}
- open={step === Step.OrganizationDetails}
- organization={organization}
- stepTitle={translate('onboarding.import_organization.import_org_details')}>
- <div className="huge-spacer-bottom">
- <p className="display-flex-center big-spacer-bottom">
- <FormattedMessage
- defaultMessage={translate('onboarding.import_organization_x')}
- id="onboarding.import_organization_x"
- values={{
- avatar: (
- <img
- alt={almApplication.name}
- className="little-spacer-left"
- src={`${getBaseUrl()}/images/sonarcloud/${sanitizeAlmId(
- almApplication.key
- )}.svg`}
- width={16}
- />
- ),
- name: <strong>{almOrganization.name}</strong>
- }}
- />
- <ClearButton className="little-spacer-left" onClick={this.props.handleCancelImport} />
- </p>
-
- {hasUnboundOrgs && (
- <RadioToggle
- name="filter"
- onCheck={this.handleOptionChange}
- options={[
- {
- label: translate('onboarding.import_organization.create_new'),
- value: Filters.Create
- },
- {
- label: translate('onboarding.import_organization.bind_existing'),
- value: Filters.Bind
- }
- ]}
- value={filter}
- />
- )}
- </div>
-
- {filter === Filters.Create && (
- <OrganizationDetailsForm
- infoBlock={
- isGithub(almKey) && (
- <Alert className="abs-width-600 big-spacer-top" display="block" variant="info">
- <p>
- {translateWithParameters(
- 'onboarding.import_organization.members_sync_info_x',
- translate('organization', almKey),
- almOrganization.name,
- translate(almKey)
- )}
- </p>
- <a
- href={getAlmMembersUrl(almApplication.key, almOrganization.almUrl)}
- rel="noopener noreferrer"
- target="_blank">
- {translateWithParameters(
- 'organization.members.see_all_members_on_x',
- translate(almKey)
- )}
- </a>
- </Alert>
- )
- }
- onContinue={this.props.handleOrgDetailsFinish}
- organization={almOrganization}
- submitText={translate('continue')}
- />
- )}
- {filter === Filters.Bind && (
- <AutoOrganizationBind
- almKey={almKey}
- onBindOrganization={this.handleBindOrganization}
- unboundOrganizations={unboundOrganizations}
- />
- )}
- </OrganizationDetailsStep>
-
- {subscriptionPlans !== undefined && filter !== Filters.Bind && (
- <PlanStep
- almApplication={this.props.almApplication}
- almOrganization={this.props.almOrganization}
- createOrganization={this.handleCreateOrganization}
- onDone={this.props.onDone}
- onUpgradeFail={this.props.onUpgradeFail}
- open={step === Step.Plan}
- subscriptionPlans={subscriptionPlans}
- />
- )}
- </div>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx b/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
deleted file mode 100644
index ac6a60056f8..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as classNames from 'classnames';
-import * as differenceInMinutes from 'date-fns/difference_in_minutes';
-import { times } from 'lodash';
-import * as React from 'react';
-import { Helmet } from 'react-helmet-async';
-import { connect } from 'react-redux';
-import { withRouter, WithRouterProps } from 'react-router';
-import Tabs from 'sonar-ui-common/components/controls/Tabs';
-import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
-import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
-import { addWhitePageClass, removeWhitePageClass } from 'sonar-ui-common/helpers/pages';
-import { get, remove } from 'sonar-ui-common/helpers/storage';
-import { slugify } from 'sonar-ui-common/helpers/strings';
-import {
- bindAlmOrganization,
- getAlmAppInfo,
- getAlmOrganization,
- GetAlmOrganizationResponse,
- listUnboundApplications
-} from '../../../api/alm-integration';
-import { getSubscriptionPlans } from '../../../api/billing';
-import * as api from '../../../api/organizations';
-import A11ySkipTarget from '../../../app/components/a11y/A11ySkipTarget';
-import addGlobalSuccessMessage from '../../../app/utils/addGlobalSuccessMessage';
-import { whenLoggedIn } from '../../../components/hoc/whenLoggedIn';
-import { withUserOrganizations } from '../../../components/hoc/withUserOrganizations';
-import { hasAdvancedALMIntegration, sanitizeAlmId } from '../../../helpers/almIntegrations';
-import { getOrganizationUrl } from '../../../helpers/urls';
-import { skipOnboarding } from '../../../store/users';
-import { deleteOrganization } from '../../organizations/actions';
-import { createOrganization } from './actions';
-import AlmApplicationInstalling from './AlmApplicationInstalling';
-import AutoOrganizationCreate from './AutoOrganizationCreate';
-import ManualOrganizationCreate from './ManualOrganizationCreate';
-import RemoteOrganizationChoose from './RemoteOrganizationChoose';
-import {
- BIND_ORGANIZATION_KEY,
- BIND_ORGANIZATION_REDIRECT_TO_ORG_TIMESTAMP,
- ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP,
- ORGANIZATION_IMPORT_REDIRECT_TO_PROJECT_TIMESTAMP,
- parseQuery,
- Query,
- serializeQuery,
- Step
-} from './utils';
-
-interface Props {
- createOrganization: (
- organization: T.Organization & { installationId?: string }
- ) => Promise<string>;
- currentUser: T.LoggedInUser;
- deleteOrganization: (key: string) => Promise<void>;
- userOrganizations: T.Organization[];
- skipOnboarding: () => void;
-}
-
-interface State {
- almApplication?: T.AlmApplication;
- almOrganization?: T.AlmOrganization;
- almOrgLoading: boolean;
- almUnboundApplications: T.AlmUnboundApplication[];
- bindingExistingOrg: boolean;
- boundOrganization?: T.OrganizationBase;
- loading: boolean;
- organization?: T.Organization;
- step: Step;
- subscriptionPlans?: T.SubscriptionPlan[];
-}
-
-type StateWithAutoImport = State & Required<Pick<State, 'almApplication'>>;
-
-type TabKeys = 'auto' | 'manual';
-
-interface LocationState {
- tab?: TabKeys;
-}
-
-export class CreateOrganization extends React.PureComponent<Props & WithRouterProps, State> {
- mounted = false;
- state: State = {
- almOrgLoading: false,
- almUnboundApplications: [],
- bindingExistingOrg: false,
- loading: true,
- step: Step.OrganizationDetails
- };
-
- componentDidMount() {
- this.mounted = true;
- addWhitePageClass();
-
- const query = parseQuery(this.props.location.query);
-
- //highjack the process for the organization settings
- if (
- hasAdvancedALMIntegration(this.props.currentUser) &&
- query.almInstallId &&
- this.isStoredTimestampValid(BIND_ORGANIZATION_REDIRECT_TO_ORG_TIMESTAMP)
- ) {
- this.bindAndRedirectToOrganizationSettings(query.almInstallId);
- } else {
- const initRequests = [this.fetchSubscriptionPlans()];
- if (hasAdvancedALMIntegration(this.props.currentUser)) {
- initRequests.push(this.fetchAlmApplication());
-
- if (query.almInstallId) {
- this.fetchAlmOrganization(query.almInstallId);
- } else {
- initRequests.push(this.fetchAlmUnboundApplications());
- }
- }
- Promise.all(initRequests).then(this.stopLoading, this.stopLoading);
- }
- }
-
- componentDidUpdate(prevProps: WithRouterProps) {
- const prevQuery = parseQuery(prevProps.location.query);
- const query = parseQuery(this.props.location.query);
- if (this.state.almApplication && prevQuery.almInstallId !== query.almInstallId) {
- if (query.almInstallId) {
- this.fetchAlmOrganization(query.almInstallId);
- } else {
- this.setState({ almOrganization: undefined, boundOrganization: undefined, loading: true });
- this.fetchAlmUnboundApplications().then(this.stopLoading, this.stopLoading);
- }
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- removeWhitePageClass();
- }
-
- deleteOrganization = () => {
- if (this.state.organization) {
- this.props.deleteOrganization(this.state.organization.key);
- }
- };
-
- fetchAlmApplication = () => {
- return getAlmAppInfo().then(({ application }) => {
- if (this.mounted) {
- this.setState({ almApplication: application });
- }
- });
- };
-
- fetchAlmOrganization = (installationId: string) => {
- this.setState({ almOrgLoading: true });
- return getAlmOrganization({ installationId })
- .then(({ almOrganization, boundOrganization }) => {
- if (boundOrganization) {
- return { almOrganization, boundOrganization };
- }
- return this.setValidOrgKey(almOrganization);
- })
- .then(
- ({ almOrganization, boundOrganization }: GetAlmOrganizationResponse) => {
- if (this.mounted) {
- if (
- boundOrganization &&
- boundOrganization.key &&
- !this.isStoredTimestampValid(ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP)
- ) {
- this.props.router.push({
- pathname: getOrganizationUrl(boundOrganization.key)
- });
- } else {
- this.setState({ almOrganization, almOrgLoading: false, boundOrganization });
- }
- }
- },
- () => {
- if (this.mounted) {
- this.setState({ almOrgLoading: false });
- }
- }
- );
- };
-
- fetchAlmUnboundApplications = () => {
- return listUnboundApplications().then(almUnboundApplications => {
- if (this.mounted) {
- this.setState({ almUnboundApplications });
- }
- });
- };
-
- fetchSubscriptionPlans = () => {
- return getSubscriptionPlans().then(subscriptionPlans => {
- if (this.mounted) {
- this.setState({ subscriptionPlans });
- }
- });
- };
-
- handleCancelImport = () => {
- this.updateUrlQuery({ almInstallId: undefined, almKey: undefined });
- };
-
- handleOrgCreated = (organization: string) => {
- this.props.skipOnboarding();
- if (this.isStoredTimestampValid(ORGANIZATION_IMPORT_REDIRECT_TO_PROJECT_TIMESTAMP)) {
- this.props.router.push({
- pathname: '/projects/create',
- state: { organization, tab: this.state.almOrganization ? 'auto' : 'manual' }
- });
- } else {
- this.props.router.push({ pathname: getOrganizationUrl(organization) });
- }
- };
-
- handleOrgDetailsFinish = (organization: T.Organization) => {
- this.setState({ organization, step: Step.Plan });
- return Promise.resolve();
- };
-
- handleOrgDetailsStepOpen = () => {
- this.setState({ step: Step.OrganizationDetails });
- };
-
- handlePlanDone = () => {
- if (this.state.organization) {
- this.handleOrgCreated(this.state.organization.key);
- }
- };
-
- hasAutoImport(state: State): state is StateWithAutoImport {
- return Boolean(state.almApplication);
- }
-
- isStoredTimestampValid = (timestampKey: string) => {
- const storedTimestamp = get(timestampKey);
- remove(timestampKey);
- return storedTimestamp && differenceInMinutes(Date.now(), Number(storedTimestamp)) < 10;
- };
-
- onTabChange = (tab: TabKeys) => {
- this.updateUrlState({ tab });
- };
-
- bindAndRedirectToOrganizationSettings(installationId: string) {
- const organizationKey = get(BIND_ORGANIZATION_KEY) || '';
- remove(BIND_ORGANIZATION_KEY);
-
- this.setState({ bindingExistingOrg: true });
-
- bindAlmOrganization({
- installationId,
- organization: organizationKey
- }).then(
- () => {
- this.props.router.push({
- pathname: `/organizations/${organizationKey}`
- });
- addGlobalSuccessMessage(translate('organization.bind.success'));
- },
- () => {}
- );
- }
-
- getHeader = (bindingExistingOrg: boolean) => {
- if (bindingExistingOrg) {
- return translate('onboarding.binding_organization');
- } else {
- return translate('onboarding.create_organization.page.header');
- }
- };
-
- setValidOrgKey = (almOrganization: T.AlmOrganization) => {
- const key = slugify(almOrganization.key);
- const keys = [key, ...times(9, i => `${key}-${i + 1}`)];
- return api
- .getOrganizations({ organizations: keys.join(',') })
- .then(
- ({ organizations }) => {
- const availableKey = keys.find(key => !organizations.find(o => o.key === key));
- return availableKey || `${key}-${Math.ceil(Math.random() * 1000) + 10}`;
- },
- () => key
- )
- .then(key => {
- return { almOrganization: { ...almOrganization, key } };
- });
- };
-
- stopLoading = () => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- };
-
- updateUrlQuery = (query: Partial<Query> = {}) => {
- this.props.router.push({
- pathname: this.props.location.pathname,
- query: serializeQuery({ ...parseQuery(this.props.location.query), ...query }),
- state: this.props.location.state
- });
- };
-
- updateUrlState = (state: Partial<LocationState> = {}) => {
- this.props.router.replace({
- pathname: this.props.location.pathname,
- query: this.props.location.query,
- state: { ...(this.props.location.state || {}), ...state }
- });
- };
-
- renderContent = (almInstallId?: string) => {
- const { location } = this.props;
- const { state } = this;
- const { organization, step, subscriptionPlans } = state;
- const { tab = 'auto' } = (location.state || {}) as LocationState;
-
- const commonProps = {
- handleOrgDetailsFinish: this.handleOrgDetailsFinish,
- handleOrgDetailsStepOpen: this.handleOrgDetailsStepOpen,
- onDone: this.handlePlanDone,
- organization,
- step,
- subscriptionPlans
- };
-
- if (!this.hasAutoImport(state)) {
- return (
- <ManualOrganizationCreate
- {...commonProps}
- createOrganization={this.props.createOrganization}
- onUpgradeFail={this.deleteOrganization}
- organization={this.state.organization}
- step={this.state.step}
- />
- );
- }
-
- const { almApplication, almOrganization, boundOrganization } = state;
-
- return (
- <>
- <Tabs<TabKeys>
- onChange={this.onTabChange}
- selected={tab || 'auto'}
- tabs={[
- {
- key: 'auto',
- node: translateWithParameters(
- 'onboarding.import_organization.import_from_x',
- translate(sanitizeAlmId(almApplication.key))
- )
- },
- {
- key: 'manual',
- node: translate('onboarding.create_organization.create_manually')
- }
- ]}
- />
-
- <ManualOrganizationCreate
- {...commonProps}
- className={classNames({ hidden: tab !== 'manual' && this.hasAutoImport(state) })}
- createOrganization={this.props.createOrganization}
- onUpgradeFail={this.deleteOrganization}
- />
-
- {almInstallId && almOrganization && !boundOrganization ? (
- <AutoOrganizationCreate
- {...commonProps}
- almApplication={almApplication}
- almInstallId={almInstallId}
- almOrganization={almOrganization}
- className={classNames({ hidden: tab !== 'auto' })}
- createOrganization={this.props.createOrganization}
- handleCancelImport={this.handleCancelImport}
- onOrgCreated={this.handleOrgCreated}
- onUpgradeFail={this.deleteOrganization}
- unboundOrganizations={this.props.userOrganizations.filter(
- ({ actions = {}, alm }) => !alm && actions.admin
- )}
- />
- ) : (
- <RemoteOrganizationChoose
- almApplication={almApplication}
- almInstallId={almInstallId}
- almOrganization={almOrganization}
- almUnboundApplications={state.almUnboundApplications}
- boundOrganization={boundOrganization}
- className={classNames({ hidden: tab !== 'auto' })}
- />
- )}
- </>
- );
- };
-
- render() {
- const { location } = this.props;
- const query = parseQuery(location.query);
-
- if (this.state.almOrgLoading) {
- return <AlmApplicationInstalling almKey={query.almKey} />;
- }
-
- const { bindingExistingOrg, subscriptionPlans } = this.state;
- const header = this.getHeader(bindingExistingOrg);
- const startedPrice = subscriptionPlans && subscriptionPlans[0] && subscriptionPlans[0].price;
-
- return (
- <>
- <Helmet defer={false} title={header} titleTemplate="%s" />
- <div className="page page-limited huge-spacer-top huge-spacer-bottom">
- <A11ySkipTarget anchor="create_org_main" />
-
- <header className="page-header huge-spacer-bottom">
- <h1 className="page-title huge big-spacer-bottom">
- <strong>{header}</strong>
- </h1>
- {startedPrice !== undefined && (
- <p className="page-description">
- {translate('onboarding.create_organization.page.description')}
- </p>
- )}
- </header>
- {this.state.loading ? <DeferredSpinner /> : this.renderContent(query.almInstallId)}
- </div>
- </>
- );
- }
-}
-
-const mapDispatchToProps = {
- createOrganization: createOrganization as any,
- deleteOrganization: deleteOrganization as any,
- skipOnboarding: skipOnboarding as any
-};
-
-export default whenLoggedIn(
- withUserOrganizations(withRouter(connect(null, mapDispatchToProps)(CreateOrganization)))
-);
diff --git a/server/sonar-web/src/main/js/apps/create/organization/ManualOrganizationCreate.tsx b/server/sonar-web/src/main/js/apps/create/organization/ManualOrganizationCreate.tsx
deleted file mode 100644
index 157acec75a5..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/ManualOrganizationCreate.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import OrganizationDetailsForm from './OrganizationDetailsForm';
-import OrganizationDetailsStep from './OrganizationDetailsStep';
-import PlanStep from './PlanStep';
-import { Step } from './utils';
-
-interface Props {
- createOrganization: (organization: T.Organization) => Promise<string>;
- className?: string;
- onUpgradeFail: () => void;
- handleOrgDetailsFinish: (organization: T.Organization) => Promise<void>;
- handleOrgDetailsStepOpen: () => void;
- onDone: () => void;
- organization?: T.Organization;
- step: Step;
- subscriptionPlans?: T.SubscriptionPlan[];
-}
-
-export default class ManualOrganizationCreate extends React.PureComponent<Props> {
- handleCreateOrganization = () => {
- const { organization } = this.props;
- if (!organization) {
- return Promise.reject();
- }
- return this.props.createOrganization(organization);
- };
-
- render() {
- const { className, organization, subscriptionPlans } = this.props;
- return (
- <div className={className}>
- <OrganizationDetailsStep
- finished={organization !== undefined}
- onOpen={this.props.handleOrgDetailsStepOpen}
- open={this.props.step === Step.OrganizationDetails}
- organization={organization}>
- <OrganizationDetailsForm
- onContinue={this.props.handleOrgDetailsFinish}
- organization={organization}
- submitText={translate('continue')}
- />
- </OrganizationDetailsStep>
-
- {subscriptionPlans !== undefined && (
- <PlanStep
- createOrganization={this.handleCreateOrganization}
- onDone={this.props.onDone}
- onUpgradeFail={this.props.onUpgradeFail}
- open={this.props.step === Step.Plan}
- subscriptionPlans={subscriptionPlans}
- />
- )}
- </div>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsForm.tsx b/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsForm.tsx
deleted file mode 100644
index 928efd8f0cc..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsForm.tsx
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { ResetButtonLink, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
-import DropdownIcon from 'sonar-ui-common/components/icons/DropdownIcon';
-import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import OrganizationAvatarInput from '../components/OrganizationAvatarInput';
-import OrganizationKeyInput from '../components/OrganizationKeyInput';
-import OrganizationUrlInput from '../components/OrganizationUrlInput';
-
-type RequiredOrganization = Required<T.OrganizationBase>;
-
-interface Props {
- infoBlock?: React.ReactNode;
- onContinue: (organization: T.Organization) => Promise<void>;
- organization?: T.Organization;
- submitText: string;
-}
-
-interface State {
- additional: boolean;
- avatar?: string;
- description?: string;
- key?: string;
- name?: string;
- submitting: boolean;
- url?: string;
-}
-
-type ValidState = Pick<State, Exclude<keyof State, RequiredOrganization>> & RequiredOrganization;
-
-export default class OrganizationDetailsForm extends React.PureComponent<Props, State> {
- mounted = false;
-
- constructor(props: Props) {
- super(props);
- const { organization } = props;
- this.state = {
- additional: false,
- avatar: (organization && organization.avatar) || '',
- description: (organization && organization.description) || '',
- key: (organization && organization.key) || undefined,
- name: (organization && organization.name) || '',
- submitting: false,
- url: (organization && organization.url) || ''
- };
- }
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- canSubmit(state: State): state is ValidState {
- return Boolean(
- state.key !== undefined &&
- state.name !== undefined &&
- state.description !== undefined &&
- state.avatar !== undefined &&
- state.url !== undefined
- );
- }
-
- handleAdditionalClick = () => {
- this.setState(state => ({ additional: !state.additional }));
- };
-
- handleAvatarUpdate = (avatar: string | undefined) => {
- this.setState({ avatar });
- };
-
- handleDescriptionUpdate = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
- this.setState({ description: event.currentTarget.value });
- };
-
- handleKeyUpdate = (key: string | undefined) => {
- this.setState({ key });
- };
-
- handleNameUpdate = (event: React.ChangeEvent<HTMLInputElement>) => {
- this.setState({ name: event.currentTarget.value });
- };
-
- handleUrlUpdate = (url: string | undefined) => {
- this.setState({ url });
- };
-
- handleSubmit = (event: React.FormEvent) => {
- event.preventDefault();
- const { state } = this;
- if (this.canSubmit(state)) {
- this.setState({ submitting: true });
- this.props
- .onContinue({
- avatar: state.avatar,
- description: state.description,
- key: state.key,
- name: state.name,
- url: state.url
- })
- .then(this.stopSubmitting, this.stopSubmitting);
- }
- };
-
- stopSubmitting = () => {
- if (this.mounted) {
- this.setState({ submitting: false });
- }
- };
-
- render() {
- const { submitting } = this.state;
- const { infoBlock } = this.props;
- return (
- <form id="organization-form" onSubmit={this.handleSubmit}>
- <OrganizationKeyInput initialValue={this.state.key} onChange={this.handleKeyUpdate} />
- <div className="big-spacer-top">
- <ResetButtonLink onClick={this.handleAdditionalClick}>
- {translate(
- this.state.additional
- ? 'onboarding.create_organization.hide_additional_info'
- : 'onboarding.create_organization.add_additional_info'
- )}
- <DropdownIcon className="little-spacer-left" turned={this.state.additional} />
- </ResetButtonLink>
- </div>
- <div className="js-additional-info" hidden={!this.state.additional}>
- <div className="big-spacer-top">
- <label htmlFor="organization-display-name">
- <strong>{translate('onboarding.create_organization.display_name')}</strong>
- </label>
- <div className="little-spacer-top">
- <input
- className="input-super-large text-middle"
- id="organization-display-name"
- maxLength={255}
- onChange={this.handleNameUpdate}
- type="text"
- value={this.state.name}
- />
- </div>
- <div className="note abs-width-400">
- {translate('onboarding.create_organization.display_name.description')}
- </div>
- </div>
- <div className="big-spacer-top">
- <OrganizationAvatarInput
- initialValue={this.state.avatar}
- name={this.state.name}
- onChange={this.handleAvatarUpdate}
- />
- </div>
- <div className="big-spacer-top">
- <label htmlFor="organization-description">
- <strong>{translate('onboarding.create_organization.description')}</strong>
- </label>
- <div className="little-spacer-top">
- <textarea
- className="input-super-large text-middle"
- id="organization-description"
- maxLength={256}
- onChange={this.handleDescriptionUpdate}
- rows={3}
- value={this.state.description}
- />
- </div>
- </div>
- <div className="big-spacer-top">
- <OrganizationUrlInput initialValue={this.state.url} onChange={this.handleUrlUpdate} />
- </div>
- </div>
-
- {infoBlock}
-
- <div className="display-flex-center big-spacer-top">
- <SubmitButton disabled={submitting || !this.canSubmit(this.state)}>
- {this.props.submitText}
- </SubmitButton>
- {submitting && <DeferredSpinner className="spacer-left" />}
- </div>
- </form>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx b/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx
deleted file mode 100644
index 91b45c1e44f..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/OrganizationDetailsStep.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import Step from '../../../components/tutorials/components/Step';
-
-interface Props {
- children: React.ReactNode;
- finished: boolean;
- onOpen: () => void;
- open: boolean;
- organization?: T.Organization;
- stepTitle?: string;
-}
-export default class OrganizationDetailsStep extends React.PureComponent<Props> {
- renderForm = () => {
- return <div className="boxed-group-inner">{this.props.children}</div>;
- };
-
- renderResult = () => {
- const { organization } = this.props;
- return organization ? (
- <div className="boxed-group-actions display-flex-center">
- <AlertSuccessIcon className="spacer-right" />
- <strong className="text-limited">{organization.key}</strong>
- </div>
- ) : null;
- };
-
- render() {
- return (
- <Step
- finished={this.props.finished}
- onOpen={this.props.onOpen}
- open={this.props.open}
- renderForm={this.renderForm}
- renderResult={this.renderResult}
- stepNumber={1}
- stepTitle={
- this.props.stepTitle || translate('onboarding.create_organization.enter_org_details')
- }
- />
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/PlanSelect.tsx b/server/sonar-web/src/main/js/apps/create/organization/PlanSelect.tsx
deleted file mode 100644
index 0c2460fd7d9..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/PlanSelect.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import FreeCardPlan from '../components/FreeCardPlan';
-import PaidCardPlan from '../components/PaidCardPlan';
-
-export enum Plan {
- Free = 'free',
- Paid = 'paid'
-}
-
-interface Props {
- almApplication?: T.AlmApplication;
- almOrganization?: T.AlmOrganization;
- onChange: (plan: Plan) => void;
- plan: Plan;
- startingPrice: number;
-}
-
-export default class PlanSelect extends React.PureComponent<Props> {
- handleFreePlanClick = () => {
- this.props.onChange(Plan.Free);
- };
-
- handlePaidPlanClick = () => {
- this.props.onChange(Plan.Paid);
- };
-
- render() {
- const { almApplication, almOrganization, plan } = this.props;
- const hasPrivateRepo = Boolean(almOrganization && almOrganization.privateRepos > 0);
- const onlyPrivateRepo = Boolean(
- hasPrivateRepo && almOrganization && almOrganization.publicRepos === 0
- );
-
- const cards = [
- <PaidCardPlan
- isRecommended={hasPrivateRepo}
- key="paid"
- onClick={this.handlePaidPlanClick}
- selected={plan === Plan.Paid}
- startingPrice={this.props.startingPrice}
- />,
- <FreeCardPlan
- almName={almApplication && almApplication.name}
- disabled={onlyPrivateRepo}
- hasWarning={hasPrivateRepo && plan === Plan.Free}
- key="free"
- onClick={this.handleFreePlanClick}
- selected={plan === Plan.Free}
- />
- ];
-
- return (
- <div
- aria-label={translate('onboarding.create_organization.choose_plan')}
- className="display-flex-row huge-spacer-bottom"
- role="radiogroup">
- {hasPrivateRepo ? cards : cards.reverse()}
- </div>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/PlanStep.tsx b/server/sonar-web/src/main/js/apps/create/organization/PlanStep.tsx
deleted file mode 100644
index 042210cee1e..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/PlanStep.tsx
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as React from 'react';
-import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';
-import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
-import { translate } from 'sonar-ui-common/helpers/l10n';
-import { withCurrentUser } from '../../../components/hoc/withCurrentUser';
-import Step from '../../../components/tutorials/components/Step';
-import { getExtensionStart } from '../../../helpers/extensions';
-import BillingFormShim from '../components/BillingFormShim';
-import PlanSelect, { Plan } from './PlanSelect';
-
-const BillingForm = withCurrentUser(BillingFormShim);
-
-interface Props {
- almApplication?: T.AlmApplication;
- almOrganization?: T.AlmOrganization;
- createOrganization: () => Promise<string>;
- onDone: () => void;
- onUpgradeFail?: () => void;
- open: boolean;
- subscriptionPlans: T.SubscriptionPlan[];
-}
-
-interface State {
- plan: Plan;
- ready: boolean;
- submitting: boolean;
-}
-
-export default class PlanStep extends React.PureComponent<Props, State> {
- mounted = false;
-
- constructor(props: Props) {
- super(props);
- this.state = {
- plan: props.almOrganization && props.almOrganization.privateRepos > 0 ? Plan.Paid : Plan.Free,
- ready: false,
- submitting: false
- };
- }
-
- componentDidMount() {
- this.mounted = true;
- getExtensionStart('billing/billing').then(
- () => {
- if (this.mounted) {
- this.setState({ ready: true });
- }
- },
- () => {}
- );
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handlePlanChange = (plan: Plan) => {
- this.setState({ plan });
- };
-
- stopSubmitting = () => {
- if (this.mounted) {
- this.setState({ submitting: false });
- }
- };
-
- handleFreePlanSubmit = (event: React.FormEvent) => {
- event.preventDefault();
- this.setState({ submitting: true });
- return this.props.createOrganization().then(() => {
- this.props.onDone();
- this.stopSubmitting();
- }, this.stopSubmitting);
- };
-
- renderForm = () => {
- const { submitting } = this.state;
- const { subscriptionPlans } = this.props;
- const startingPrice = subscriptionPlans && subscriptionPlans[0] && subscriptionPlans[0].price;
- return (
- <div className="boxed-group-inner">
- {this.state.ready && (
- <>
- <PlanSelect
- almApplication={this.props.almApplication}
- almOrganization={this.props.almOrganization}
- onChange={this.handlePlanChange}
- plan={this.state.plan}
- startingPrice={startingPrice}
- />
-
- {this.state.plan === Plan.Paid ? (
- <BillingForm
- onCommit={this.props.onDone}
- onFailToUpgrade={this.props.onUpgradeFail}
- organizationKey={this.props.createOrganization}
- subscriptionPlans={this.props.subscriptionPlans}>
- {({ onSubmit, renderFormFields, renderSubmitGroup }) => (
- <form id="organization-paid-plan-form" onSubmit={onSubmit}>
- {renderFormFields()}
- <div className="billing-input-large big-spacer-top">
- {renderSubmitGroup(
- translate('onboarding.create_organization.create_and_upgrade')
- )}
- </div>
- </form>
- )}
- </BillingForm>
- ) : (
- <form
- className="display-flex-center big-spacer-top"
- id="organization-free-plan-form"
- onSubmit={this.handleFreePlanSubmit}>
- <SubmitButton disabled={submitting}>
- {translate('my_account.create_organization')}
- </SubmitButton>
- {submitting && <DeferredSpinner className="spacer-left" />}
- </form>
- )}
- </>
- )}
- </div>
- );
- };
-
- render() {
- const { almOrganization } = this.props;
- const stepTitle = translate(
- almOrganization && almOrganization.privateRepos > 0 && almOrganization.publicRepos === 0
- ? 'onboarding.create_organization.enter_payment_details'
- : 'onboarding.create_organization.choose_plan'
- );
-
- return (
- <Step
- finished={false}
- onOpen={() => {}}
- open={this.props.open}
- renderForm={this.renderForm}
- renderResult={() => null}
- stepNumber={2}
- stepTitle={stepTitle}
- />
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/RemoteOrganizationChoose.tsx b/server/sonar-web/src/main/js/apps/create/organization/RemoteOrganizationChoose.tsx
deleted file mode 100644
index 00b9744b7cb..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/RemoteOrganizationChoose.tsx
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 * as classNames from 'classnames';
-import { sortBy } from 'lodash';
-import * as React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { withRouter, WithRouterProps } from 'react-router';
-import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';
-import IdentityProviderLink from 'sonar-ui-common/components/controls/IdentityProviderLink';
-import Select from 'sonar-ui-common/components/controls/Select';
-import { Alert } from 'sonar-ui-common/components/ui/Alert';
-import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
-import { save } from 'sonar-ui-common/helpers/storage';
-import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
-import OrganizationAvatar from '../../../components/common/OrganizationAvatar';
-import { sanitizeAlmId } from '../../../helpers/almIntegrations';
-import { ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP, serializeQuery } from './utils';
-
-interface Props {
- almApplication: T.AlmApplication;
- almInstallId?: string;
- almOrganization?: T.AlmOrganization;
- almUnboundApplications: T.AlmUnboundApplication[];
- boundOrganization?: T.OrganizationBase;
- className?: string;
-}
-
-interface State {
- unboundInstallationId: string;
-}
-
-export class RemoteOrganizationChoose extends React.PureComponent<Props & WithRouterProps, State> {
- state: State = { unboundInstallationId: '' };
-
- handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
- event.preventDefault();
-
- const { unboundInstallationId } = this.state;
- if (unboundInstallationId) {
- this.props.router.push({
- pathname: '/create-organization',
- query: serializeQuery({
- almInstallId: unboundInstallationId,
- almKey: this.props.almApplication.key
- })
- });
- }
- };
-
- handleInstallAppClick = () => {
- save(ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP, Date.now().toString(10));
- };
-
- handleInstallationChange = ({ installationId }: T.AlmUnboundApplication) => {
- this.setState({ unboundInstallationId: installationId });
- };
-
- renderOption = (organization: T.AlmUnboundApplication) => {
- const { almApplication } = this.props;
- return (
- <span>
- <img
- alt={almApplication.name}
- className="spacer-right"
- height={14}
- src={`${getBaseUrl()}/images/sonarcloud/${sanitizeAlmId(almApplication.key)}.svg`}
- />
- {organization.name}
- </span>
- );
- };
-
- render() {
- const {
- almApplication,
- almInstallId,
- almOrganization,
- almUnboundApplications,
- boundOrganization,
- className
- } = this.props;
- const { unboundInstallationId } = this.state;
- return (
- <div className={classNames('boxed-group', className)}>
- <div className="boxed-group-header">
- <h2>{translate('onboarding.import_organization.import_org_details')}</h2>
- </div>
- <div className="boxed-group-inner">
- {almInstallId && !almOrganization && (
- <Alert className="big-spacer-bottom width-60" variant="error">
- <div className="markdown">
- {translate('onboarding.import_organization.org_not_found')}
- <ul>
- <li>{translate('onboarding.import_organization.org_not_found.tips_1')}</li>
- <li>{translate('onboarding.import_organization.org_not_found.tips_2')}</li>
- </ul>
- </div>
- </Alert>
- )}
- {almOrganization && boundOrganization && (
- <Alert className="big-spacer-bottom width-60" variant="error">
- <FormattedMessage
- defaultMessage={translate('onboarding.import_organization.already_bound_x')}
- id="onboarding.import_organization.already_bound_x"
- values={{
- avatar: (
- <img
- alt={almApplication.name}
- className="little-spacer-left"
- src={`${getBaseUrl()}/images/sonarcloud/${sanitizeAlmId(
- almApplication.key
- )}.svg`}
- width={16}
- />
- ),
- name: <strong>{almOrganization.name}</strong>,
- boundAvatar: (
- <OrganizationAvatar
- className="little-spacer-left"
- organization={boundOrganization}
- small={true}
- />
- ),
- boundName: <strong>{boundOrganization.name}</strong>
- }}
- />
- </Alert>
- )}
- <div className="display-flex-center">
- <div className="display-inline-block">
- <IdentityProviderLink
- backgroundColor={almApplication.backgroundColor}
- className="display-inline-block"
- iconPath={almApplication.iconPath}
- name={almApplication.name}
- onClick={this.handleInstallAppClick}
- small={true}
- url={almApplication.installationUrl}>
- {translate(
- 'onboarding.import_organization.choose_organization_button',
- almApplication.key
- )}
- </IdentityProviderLink>
- </div>
- {almUnboundApplications.length > 0 && (
- <div className="display-flex-stretch">
- <div className="vertical-pipe-separator">
- <div className="vertical-separator " />
- <span className="note">{translate('or')}</span>
- <div className="vertical-separator" />
- </div>
- <form className="big-spacer-top big-spacer-bottom" onSubmit={this.handleSubmit}>
- <div className="form-field abs-width-400">
- <label className="text-normal" htmlFor="select-unbound-installation">
- {translateWithParameters(
- 'onboarding.import_organization.choose_unbound_installation_x',
- translate(sanitizeAlmId(almApplication.key))
- )}
- </label>
- <Select
- className="input-super-large"
- clearable={false}
- id="select-unbound-installation"
- labelKey="name"
- onChange={this.handleInstallationChange}
- optionRenderer={this.renderOption}
- options={sortBy(almUnboundApplications, o => o.name.toLowerCase())}
- placeholder={translate('onboarding.import_organization.choose_organization')}
- value={unboundInstallationId}
- valueKey="installationId"
- valueRenderer={this.renderOption}
- />
- </div>
- <SubmitButton disabled={!unboundInstallationId}>
- {translate('continue')}
- </SubmitButton>
- </form>
- </div>
- )}
- </div>
- </div>
- </div>
- );
- }
-}
-
-export default withRouter(RemoteOrganizationChoose);
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AlmApplicationInstalling-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/AlmApplicationInstalling-test.tsx
deleted file mode 100644
index 352e72f3781..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AlmApplicationInstalling-test.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 AlmApplicationInstalling from '../AlmApplicationInstalling';
-
-it('should render correctly', () => {
- expect(shallow(<AlmApplicationInstalling />)).toMatchSnapshot();
- expect(shallow(<AlmApplicationInstalling almKey="github" />)).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationBind-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationBind-test.tsx
deleted file mode 100644
index ecc8107689c..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationBind-test.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { submit } from 'sonar-ui-common/helpers/testUtils';
-import { mockOrganization } from '../../../../helpers/testMocks';
-import AutoOrganizationBind from '../AutoOrganizationBind';
-
-it('should render correctly', () => {
- const onBindOrganization = jest.fn().mockResolvedValue({});
- const wrapper = shallowRender({ onBindOrganization });
- expect(wrapper).toMatchSnapshot();
-
- submit(wrapper.find('form'));
- expect(onBindOrganization).toHaveBeenCalled();
-});
-
-it('should not show member sync info box for Bitbucket', () => {
- expect(
- shallowRender({ almKey: 'bitbucket' })
- .find('Alert')
- .exists()
- ).toBe(false);
-});
-
-function shallowRender(props: Partial<AutoOrganizationBind['props']> = {}) {
- return shallow(
- <AutoOrganizationBind
- almKey="github"
- onBindOrganization={jest.fn()}
- unboundOrganizations={[mockOrganization()]}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx
deleted file mode 100644
index c358824365d..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { click, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import { bindAlmOrganization } from '../../../../api/alm-integration';
-import { mockAlmApplication, mockAlmOrganization } from '../../../../helpers/testMocks';
-import AutoOrganizationCreate from '../AutoOrganizationCreate';
-import { Step } from '../utils';
-
-jest.mock('../../../../api/alm-integration', () => ({
- bindAlmOrganization: jest.fn().mockResolvedValue({})
-}));
-
-const organization = mockAlmOrganization();
-
-it('should render prefilled and create org', async () => {
- const createOrganization = jest.fn().mockResolvedValue({ key: 'foo' });
- const handleOrgDetailsFinish = jest.fn();
- const almOrganization = mockAlmOrganization({ almUrl: 'http://github.com/thing' });
- const wrapper = shallowRender({
- almOrganization,
- createOrganization,
- handleOrgDetailsFinish
- });
-
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('OrganizationDetailsForm').prop<Function>('onContinue')(organization);
- await waitAndUpdate(wrapper);
- expect(handleOrgDetailsFinish).toBeCalled();
-
- wrapper.setProps({ organization });
- wrapper.find('PlanStep').prop<Function>('createOrganization')();
-
- const alm: T.Organization['alm'] = {
- key: 'github',
- membersSync: true,
- personal: false,
- url: 'http://github.com/thing'
- };
- expect(createOrganization).toBeCalledWith({ ...organization, alm, installationId: 'id-foo' });
-});
-
-it('should allow to cancel org import', () => {
- const handleCancelImport = jest.fn().mockResolvedValue({ key: 'foo' });
- const wrapper = shallowRender({ handleCancelImport });
-
- click(wrapper.find('ClearButton'));
- expect(handleCancelImport).toBeCalled();
-});
-
-it('should display choice between import or creation', () => {
- const wrapper = shallowRender({ unboundOrganizations: [organization] });
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('RadioToggle').prop<Function>('onCheck')('create');
- wrapper.update();
- expect(wrapper.find('OrganizationDetailsForm').exists()).toBe(true);
-
- wrapper.find('RadioToggle').prop<Function>('onCheck')('bind');
- wrapper.update();
- expect(wrapper.find('AutoOrganizationBind').exists()).toBe(true);
-});
-
-it('should bind existing organization', async () => {
- const onOrgCreated = jest.fn();
- const wrapper = shallowRender({ onOrgCreated, unboundOrganizations: [organization] });
-
- wrapper.find('RadioToggle').prop<Function>('onCheck')('bind');
- wrapper.update();
- wrapper.find('AutoOrganizationBind').prop<Function>('onBindOrganization')('foo');
- expect(bindAlmOrganization as jest.Mock<any>).toHaveBeenCalledWith({
- installationId: 'id-foo',
- organization: 'foo'
- });
- await waitAndUpdate(wrapper);
- expect(onOrgCreated).toHaveBeenCalledWith('foo');
-});
-
-it('should not show member sync info box for Bitbucket', () => {
- expect(
- shallowRender({ almApplication: mockAlmApplication({ key: 'bitbucket-cloud' }) })
- .find('Alert')
- .exists()
- ).toBe(false);
-});
-
-function shallowRender(props: Partial<AutoOrganizationCreate['props']> = {}) {
- return shallow(
- <AutoOrganizationCreate
- almApplication={mockAlmApplication()}
- almInstallId="id-foo"
- almOrganization={organization}
- createOrganization={jest.fn()}
- handleCancelImport={jest.fn()}
- handleOrgDetailsFinish={jest.fn()}
- handleOrgDetailsStepOpen={jest.fn()}
- onDone={jest.fn()}
- onOrgCreated={jest.fn()}
- onUpgradeFail={jest.fn()}
- step={Step.OrganizationDetails}
- subscriptionPlans={[
- { maxNcloc: 100000, price: 10 },
- { maxNcloc: 250000, price: 75 }
- ]}
- unboundOrganizations={[]}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
deleted file mode 100644
index 1f1e0a03dad..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { mount, shallow } from 'enzyme';
-import { Location } from 'history';
-import { times } from 'lodash';
-import * as React from 'react';
-import { HelmetProvider } from 'react-helmet-async';
-import { get, remove } from 'sonar-ui-common/helpers/storage';
-import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import {
- bindAlmOrganization,
- getAlmAppInfo,
- getAlmOrganization,
- listUnboundApplications
-} from '../../../../api/alm-integration';
-import { getSubscriptionPlans } from '../../../../api/billing';
-import { getOrganizations } from '../../../../api/organizations';
-import {
- mockAlmOrganization,
- mockLocation,
- mockLoggedInUser,
- mockOrganizationWithAdminActions,
- mockOrganizationWithAlm,
- mockRouter
-} from '../../../../helpers/testMocks';
-import { CreateOrganization } from '../CreateOrganization';
-
-jest.mock('../../../../api/billing', () => ({
- getSubscriptionPlans: jest.fn().mockResolvedValue([
- { maxNcloc: 100000, price: 10 },
- { maxNcloc: 250000, price: 75 }
- ])
-}));
-
-jest.mock('../../../../api/alm-integration', () => ({
- getAlmAppInfo: jest.fn().mockResolvedValue({
- application: {
- backgroundColor: 'blue',
- iconPath: 'icon/path',
- installationUrl: 'https://alm.installation.url',
- key: 'github',
- name: 'GitHub'
- }
- }),
- getAlmOrganization: jest.fn().mockResolvedValue({
- almOrganization: {
- avatar: 'my-avatar',
- description: 'Continuous Code Quality',
- key: 'sonarsource',
- name: 'SonarSource',
- privateRepos: 0,
- publicRepos: 3,
- url: 'https://www.sonarsource.com'
- }
- }),
- listUnboundApplications: jest.fn().mockResolvedValue([]),
- bindAlmOrganization: jest.fn().mockResolvedValue({})
-}));
-
-jest.mock('../../../../api/organizations', () => ({
- getOrganizations: jest.fn().mockResolvedValue({ organizations: [] })
-}));
-
-jest.mock('sonar-ui-common/helpers/storage', () => ({
- get: jest.fn().mockReturnValue(undefined),
- remove: jest.fn()
-}));
-
-const user = mockLoggedInUser();
-const fooAlmOrganization = mockAlmOrganization();
-const fooBarAlmOrganization = mockAlmOrganization({
- avatar: 'https://avatars3.githubusercontent.com/u/37629810?v=4',
- key: 'Foo&Bar',
- name: 'Foo & Bar'
-});
-
-const boundOrganization = { key: 'foobar', name: 'Foo & Bar' };
-
-beforeEach(() => {
- (getAlmAppInfo as jest.Mock<any>).mockClear();
- (getAlmOrganization as jest.Mock<any>).mockClear();
- (listUnboundApplications as jest.Mock<any>).mockClear();
- (getSubscriptionPlans as jest.Mock<any>).mockClear();
- (getOrganizations as jest.Mock<any>).mockClear();
- (get as jest.Mock<any>).mockClear();
- (remove as jest.Mock<any>).mockClear();
-});
-
-it('should render with manual tab displayed', async () => {
- const wrapper = shallowRender();
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
- expect(getSubscriptionPlans).toHaveBeenCalled();
- expect(getAlmAppInfo).not.toHaveBeenCalled();
-});
-
-it('should render with auto tab displayed', async () => {
- const wrapper = shallowRender({ currentUser: { ...user, externalProvider: 'github' } });
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
- expect(getAlmAppInfo).toHaveBeenCalled();
- expect(listUnboundApplications).toHaveBeenCalled();
-});
-
-it('should render with auto tab selected and manual disabled', async () => {
- const wrapper = shallowRender({
- currentUser: { ...user, externalProvider: 'github' },
- location: { query: { installation_id: 'foo' } } as Location
- });
- expect(wrapper).toMatchSnapshot();
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
- expect(getAlmAppInfo).toHaveBeenCalled();
- expect(getAlmOrganization).toHaveBeenCalled();
- expect(getOrganizations).toHaveBeenCalled();
-});
-
-it('should render with organization bind page', async () => {
- (getAlmOrganization as jest.Mock<any>).mockResolvedValueOnce({
- almOrganization: fooAlmOrganization
- });
- const wrapper = shallowRender({
- currentUser: { ...user, externalProvider: 'github' },
- location: { query: { installation_id: 'foo' } } as Location
- });
- expect(wrapper).toMatchSnapshot();
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should slugify and find a uniq organization key', async () => {
- (getAlmOrganization as jest.Mock<any>).mockResolvedValueOnce({
- almOrganization: fooBarAlmOrganization
- });
- (getOrganizations as jest.Mock<any>).mockResolvedValueOnce({
- organizations: [{ key: 'foo-and-bar' }, { key: 'foo-and-bar-1' }]
- });
- const wrapper = shallowRender({
- currentUser: { ...user, externalProvider: 'github' },
- location: { query: { installation_id: 'foo' } } as Location
- });
- await waitAndUpdate(wrapper);
- expect(getOrganizations).toHaveBeenCalledWith({
- organizations: ['foo-and-bar', ...times(9, i => `foo-and-bar-${i + 1}`)].join(',')
- });
- expect(wrapper.find('AutoOrganizationCreate').prop('almOrganization')).toMatchObject({
- key: 'foo-and-bar-2'
- });
-});
-
-it('should switch tabs', async () => {
- const replace = jest.fn();
- const wrapper = shallowRender({
- currentUser: { ...user, externalProvider: 'github' },
- router: mockRouter({ replace })
- });
-
- replace.mockImplementation(location => {
- wrapper.setProps({ location }).update();
- });
-
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
-
- (wrapper.find('Tabs').prop('onChange') as Function)('manual');
- expect(wrapper.find('ManualOrganizationCreate').hasClass('hidden')).toBe(false);
- expect(wrapper.find('withRouter(RemoteOrganizationChoose)').hasClass('hidden')).toBe(true);
- (wrapper.find('Tabs').prop('onChange') as Function)('auto');
- expect(wrapper.find('withRouter(RemoteOrganizationChoose)').hasClass('hidden')).toBe(false);
- expect(wrapper.find('ManualOrganizationCreate').hasClass('hidden')).toBe(true);
-});
-
-it('should reload the alm organization when the url query changes', async () => {
- const wrapper = shallowRender({ currentUser: { ...user, externalProvider: 'github' } });
- await waitAndUpdate(wrapper);
- expect(getAlmOrganization).not.toHaveBeenCalled();
- wrapper.setProps({ location: { query: { installation_id: 'foo' } } as Location });
- expect(getAlmOrganization).toHaveBeenCalledWith({ installationId: 'foo' });
- wrapper.setProps({ location: { query: {} } as Location });
- expect(wrapper.state('almOrganization')).toBeUndefined();
- expect(listUnboundApplications).toHaveBeenCalledTimes(2);
-});
-
-it('should redirect to organization page after creation', async () => {
- const push = jest.fn();
- const wrapper = shallowRender({ router: mockRouter({ push }) });
- await waitAndUpdate(wrapper);
-
- wrapper.setState({ organization: boundOrganization });
- wrapper.instance().handleOrgCreated('foo');
- expect(push).toHaveBeenCalledWith({ pathname: '/organizations/foo' });
-});
-
-it('should redirect to projects creation page after creation', async () => {
- const push = jest.fn();
- const wrapper = shallowRender({ router: mockRouter({ push }) });
- await waitAndUpdate(wrapper);
-
- (get as jest.Mock<any>).mockReturnValueOnce(Date.now().toString());
- wrapper.instance().handleOrgCreated('foo');
- expect(get).toHaveBeenCalled();
- expect(remove).toHaveBeenCalled();
- expect(push).toHaveBeenCalledWith({
- pathname: '/projects/create',
- state: { organization: 'foo', tab: 'manual' }
- });
-
- wrapper.setState({ almOrganization: fooAlmOrganization });
- (get as jest.Mock<any>).mockReturnValueOnce(Date.now().toString());
- wrapper.instance().handleOrgCreated('foo');
- expect(push).toHaveBeenCalledWith({
- pathname: '/projects/create',
- state: { organization: 'foo', tab: 'auto' }
- });
-});
-
-it('should display AutoOrganizationCreate with already bound organization', async () => {
- (getAlmOrganization as jest.Mock<any>).mockResolvedValueOnce({
- almOrganization: fooBarAlmOrganization,
- boundOrganization
- });
- (get as jest.Mock<any>)
- .mockReturnValueOnce(undefined) // For BIND_ORGANIZATION_REDIRECT_TO_ORG_TIMESTAMP
- .mockReturnValueOnce(Date.now().toString()); // For ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP
- const push = jest.fn();
- const wrapper = shallowRender({
- currentUser: { ...user, externalProvider: 'github' },
- location: { query: { installation_id: 'foo' } } as Location,
- router: mockRouter({ push })
- });
- await waitAndUpdate(wrapper);
- expect(get).toHaveBeenCalled();
- expect(remove).toHaveBeenCalled();
- expect(getAlmOrganization).toHaveBeenCalledWith({ installationId: 'foo' });
- expect(push).not.toHaveBeenCalled();
- expect(wrapper.find('withRouter(RemoteOrganizationChoose)').prop('boundOrganization')).toEqual({
- key: 'foobar',
- name: 'Foo & Bar'
- });
-});
-
-it('should redirect to org page when already bound and no binding in progress', async () => {
- (getAlmOrganization as jest.Mock<any>).mockResolvedValueOnce({
- almOrganization: fooBarAlmOrganization,
- boundOrganization
- });
- const push = jest.fn();
- const wrapper = shallowRender({
- currentUser: { ...user, externalProvider: 'github' },
- location: { query: { installation_id: 'foo' } } as Location,
- router: mockRouter({ push })
- });
- await waitAndUpdate(wrapper);
- expect(getAlmOrganization).toHaveBeenCalledWith({ installationId: 'foo' });
- expect(push).toHaveBeenCalledWith({ pathname: '/organizations/foobar' });
-});
-
-it('should roll back after upgrade failure', async () => {
- const deleteOrganization = jest.fn();
- const wrapper = shallowRender({ deleteOrganization });
- await waitAndUpdate(wrapper);
- wrapper.setState({ organization: boundOrganization });
- wrapper.find('ManualOrganizationCreate').prop<Function>('onUpgradeFail')();
- expect(deleteOrganization).toBeCalled();
-});
-
-it('should cancel imports', async () => {
- const push = jest.fn();
- const wrapper = shallowRender({ router: mockRouter({ push }) });
- await waitAndUpdate(wrapper);
- wrapper.instance().handleCancelImport();
- expect(push).toBeCalledWith({ pathname: '/path', query: {}, state: {} });
-});
-
-it('should bind org and redirect to org home when coming from org binding', async () => {
- const installation_id = '5328';
- const orgKey = 'org4test';
- const push = jest.fn();
-
- (get as jest.Mock<any>)
- .mockReturnValueOnce(Date.now().toString()) // For BIND_ORGANIZATION_REDIRECT_TO_ORG_TIMESTAMP
- .mockReturnValueOnce(orgKey); // For BIND_ORGANIZATION_KEY
-
- const wrapper = mountRender({
- currentUser: mockLoggedInUser({ ...user, externalProvider: 'github' }),
- location: mockLocation({ query: { installation_id } }),
- router: mockRouter({ push })
- });
- await waitAndUpdate(wrapper);
-
- expect(bindAlmOrganization).toBeCalled();
- expect(getAlmOrganization).not.toBeCalled();
- expect(push).toBeCalledWith({
- pathname: `/organizations/${orgKey}`
- });
-});
-
-function mountRender(props: Partial<CreateOrganization['props']> = {}) {
- return mount<CreateOrganization>(<HelmetProvider>{createComponent(props)}</HelmetProvider>);
-}
-
-function shallowRender(props: Partial<CreateOrganization['props']> = {}) {
- return shallow<CreateOrganization>(createComponent(props));
-}
-
-function createComponent(props: Partial<CreateOrganization['props']> = {}) {
- return (
- <CreateOrganization
- createOrganization={jest.fn()}
- currentUser={user}
- deleteOrganization={jest.fn()}
- location={mockLocation()}
- params={{}}
- router={mockRouter()}
- routes={[]}
- skipOnboarding={jest.fn()}
- userOrganizations={[
- mockOrganizationWithAdminActions(),
- mockOrganizationWithAdminActions(mockOrganizationWithAlm({ key: 'bar', name: 'Bar' })),
- mockOrganizationWithAdminActions({ key: 'baz', name: 'Baz' }, { admin: false })
- ]}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/ManualOrganizationCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/ManualOrganizationCreate-test.tsx
deleted file mode 100644
index 46c1fab37f4..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/ManualOrganizationCreate-test.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import { mockOrganization } from '../../../../helpers/testMocks';
-import ManualOrganizationCreate from '../ManualOrganizationCreate';
-import { Step } from '../utils';
-
-it('should render and create organization', async () => {
- const createOrganization = jest.fn().mockResolvedValue({ key: 'foo' });
- const onDone = jest.fn();
- const handleOrgDetailsFinish = jest.fn();
- const wrapper = shallowRender({ createOrganization, handleOrgDetailsFinish, onDone });
-
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('OrganizationDetailsForm').prop<Function>('onContinue')(mockOrganization());
- await waitAndUpdate(wrapper);
- expect(handleOrgDetailsFinish).toHaveBeenCalled();
- wrapper.setProps({ step: Step.Plan });
- expect(wrapper).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<ManualOrganizationCreate['props']> = {}) {
- return shallow(
- <ManualOrganizationCreate
- createOrganization={jest.fn()}
- handleOrgDetailsFinish={jest.fn()}
- handleOrgDetailsStepOpen={jest.fn()}
- onDone={jest.fn()}
- onUpgradeFail={jest.fn()}
- step={Step.OrganizationDetails}
- subscriptionPlans={[
- { maxNcloc: 100000, price: 10 },
- { maxNcloc: 250000, price: 75 }
- ]}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsForm-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsForm-test.tsx
deleted file mode 100644
index 548d59e4cec..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsForm-test.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { click, submit } from 'sonar-ui-common/helpers/testUtils';
-import OrganizationDetailsForm from '../OrganizationDetailsForm';
-
-it('should render form', () => {
- const wrapper = shallowRender();
- expect(wrapper).toMatchSnapshot();
- expect(wrapper.find('.js-additional-info').prop('hidden')).toBe(true);
-
- click(wrapper.find('ResetButtonLink'));
- wrapper.update();
- expect(wrapper.find('.js-additional-info').prop('hidden')).toBe(false);
-});
-
-it('should validate before submit', () => {
- const wrapper = shallowRender();
- const instance = wrapper.instance() as OrganizationDetailsForm;
-
- expect(
- instance.canSubmit({
- additional: false,
- avatar: '',
- description: '',
- name: '',
- key: 'foo',
- submitting: false,
- url: ''
- })
- ).toBe(true);
-
- expect(
- instance.canSubmit({
- additional: false,
- avatar: '',
- description: '',
- name: '',
- key: undefined,
- submitting: false,
- url: ''
- })
- ).toBe(false);
-
- expect(
- instance.canSubmit({
- additional: false,
- avatar: undefined,
- description: '',
- name: '',
- key: 'foo',
- submitting: false,
- url: ''
- })
- ).toBe(false);
-
- instance.canSubmit = jest.fn() as any;
- submit(wrapper.find('form'));
- expect(instance.canSubmit).toHaveBeenCalled();
-});
-
-function shallowRender(props: Partial<OrganizationDetailsForm['props']> = {}) {
- return shallow(
- <OrganizationDetailsForm onContinue={jest.fn()} submitText="continue" {...props} />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsStep-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsStep-test.tsx
deleted file mode 100644
index c88443b685d..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/OrganizationDetailsStep-test.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 OrganizationDetailsStep from '../OrganizationDetailsStep';
-
-it('should render form', () => {
- const wrapper = shallow(
- <OrganizationDetailsStep finished={false} onOpen={jest.fn()} open={true}>
- <form />
- </OrganizationDetailsStep>
- );
- expect(wrapper).toMatchSnapshot();
- expect(
- wrapper
- .dive()
- .find('form')
- .exists()
- ).toBe(true);
-});
-
-it('should render result', () => {
- const wrapper = shallow(
- <OrganizationDetailsStep
- finished={true}
- onOpen={jest.fn()}
- open={false}
- organization={{ avatar: '', description: '', key: 'org', name: 'Organization', url: '' }}>
- <div />
- </OrganizationDetailsStep>
- );
- expect(wrapper.dive().find('.boxed-group-actions')).toMatchSnapshot();
- expect(
- wrapper
- .dive()
- .find('.hidden')
- .exists()
- ).toBe(true);
-});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanSelect-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanSelect-test.tsx
deleted file mode 100644
index 55fa395aead..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanSelect-test.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { click } from 'sonar-ui-common/helpers/testUtils';
-import { mockAlmOrganization } from '../../../../helpers/testMocks';
-import PlanSelect, { Plan } from '../PlanSelect';
-
-it('should render and select', () => {
- const onChange = jest.fn();
- const wrapper = shallowRender({ onChange });
- expect(wrapper).toMatchSnapshot();
-
- click(wrapper.find('PaidCardPlan'));
- expect(onChange).toBeCalledWith(Plan.Paid);
- wrapper.setProps({ plan: Plan.Paid });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('should recommend paid plan', () => {
- const wrapper = shallowRender({
- almOrganization: mockAlmOrganization({ privateRepos: 1, publicRepos: 5 }),
- plan: Plan.Paid
- });
- expect(wrapper.find('PaidCardPlan').prop('isRecommended')).toBe(true);
- expect(wrapper.find('FreeCardPlan').prop('disabled')).toBe(false);
- expect(wrapper.find('FreeCardPlan').prop('hasWarning')).toBe(false);
-
- wrapper.setProps({ plan: Plan.Free });
- expect(wrapper.find('FreeCardPlan').prop('hasWarning')).toBe(true);
-});
-
-it('should recommend paid plan and disable free plan', () => {
- const wrapper = shallowRender({
- almOrganization: mockAlmOrganization({ privateRepos: 1, publicRepos: 0 })
- });
- expect(wrapper.find('PaidCardPlan').prop('isRecommended')).toBe(true);
- expect(wrapper.find('FreeCardPlan').prop('disabled')).toBe(true);
-});
-
-function shallowRender(props: Partial<PlanSelect['props']> = {}) {
- return shallow(
- <PlanSelect onChange={jest.fn()} plan={Plan.Free} startingPrice={10} {...props} />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanStep-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanStep-test.tsx
deleted file mode 100644
index a306d1ccf0a..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanStep-test.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { submit, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
-import { mockAlmOrganization } from '../../../../helpers/testMocks';
-import { Plan } from '../PlanSelect';
-import PlanStep from '../PlanStep';
-
-jest.mock('../../../../helpers/extensions', () => ({
- getExtensionStart: jest.fn().mockResolvedValue(undefined)
-}));
-const subscriptionPlans = [{ maxNcloc: 1000, price: 100 }];
-
-it('should render and use free plan', async () => {
- const onDone = jest.fn();
- const createOrganization = jest.fn().mockResolvedValue('org');
- const wrapper = shallow(
- <PlanStep
- createOrganization={createOrganization}
- onDone={onDone}
- onUpgradeFail={jest.fn()}
- open={true}
- subscriptionPlans={subscriptionPlans}
- />
- );
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
- expect(wrapper.dive()).toMatchSnapshot();
-
- submit(wrapper.dive().find('form'));
- await waitAndUpdate(wrapper);
- expect(createOrganization).toBeCalled();
- expect(onDone).toBeCalled();
-});
-
-it('should upgrade', async () => {
- const onDone = jest.fn();
- const wrapper = shallow(
- <PlanStep
- createOrganization={jest.fn().mockResolvedValue('org')}
- onDone={onDone}
- onUpgradeFail={jest.fn()}
- open={true}
- subscriptionPlans={subscriptionPlans}
- />
- );
- await waitAndUpdate(wrapper);
-
- wrapper
- .dive()
- .find('PlanSelect')
- .prop<Function>('onChange')(Plan.Paid);
- expect(wrapper.dive()).toMatchSnapshot();
-
- wrapper
- .dive()
- .find('Connect(withCurrentUser(BillingFormShim))')
- .prop<Function>('onCommit')();
- expect(onDone).toBeCalled();
-});
-
-it('should preselect paid plan', async () => {
- const wrapper = shallow(
- <PlanStep
- almOrganization={mockAlmOrganization({ privateRepos: 5, publicRepos: 0 })}
- createOrganization={jest.fn()}
- onDone={jest.fn()}
- onUpgradeFail={jest.fn()}
- open={true}
- subscriptionPlans={subscriptionPlans}
- />
- );
- await waitAndUpdate(wrapper);
- expect(wrapper.dive()).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/RemoteOrganizationChoose-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/RemoteOrganizationChoose-test.tsx
deleted file mode 100644
index b19e2bfa6c3..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/RemoteOrganizationChoose-test.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { submit } from 'sonar-ui-common/helpers/testUtils';
-import { mockAlmOrganization, mockRouter } from '../../../../helpers/testMocks';
-import { RemoteOrganizationChoose } from '../RemoteOrganizationChoose';
-
-it('should render', () => {
- expect(shallowRender()).toMatchSnapshot();
-});
-
-it('should display an alert message', () => {
- expect(shallowRender({ almInstallId: 'foo' }).find('Alert')).toMatchSnapshot();
-});
-
-it('should display unbound installations', () => {
- const installation = { installationId: '12345', key: 'foo', name: 'Foo' };
- const push = jest.fn();
- const wrapper = shallowRender({
- almUnboundApplications: [installation],
- router: mockRouter({ push })
- });
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('Select').prop<Function>('onChange')(installation);
- submit(wrapper.find('form'));
- expect(push).toHaveBeenCalledWith({
- pathname: '/create-organization',
- query: { installation_id: installation.installationId }
- });
-});
-
-it('should display already bound alert message', () => {
- expect(
- shallowRender({
- almInstallId: 'foo',
- almOrganization: mockAlmOrganization(),
- boundOrganization: { avatar: 'bound-avatar', key: 'bound', name: 'Bound' }
- }).find('Alert')
- ).toMatchSnapshot();
-});
-
-function shallowRender(props: Partial<RemoteOrganizationChoose['props']> = {}) {
- return shallow(
- // @ts-ignore avoid passing everything from WithRouterProps
- <RemoteOrganizationChoose
- almApplication={{
- backgroundColor: 'blue',
- iconPath: 'icon/path',
- installationUrl: 'https://alm.application.url',
- key: 'github',
- name: 'GitHub'
- }}
- almUnboundApplications={[]}
- router={mockRouter()}
- {...props}
- />
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AlmApplicationInstalling-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AlmApplicationInstalling-test.tsx.snap
deleted file mode 100644
index 135829ce072..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AlmApplicationInstalling-test.tsx.snap
+++ /dev/null
@@ -1,47 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<DeferredSpinner
- customSpinner={
- <div
- className="sonarcloud page page-limited"
- >
- <div
- className="huge-spacer-top text-center"
- >
- <i
- className="spinner"
- />
- <p
- className="big-spacer-top"
- >
- onboarding.import_organization.installing.ALM
- </p>
- </div>
- </div>
- }
-/>
-`;
-
-exports[`should render correctly 2`] = `
-<DeferredSpinner
- customSpinner={
- <div
- className="sonarcloud page page-limited"
- >
- <div
- className="huge-spacer-top text-center"
- >
- <i
- className="spinner"
- />
- <p
- className="big-spacer-top"
- >
- onboarding.import_organization.installing.github
- </p>
- </div>
- </div>
- }
-/>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationBind-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationBind-test.tsx.snap
deleted file mode 100644
index 7c32193e58c..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationBind-test.tsx.snap
+++ /dev/null
@@ -1,50 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<form
- id="bind-organization-form"
- onSubmit={[Function]}
->
- <OrganizationSelect
- onChange={[Function]}
- organization="foo"
- organizations={
- Array [
- Object {
- "key": "foo",
- "name": "Foo",
- },
- ]
- }
- />
- <Alert
- className="abs-width-400 big-spacer-top"
- display="block"
- variant="info"
- >
- onboarding.import_organization.bind_members_not_sync_info_x.organization.github
- <Link
- className="spacer-left"
- onlyActiveOnIndex={false}
- style={Object {}}
- target="_blank"
- to={
- Object {
- "pathname": "/documentation/organizations/manage-team/",
- }
- }
- >
- learn_more
- </Link>
- </Alert>
- <div
- className="display-flex-center big-spacer-top"
- >
- <SubmitButton
- disabled={false}
- >
- onboarding.import_organization.bind
- </SubmitButton>
- </div>
-</form>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap
deleted file mode 100644
index 9b74fb68d47..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap
+++ /dev/null
@@ -1,216 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should display choice between import or creation 1`] = `
-<div>
- <OrganizationDetailsStep
- finished={false}
- onOpen={[MockFunction]}
- open={true}
- stepTitle="onboarding.import_organization.import_org_details"
- >
- <div
- className="huge-spacer-bottom"
- >
- <p
- className="display-flex-center big-spacer-bottom"
- >
- <FormattedMessage
- defaultMessage="onboarding.import_organization_x"
- id="onboarding.import_organization_x"
- values={
- Object {
- "avatar": <img
- alt="GitHub"
- className="little-spacer-left"
- src="/images/sonarcloud/github.svg"
- width={16}
- />,
- "name": <strong>
- foo
- </strong>,
- }
- }
- />
- <ClearButton
- className="little-spacer-left"
- onClick={[MockFunction]}
- />
- </p>
- <RadioToggle
- disabled={false}
- name="filter"
- onCheck={[Function]}
- options={
- Array [
- Object {
- "label": "onboarding.import_organization.create_new",
- "value": "create",
- },
- Object {
- "label": "onboarding.import_organization.bind_existing",
- "value": "bind",
- },
- ]
- }
- value={null}
- />
- </div>
- </OrganizationDetailsStep>
- <PlanStep
- almApplication={
- Object {
- "backgroundColor": "#444444",
- "iconPath": "/images/sonarcloud/github-white.svg",
- "installationUrl": "https://github.com/apps/greg-sonarcloud/installations/new",
- "key": "github",
- "name": "GitHub",
- }
- }
- almOrganization={
- Object {
- "almUrl": "https://github.com/foo",
- "avatar": "http://example.com/avatar",
- "description": "description-foo",
- "key": "foo",
- "name": "foo",
- "personal": false,
- "privateRepos": 0,
- "publicRepos": 3,
- "url": "http://example.com/foo",
- }
- }
- createOrganization={[Function]}
- onDone={[MockFunction]}
- onUpgradeFail={[MockFunction]}
- open={false}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
-</div>
-`;
-
-exports[`should render prefilled and create org 1`] = `
-<div>
- <OrganizationDetailsStep
- finished={false}
- onOpen={[MockFunction]}
- open={true}
- stepTitle="onboarding.import_organization.import_org_details"
- >
- <div
- className="huge-spacer-bottom"
- >
- <p
- className="display-flex-center big-spacer-bottom"
- >
- <FormattedMessage
- defaultMessage="onboarding.import_organization_x"
- id="onboarding.import_organization_x"
- values={
- Object {
- "avatar": <img
- alt="GitHub"
- className="little-spacer-left"
- src="/images/sonarcloud/github.svg"
- width={16}
- />,
- "name": <strong>
- foo
- </strong>,
- }
- }
- />
- <ClearButton
- className="little-spacer-left"
- onClick={[MockFunction]}
- />
- </p>
- </div>
- <OrganizationDetailsForm
- infoBlock={
- <Alert
- className="abs-width-600 big-spacer-top"
- display="block"
- variant="info"
- >
- <p>
- onboarding.import_organization.members_sync_info_x.organization.github.foo.github
- </p>
- <a
- href="http://github.com/orgs/thing/people"
- rel="noopener noreferrer"
- target="_blank"
- >
- organization.members.see_all_members_on_x.github
- </a>
- </Alert>
- }
- onContinue={[MockFunction]}
- organization={
- Object {
- "almUrl": "http://github.com/thing",
- "avatar": "http://example.com/avatar",
- "description": "description-foo",
- "key": "foo",
- "name": "foo",
- "personal": false,
- "privateRepos": 0,
- "publicRepos": 3,
- "url": "http://example.com/foo",
- }
- }
- submitText="continue"
- />
- </OrganizationDetailsStep>
- <PlanStep
- almApplication={
- Object {
- "backgroundColor": "#444444",
- "iconPath": "/images/sonarcloud/github-white.svg",
- "installationUrl": "https://github.com/apps/greg-sonarcloud/installations/new",
- "key": "github",
- "name": "GitHub",
- }
- }
- almOrganization={
- Object {
- "almUrl": "http://github.com/thing",
- "avatar": "http://example.com/avatar",
- "description": "description-foo",
- "key": "foo",
- "name": "foo",
- "personal": false,
- "privateRepos": 0,
- "publicRepos": 3,
- "url": "http://example.com/foo",
- }
- }
- createOrganization={[Function]}
- onDone={[MockFunction]}
- onUpgradeFail={[MockFunction]}
- open={false}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap
deleted file mode 100644
index 927b7d368f9..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap
+++ /dev/null
@@ -1,489 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render with auto tab displayed 1`] = `
-<Fragment>
- <Helmet
- defer={false}
- encodeSpecialCharacters={true}
- title="onboarding.create_organization.page.header"
- titleTemplate="%s"
- />
- <div
- className="page page-limited huge-spacer-top huge-spacer-bottom"
- >
- <A11ySkipTarget
- anchor="create_org_main"
- />
- <header
- className="page-header huge-spacer-bottom"
- >
- <h1
- className="page-title huge big-spacer-bottom"
- >
- <strong>
- onboarding.create_organization.page.header
- </strong>
- </h1>
- <p
- className="page-description"
- >
- onboarding.create_organization.page.description
- </p>
- </header>
- <Tabs
- onChange={[Function]}
- selected="auto"
- tabs={
- Array [
- Object {
- "key": "auto",
- "node": "onboarding.import_organization.import_from_x.github",
- },
- Object {
- "key": "manual",
- "node": "onboarding.create_organization.create_manually",
- },
- ]
- }
- />
- <ManualOrganizationCreate
- className="hidden"
- createOrganization={[MockFunction]}
- handleOrgDetailsFinish={[Function]}
- handleOrgDetailsStepOpen={[Function]}
- onDone={[Function]}
- onUpgradeFail={[Function]}
- step={0}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
- <withRouter(RemoteOrganizationChoose)
- almApplication={
- Object {
- "backgroundColor": "blue",
- "iconPath": "icon/path",
- "installationUrl": "https://alm.installation.url",
- "key": "github",
- "name": "GitHub",
- }
- }
- almUnboundApplications={Array []}
- className=""
- />
- </div>
-</Fragment>
-`;
-
-exports[`should render with auto tab selected and manual disabled 1`] = `
-<AlmApplicationInstalling
- almKey="github"
-/>
-`;
-
-exports[`should render with auto tab selected and manual disabled 2`] = `
-<Fragment>
- <Helmet
- defer={false}
- encodeSpecialCharacters={true}
- title="onboarding.create_organization.page.header"
- titleTemplate="%s"
- />
- <div
- className="page page-limited huge-spacer-top huge-spacer-bottom"
- >
- <A11ySkipTarget
- anchor="create_org_main"
- />
- <header
- className="page-header huge-spacer-bottom"
- >
- <h1
- className="page-title huge big-spacer-bottom"
- >
- <strong>
- onboarding.create_organization.page.header
- </strong>
- </h1>
- <p
- className="page-description"
- >
- onboarding.create_organization.page.description
- </p>
- </header>
- <Tabs
- onChange={[Function]}
- selected="auto"
- tabs={
- Array [
- Object {
- "key": "auto",
- "node": "onboarding.import_organization.import_from_x.github",
- },
- Object {
- "key": "manual",
- "node": "onboarding.create_organization.create_manually",
- },
- ]
- }
- />
- <ManualOrganizationCreate
- className="hidden"
- createOrganization={[MockFunction]}
- handleOrgDetailsFinish={[Function]}
- handleOrgDetailsStepOpen={[Function]}
- onDone={[Function]}
- onUpgradeFail={[Function]}
- step={0}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
- <AutoOrganizationCreate
- almApplication={
- Object {
- "backgroundColor": "blue",
- "iconPath": "icon/path",
- "installationUrl": "https://alm.installation.url",
- "key": "github",
- "name": "GitHub",
- }
- }
- almInstallId="foo"
- almOrganization={
- Object {
- "avatar": "my-avatar",
- "description": "Continuous Code Quality",
- "key": "sonarsource",
- "name": "SonarSource",
- "privateRepos": 0,
- "publicRepos": 3,
- "url": "https://www.sonarsource.com",
- }
- }
- className=""
- createOrganization={[MockFunction]}
- handleCancelImport={[Function]}
- handleOrgDetailsFinish={[Function]}
- handleOrgDetailsStepOpen={[Function]}
- onDone={[Function]}
- onOrgCreated={[Function]}
- onUpgradeFail={[Function]}
- step={0}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- unboundOrganizations={
- Array [
- Object {
- "actions": Object {
- "admin": true,
- },
- "key": "foo",
- "name": "Foo",
- },
- ]
- }
- />
- </div>
-</Fragment>
-`;
-
-exports[`should render with manual tab displayed 1`] = `
-<Fragment>
- <Helmet
- defer={false}
- encodeSpecialCharacters={true}
- title="onboarding.create_organization.page.header"
- titleTemplate="%s"
- />
- <div
- className="page page-limited huge-spacer-top huge-spacer-bottom"
- >
- <A11ySkipTarget
- anchor="create_org_main"
- />
- <header
- className="page-header huge-spacer-bottom"
- >
- <h1
- className="page-title huge big-spacer-bottom"
- >
- <strong>
- onboarding.create_organization.page.header
- </strong>
- </h1>
- <p
- className="page-description"
- >
- onboarding.create_organization.page.description
- </p>
- </header>
- <ManualOrganizationCreate
- createOrganization={[MockFunction]}
- handleOrgDetailsFinish={[Function]}
- handleOrgDetailsStepOpen={[Function]}
- onDone={[Function]}
- onUpgradeFail={[Function]}
- step={0}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
- </div>
-</Fragment>
-`;
-
-exports[`should render with organization bind page 1`] = `
-<AlmApplicationInstalling
- almKey="github"
-/>
-`;
-
-exports[`should render with organization bind page 2`] = `
-<Fragment>
- <Helmet
- defer={false}
- encodeSpecialCharacters={true}
- title="onboarding.create_organization.page.header"
- titleTemplate="%s"
- />
- <div
- className="page page-limited huge-spacer-top huge-spacer-bottom"
- >
- <A11ySkipTarget
- anchor="create_org_main"
- />
- <header
- className="page-header huge-spacer-bottom"
- >
- <h1
- className="page-title huge big-spacer-bottom"
- >
- <strong>
- onboarding.create_organization.page.header
- </strong>
- </h1>
- <p
- className="page-description"
- >
- onboarding.create_organization.page.description
- </p>
- </header>
- <Tabs
- onChange={[Function]}
- selected="auto"
- tabs={
- Array [
- Object {
- "key": "auto",
- "node": "onboarding.import_organization.import_from_x.github",
- },
- Object {
- "key": "manual",
- "node": "onboarding.create_organization.create_manually",
- },
- ]
- }
- />
- <ManualOrganizationCreate
- className="hidden"
- createOrganization={[MockFunction]}
- handleOrgDetailsFinish={[Function]}
- handleOrgDetailsStepOpen={[Function]}
- onDone={[Function]}
- onUpgradeFail={[Function]}
- step={0}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
- <AutoOrganizationCreate
- almApplication={
- Object {
- "backgroundColor": "blue",
- "iconPath": "icon/path",
- "installationUrl": "https://alm.installation.url",
- "key": "github",
- "name": "GitHub",
- }
- }
- almInstallId="foo"
- almOrganization={
- Object {
- "almUrl": "https://github.com/foo",
- "avatar": "http://example.com/avatar",
- "description": "description-foo",
- "key": "foo",
- "name": "foo",
- "personal": false,
- "privateRepos": 0,
- "publicRepos": 3,
- "url": "http://example.com/foo",
- }
- }
- className=""
- createOrganization={[MockFunction]}
- handleCancelImport={[Function]}
- handleOrgDetailsFinish={[Function]}
- handleOrgDetailsStepOpen={[Function]}
- onDone={[Function]}
- onOrgCreated={[Function]}
- onUpgradeFail={[Function]}
- step={0}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- unboundOrganizations={
- Array [
- Object {
- "actions": Object {
- "admin": true,
- },
- "key": "foo",
- "name": "Foo",
- },
- ]
- }
- />
- </div>
-</Fragment>
-`;
-
-exports[`should switch tabs 1`] = `
-<Fragment>
- <Helmet
- defer={false}
- encodeSpecialCharacters={true}
- title="onboarding.create_organization.page.header"
- titleTemplate="%s"
- />
- <div
- className="page page-limited huge-spacer-top huge-spacer-bottom"
- >
- <A11ySkipTarget
- anchor="create_org_main"
- />
- <header
- className="page-header huge-spacer-bottom"
- >
- <h1
- className="page-title huge big-spacer-bottom"
- >
- <strong>
- onboarding.create_organization.page.header
- </strong>
- </h1>
- <p
- className="page-description"
- >
- onboarding.create_organization.page.description
- </p>
- </header>
- <Tabs
- onChange={[Function]}
- selected="auto"
- tabs={
- Array [
- Object {
- "key": "auto",
- "node": "onboarding.import_organization.import_from_x.github",
- },
- Object {
- "key": "manual",
- "node": "onboarding.create_organization.create_manually",
- },
- ]
- }
- />
- <ManualOrganizationCreate
- className="hidden"
- createOrganization={[MockFunction]}
- handleOrgDetailsFinish={[Function]}
- handleOrgDetailsStepOpen={[Function]}
- onDone={[Function]}
- onUpgradeFail={[Function]}
- step={0}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
- <withRouter(RemoteOrganizationChoose)
- almApplication={
- Object {
- "backgroundColor": "blue",
- "iconPath": "icon/path",
- "installationUrl": "https://alm.installation.url",
- "key": "github",
- "name": "GitHub",
- }
- }
- almUnboundApplications={Array []}
- className=""
- />
- </div>
-</Fragment>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ManualOrganizationCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ManualOrganizationCreate-test.tsx.snap
deleted file mode 100644
index 9ede472a8d9..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ManualOrganizationCreate-test.tsx.snap
+++ /dev/null
@@ -1,84 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render and create organization 1`] = `
-<div>
- <OrganizationDetailsStep
- finished={false}
- onOpen={[MockFunction]}
- open={true}
- >
- <OrganizationDetailsForm
- onContinue={[MockFunction]}
- submitText="continue"
- />
- </OrganizationDetailsStep>
- <PlanStep
- createOrganization={[Function]}
- onDone={[MockFunction]}
- onUpgradeFail={[MockFunction]}
- open={false}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
-</div>
-`;
-
-exports[`should render and create organization 2`] = `
-<div>
- <OrganizationDetailsStep
- finished={false}
- onOpen={[MockFunction]}
- open={false}
- >
- <OrganizationDetailsForm
- onContinue={
- [MockFunction] {
- "calls": Array [
- Array [
- Object {
- "key": "foo",
- "name": "Foo",
- },
- ],
- ],
- "results": Array [
- Object {
- "type": "return",
- "value": undefined,
- },
- ],
- }
- }
- submitText="continue"
- />
- </OrganizationDetailsStep>
- <PlanStep
- createOrganization={[Function]}
- onDone={[MockFunction]}
- onUpgradeFail={[MockFunction]}
- open={true}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsForm-test.tsx.snap
deleted file mode 100644
index b29f23245fe..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsForm-test.tsx.snap
+++ /dev/null
@@ -1,107 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render form 1`] = `
-<form
- id="organization-form"
- onSubmit={[Function]}
->
- <OrganizationKeyInput
- onChange={[Function]}
- />
- <div
- className="big-spacer-top"
- >
- <ResetButtonLink
- onClick={[Function]}
- >
- onboarding.create_organization.add_additional_info
- <DropdownIcon
- className="little-spacer-left"
- turned={false}
- />
- </ResetButtonLink>
- </div>
- <div
- className="js-additional-info"
- hidden={true}
- >
- <div
- className="big-spacer-top"
- >
- <label
- htmlFor="organization-display-name"
- >
- <strong>
- onboarding.create_organization.display_name
- </strong>
- </label>
- <div
- className="little-spacer-top"
- >
- <input
- className="input-super-large text-middle"
- id="organization-display-name"
- maxLength={255}
- onChange={[Function]}
- type="text"
- value=""
- />
- </div>
- <div
- className="note abs-width-400"
- >
- onboarding.create_organization.display_name.description
- </div>
- </div>
- <div
- className="big-spacer-top"
- >
- <OrganizationAvatarInput
- initialValue=""
- name=""
- onChange={[Function]}
- />
- </div>
- <div
- className="big-spacer-top"
- >
- <label
- htmlFor="organization-description"
- >
- <strong>
- onboarding.create_organization.description
- </strong>
- </label>
- <div
- className="little-spacer-top"
- >
- <textarea
- className="input-super-large text-middle"
- id="organization-description"
- maxLength={256}
- onChange={[Function]}
- rows={3}
- value=""
- />
- </div>
- </div>
- <div
- className="big-spacer-top"
- >
- <OrganizationUrlInput
- initialValue=""
- onChange={[Function]}
- />
- </div>
- </div>
- <div
- className="display-flex-center big-spacer-top"
- >
- <SubmitButton
- disabled={true}
- >
- continue
- </SubmitButton>
- </div>
-</form>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsStep-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsStep-test.tsx.snap
deleted file mode 100644
index 3b15b770b40..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/OrganizationDetailsStep-test.tsx.snap
+++ /dev/null
@@ -1,28 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render form 1`] = `
-<Step
- finished={false}
- onOpen={[MockFunction]}
- open={true}
- renderForm={[Function]}
- renderResult={[Function]}
- stepNumber={1}
- stepTitle="onboarding.create_organization.enter_org_details"
-/>
-`;
-
-exports[`should render result 1`] = `
-<div
- className="boxed-group-actions display-flex-center"
->
- <AlertSuccessIcon
- className="spacer-right"
- />
- <strong
- className="text-limited"
- >
- org
- </strong>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanSelect-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanSelect-test.tsx.snap
deleted file mode 100644
index cb99c558c4a..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanSelect-test.tsx.snap
+++ /dev/null
@@ -1,47 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render and select 1`] = `
-<div
- aria-label="onboarding.create_organization.choose_plan"
- className="display-flex-row huge-spacer-bottom"
- role="radiogroup"
->
- <FreeCardPlan
- disabled={false}
- hasWarning={false}
- key="free"
- onClick={[Function]}
- selected={true}
- />
- <PaidCardPlan
- isRecommended={false}
- key="paid"
- onClick={[Function]}
- selected={false}
- startingPrice={10}
- />
-</div>
-`;
-
-exports[`should render and select 2`] = `
-<div
- aria-label="onboarding.create_organization.choose_plan"
- className="display-flex-row huge-spacer-bottom"
- role="radiogroup"
->
- <FreeCardPlan
- disabled={false}
- hasWarning={false}
- key="free"
- onClick={[Function]}
- selected={false}
- />
- <PaidCardPlan
- isRecommended={false}
- key="paid"
- onClick={[Function]}
- selected={true}
- startingPrice={10}
- />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanStep-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanStep-test.tsx.snap
deleted file mode 100644
index ca7cb711940..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanStep-test.tsx.snap
+++ /dev/null
@@ -1,163 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should preselect paid plan 1`] = `
-<div
- className="boxed-group onboarding-step is-open"
->
- <div
- className="onboarding-step-number"
- >
- 2
- </div>
- <div
- className="boxed-group-header"
- >
- <h2>
- onboarding.create_organization.enter_payment_details
- </h2>
- </div>
- <div
- className=""
- >
- <div
- className="boxed-group-inner"
- >
- <PlanSelect
- almOrganization={
- Object {
- "almUrl": "https://github.com/foo",
- "avatar": "http://example.com/avatar",
- "description": "description-foo",
- "key": "foo",
- "name": "foo",
- "personal": false,
- "privateRepos": 5,
- "publicRepos": 0,
- "url": "http://example.com/foo",
- }
- }
- onChange={[Function]}
- plan="paid"
- startingPrice={100}
- />
- <Connect(withCurrentUser(BillingFormShim))
- onCommit={[MockFunction]}
- onFailToUpgrade={[MockFunction]}
- organizationKey={[MockFunction]}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 1000,
- "price": 100,
- },
- ]
- }
- >
- <Component />
- </Connect(withCurrentUser(BillingFormShim))>
- </div>
- </div>
-</div>
-`;
-
-exports[`should render and use free plan 1`] = `
-<Step
- finished={false}
- onOpen={[Function]}
- open={true}
- renderForm={[Function]}
- renderResult={[Function]}
- stepNumber={2}
- stepTitle="onboarding.create_organization.choose_plan"
-/>
-`;
-
-exports[`should render and use free plan 2`] = `
-<div
- className="boxed-group onboarding-step is-open"
->
- <div
- className="onboarding-step-number"
- >
- 2
- </div>
- <div
- className="boxed-group-header"
- >
- <h2>
- onboarding.create_organization.choose_plan
- </h2>
- </div>
- <div
- className=""
- >
- <div
- className="boxed-group-inner"
- >
- <PlanSelect
- onChange={[Function]}
- plan="free"
- startingPrice={100}
- />
- <form
- className="display-flex-center big-spacer-top"
- id="organization-free-plan-form"
- onSubmit={[Function]}
- >
- <SubmitButton
- disabled={false}
- >
- my_account.create_organization
- </SubmitButton>
- </form>
- </div>
- </div>
-</div>
-`;
-
-exports[`should upgrade 1`] = `
-<div
- className="boxed-group onboarding-step is-open"
->
- <div
- className="onboarding-step-number"
- >
- 2
- </div>
- <div
- className="boxed-group-header"
- >
- <h2>
- onboarding.create_organization.choose_plan
- </h2>
- </div>
- <div
- className=""
- >
- <div
- className="boxed-group-inner"
- >
- <PlanSelect
- onChange={[Function]}
- plan="paid"
- startingPrice={100}
- />
- <Connect(withCurrentUser(BillingFormShim))
- onCommit={[MockFunction]}
- onFailToUpgrade={[MockFunction]}
- organizationKey={[MockFunction]}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 1000,
- "price": 100,
- },
- ]
- }
- >
- <Component />
- </Connect(withCurrentUser(BillingFormShim))>
- </div>
- </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/RemoteOrganizationChoose-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/RemoteOrganizationChoose-test.tsx.snap
deleted file mode 100644
index 946d551efa3..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/RemoteOrganizationChoose-test.tsx.snap
+++ /dev/null
@@ -1,195 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should display already bound alert message 1`] = `
-<Alert
- className="big-spacer-bottom width-60"
- variant="error"
->
- <FormattedMessage
- defaultMessage="onboarding.import_organization.already_bound_x"
- id="onboarding.import_organization.already_bound_x"
- values={
- Object {
- "avatar": <img
- alt="GitHub"
- className="little-spacer-left"
- src="/images/sonarcloud/github.svg"
- width={16}
- />,
- "boundAvatar": <OrganizationAvatar
- className="little-spacer-left"
- organization={
- Object {
- "avatar": "bound-avatar",
- "key": "bound",
- "name": "Bound",
- }
- }
- small={true}
- />,
- "boundName": <strong>
- Bound
- </strong>,
- "name": <strong>
- foo
- </strong>,
- }
- }
- />
-</Alert>
-`;
-
-exports[`should display an alert message 1`] = `
-<Alert
- className="big-spacer-bottom width-60"
- variant="error"
->
- <div
- className="markdown"
- >
- onboarding.import_organization.org_not_found
- <ul>
- <li>
- onboarding.import_organization.org_not_found.tips_1
- </li>
- <li>
- onboarding.import_organization.org_not_found.tips_2
- </li>
- </ul>
- </div>
-</Alert>
-`;
-
-exports[`should display unbound installations 1`] = `
-<div
- className="boxed-group"
->
- <div
- className="boxed-group-header"
- >
- <h2>
- onboarding.import_organization.import_org_details
- </h2>
- </div>
- <div
- className="boxed-group-inner"
- >
- <div
- className="display-flex-center"
- >
- <div
- className="display-inline-block"
- >
- <IdentityProviderLink
- backgroundColor="blue"
- className="display-inline-block"
- iconPath="icon/path"
- name="GitHub"
- onClick={[Function]}
- small={true}
- url="https://alm.application.url"
- >
- onboarding.import_organization.choose_organization_button.github
- </IdentityProviderLink>
- </div>
- <div
- className="display-flex-stretch"
- >
- <div
- className="vertical-pipe-separator"
- >
- <div
- className="vertical-separator "
- />
- <span
- className="note"
- >
- or
- </span>
- <div
- className="vertical-separator"
- />
- </div>
- <form
- className="big-spacer-top big-spacer-bottom"
- onSubmit={[Function]}
- >
- <div
- className="form-field abs-width-400"
- >
- <label
- className="text-normal"
- htmlFor="select-unbound-installation"
- >
- onboarding.import_organization.choose_unbound_installation_x.github
- </label>
- <Select
- className="input-super-large"
- clearable={false}
- id="select-unbound-installation"
- labelKey="name"
- onChange={[Function]}
- optionRenderer={[Function]}
- options={
- Array [
- Object {
- "installationId": "12345",
- "key": "foo",
- "name": "Foo",
- },
- ]
- }
- placeholder="onboarding.import_organization.choose_organization"
- value=""
- valueKey="installationId"
- valueRenderer={[Function]}
- />
- </div>
- <SubmitButton
- disabled={true}
- >
- continue
- </SubmitButton>
- </form>
- </div>
- </div>
- </div>
-</div>
-`;
-
-exports[`should render 1`] = `
-<div
- className="boxed-group"
->
- <div
- className="boxed-group-header"
- >
- <h2>
- onboarding.import_organization.import_org_details
- </h2>
- </div>
- <div
- className="boxed-group-inner"
- >
- <div
- className="display-flex-center"
- >
- <div
- className="display-inline-block"
- >
- <IdentityProviderLink
- backgroundColor="blue"
- className="display-inline-block"
- iconPath="icon/path"
- name="GitHub"
- onClick={[Function]}
- small={true}
- url="https://alm.application.url"
- >
- onboarding.import_organization.choose_organization_button.github
- </IdentityProviderLink>
- </div>
- </div>
- </div>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/actions-test.ts b/server/sonar-web/src/main/js/apps/create/organization/__tests__/actions-test.ts
deleted file mode 100644
index 9248d38b46b..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/actions-test.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { createOrganization, syncMembers } from '../../../../api/organizations';
-import { mockOrganization, mockOrganizationWithAlm } from '../../../../helpers/testMocks';
-import * as actions from '../actions';
-
-jest.mock('../../../../api/alm-integration', () => ({
- bindAlmOrganization: jest.fn().mockResolvedValue({})
-}));
-
-jest.mock('../../../../api/organizations', () => ({
- createOrganization: jest.fn().mockResolvedValue({ key: 'foo', name: 'Foo' }),
- updateOrganization: jest.fn().mockResolvedValue({}),
- syncMembers: jest.fn()
-}));
-
-const dispatch = jest.fn();
-
-beforeEach(() => {
- jest.clearAllMocks();
-});
-
-describe('#createOrganization', () => {
- it('should create and return an org key', async () => {
- const org = mockOrganization();
- const promise = actions.createOrganization(org)(dispatch);
-
- expect(createOrganization).toHaveBeenCalledWith(org);
- const returnValue = await promise;
- expect(dispatch).toHaveBeenCalledWith({ organization: org, type: 'CREATE_ORGANIZATION' });
- expect(syncMembers).not.toBeCalled();
- expect(returnValue).toBe(org.key);
- });
-
- it('should create and sync members', async () => {
- const { alm, ...org } = mockOrganizationWithAlm(
- {},
- { key: 'github', membersSync: true, url: 'https://github.com/foo' }
- );
-
- (createOrganization as jest.Mock).mockResolvedValueOnce(org);
- const promise = actions.createOrganization({ alm, ...org })(dispatch);
-
- expect(createOrganization).toHaveBeenCalledWith(org);
- await promise;
- expect(syncMembers).toHaveBeenCalledWith(org.key);
- });
-
- it('should not sync members for personal Github orgs', async () => {
- const { alm, ...org } = mockOrganizationWithAlm(
- {},
- { key: 'github', membersSync: true, personal: true, url: 'https://github.com/foo' }
- );
-
- (createOrganization as jest.Mock).mockResolvedValueOnce(org);
- const promise = actions.createOrganization({ alm, ...org })(dispatch);
-
- expect(createOrganization).toHaveBeenCalledWith(org);
- await promise;
- expect(syncMembers).not.toBeCalled();
- });
-});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/utils-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/utils-test.tsx
deleted file mode 100644
index 8ba2a9f1824..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/utils-test.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { formatPrice } from '../utils';
-
-jest.mock('sonar-ui-common/helpers/urls', () => ({
- getHostUrl: () => 'http://host.url'
-}));
-
-describe('#formatPrice', () => {
- it('formats correctly', () => {
- expect(formatPrice(10)).toBe('billing.price_format.10');
- expect(formatPrice(10000)).toBe('billing.price_format.10,000');
- expect(formatPrice(10000, true)).toBe('10,000');
- });
-});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/actions.ts b/server/sonar-web/src/main/js/apps/create/organization/actions.ts
deleted file mode 100644
index 4abaa682d0f..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/actions.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { Dispatch } from 'redux';
-import * as api from '../../../api/organizations';
-import { isGithub } from '../../../helpers/almIntegrations';
-import * as actions from '../../../store/organizations';
-
-export function createOrganization({
- alm,
- ...organization
-}: T.Organization & { installationId?: string }) {
- return (dispatch: Dispatch) => {
- return api
- .createOrganization({ ...organization, name: organization.name || organization.key })
- .then((newOrganization: T.Organization) => {
- dispatch(actions.createOrganization({ ...newOrganization, alm }));
- if (alm && alm.membersSync && !alm.personal && isGithub(alm.key)) {
- api.syncMembers(newOrganization.key);
- }
- return newOrganization.key;
- });
- };
-}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/utils.ts b/server/sonar-web/src/main/js/apps/create/organization/utils.ts
deleted file mode 100644
index e0d5ca58124..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/utils.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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 { memoize } from 'lodash';
-import { translateWithParameters } from 'sonar-ui-common/helpers/l10n';
-import { formatMeasure } from 'sonar-ui-common/helpers/measures';
-import { cleanQuery, parseAsOptionalString, serializeString } from 'sonar-ui-common/helpers/query';
-import { decodeJwt } from 'sonar-ui-common/helpers/strings';
-import { isBitbucket, isGithub } from '../../../helpers/almIntegrations';
-
-export const ORGANIZATION_IMPORT_BINDING_IN_PROGRESS_TIMESTAMP =
- 'sonarcloud.import_org.binding_in_progress';
-
-export const ORGANIZATION_IMPORT_REDIRECT_TO_PROJECT_TIMESTAMP =
- 'sonarcloud.import_org.redirect_to_projects';
-
-export const BIND_ORGANIZATION_KEY = 'sonarcloud.bind_org.key';
-
-export const BIND_ORGANIZATION_REDIRECT_TO_ORG_TIMESTAMP = 'sonarcloud.bind_org.redirect_to_org';
-
-export enum Step {
- OrganizationDetails,
- Plan
-}
-
-export function formatPrice(price?: number, noSign?: boolean) {
- const priceFormatted = formatMeasure(price, 'FLOAT')
- .replace(/[.|,]0$/, '')
- .replace(/([.|,]\d)$/, '$10');
- return noSign ? priceFormatted : translateWithParameters('billing.price_format', priceFormatted);
-}
-
-export interface Query {
- almInstallId?: string;
- almKey?: string;
-}
-
-export const parseQuery = memoize(
- (urlQuery: T.RawQuery = {}): Query => {
- let almInstallId = undefined;
- let almKey = undefined;
-
- if (urlQuery['installation_id']) {
- almKey = 'github';
- almInstallId = parseAsOptionalString(urlQuery['installation_id']);
- } else if (urlQuery['clientKey']) {
- almKey = 'bitbucket';
- almInstallId = parseAsOptionalString(urlQuery['clientKey']);
- } else if (urlQuery['jwt']) {
- const jwt = decodeJwt(urlQuery['jwt']);
- if (jwt && jwt.iss) {
- almKey = 'bitbucket';
- almInstallId = jwt.iss;
- }
- }
- return { almInstallId, almKey };
- }
-);
-
-export const serializeQuery = (query: Query): T.RawQuery =>
- cleanQuery({
- installation_id: isGithub(query.almKey) ? serializeString(query.almInstallId) : undefined,
- clientKey: isBitbucket(query.almKey) ? serializeString(query.almInstallId) : undefined
- });