@@ -1 +0,0 @@ | |||
A coupon is a way to pay for yearly subscriptions or to use other payment methods than card. Contact us for more information. |
@@ -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, |
@@ -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[]; | |||
} | |||
@@ -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); |
@@ -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); |
@@ -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> | |||
); | |||
} | |||
} |
@@ -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}> |
@@ -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> | |||
); |
@@ -38,7 +38,6 @@ it('should render', () => { | |||
shallow( | |||
<BillingFormShim | |||
currentUser={{ isLoggedIn: false }} | |||
onClose={jest.fn()} | |||
onCommit={jest.fn()} | |||
organizationKey="org" | |||
subscriptionPlans={[]}> |
@@ -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(); | |||
}); |
@@ -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(); | |||
}); |
@@ -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(); | |||
}); |
@@ -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(); | |||
}); | |||
@@ -7,7 +7,6 @@ exports[`should render 1`] = ` | |||
"isLoggedIn": false, | |||
} | |||
} | |||
onClose={[MockFunction]} | |||
onCommit={[MockFunction]} | |||
organizationKey="org" | |||
subscriptionPlans={Array []} |
@@ -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> | |||
`; |
@@ -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> | |||
`; |
@@ -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> | |||
`; |
@@ -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> |
@@ -32,6 +32,10 @@ | |||
line-height: var(--controlHeight); | |||
} | |||
.onboarding-step hr { | |||
margin-left: -54px; | |||
} | |||
.onboarding-step-number { | |||
position: absolute; | |||
top: 15px; |
@@ -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> | |||
); |
@@ -2736,7 +2736,6 @@ onboarding.create_organization.description=Description | |||
onboarding.create_organization.enter_org_details=Enter your organization details | |||
onboarding.create_organization.enter_payment_details=Enter payment details | |||
onboarding.create_organization.choose_plan=Choose a plan | |||
onboarding.create_organization.choose_payment_method=Choose payment solution | |||
onboarding.create_organization.enter_your_coupon=Enter your coupon | |||
onboarding.create_organization.create_and_upgrade=Create Organization and Upgrade | |||
onboarding.create_organization.ready=All set! Your organization is now ready to go |