Skip to content
This repository was archived by the owner on Nov 4, 2024. It is now read-only.

Commit cff837f

Browse files
authored
refactor: Stripe on submit to use sagas (#688)
REV-3089
1 parent c0bb385 commit cff837f

File tree

17 files changed

+313
-197
lines changed

17 files changed

+313
-197
lines changed

src/feedback/data/sagas.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ export function* handleErrors(e, clearExistingMessages) {
1515
if (e.errors !== undefined) {
1616
for (let i = 0; i < e.errors.length; i++) { // eslint-disable-line no-plusplus
1717
const error = e.errors[i];
18-
yield put(addMessage(error.code, error.userMessage, error.data, error.messageType));
18+
if (error.code === 'sku-error-message') {
19+
yield put(addMessage(error.code, error.userMessage, {}, MESSAGE_TYPES.ERROR));
20+
} else if (error.data === undefined && error.messageType === null) {
21+
yield put(addMessage('transaction-declined-message', error.userMessage, {}, MESSAGE_TYPES.ERROR));
22+
} else {
23+
yield put(addMessage(error.code, error.userMessage, error.data, error.messageType));
24+
}
1925
}
2026
}
2127
if (e.messages !== undefined) {

src/feedback/data/sagas.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,54 @@ describe('saga tests', () => {
3232
expect(caughtErrors).toEqual([]);
3333
});
3434

35+
it('should add a transaction declined error message on errors with undefined data', async () => {
36+
error.errors = [
37+
{
38+
data: undefined,
39+
userMessage: 'error',
40+
messageType: null,
41+
},
42+
];
43+
try {
44+
await runSaga(
45+
{
46+
dispatch: action => dispatched.push(action),
47+
onError: err => caughtErrors.push(err),
48+
},
49+
handleErrors,
50+
error,
51+
).toPromise();
52+
} catch (e) {} // eslint-disable-line no-empty
53+
54+
const lastAction = dispatched[dispatched.length - 1];
55+
expect(lastAction.payload).toEqual(expect.objectContaining({ code: 'transaction-declined-message' }));
56+
expect(caughtErrors).toEqual([]);
57+
});
58+
59+
it('should add a sku error message on sku mismatch error from ecommerce', async () => {
60+
error.errors = [
61+
{
62+
code: 'sku-error-message',
63+
userMessage: 'error',
64+
messageType: MESSAGE_TYPES.ERROR,
65+
},
66+
];
67+
try {
68+
await runSaga(
69+
{
70+
dispatch: action => dispatched.push(action),
71+
onError: err => caughtErrors.push(err),
72+
},
73+
handleErrors,
74+
error,
75+
).toPromise();
76+
} catch (e) {} // eslint-disable-line no-empty
77+
78+
const lastAction = dispatched[dispatched.length - 1];
79+
expect(lastAction.payload).toEqual(expect.objectContaining({ code: 'sku-error-message' }));
80+
expect(caughtErrors).toEqual([]);
81+
});
82+
3583
it('should dispatch addMessage actions on API errors', async () => {
3684
error.errors = [
3785
{

src/payment/checkout/Checkout.jsx

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class Checkout extends React.Component {
8787
);
8888
};
8989

90+
handleSubmitStripe = (formData) => {
91+
this.props.submitPayment({ method: 'stripe', ...formData });
92+
};
93+
9094
handleSubmitStripeButtonClick = () => {
9195
sendTrackEvent(
9296
'edx.bi.ecommerce.basket.payment_selected',
@@ -210,15 +214,8 @@ class Checkout extends React.Component {
210214

211215
const basketClassName = 'basket-section';
212216

213-
// TODO: fix loading, enableStripePaymentProcessor and clientSecretId distinction
214-
// 1. loading should be renamed to loadingBasket
215-
// 2. enableStripePaymentProcessor can be temporarily false while loading is true
216-
// since the flag is in the BFF basket endpoint. Possibly change this?
217-
// 3. Right now when fetching capture context, CyberSource's captureKey is saved as clientSecretId
217+
// TODO: Right now when fetching capture context, CyberSource's captureKey is saved as clientSecretId
218218
// so we cannot rely on !options.clientSecret to distinguish btw payment processors
219-
// 4. There is a delay from when the basket is done loading (plus the flag value)
220-
// and when we get the clientSecretId so there is a point in time when loading skeleton
221-
// is hidden but the Stripe billing and credit card fields are not shown
222219
const shouldDisplayStripePaymentForm = !loading && enableStripePaymentProcessor && options.clientSecret;
223220
const shouldDisplayCyberSourcePaymentForm = !loading && !enableStripePaymentProcessor;
224221

@@ -271,14 +268,11 @@ class Checkout extends React.Component {
271268
<Elements options={options} stripe={stripePromise}>
272269
<StripePaymentForm
273270
options={options}
271+
onSubmitPayment={this.handleSubmitStripe}
274272
onSubmitButtonClick={this.handleSubmitStripeButtonClick}
275-
disabled={submitting}
276273
isBulkOrder={isBulkOrder}
277274
isProcessing={stripeIsSubmitting}
278-
loading={loading}
279275
isQuantityUpdating={isQuantityUpdating}
280-
enableStripePaymentProcessor={enableStripePaymentProcessor}
281-
products={this.props.products}
282276
/>
283277
</Elements>
284278
) : (loading && (this.renderBillingFormSkeleton()))}
@@ -321,11 +315,10 @@ Checkout.propTypes = {
321315
isFreeBasket: PropTypes.bool,
322316
submitting: PropTypes.bool,
323317
isBasketProcessing: PropTypes.bool,
324-
paymentMethod: PropTypes.oneOf(['paypal', 'apple-pay', 'cybersource']),
318+
paymentMethod: PropTypes.oneOf(['paypal', 'apple-pay', 'cybersource', 'stripe']),
325319
orderType: PropTypes.oneOf(Object.values(ORDER_TYPES)),
326320
enableStripePaymentProcessor: PropTypes.bool,
327321
clientSecretId: PropTypes.string,
328-
products: PropTypes.array, // eslint-disable-line react/forbid-prop-types,
329322
};
330323

331324
Checkout.defaultProps = {
@@ -338,7 +331,6 @@ Checkout.defaultProps = {
338331
orderType: ORDER_TYPES.SEAT,
339332
enableStripePaymentProcessor: false,
340333
clientSecretId: null,
341-
products: [],
342334
};
343335

344336
const mapStateToProps = (state) => ({

src/payment/checkout/payment-form/PaymentForm.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ export class PaymentFormComponent extends React.Component {
129129
isQuantityUpdating,
130130
} = this.props;
131131

132-
const showLoadingButton = loading || isQuantityUpdating || !window.microform;
132+
const showLoadingButton = (loading || isQuantityUpdating || !window.microform) && !isProcessing;
133133

134134
return (
135135
<ErrorFocusContext.Provider value={this.state.firstErrorId}>

0 commit comments

Comments
 (0)