Skip to content

Commit

Permalink
feat: Add PageLoadingDynamicPaymentMethods with timeout for DPM recei…
Browse files Browse the repository at this point in the history
…pt redirect (#11)

REV-4049
  • Loading branch information
julianajlk authored May 16, 2024
1 parent bc3becb commit 4aeb2f5
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 22 deletions.
20 changes: 0 additions & 20 deletions src/payment/PageLoading.jsx
Original file line number Diff line number Diff line change
@@ -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() {
Expand All @@ -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 (
<div>
<div
Expand All @@ -47,11 +34,4 @@ export default class PageLoading extends Component {

PageLoading.propTypes = {
srMessage: PropTypes.string.isRequired,
shouldRedirectToReceipt: PropTypes.bool,
orderNumber: PropTypes.string,
};

PageLoading.defaultProps = {
shouldRedirectToReceipt: false,
orderNumber: null,
};
58 changes: 58 additions & 0 deletions src/payment/PageLoadingDynamicPaymentMethods.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
import { logInfo } from '@edx/frontend-platform/logging';

const PageLoadingDynamicPaymentMethods = ({ srMessage, orderNumber }) => {
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 (
<span className="sr-only">
{srMessage}
</span>
);
};

return (
<div>
<div
className="d-flex justify-content-center align-items-center flex-column"
style={{
height: '50vh',
}}
>
<div className="spinner-border text-primary" data-testid="loading-page" role="status">
{renderSrMessage()}
</div>
</div>
</div>
);
};

PageLoadingDynamicPaymentMethods.propTypes = {
srMessage: PropTypes.string.isRequired,
orderNumber: PropTypes.string,
};

PageLoadingDynamicPaymentMethods.defaultProps = {
orderNumber: null,
};

export default PageLoadingDynamicPaymentMethods;
77 changes: 77 additions & 0 deletions src/payment/PageLoadingDynamicPaymentMethods.test.jsx
Original file line number Diff line number Diff line change
@@ -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 <PageLoadingDynamicPaymentMethods />', () => {
const component = (
<IntlProvider locale="en">
<Provider store={store}>
<PageLoadingDynamicPaymentMethods
srMessage=""
orderNumber="EDX-100001"
/>
</Provider>
</IntlProvider>
);
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(
<IntlProvider locale="en">
<Provider store={store}>
<PageLoadingDynamicPaymentMethods
srMessage=""
orderNumber={orderNumber}
/>
</Provider>
</IntlProvider>,
);

act(() => {
jest.advanceTimersByTime(3000);
});
expect(logInfo).toHaveBeenCalledWith(expect.stringMatching(logMessage));
});

it('cleans up the timer on unmount', () => {
const { unmount } = render(
<PageLoadingDynamicPaymentMethods
srMessage=""
orderNumber="EDX-100001"
/>,
);
unmount();
act(() => {
jest.advanceTimersByTime(3000);
});
expect(logInfo).not.toHaveBeenCalled();
});
});
4 changes: 2 additions & 2 deletions src/payment/PaymentPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 (
<PageLoading
<PageLoadingDynamicPaymentMethods
srMessage={this.props.intl.formatMessage(messages['payment.loading.payment'])}
shouldRedirectToReceipt={shouldRedirectToReceipt}
orderNumber={orderNumber}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PageLoadingDynamicPaymentMethods renders <PageLoadingDynamicPaymentMethods /> 1`] = `
<div>
<div>
<div
class="d-flex justify-content-center align-items-center flex-column"
style="height: 50vh;"
>
<div
class="spinner-border text-primary"
data-testid="loading-page"
role="status"
/>
</div>
</div>
</div>
`;

0 comments on commit 4aeb2f5

Please sign in to comment.