From f462afdd1fec2d8dd5c267caba93bbcbbddbb72f Mon Sep 17 00:00:00 2001 From: Juliana Kang Date: Thu, 16 May 2024 13:00:12 -0400 Subject: [PATCH] feat: Added paypal redirect (#11) REV-4049 --- src/payment/PageLoading.jsx | 20 ----- .../PageLoadingDynamicPaymentMethods.jsx | 58 ++++++++++++++ .../PageLoadingDynamicPaymentMethods.test.jsx | 77 +++++++++++++++++++ src/payment/PaymentPage.jsx | 4 +- ...LoadingDynamicPaymentMethods.test.jsx.snap | 18 +++++ 5 files changed, 155 insertions(+), 22 deletions(-) create mode 100644 src/payment/PageLoadingDynamicPaymentMethods.jsx create mode 100644 src/payment/PageLoadingDynamicPaymentMethods.test.jsx create mode 100644 src/payment/__snapshots__/PageLoadingDynamicPaymentMethods.test.jsx.snap diff --git a/src/payment/PageLoading.jsx b/src/payment/PageLoading.jsx index 15e55c167..de61fb2b7 100644 --- a/src/payment/PageLoading.jsx +++ b/src/payment/PageLoading.jsx @@ -1,7 +1,5 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { getConfig } from '@edx/frontend-platform'; -import { logInfo } from '@edx/frontend-platform/logging'; export default class PageLoading extends Component { renderSrMessage() { @@ -17,17 +15,6 @@ export default class PageLoading extends Component { } render() { - const { shouldRedirectToReceipt, orderNumber } = this.props; - - if (shouldRedirectToReceipt) { - logInfo(`Dynamic Payment Methods payment succeeded for edX order number ${orderNumber}, redirecting to ecommerce receipt page.`); - const queryParams = `order_number=${orderNumber}&disable_back_button=${Number(true)}&dpm_enabled=${true}`; - if (getConfig().ENVIRONMENT !== 'test') { - /* istanbul ignore next */ - global.location.assign(`${getConfig().ECOMMERCE_BASE_URL}/checkout/receipt/?${queryParams}`); - } - } - return (
{ + useEffect(() => { + const timer = setTimeout(() => { + logInfo(`Dynamic Payment Methods payment succeeded for edX order number ${orderNumber}, redirecting to ecommerce receipt page.`); + const queryParams = `order_number=${orderNumber}&disable_back_button=${Number(true)}&dpm_enabled=${true}`; + + if (getConfig().ENVIRONMENT !== 'test') { + /* istanbul ignore next */ + global.location.assign(`${getConfig().ECOMMERCE_BASE_URL}/checkout/receipt/?${queryParams}`); + } + }, 3000); // Delay the redirect to receipt page by 3 seconds to make sure ecomm order fulfillment is done. + + return () => clearTimeout(timer); // On unmount, clear the timer + }, [srMessage, orderNumber]); + + const renderSrMessage = () => { + if (!srMessage) { + return null; + } + + return ( + + {srMessage} + + ); + }; + + return ( +
+
+
+ {renderSrMessage()} +
+
+
+ ); +}; + +PageLoadingDynamicPaymentMethods.propTypes = { + srMessage: PropTypes.string.isRequired, + orderNumber: PropTypes.string, +}; + +PageLoadingDynamicPaymentMethods.defaultProps = { + orderNumber: null, +}; + +export default PageLoadingDynamicPaymentMethods; diff --git a/src/payment/PageLoadingDynamicPaymentMethods.test.jsx b/src/payment/PageLoadingDynamicPaymentMethods.test.jsx new file mode 100644 index 000000000..192fd2e75 --- /dev/null +++ b/src/payment/PageLoadingDynamicPaymentMethods.test.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { createStore } from 'redux'; +import { Provider } from 'react-redux'; +import { render, act } from '@testing-library/react'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { logInfo } from '@edx/frontend-platform/logging'; + +import createRootReducer from '../data/reducers'; +import PageLoadingDynamicPaymentMethods from './PageLoadingDynamicPaymentMethods'; + +jest.mock('@edx/frontend-platform/logging', () => ({ + logInfo: jest.fn(), +})); + +describe('PageLoadingDynamicPaymentMethods', () => { + let store; + + beforeEach(() => { + store = createStore(createRootReducer()); + jest.useFakeTimers(); + jest.clearAllMocks(); + }); + + afterEach(() => { + jest.runOnlyPendingTimers(); + jest.useRealTimers(); + }); + + it('renders ', () => { + const component = ( + + + + + + ); + const { container: tree } = render(component); + expect(tree).toMatchSnapshot(); + }); + + it('it redirects to receipt page after 3 seconds delay', () => { + const orderNumber = 'EDX-100001'; + const logMessage = `Dynamic Payment Methods payment succeeded for edX order number ${orderNumber}, redirecting to ecommerce receipt page.`; + render( + + + + + , + ); + + act(() => { + jest.advanceTimersByTime(3000); + }); + expect(logInfo).toHaveBeenCalledWith(expect.stringMatching(logMessage)); + }); + + it('cleans up the timer on unmount', () => { + const { unmount } = render( + , + ); + unmount(); + act(() => { + jest.advanceTimersByTime(3000); + }); + expect(logInfo).not.toHaveBeenCalled(); + }); +}); diff --git a/src/payment/PaymentPage.jsx b/src/payment/PaymentPage.jsx index f0902f38e..bdf43cd4a 100644 --- a/src/payment/PaymentPage.jsx +++ b/src/payment/PaymentPage.jsx @@ -26,6 +26,7 @@ import EmptyCartMessage from './EmptyCartMessage'; import Cart from './cart/Cart'; import Checkout from './checkout/Checkout'; import { FormattedAlertList } from '../components/formatted-alert-list/FormattedAlertList'; +import PageLoadingDynamicPaymentMethods from './PageLoadingDynamicPaymentMethods'; class PaymentPage extends React.Component { constructor(props) { @@ -113,9 +114,8 @@ class PaymentPage extends React.Component { // lag between when the paymentStatus is no longer null but the redirect hasn't happened yet. if (shouldRedirectToReceipt) { return ( - ); diff --git a/src/payment/__snapshots__/PageLoadingDynamicPaymentMethods.test.jsx.snap b/src/payment/__snapshots__/PageLoadingDynamicPaymentMethods.test.jsx.snap new file mode 100644 index 000000000..c3dda9f75 --- /dev/null +++ b/src/payment/__snapshots__/PageLoadingDynamicPaymentMethods.test.jsx.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PageLoadingDynamicPaymentMethods renders 1`] = ` +
+
+
+
+
+
+
+`;