DefinitelyTyped/types/react-stripe-elements/react-stripe-elements-tests.tsx
Benedikt Bauer b280439d65
[@types/react-stripe-elements] Update createToken to accept BankAccountOptions as well (#41946)
* Update react-stripe-elements definitions to allow BankAccountOptions to be passed to createToken
Also add some tests for the Iban, IdealBank and PaymentRequestButton elements

* Update stripe-v3 to accept BankAccountOptions on createToken
2020-02-03 10:21:24 -08:00

425 lines
13 KiB
TypeScript

import * as React from 'react';
import {
StripeProvider,
CardElement,
Elements,
injectStripe,
CardNumberElement,
CardExpiryElement,
CardCvcElement,
CardCVCElement,
IbanElement,
IdealBankElement,
PostalCodeElement,
PaymentRequestButtonElement,
ReactStripeElements,
} from 'react-stripe-elements';
import InjectedStripeProps = ReactStripeElements.InjectedStripeProps;
import ElementChangeResponse = stripe.elements.ElementChangeResponse;
import ElementsOptions = stripe.elements.ElementsOptions;
import ElementsCreateOptions = stripe.elements.ElementsCreateOptions;
import HTMLStripeElement = ReactStripeElements.HTMLStripeElement;
import TokenResponse = ReactStripeElements.TokenResponse;
const cardElementProps: ElementsOptions = {
iconStyle: 'solid',
style: {
base: {
color: '#32325d',
lineHeight: '24px',
fontFamily: 'Roboto, "Helvetica Neue", sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4',
},
},
invalid: {
color: '#B71C1C',
iconColor: '#B71C1C',
},
},
hidePostalCode: true,
classes: {
base: 'field',
complete: 'complete',
empty: 'is-empty',
focus: 'is-focused',
invalid: 'is-invalid',
webkitAutofill: 'webkit-autofill',
},
hideIcon: true,
};
const fontElementsProps: ElementsCreateOptions = {
fonts: [
{
cssSrc: 'https://fonts.googleapis.com/css?family=Dosis',
},
{
family: 'Dosis, sanz',
src: 'url(https://somewebsite.com/path/to/font.woff)',
style: 'normal',
weight: 'bold',
unicodeRange: 'U+26',
},
],
locale: 'es',
};
const ElementsWithPropsTest: React.FC = () => (
<div>
<CardElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<CardNumberElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<CardExpiryElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<CardCvcElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<CardCVCElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<IbanElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<IdealBankElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<PostalCodeElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
/>
<PaymentRequestButtonElement
{...cardElementProps}
onChange={(event: ElementChangeResponse) => void 0}
onBlur={(event: ElementChangeResponse) => void 0}
onReady={(el: HTMLStripeElement) => void 0}
onFocus={(event: ElementChangeResponse) => void 0}
onClick={(event: ElementChangeResponse) => void 0}
/>
</div>
);
interface ComponentProps {
tokenCallback(token: TokenResponse): void;
}
class WrappedComponent extends React.Component<ComponentProps & InjectedStripeProps> {
constructor(props: ComponentProps & InjectedStripeProps) {
super(props);
// Test for paymentRequest
const paymentRequest =
props.stripe &&
props.stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Demo total',
amount: 1,
},
});
if (paymentRequest) {
paymentRequest.on('token', ({ complete, token, ...data }) => undefined);
paymentRequest.canMakePayment().then(res => undefined);
}
}
onSubmit = () => {
const elements = this.props.elements;
// createToken(options?: TokenOptions)
this.props
.stripe!.createToken({
name: '',
address_line1: '',
address_line2: '',
address_city: '',
address_state: '',
address_zip: '',
address_country: '',
currency: '',
})
.then((response: TokenResponse) => this.props.tokenCallback(response));
// createToken(options?: BankAccountTokenOptions)
this.props
.stripe!.createToken({
country: '',
currency: '',
routing_number: '',
account_number: '',
account_holder_name: '',
account_holder_type: '',
})
.then((response: TokenResponse) => this.props.tokenCallback(response));
}
isFormValid = () => {
// use onChange callbacks from *Element components to detect if form is valid for submission
return false;
}
render() {
return (
<form onSubmit={this.onSubmit}>
<ElementsWithPropsTest />
<button disabled={!this.isFormValid()} />
</form>
);
}
}
const ExportedComponent: React.ComponentType<ComponentProps> = injectStripe(WrappedComponent);
class MainComponent extends React.Component {
onTokenReceived = (token: TokenResponse) => void 0;
render() {
return <ExportedComponent tokenCallback={this.onTokenReceived} />;
}
}
class TestHOCs extends React.Component {
render() {
return (
<StripeProvider apiKey="">
<Elements {...fontElementsProps}>
<MainComponent />
</Elements>
</StripeProvider>
);
}
}
/**
* Just an extra test to check default props
*/
const ElementsDefaultPropsTest: React.FC = () => (
<div>
<CardElement />
<CardNumberElement />
<CardExpiryElement />
<CardCvcElement />
<CardCVCElement />
<PostalCodeElement />
</div>
);
/**
* StripeProvider should either receive `apiKey` or `stripe`, but not both.
* See: https://github.com/stripe/react-stripe-elements/blob/d30b32b6b8df282dd8880a3521667c371e90083f/src/components/Provider.js#L83-L86
*/
const TestStripeProviderProps1: React.FC = () => <StripeProvider apiKey="" />;
const TestStripeProviderProps2: React.FC<{
stripe: stripe.Stripe;
}> = props => <StripeProvider stripe={props.stripe} />;
/**
* props.stripe is null until loaded.
* See: https://github.com/stripe/react-stripe-elements#props-shape
*/
const TestStripeProviderProps3: React.FC<{
stripe: stripe.Stripe;
}> = props => <StripeProvider stripe={null} />;
/**
* End-to-end usage of loading stripe.js asynchronously.
* See: https://github.com/stripe/react-stripe-elements#loading-stripejs-asynchronously
*/
const TestStripeProviderProps4: React.FC<{
stripe: null | stripe.Stripe;
}> = props => (
<StripeProvider stripe={props.stripe}>
<Elements>
<div />
</Elements>
</StripeProvider>
);
/**
* StripeProvider should be able to accept options.
* See: https://stripe.com/docs/stripe-js/reference#stripe-function for options.
*/
const TestStripeProviderOptions: React.FC = () => <StripeProvider apiKey="" stripeAccount="" />;
class CreatePaymentMethod extends React.Component<InjectedStripeProps> {
testCreatePaymentMethod = () => {
this.props
.stripe!.createPaymentMethod('card')
.then((response) => response.paymentMethod);
}
testCreatePaymentMethodWithData = () => {
this.props
.stripe!.createPaymentMethod('card', {
billing_details: {
name: 'John Doe'
},
metadata: {
foo: 'bar'
}
})
.then((response) => response.paymentMethod);
}
testCreatePaymentMethodWithNewData = () => {
const cardEl = this.props.elements!.getElement('card') || undefined;
this.props
.stripe!.createPaymentMethod({
type: 'card',
card: cardEl,
billing_details: {
name: 'Jenny Rosen'
}
})
.then((response) => response.paymentMethod);
}
testCreatePaymentMethodWithError = () => {
this.props
.stripe!.createPaymentMethod('card')
.then((response) => response.error);
}
}
class HandleCardPayment extends React.Component<InjectedStripeProps> {
testHandleCardAction = () => {
this.props
.stripe!.handleCardAction('{PAYMENT_INTENT_CLIENT_SECRET}')
.then((response) => response.paymentIntent);
}
testHandleCardPayment = () => {
this.props
.stripe!.handleCardPayment('clientSecret')
.then((response) => response.paymentIntent);
}
testHandleCardPaymentWithOptions = () => {
this.props
.stripe!.handleCardPayment('clientSecret', {
payment_method_data: {
billing_details: {
name: 'John Doe'
}
},
receipt_email: 'john@doe.com'
})
.then((response) => response.paymentIntent);
}
testHandleCardPaymentWithError = () => {
this.props
.stripe!.handleCardPayment('clientSecret')
.then((response) => response.error);
}
}
class HandleCardSetup extends React.Component<InjectedStripeProps> {
testHandleCardSetup = () => {
this.props
.stripe!.handleCardSetup('clientSecret')
.then((response) => response.setupIntent);
}
testHandleCardSetupWithData = () => {
this.props
.stripe!.handleCardSetup('clientSecret', {
payment_method_data: {
billing_details: {
name: 'John Doe'
}
}
})
.then((response) => response.setupIntent);
}
testHandleCardSetupWithError = () => {
this.props
.stripe!.handleCardSetup('clientSecret')
.then((response) => response.error);
}
}
class ConfirmPaymentPayment extends React.Component<InjectedStripeProps> {
testConfirmCardPayment = () => {
const el = this.props.elements!.getElement('card');
this.props
.stripe!.confirmCardPayment('clientSecret', {
payment_method: {
card: el || { token: 'test token' },
billing_details: {
name: 'Jenny Rosen'
}
}
})
.then((response) => response.paymentIntent);
}
testConfirmCardPaymentWithError = () => {
this.props
.stripe!.handleCardSetup('clientSecret')
.then((response) => response.error);
}
}
class ConfirmCardSetup extends React.Component<InjectedStripeProps> {
testConfirmCardSetup = () => {
const el = this.props.elements!.getElement('cardNumber');
this.props
.stripe!.confirmCardSetup('clientSecret', {
payment_method: {
card: el || { token: 'test with token' },
billing_details: {
name: 'Jenny Rosen'
}
}
})
.then((response) => response.setupIntent);
}
testConfirmCardSetupWithError = () => {
this.props
.stripe!.handleCardSetup('clientSecret')
.then((response) => response.error);
}
}