aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-09-28 16:49:25 +0200
committerSonarTech <sonartech@sonarsource.com>2018-10-12 20:20:58 +0200
commitf52d0c2586ee1fffb12e882cc86c41e036b46ce0 (patch)
tree4476fce44ad69671550bd470e29097a709d2cc0e /server/sonar-web/src/main/js
parentf0350c5cf3622e723e79e4ea7695741a47c0dbe2 (diff)
downloadsonarqube-f52d0c2586ee1fffb12e882cc86c41e036b46ce0.tar.gz
sonarqube-f52d0c2586ee1fffb12e882cc86c41e036b46ce0.zip
SONARCLOUD-138 Make forms clearer when upgrading an organization (#761)
Diffstat (limited to 'server/sonar-web/src/main/js')
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts2
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/BillingFormShim.tsx24
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/CardForm.tsx91
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/CouponForm.tsx122
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/PaymentMethodSelect.tsx57
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/PlanStep.tsx47
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__mocks__/BillingFormShim.tsx17
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/BillingFormShim-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/CardForm-test.tsx38
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/CouponForm-test.tsx36
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/PaymentMethodSelect-test.tsx34
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/PlanStep-test.tsx47
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/BillingFormShim-test.tsx.snap1
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CardForm-test.tsx.snap107
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CouponForm-test.tsx.snap22
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PaymentMethodSelect-test.tsx.snap79
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PlanStep-test.tsx.snap152
-rw-r--r--server/sonar-web/src/main/js/apps/tutorials/styles.css4
-rw-r--r--server/sonar-web/src/main/js/components/controls/HelpTooltip.tsx9
19 files changed, 53 insertions, 837 deletions
diff --git a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts
index 3198accbe06..c4fc23fa0db 100644
--- a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts
+++ b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts
@@ -62,6 +62,7 @@ import ActionsDropdown, { ActionsDropdownItem } from '../../../components/contro
import ConfirmButton from '../../../components/controls/ConfirmButton';
import SimpleModal from '../../../components/controls/SimpleModal';
import SearchSelect from '../../../components/controls/SearchSelect';
+import RadioToggle from '../../../components/controls/RadioToggle';
const exposeLibraries = () => {
const global = window as any;
@@ -103,6 +104,7 @@ const exposeLibraries = () => {
Modal,
PullRequestIcon,
QualifierIcon,
+ RadioToggle,
Rating,
ReloadButton,
ResetButtonLink,
diff --git a/server/sonar-web/src/main/js/apps/create/organization/BillingFormShim.tsx b/server/sonar-web/src/main/js/apps/create/organization/BillingFormShim.tsx
index f08e3ffc80e..df4a59ebce6 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/BillingFormShim.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/BillingFormShim.tsx
@@ -18,37 +18,21 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { CurrentUser, SubscriptionPlan, Coupon } from '../../../app/types';
+import { CurrentUser, SubscriptionPlan } from '../../../app/types';
interface ChildrenProps {
- alertError: string | undefined;
- couponValue: string;
onSubmit: React.FormEventHandler;
- renderAdditionalInfo: () => React.ReactNode;
- renderBillingNameInput: () => React.ReactNode;
- renderBraintreeClient: () => React.ReactNode;
- renderCountrySelect: () => React.ReactNode;
- renderCouponInput: (children?: React.ReactNode) => React.ReactNode;
- renderEmailInput: () => React.ReactNode;
- renderNextCharge: () => React.ReactNode;
- renderPlanSelect: () => React.ReactNode;
- renderResetButton: () => React.ReactNode;
- renderSpinner: () => React.ReactNode;
- renderSubmitButton: (text?: string) => React.ReactNode;
- renderTermsOfService: () => React.ReactNode;
- renderTypeOfUseSelect: () => React.ReactNode;
+ renderFormFields: () => React.ReactElement<any>;
+ renderSubmitGroup: (submitText?: string) => React.ReactElement<any>;
}
interface Props {
children: (props: ChildrenProps) => React.ReactElement<any>;
- country?: string;
+ initialCountry?: string;
currentUser: CurrentUser;
- onClose: () => void;
onCommit: () => void;
- onCouponUpdate?: (coupon?: Coupon) => void;
onFailToUpgrade?: () => void;
organizationKey: string | (() => Promise<string>);
- skipBraintreeInit?: boolean;
subscriptionPlans: SubscriptionPlan[];
}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/CardForm.tsx b/server/sonar-web/src/main/js/apps/create/organization/CardForm.tsx
deleted file mode 100644
index 39a739f8ff3..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/CardForm.tsx
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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 * as classNames from 'classnames';
-import BillingFormShim from './BillingFormShim';
-import { withCurrentUser } from './withCurrentUser';
-import { CurrentUser, SubscriptionPlan } from '../../../app/types';
-import { translate } from '../../../helpers/l10n';
-
-interface Props {
- createOrganization: () => Promise<string>;
- currentUser: CurrentUser;
- onFailToUpgrade: () => void;
- onSubmit: () => void;
- subscriptionPlans: SubscriptionPlan[];
-}
-
-export class CardForm extends React.PureComponent<Props> {
- handleClose = () => {
- // do nothing
- };
-
- render() {
- return (
- <div className="huge-spacer-top">
- <BillingFormShim
- currentUser={this.props.currentUser}
- onClose={this.handleClose}
- onCommit={this.props.onSubmit}
- onFailToUpgrade={this.props.onFailToUpgrade}
- organizationKey={this.props.createOrganization}
- subscriptionPlans={this.props.subscriptionPlans}>
- {form => (
- <form onSubmit={form.onSubmit}>
- <div className="columns column-show-overflow">
- <div className="column-half">
- <h3>{translate('billing.upgrade.billing_info')}</h3>
- {form.renderEmailInput()}
- {form.renderTypeOfUseSelect()}
- {form.renderBillingNameInput()}
- {form.renderCountrySelect()}
- {form.renderAdditionalInfo()}
- </div>
- <div className="column-half">
- <h3>{translate('billing.upgrade.plan')}</h3>
- {form.renderPlanSelect()}
- <h3>{translate('billing.upgrade.card_info')}</h3>
- {form.renderBraintreeClient()}
- </div>
- </div>
- <div className="upgrade-footer big-spacer-top">
- {form.renderNextCharge()}
- <hr className="big-spacer-bottom" />
- {form.alertError && <p className="alert alert-danger">{form.alertError}</p>}
- </div>
- <div
- className={classNames({
- 'big-spacer-top': form.alertError !== undefined
- })}>
- {form.renderSpinner()}
- {form.renderSubmitButton(
- translate('onboarding.create_organization.create_and_upgrade')
- )}
- </div>
- {form.renderTermsOfService()}
- </form>
- )}
- </BillingFormShim>
- </div>
- );
- }
-}
-
-export default withCurrentUser(CardForm);
diff --git a/server/sonar-web/src/main/js/apps/create/organization/CouponForm.tsx b/server/sonar-web/src/main/js/apps/create/organization/CouponForm.tsx
deleted file mode 100644
index fc0a7ab28fe..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/CouponForm.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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 * as classNames from 'classnames';
-import BillingFormShim from './BillingFormShim';
-import { withCurrentUser } from './withCurrentUser';
-import { CurrentUser, Coupon } from '../../../app/types';
-import { translate } from '../../../helpers/l10n';
-import DocTooltip from '../../../components/docs/DocTooltip';
-
-interface Props {
- createOrganization: () => Promise<string>;
- currentUser: CurrentUser;
- onFailToUpgrade: () => void;
- onSubmit: () => void;
-}
-
-interface State {
- coupon?: Coupon;
-}
-
-export class CouponForm extends React.PureComponent<Props, State> {
- state: State = {};
-
- handleClose = () => {
- // do nothing
- };
-
- handleCouponUpdate = (coupon?: Coupon) => {
- this.setState({ coupon });
- };
-
- renderBillingInformation() {
- if (!this.state.coupon || !this.state.coupon.billing) {
- return null;
- }
- const { billing } = this.state.coupon;
- return (
- <div className="big-spacer-top big-spacer-bottom" id="coupon-billing-information">
- <h3 className="note">{translate('billing.upgrade.billing_info')}</h3>
- <ul className="note">
- {Boolean(billing.name) && <li>{billing.name}</li>}
- {Boolean(billing.address) && <li>{billing.address}</li>}
- {Boolean(billing.country) && <li>{billing.country}</li>}
- {Boolean(billing.email) && <li>{billing.email}</li>}
- </ul>
- </div>
- );
- }
-
- render() {
- return (
- <div className="huge-spacer-top">
- <BillingFormShim
- currentUser={this.props.currentUser}
- onClose={this.handleClose}
- onCommit={this.props.onSubmit}
- onCouponUpdate={this.handleCouponUpdate}
- onFailToUpgrade={this.props.onFailToUpgrade}
- organizationKey={this.props.createOrganization}
- skipBraintreeInit={true}
- subscriptionPlans={[]}>
- {form => (
- <form onSubmit={form.onSubmit}>
- {form.renderCouponInput(
- <label htmlFor="coupon">
- {translate('billing.upgrade.coupon')}
- <DocTooltip
- className="little-spacer-left"
- doc={import(/* webpackMode: "eager" */ 'Docs/tooltips/billing/coupon.md')}
- />
- </label>
- )}
- {this.renderBillingInformation()}
- {this.state.coupon &&
- !this.state.coupon.billing && (
- <>
- <h3 className="big-spacer-top">{translate('billing.upgrade.billing_info')}</h3>
- {form.renderEmailInput()}
- {form.renderTypeOfUseSelect()}
- {form.renderBillingNameInput()}
- {form.renderCountrySelect()}
- {form.renderAdditionalInfo()}
- </>
- )}
- {this.state.coupon && (
- <div className="big-spacer-bottom">{form.renderNextCharge()}</div>
- )}
- {form.alertError && <p className="alert alert-danger">{form.alertError}</p>}
- <div className={classNames({ 'big-spacer-top': form.alertError !== undefined })}>
- {form.renderSpinner()}
- {form.renderSubmitButton(
- translate('onboarding.create_organization.create_and_upgrade')
- )}
- </div>
- {form.renderTermsOfService()}
- </form>
- )}
- </BillingFormShim>
- </div>
- );
- }
-}
-
-export default withCurrentUser(CouponForm);
diff --git a/server/sonar-web/src/main/js/apps/create/organization/PaymentMethodSelect.tsx b/server/sonar-web/src/main/js/apps/create/organization/PaymentMethodSelect.tsx
deleted file mode 100644
index ddf53728c55..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/PaymentMethodSelect.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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 RadioToggle from '../../../components/controls/RadioToggle';
-import { translate } from '../../../helpers/l10n';
-
-export enum PaymentMethod {
- Card = 'card',
- Coupon = 'coupon'
-}
-
-interface Props {
- onChange: (paymentMethod: PaymentMethod) => void;
- paymentMethod: PaymentMethod | undefined;
-}
-
-export default class PaymentMethodSelect extends React.PureComponent<Props> {
- render() {
- const options = Object.values(PaymentMethod).map(value => ({
- label: translate('billing', value),
- value
- }));
-
- return (
- <div>
- <label className="spacer-bottom">
- {translate('onboarding.create_organization.choose_payment_method')}
- </label>
- <div className="little-spacer-top">
- <RadioToggle
- name="payment-method"
- onCheck={this.props.onChange}
- options={options}
- value={this.props.paymentMethod}
- />
- </div>
- </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
index f715a4f4d48..5118540ce81 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/PlanStep.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/PlanStep.tsx
@@ -18,9 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import PaymentMethodSelect, { PaymentMethod } from './PaymentMethodSelect';
-import CardForm from './CardForm';
-import CouponForm from './CouponForm';
+import BillingFormShim from './BillingFormShim';
+import { withCurrentUser } from './withCurrentUser';
import PlanSelect, { Plan } from './PlanSelect';
import Step from '../../tutorials/components/Step';
import { translate } from '../../../helpers/l10n';
@@ -29,6 +28,8 @@ import { SubscriptionPlan } from '../../../app/types';
import { SubmitButton } from '../../../components/ui/buttons';
import DeferredSpinner from '../../../components/common/DeferredSpinner';
+const BillingForm = withCurrentUser(BillingFormShim);
+
interface Props {
createOrganization: () => Promise<string>;
deleteOrganization: () => void;
@@ -41,7 +42,6 @@ interface Props {
}
interface State {
- paymentMethod?: PaymentMethod;
plan: Plan;
ready: boolean;
submitting: boolean;
@@ -79,10 +79,6 @@ export default class PlanStep extends React.PureComponent<Props, State> {
this.setState({ plan });
};
- handlePaymentMethodChange = (paymentMethod: PaymentMethod) => {
- this.setState({ paymentMethod });
- };
-
stopSubmitting = () => {
if (this.mounted) {
this.setState({ submitting: false });
@@ -108,27 +104,22 @@ export default class PlanStep extends React.PureComponent<Props, State> {
)}
{this.state.plan === Plan.Paid ? (
- <>
- <PaymentMethodSelect
- onChange={this.handlePaymentMethodChange}
- paymentMethod={this.state.paymentMethod}
- />
- {this.state.paymentMethod === PaymentMethod.Card && (
- <CardForm
- createOrganization={this.props.createOrganization}
- onFailToUpgrade={this.props.deleteOrganization}
- onSubmit={this.props.onPaidPlanChoose}
- subscriptionPlans={this.props.subscriptionPlans}
- />
- )}
- {this.state.paymentMethod === PaymentMethod.Coupon && (
- <CouponForm
- createOrganization={this.props.createOrganization}
- onFailToUpgrade={this.props.deleteOrganization}
- onSubmit={this.props.onPaidPlanChoose}
- />
+ <BillingForm
+ onCommit={this.props.onPaidPlanChoose}
+ onFailToUpgrade={this.props.deleteOrganization}
+ organizationKey={this.props.createOrganization}
+ subscriptionPlans={this.props.subscriptionPlans}>
+ {({ onSubmit, renderFormFields, renderSubmitGroup }) => (
+ <form onSubmit={onSubmit}>
+ {renderFormFields()}
+ <div className="billing-input-large big-spacer-top">
+ {renderSubmitGroup(
+ translate('onboarding.create_organization.create_and_upgrade')
+ )}
+ </div>
+ </form>
)}
- </>
+ </BillingForm>
) : (
<div className="display-flex-center big-spacer-top">
<SubmitButton disabled={this.state.submitting} onClick={this.handleFreePlanSubmit}>
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__mocks__/BillingFormShim.tsx b/server/sonar-web/src/main/js/apps/create/organization/__mocks__/BillingFormShim.tsx
index 4c9b4e3596a..48f5e0dc984 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__mocks__/BillingFormShim.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/__mocks__/BillingFormShim.tsx
@@ -24,22 +24,9 @@ export default class BillingFormShim extends React.Component<{ children: any }>
return (
<div id="BillingFormShim">
{this.props.children({
- alertError: undefined,
- couponValue: '',
onSubmit: jest.fn(),
- renderAdditionalInfo: () => <div id="additional-info" />,
- renderBillingNameInput: () => <div id="billing-name" />,
- renderBraintreeClient: () => <div id="braintree-client" />,
- renderCountrySelect: () => <div id="country-select" />,
- renderCouponInput: () => <div id="coupon-input" />,
- renderEmailInput: () => <div id="email-input" />,
- renderNextCharge: () => <div id="next-charge" />,
- renderPlanSelect: () => <div id="plan-select" />,
- renderResetButton: () => <div id="reset-button" />,
- renderSpinner: () => <div id="spinner" />,
- renderSubmitButton: () => <div id="submit-button" />,
- renderTermsOfService: () => <div id="terms-of-service" />,
- renderTypeOfUseSelect: () => <div id="type-of-use-select" />
+ renderFormFields: () => <div id="form-fields" />,
+ renderSubmitGroup: () => <div id="submit-group" />
})}
</div>
);
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/BillingFormShim-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/BillingFormShim-test.tsx
index 91e2eb8a4ef..71119febaf6 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/BillingFormShim-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/BillingFormShim-test.tsx
@@ -38,7 +38,6 @@ it('should render', () => {
shallow(
<BillingFormShim
currentUser={{ isLoggedIn: false }}
- onClose={jest.fn()}
onCommit={jest.fn()}
organizationKey="org"
subscriptionPlans={[]}>
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CardForm-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/CardForm-test.tsx
deleted file mode 100644
index 0d8c015ad02..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CardForm-test.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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 { shallow } from 'enzyme';
-import { CardForm } from '../CardForm';
-
-jest.mock('../BillingFormShim');
-
-it('should render', () => {
- const wrapper = shallow(
- <CardForm
- createOrganization={jest.fn()}
- currentUser={{ isLoggedIn: false }}
- onFailToUpgrade={jest.fn()}
- onSubmit={jest.fn()}
- subscriptionPlans={[{ maxNcloc: 100000, price: 10 }, { maxNcloc: 250000, price: 75 }]}
- />
- );
- expect(wrapper).toMatchSnapshot();
- expect(wrapper.find('BillingFormShim').dive()).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CouponForm-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/CouponForm-test.tsx
deleted file mode 100644
index 110e213413c..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CouponForm-test.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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 { shallow } from 'enzyme';
-import { CouponForm } from '../CouponForm';
-
-jest.mock('../BillingFormShim');
-
-it('should render', () => {
- const wrapper = shallow(
- <CouponForm
- createOrganization={jest.fn()}
- currentUser={{ isLoggedIn: false }}
- onFailToUpgrade={jest.fn()}
- onSubmit={jest.fn()}
- />
- );
- expect(wrapper).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/PaymentMethodSelect-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/PaymentMethodSelect-test.tsx
deleted file mode 100644
index fea97e71637..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/PaymentMethodSelect-test.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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 { shallow } from 'enzyme';
-import PaymentMethodSelect, { PaymentMethod } from '../PaymentMethodSelect';
-
-it('should render and change', () => {
- const onChange = jest.fn();
- const wrapper = shallow(<PaymentMethodSelect onChange={onChange} paymentMethod={undefined} />);
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('RadioToggle').prop<Function>('onCheck')(PaymentMethod.Card);
- expect(onChange).toBeCalledWith(PaymentMethod.Card);
-
- wrapper.setProps({ paymentMethod: PaymentMethod.Card });
- expect(wrapper).toMatchSnapshot();
-});
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
index ff6937f0014..876a20f0bfd 100644
--- 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
@@ -22,7 +22,6 @@ import { shallow } from 'enzyme';
import PlanStep from '../PlanStep';
import { waitAndUpdate, click } from '../../../../helpers/testUtils';
import { Plan } from '../PlanSelect';
-import { PaymentMethod } from '../PaymentMethodSelect';
jest.mock('../../../../app/components/extensions/utils', () => ({
getExtensionStart: jest.fn().mockResolvedValue(undefined)
@@ -49,7 +48,7 @@ it('should render and use free plan', async () => {
expect(onFreePlanChoose).toBeCalled();
});
-it('should upgrade using card', async () => {
+it('should upgrade', async () => {
const onPaidPlanChoose = jest.fn();
const wrapper = shallow(
<PlanStep
@@ -72,48 +71,8 @@ it('should upgrade using card', async () => {
wrapper
.dive()
- .find('PaymentMethodSelect')
- .prop<Function>('onChange')(PaymentMethod.Card);
- expect(wrapper.dive()).toMatchSnapshot();
-
- wrapper
- .dive()
- .find('Connect(withCurrentUser(CardForm))')
- .prop<Function>('onSubmit')();
- expect(onPaidPlanChoose).toBeCalled();
-});
-
-it('should upgrade using coupon', async () => {
- const onPaidPlanChoose = jest.fn();
- const wrapper = shallow(
- <PlanStep
- createOrganization={jest.fn().mockResolvedValue('org')}
- deleteOrganization={jest.fn().mockResolvedValue(undefined)}
- onFreePlanChoose={jest.fn().mockResolvedValue(undefined)}
- onPaidPlanChoose={onPaidPlanChoose}
- open={true}
- startingPrice="10"
- subscriptionPlans={[]}
- />
- );
- await waitAndUpdate(wrapper);
-
- wrapper
- .dive()
- .find('PlanSelect')
- .prop<Function>('onChange')(Plan.Paid);
- expect(wrapper.dive()).toMatchSnapshot();
-
- wrapper
- .dive()
- .find('PaymentMethodSelect')
- .prop<Function>('onChange')(PaymentMethod.Coupon);
- expect(wrapper.dive()).toMatchSnapshot();
-
- wrapper
- .dive()
- .find('Connect(withCurrentUser(CouponForm))')
- .prop<Function>('onSubmit')();
+ .find('Connect(withCurrentUser(BillingFormShim))')
+ .prop<Function>('onCommit')();
expect(onPaidPlanChoose).toBeCalled();
});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/BillingFormShim-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/BillingFormShim-test.tsx.snap
index 5ed8a8cf920..3ab9b1995c6 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/BillingFormShim-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/BillingFormShim-test.tsx.snap
@@ -7,7 +7,6 @@ exports[`should render 1`] = `
"isLoggedIn": false,
}
}
- onClose={[MockFunction]}
onCommit={[MockFunction]}
organizationKey="org"
subscriptionPlans={Array []}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CardForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CardForm-test.tsx.snap
deleted file mode 100644
index 6d8afdea20e..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CardForm-test.tsx.snap
+++ /dev/null
@@ -1,107 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<div
- className="huge-spacer-top"
->
- <BillingFormShim
- currentUser={
- Object {
- "isLoggedIn": false,
- }
- }
- onClose={[Function]}
- onCommit={[MockFunction]}
- onFailToUpgrade={[MockFunction]}
- organizationKey={[MockFunction]}
- subscriptionPlans={
- Array [
- Object {
- "maxNcloc": 100000,
- "price": 10,
- },
- Object {
- "maxNcloc": 250000,
- "price": 75,
- },
- ]
- }
- />
-</div>
-`;
-
-exports[`should render 2`] = `
-<div
- id="BillingFormShim"
->
- <form
- onSubmit={[MockFunction]}
- >
- <div
- className="columns column-show-overflow"
- >
- <div
- className="column-half"
- >
- <h3>
- billing.upgrade.billing_info
- </h3>
- <div
- id="email-input"
- />
- <div
- id="type-of-use-select"
- />
- <div
- id="billing-name"
- />
- <div
- id="country-select"
- />
- <div
- id="additional-info"
- />
- </div>
- <div
- className="column-half"
- >
- <h3>
- billing.upgrade.plan
- </h3>
- <div
- id="plan-select"
- />
- <h3>
- billing.upgrade.card_info
- </h3>
- <div
- id="braintree-client"
- />
- </div>
- </div>
- <div
- className="upgrade-footer big-spacer-top"
- >
- <div
- id="next-charge"
- />
- <hr
- className="big-spacer-bottom"
- />
- </div>
- <div
- className=""
- >
- <div
- id="spinner"
- />
- <div
- id="submit-button"
- />
- </div>
- <div
- id="terms-of-service"
- />
- </form>
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CouponForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CouponForm-test.tsx.snap
deleted file mode 100644
index b6a054b1c6b..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CouponForm-test.tsx.snap
+++ /dev/null
@@ -1,22 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render 1`] = `
-<div
- className="huge-spacer-top"
->
- <BillingFormShim
- currentUser={
- Object {
- "isLoggedIn": false,
- }
- }
- onClose={[Function]}
- onCommit={[MockFunction]}
- onCouponUpdate={[Function]}
- onFailToUpgrade={[MockFunction]}
- organizationKey={[MockFunction]}
- skipBraintreeInit={true}
- subscriptionPlans={Array []}
- />
-</div>
-`;
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PaymentMethodSelect-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PaymentMethodSelect-test.tsx.snap
deleted file mode 100644
index 101582f6012..00000000000
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/PaymentMethodSelect-test.tsx.snap
+++ /dev/null
@@ -1,79 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render and change 1`] = `
-<div>
- <label
- className="spacer-bottom"
- >
- onboarding.create_organization.choose_payment_method
- </label>
- <div
- className="little-spacer-top"
- >
- <RadioToggle
- disabled={false}
- name="payment-method"
- onCheck={[MockFunction]}
- options={
- Array [
- Object {
- "label": "billing.card",
- "value": "card",
- },
- Object {
- "label": "billing.coupon",
- "value": "coupon",
- },
- ]
- }
- value={null}
- />
- </div>
-</div>
-`;
-
-exports[`should render and change 2`] = `
-<div>
- <label
- className="spacer-bottom"
- >
- onboarding.create_organization.choose_payment_method
- </label>
- <div
- className="little-spacer-top"
- >
- <RadioToggle
- disabled={false}
- name="payment-method"
- onCheck={
- [MockFunction] {
- "calls": Array [
- Array [
- "card",
- ],
- ],
- "results": Array [
- Object {
- "isThrow": false,
- "value": undefined,
- },
- ],
- }
- }
- options={
- Array [
- Object {
- "label": "billing.card",
- "value": "card",
- },
- Object {
- "label": "billing.coupon",
- "value": "coupon",
- },
- ]
- }
- value="card"
- />
- </div>
-</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
index 099c34d7256..d727d30c24b 100644
--- 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
@@ -35,11 +35,12 @@ exports[`should preselect paid plan 2`] = `
className="boxed-group-inner"
>
<React.Fragment>
- <React.Fragment>
- <PaymentMethodSelect
- onChange={[Function]}
- />
- </React.Fragment>
+ <Connect(withCurrentUser(BillingFormShim))
+ onCommit={[MockFunction]}
+ onFailToUpgrade={[MockFunction]}
+ organizationKey={[MockFunction]}
+ subscriptionPlans={Array []}
+ />
</React.Fragment>
</div>
</div>
@@ -102,46 +103,7 @@ exports[`should render and use free plan 2`] = `
</div>
`;
-exports[`should upgrade using card 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"
- >
- <React.Fragment>
- <PlanSelect
- onChange={[Function]}
- plan="paid"
- startingPrice="10"
- />
- <React.Fragment>
- <PaymentMethodSelect
- onChange={[Function]}
- />
- </React.Fragment>
- </React.Fragment>
- </div>
- </div>
-</div>
-`;
-
-exports[`should upgrade using card 2`] = `
+exports[`should upgrade 1`] = `
<div
className="boxed-group onboarding-step is-open"
>
@@ -169,102 +131,12 @@ exports[`should upgrade using card 2`] = `
plan="paid"
startingPrice="10"
/>
- <React.Fragment>
- <PaymentMethodSelect
- onChange={[Function]}
- paymentMethod="card"
- />
- <Connect(withCurrentUser(CardForm))
- createOrganization={[MockFunction]}
- onFailToUpgrade={[MockFunction]}
- onSubmit={[MockFunction]}
- subscriptionPlans={Array []}
- />
- </React.Fragment>
- </React.Fragment>
- </div>
- </div>
-</div>
-`;
-
-exports[`should upgrade using coupon 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"
- >
- <React.Fragment>
- <PlanSelect
- onChange={[Function]}
- plan="paid"
- startingPrice="10"
- />
- <React.Fragment>
- <PaymentMethodSelect
- onChange={[Function]}
- />
- </React.Fragment>
- </React.Fragment>
- </div>
- </div>
-</div>
-`;
-
-exports[`should upgrade using coupon 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"
- >
- <React.Fragment>
- <PlanSelect
- onChange={[Function]}
- plan="paid"
- startingPrice="10"
+ <Connect(withCurrentUser(BillingFormShim))
+ onCommit={[MockFunction]}
+ onFailToUpgrade={[MockFunction]}
+ organizationKey={[MockFunction]}
+ subscriptionPlans={Array []}
/>
- <React.Fragment>
- <PaymentMethodSelect
- onChange={[Function]}
- paymentMethod="coupon"
- />
- <Connect(withCurrentUser(CouponForm))
- createOrganization={[MockFunction]}
- onFailToUpgrade={[MockFunction]}
- onSubmit={[MockFunction]}
- />
- </React.Fragment>
</React.Fragment>
</div>
</div>
diff --git a/server/sonar-web/src/main/js/apps/tutorials/styles.css b/server/sonar-web/src/main/js/apps/tutorials/styles.css
index e7cc5a727f6..86f633a3a3b 100644
--- a/server/sonar-web/src/main/js/apps/tutorials/styles.css
+++ b/server/sonar-web/src/main/js/apps/tutorials/styles.css
@@ -32,6 +32,10 @@
line-height: var(--controlHeight);
}
+.onboarding-step hr {
+ margin-left: -54px;
+}
+
.onboarding-step-number {
position: absolute;
top: 15px;
diff --git a/server/sonar-web/src/main/js/components/controls/HelpTooltip.tsx b/server/sonar-web/src/main/js/components/controls/HelpTooltip.tsx
index bc68b868f4d..0cba9b66e12 100644
--- a/server/sonar-web/src/main/js/components/controls/HelpTooltip.tsx
+++ b/server/sonar-web/src/main/js/components/controls/HelpTooltip.tsx
@@ -19,7 +19,7 @@
*/
import * as React from 'react';
import * as classNames from 'classnames';
-import Tooltip from './Tooltip';
+import Tooltip, { Placement } from './Tooltip';
import HelpIcon from '../icons-components/HelpIcon';
import * as theme from '../../app/theme';
import './HelpTooltip.css';
@@ -29,6 +29,7 @@ interface Props {
children?: React.ReactNode;
onShow?: () => void;
overlay: React.ReactNode;
+ placement?: Placement;
tagName?: string;
}
@@ -38,7 +39,11 @@ export default function HelpTooltip(props: Props) {
return React.createElement(
tagName,
{ className: classNames('help-tooltip', props.className) },
- <Tooltip mouseLeaveDelay={0.25} onShow={props.onShow} overlay={props.overlay}>
+ <Tooltip
+ mouseLeaveDelay={0.25}
+ onShow={props.onShow}
+ overlay={props.overlay}
+ placement={props.placement}>
<span className="display-inline-flex-center">{children}</span>
</Tooltip>
);