From 600969694df4798b96ef9e96604166ff9ab742c0 Mon Sep 17 00:00:00 2001
From: Jenni Laakso
Date: Fri, 5 Feb 2021 14:28:01 +0200
Subject: [PATCH 01/10] Add test data to stripe-config.js
---
src/config.js | 3 ++-
src/stripe-config.js | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/src/config.js b/src/config.js
index 0c6f67a6..17a1fa17 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,6 +1,6 @@
import * as custom from './marketplace-custom-config.js';
import defaultLocationSearches from './default-location-searches';
-import { defaultMCC, stripePublishableKey, stripeCountryDetails } from './stripe-config';
+import { defaultMCC, stripePublishableKey, stripeCountryDetails, testData } from './stripe-config';
import { currencyConfiguration } from './currency-config';
const env = process.env.REACT_APP_ENV;
@@ -229,6 +229,7 @@ const config = {
defaultMCC: defaultMCC,
publishableKey: stripePublishableKey,
supportedCountries: stripeCountryDetails,
+ testData: testData,
},
canonicalRootURL,
address: {
diff --git a/src/stripe-config.js b/src/stripe-config.js
index 89585206..4bae7219 100644
--- a/src/stripe-config.js
+++ b/src/stripe-config.js
@@ -1,3 +1,6 @@
+import { types as sdkTypes } from './util/sdkLoader';
+const { UUID } = sdkTypes;
+
/* Stripe related configuration.
NOTE: REACT_APP_STRIPE_PUBLISHABLE_KEY is mandatory environment variable.
@@ -329,6 +332,41 @@ export const stripeCountryDetails = [
},
];
+/**
+ * Stripe test data
+ *
+ * This data is for filling up the test values related to Stripe
+ * in the demo application to make testing easier.
+ */
+
+export const testData = {
+ basicTestCardToken: 'tok_visa',
+ basicTestCardDetails: {
+ id: new UUID('test-card'),
+ type: 'stripePaymentMethod',
+ attributes: {
+ type: 'stripe-payment-method/card',
+ stripePaymentMethodId: 'test-card',
+ card: {
+ brand: 'visa',
+ last4Digits: '4242',
+ expirationMonth: 4,
+ expirationYear: 2424,
+ },
+ },
+ },
+ address: {
+ addressLine1: 'Erottajankatu 19',
+ postal: '00130',
+ city: 'Helsinki',
+ country: 'FI',
+ },
+ accountType: 'individual',
+ country: 'FI',
+ bankAccountNumber: 'FI89370400440532013000',
+ bankAccountType: 'iban',
+};
+
/*
NOTE: This configuration will not be updated!
We might remove this code in the later releases.
From 78137058c7e21944566e39e327c3bc5fc7b9204d Mon Sep 17 00:00:00 2001
From: Jenni Laakso
Date: Fri, 5 Feb 2021 14:30:25 +0200
Subject: [PATCH 02/10] Use test data for payout details
---
.../EditListingWizard/EditListingWizard.js | 23 ++++++++++++++++++-
.../EditListingWizard.module.css | 7 ++++++
.../StripeBankAccountTokenInputField.js | 11 ++++++++-
.../StripeConnectAccountForm.js | 14 ++++++++++-
4 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/src/components/EditListingWizard/EditListingWizard.js b/src/components/EditListingWizard/EditListingWizard.js
index 00a3c167..09e2f0c9 100644
--- a/src/components/EditListingWizard/EditListingWizard.js
+++ b/src/components/EditListingWizard/EditListingWizard.js
@@ -15,7 +15,13 @@ import {
} from '../../util/urlHelpers';
import { ensureCurrentUser, ensureListing } from '../../util/data';
-import { Modal, NamedRedirect, Tabs, StripeConnectAccountStatusBox } from '../../components';
+import {
+ Button,
+ Modal,
+ NamedRedirect,
+ Tabs,
+ StripeConnectAccountStatusBox,
+} from '../../components';
import { StripeConnectAccountForm } from '../../forms';
import EditListingWizardTab, {
@@ -193,6 +199,7 @@ class EditListingWizard extends Component {
this.state = {
draftId: null,
showPayoutDetails: false,
+ useDefaultTestData: false,
};
this.handleCreateFlowTabScrolling = this.handleCreateFlowTabScrolling.bind(this);
this.handlePublishListing = this.handlePublishListing.bind(this);
@@ -366,6 +373,15 @@ class EditListingWizard extends Component {
return ;
}
+ const handleStripeTestData = () => {
+ this.setState({ useDefaultTestData: true });
+ };
+
+ const stripeDefaultTestData = config.stripe.testData;
+ const stripeInitialValues = this.state.useDefaultTestData
+ ? { accountType: stripeDefaultTestData.accountType, country: stripeDefaultTestData.country }
+ : null;
+
return (
+
{stripeConnected && !returnedAbnormallyFromStripe && showVerificationNeeded ? (
{
this.initialState[inputType] = {
- value: '',
+ value: this.props.useDefaultTestData ? config.stripe.testData.bankAccountNumber : null,
touched: false,
error: formatFieldMessage(intl, inputType, 'required'),
};
@@ -76,6 +76,15 @@ class TokenInputFieldComponent extends Component {
}
this.stripe = window.Stripe(config.stripe.publishableKey);
this._isMounted = true;
+
+ if (!!this.props.useDefaultTestData) {
+ this.handleInputChange(
+ { target: { value: config.stripe.testData.bankAccountNumber } },
+ config.stripe.testData.bankAccountType,
+ config.stripe.testData.country,
+ this.props.intl
+ );
+ }
}
componentDidUpdate(prevProps) {
diff --git a/src/forms/StripeConnectAccountForm/StripeConnectAccountForm.js b/src/forms/StripeConnectAccountForm/StripeConnectAccountForm.js
index f2a37ffa..63cbdb1a 100644
--- a/src/forms/StripeConnectAccountForm/StripeConnectAccountForm.js
+++ b/src/forms/StripeConnectAccountForm/StripeConnectAccountForm.js
@@ -40,7 +40,16 @@ const countryCurrency = countryCode => {
};
const CreateStripeAccountFields = props => {
- const { disabled, countryLabel, showAsRequired, form, values, intl, currentUserId } = props;
+ const {
+ disabled,
+ countryLabel,
+ showAsRequired,
+ form,
+ values,
+ intl,
+ currentUserId,
+ useDefaultTestData,
+ } = props;
/*
We pass some default values to Stripe when creating a new Stripe account in order to reduce couple of steps from Connect Onboarding form.
@@ -138,6 +147,7 @@ const CreateStripeAccountFields = props => {
country={country}
currency={countryCurrency(country)}
validate={validators.required(' ')}
+ useDefaultTestData={useDefaultTestData}
/>
) : null}
@@ -242,6 +252,7 @@ const StripeConnectAccountFormComponent = props => {
values,
stripeConnected,
currentUser,
+ useDefaultTestData,
} = fieldRenderProps;
const accountDataLoaded = stripeConnected && stripeAccountFetched && savedCountry;
@@ -278,6 +289,7 @@ const StripeConnectAccountFormComponent = props => {
form={form}
values={values}
intl={intl}
+ useDefaultTestData={useDefaultTestData}
/>
) : (
Date: Fri, 5 Feb 2021 14:31:46 +0200
Subject: [PATCH 03/10] Use test data for billing details
---
src/containers/CheckoutPage/CheckoutPage.js | 64 +++++++++++++------
.../CheckoutPage/CheckoutPage.module.css | 10 ++-
.../StripePaymentForm/StripePaymentForm.js | 40 +++++++++---
3 files changed, 83 insertions(+), 31 deletions(-)
diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js
index 02324629..5d5af28f 100644
--- a/src/containers/CheckoutPage/CheckoutPage.js
+++ b/src/containers/CheckoutPage/CheckoutPage.js
@@ -39,6 +39,7 @@ import {
NamedRedirect,
Page,
ResponsiveImage,
+ Button,
} from '../../components';
import { StripePaymentForm } from '../../forms';
import { isScrollingDisabled } from '../../ducks/UI.duck';
@@ -101,6 +102,7 @@ export class CheckoutPageComponent extends Component {
pageData: {},
dataLoaded: false,
submitting: false,
+ useDefaultTestData: false,
};
this.stripe = null;
@@ -108,6 +110,7 @@ export class CheckoutPageComponent extends Component {
this.loadInitialData = this.loadInitialData.bind(this);
this.handlePaymentIntent = this.handlePaymentIntent.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
+ this.handleInitialTestData = this.handleInitialTestData.bind(this);
}
componentDidMount() {
@@ -462,6 +465,10 @@ export class CheckoutPageComponent extends Component {
});
}
+ handleInitialTestData = () => {
+ this.setState({ useDefaultTestData: true });
+ };
+
onStripeInitialized(stripe) {
this.stripe = stripe;
@@ -746,7 +753,9 @@ export class CheckoutPageComponent extends Component {
// If your marketplace works mostly in one country you can use initial values to select country automatically
// e.g. {country: 'FI'}
- const initalValuesForStripePayment = { name: userName };
+ const initalValuesForStripePayment = !this.state.useDefaultTestData
+ ? { name: userName }
+ : { name: userName, ...config.stripe.testData.address };
return (
@@ -792,26 +801,39 @@ export class CheckoutPageComponent extends Component {
) : null}
{showPaymentForm ? (
-
+ <>
+ {!hasDefaultPaymentMethod ? (
+
+ ) : null}
+
+ >
) : null}
{isPaymentExpired ? (
diff --git a/src/containers/CheckoutPage/CheckoutPage.module.css b/src/containers/CheckoutPage/CheckoutPage.module.css
index fa1f4312..b702eec2 100644
--- a/src/containers/CheckoutPage/CheckoutPage.module.css
+++ b/src/containers/CheckoutPage/CheckoutPage.module.css
@@ -141,12 +141,11 @@
@media (--viewportMedium) {
margin-top: 27px;
- margin-bottom: 30px;
+ margin-bottom: 22px;
}
@media (--viewportLarge) {
margin-top: 0px;
- margin-bottom: 54px;
padding: 0;
}
}
@@ -331,3 +330,10 @@
margin: 0 48px;
}
}
+
+.stripeTestDataButton {
+ @apply --marketplaceSmallFontStyles;
+ width: 100%;
+ min-height: 40px;
+ margin-bottom: 16px;
+}
diff --git a/src/forms/StripePaymentForm/StripePaymentForm.js b/src/forms/StripePaymentForm/StripePaymentForm.js
index 399c407e..caf85998 100644
--- a/src/forms/StripePaymentForm/StripePaymentForm.js
+++ b/src/forms/StripePaymentForm/StripePaymentForm.js
@@ -86,7 +86,16 @@ const cardStyles = {
};
const OneTimePaymentWithCardElement = props => {
- const { cardClasses, formId, handleStripeElementRef, hasCardError, error, label, intl } = props;
+ const {
+ cardClasses,
+ formId,
+ handleStripeElementRef,
+ hasCardError,
+ error,
+ label,
+ intl,
+ useDefaultTestData,
+ } = props;
const labelText =
label || intl.formatMessage({ id: 'StripePaymentForm.saveAfterOnetimePayment' });
return (
@@ -94,8 +103,14 @@ const OneTimePaymentWithCardElement = props => {
-
- {hasCardError ? {error} : null}
+ {useDefaultTestData ? (
+ <>Use test card>
+ ) : (
+ <>
+
+ {hasCardError ? {error} : null}
+ >
+ )}
{
error,
paymentMethod,
intl,
+ useDefaultTestData,
} = props;
const last4Digits = defaultPaymentMethod.attributes.card.last4Digits;
const labelText = intl.formatMessage(
@@ -151,6 +167,7 @@ const PaymentMethodSelector = props => {
error={error}
label={labelText}
intl={intl}
+ useDefaultTestData={useDefaultTestData}
/>
) : null}
@@ -289,7 +306,8 @@ class StripePaymentForm extends Component {
const { initialMessage } = values;
const { cardValueValid, paymentMethod } = this.state;
const billingDetailsKnown = hasHandledCardPayment || defaultPaymentMethod;
- const onetimePaymentNeedsAttention = !billingDetailsKnown && !cardValueValid;
+ const onetimePaymentNeedsAttention =
+ !billingDetailsKnown && !cardValueValid && !this.props.useDefaultTestData;
if (inProgress || onetimePaymentNeedsAttention) {
// Already submitting or card value incomplete/invalid
@@ -298,7 +316,11 @@ class StripePaymentForm extends Component {
const params = {
message: initialMessage ? initialMessage.trim() : null,
- card: this.card,
+ card: this.props.useDefaultTestData
+ ? {
+ token: config.stripe.testData.basicTestCardToken,
+ }
+ : card,
formId,
formValues: values,
paymentMethod: getPaymentMethod(
@@ -328,6 +350,7 @@ class StripePaymentForm extends Component {
form,
hasHandledCardPayment,
defaultPaymentMethod,
+ useDefaultTestData,
} = formRenderProps;
this.finalFormAPI = form;
@@ -392,9 +415,8 @@ class StripePaymentForm extends Component {
this.state.paymentMethod,
showPaymentMethodSelector
);
- const showOnetimePaymentFields = ['onetimeCardPayment', 'replaceCard'].includes(
- selectedPaymentMethod
- );
+ const showOnetimePaymentFields =
+ !!useDefaultTestData || ['onetimeCardPayment', 'replaceCard'].includes(selectedPaymentMethod);
return hasStripeKey ? (
diff --git a/src/containers/StripePayoutPage/StripePayoutPage.module.css b/src/containers/StripePayoutPage/StripePayoutPage.module.css
index 567ac1ef..3d1bc22f 100644
--- a/src/containers/StripePayoutPage/StripePayoutPage.module.css
+++ b/src/containers/StripePayoutPage/StripePayoutPage.module.css
@@ -1,3 +1,5 @@
+@import '../../styles/propertySets.css';
+
.content {
@media (--viewportMedium) {
margin: 32px auto 0 auto;
@@ -24,3 +26,10 @@
margin-bottom: 47px;
}
}
+
+.stripeTestDataButton {
+ @apply --marketplaceSmallFontStyles;
+ width: 100%;
+ min-height: 40px;
+ margin-top: 24px;
+}
From 62b01caadae9ea9d3c3fe809a1d6a46c7e28579a Mon Sep 17 00:00:00 2001
From: Jenni Laakso
Date: Mon, 8 Feb 2021 17:00:21 +0200
Subject: [PATCH 05/10] Use test data on PaymentMethodPage
---
.../PaymentMethodsPage/PaymentMethodsPage.js | 43 +++++++++++++------
.../PaymentMethodsForm/PaymentMethodsForm.js | 39 ++++++++++-------
2 files changed, 52 insertions(+), 30 deletions(-)
diff --git a/src/containers/PaymentMethodsPage/PaymentMethodsPage.js b/src/containers/PaymentMethodsPage/PaymentMethodsPage.js
index 62d10cbc..7d503eed 100644
--- a/src/containers/PaymentMethodsPage/PaymentMethodsPage.js
+++ b/src/containers/PaymentMethodsPage/PaymentMethodsPage.js
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
import { bool, func, object } from 'prop-types';
import { compose } from 'redux';
import { connect } from 'react-redux';
+import config from '../../config';
import { FormattedMessage, injectIntl, intlShape } from '../../util/reactIntl';
import { ensureCurrentUser, ensureStripeCustomer, ensurePaymentMethodCard } from '../../util/data';
import { propTypes } from '../../util/types';
@@ -9,6 +10,7 @@ import { savePaymentMethod, deletePaymentMethod } from '../../ducks/paymentMetho
import { handleCardSetup } from '../../ducks/stripe.duck';
import { manageDisableScrolling, isScrollingDisabled } from '../../ducks/UI.duck';
import {
+ Button,
SavedCardDetails,
LayoutSideNavigation,
LayoutWrapperMain,
@@ -28,6 +30,7 @@ import css from './PaymentMethodsPage.module.css';
const PaymentMethodsPageComponent = props => {
const [isSubmitting, setIsSubmitting] = useState(false);
const [cardState, setCardState] = useState(null);
+ const [useDefaultTestData, setUseDefaultTestData] = useState(false);
const {
currentUser,
@@ -136,7 +139,13 @@ const PaymentMethodsPageComponent = props => {
? `${ensuredCurrentUser.attributes.profile.firstName} ${ensuredCurrentUser.attributes.profile.lastName}`
: null;
- const initalValuesForStripePayment = { name: userName };
+ const initalValuesForStripePayment = !useDefaultTestData
+ ? { name: userName }
+ : { name: userName, ...config.stripe.testData.address };
+
+ const handleInitialTestData = () => {
+ setUseDefaultTestData(true);
+ };
const card = hasDefaultPaymentMethod
? ensurePaymentMethodCard(currentUser.stripeCustomer.defaultPaymentMethod).attributes.card
@@ -173,19 +182,25 @@ const PaymentMethodsPageComponent = props => {
/>
) : null}
{showForm ? (
-
+ <>
+
+
+ >
) : null}
>
)}
diff --git a/src/forms/PaymentMethodsForm/PaymentMethodsForm.js b/src/forms/PaymentMethodsForm/PaymentMethodsForm.js
index e90927fe..eacd0650 100644
--- a/src/forms/PaymentMethodsForm/PaymentMethodsForm.js
+++ b/src/forms/PaymentMethodsForm/PaymentMethodsForm.js
@@ -146,7 +146,7 @@ class PaymentMethodsForm extends Component {
}
handleSubmit(values) {
const { onSubmit, inProgress, formId } = this.props;
- const cardInputNeedsAttention = !this.state.cardValueValid;
+ const cardInputNeedsAttention = !this.state.cardValueValid && !this.props.useDefaultTestData;
if (inProgress || cardInputNeedsAttention) {
// Already submitting or card value incomplete/invalid
@@ -155,7 +155,7 @@ class PaymentMethodsForm extends Component {
const params = {
stripe: this.stripe,
- card: this.card,
+ card: this.props.useDefaultTestData ? { payment_method: 'pm_card_visa' } : this.card,
formId,
formValues: values,
};
@@ -177,10 +177,11 @@ class PaymentMethodsForm extends Component {
createStripeCustomerError,
handleCardSetupError,
form,
+ useDefaultTestData,
} = formRenderProps;
this.finalFormAPI = form;
- const cardInputNeedsAttention = !this.state.cardValueValid;
+ const cardInputNeedsAttention = !this.state.cardValueValid && !useDefaultTestData;
const submitDisabled = invalid || cardInputNeedsAttention || submitInProgress;
const hasCardError = this.state.error && !submitInProgress;
const classes = classNames(rootClassName || css.root, className);
@@ -219,19 +220,25 @@ class PaymentMethodsForm extends Component {
return hasStripeKey ? (