Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Int b 22701 ppm document loading mask service member #14953

Open
wants to merge 23 commits into
base: integrationTesting
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
959e258
Bump store2 from 2.14.2 to 2.14.4
dependabot[bot] Feb 4, 2025
7ad4c72
Merge branch 'main' of github.com:transcom/mymove into MAIN-B-22039-r…
ryan-mchugh Feb 25, 2025
109973b
B-22701 First commit
msaki-caci Feb 27, 2025
2842549
B-22701 Remove unnecessary code
msaki-caci Feb 28, 2025
8191575
Merge branch 'main' of github.com:transcom/mymove into MAIN-B-22039-r…
ryan-mchugh Feb 28, 2025
29c9e8a
Merge branch 'main' of github.com:transcom/mymove into MAIN-B-22039-r…
ryan-mchugh Feb 28, 2025
3ebb152
Merge branch 'main' into MAIN-B-22039-remove_lat_lon
brianmanley-caci Mar 3, 2025
8ea2d31
B-22701 Refactor LoadingSpinner to use ellipsis by default
msaki-caci Mar 3, 2025
b670a71
B-22701 Refactor initial implementation
msaki-caci Mar 3, 2025
2fe22cc
B-22701 Add the LoadingSpinner to MoveHome page
msaki-caci Mar 3, 2025
f5905ed
Merge branch 'main' into MAIN-B-22701_AOA_Loading_mask
msaki-caci Mar 3, 2025
be8a59a
Merge branch 'main' into MAIN-B-22039-remove_lat_lon
brianmanley-caci Mar 3, 2025
d13d25a
Merge pull request #14924 from transcom/MAIN-B-22039-remove_lat_lon
brianmanley-caci Mar 3, 2025
e3e9dd3
B-22701 Fix spelling of 'ellipsis'
msaki-caci Mar 3, 2025
ee30031
Merge branch 'main' into dependabot/npm_and_yarn/store2-2.14.4
deandreJones Mar 3, 2025
dc3fd38
Merge pull request #14660 from transcom/dependabot/npm_and_yarn/store…
deandreJones Mar 3, 2025
4854da1
B-22701 Update PPMSummaryList test and onDownloadError
msaki-caci Mar 4, 2025
a85cb36
B-22701 Add test for onStart prop for AsyncPacketDownloadLink
msaki-caci Mar 4, 2025
b4fbeaa
Merge branch 'main' into MAIN-B-22701_AOA_Loading_mask
msaki-caci Mar 4, 2025
30e357b
Merge branch 'MAIN-B-22701_PPM_Document_Loading_mask_service_member' …
msaki-caci Mar 4, 2025
f4c077b
B-22701 Update loading message and Add tests
msaki-caci Mar 4, 2025
bbace09
B-22701 Replace waitFor with act in MoveHome.test.jsx
msaki-caci Mar 4, 2025
083785e
Merge branch 'MAIN-B-22701_PPM_Document_Loading_mask_service_member' …
msaki-caci Mar 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/LoadingSpinner/LoadingSpinner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const LoadingSpinner = ({ message }) => (
secondaryColor="#565c65"
ariaLabel="Loading content, please wait"
/>
<p className={styles.message}>{message || 'Loading, please wait...'}</p>
<p className={styles.message}>{message || 'Loading, please wait'}...</p>
</div>
</div>
);
Expand Down
6 changes: 4 additions & 2 deletions src/components/LoadingSpinner/LoadingSpinner.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ describe('LoadingSpinner Component', () => {
});

test('renders the loading spinner with a custom message', () => {
const customMessage = 'Fetching data...';
const customMessage = 'Fetching data';
const ellipsis = '...';
const expectedMessage = customMessage + ellipsis;
render(<LoadingSpinner message={customMessage} />);

expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();

expect(screen.getByText(customMessage)).toBeInTheDocument();
expect(screen.getByText(expectedMessage)).toBeInTheDocument();
});
});
57 changes: 44 additions & 13 deletions src/components/PPMSummaryList/PPMSummaryList.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { arrayOf, bool, func, number } from 'prop-types';
import { Button } from '@trussworks/react-uswds';

import styles from './PPMSummaryList.module.scss';

import SectionWrapper from 'components/Customer/SectionWrapper';
import LoadingSpinner from 'components/LoadingSpinner/LoadingSpinner';
import { ppmShipmentStatuses } from 'constants/shipments';
import { ShipmentShape } from 'types/shipment';
import { formatCustomerDate, formatAddressShort } from 'utils/formatters';
import AsyncPacketDownloadLink from 'shared/AsyncPacketDownloadLink/AsyncPacketDownloadLink';
import AsyncPacketDownloadLink, {
onPacketDownloadSuccessHandler,
} from 'shared/AsyncPacketDownloadLink/AsyncPacketDownloadLink';
import { downloadPPMPaymentPacket } from 'services/internalApi';
import { isFeedbackAvailable } from 'constants/ppmFeedback';

Expand Down Expand Up @@ -90,10 +93,33 @@ const paymentReviewed = (approvedAt, submittedAt, reviewedAt, pickupAddress, des
};

const PPMSummaryStatus = (shipment, orderLabel, onButtonClick, onDownloadError, onFeedbackClick) => {
const [isDownloading, setIsDownloading] = useState(false);
const {
ppmShipment: { status, approvedAt, submittedAt, reviewedAt, pickupAddress, destinationAddress },
} = shipment;

useEffect(() => {
if (isDownloading) {
document.body.classList.add('has-overlay');
} else {
document.body.classList.remove('has-overlay');
}

return () => {
document.body.classList.remove('has-overlay');
};
}, [isDownloading]);

const handleDownloadSuccess = (response) => {
setIsDownloading(false);
onPacketDownloadSuccessHandler(response);
};

const handleDownloadFailure = () => {
setIsDownloading(false);
onDownloadError();
};

let actionButtons;
let content;

Expand Down Expand Up @@ -128,7 +154,9 @@ const PPMSummaryStatus = (shipment, orderLabel, onButtonClick, onDownloadError,
id={shipment?.ppmShipment?.id}
label="Download Payment Packet"
asyncRetrieval={downloadPPMPaymentPacket}
onFailure={onDownloadError}
onSuccess={handleDownloadSuccess}
onFailure={handleDownloadFailure}
onStart={() => setIsDownloading(true)}
className="styles.btn"
/>
</div>,
Expand All @@ -138,7 +166,9 @@ const PPMSummaryStatus = (shipment, orderLabel, onButtonClick, onDownloadError,
id={shipment?.ppmShipment?.id}
label="Download Payment Packet"
asyncRetrieval={downloadPPMPaymentPacket}
onFailure={onDownloadError}
onSuccess={handleDownloadSuccess}
onFailure={handleDownloadFailure}
onStart={() => setIsDownloading(true)}
className="styles.btn"
/>
);
Expand All @@ -147,15 +177,17 @@ const PPMSummaryStatus = (shipment, orderLabel, onButtonClick, onDownloadError,
break;
default:
}

return (
<SectionWrapper className={styles['ppm-shipment']}>
<div className={styles['ppm-shipment__heading-section']}>
<strong>{orderLabel}</strong>
{actionButtons}
</div>
<div className={styles['ppm-shipment__content']}>{content}</div>
</SectionWrapper>
<div>
{isDownloading && <LoadingSpinner message="Downloading Payment Packet (PDF)" />}
<SectionWrapper className={styles['ppm-shipment']}>
<div className={styles['ppm-shipment__heading-section']}>
<strong>{orderLabel}</strong>
{actionButtons}
</div>
<div className={styles['ppm-shipment__content']}>{content}</div>
</SectionWrapper>
</div>
);
};

Expand All @@ -178,7 +210,6 @@ const PPMSummaryList = ({ shipments, onUploadClick, onDownloadError, onFeedbackC

const PPMSummaryListItem = ({ shipment, hasMany, index, onUploadClick, onDownloadError, onFeedbackClick }) => {
const orderLabel = hasMany ? `PPM ${index + 1}` : 'PPM';

return PPMSummaryStatus(shipment, orderLabel, onUploadClick, onDownloadError, onFeedbackClick);
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/PPMSummaryList/PPMSummaryList.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@
&:last-of-type {
@include u-margin-bottom(0);
}
}
}
44 changes: 37 additions & 7 deletions src/components/PPMSummaryList/PPMSummaryList.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ afterEach(() => {
jest.resetAllMocks();
});

const onDownloadError = jest.fn();

const shipments = [
{
id: '1',
Expand Down Expand Up @@ -143,6 +145,7 @@ const onUploadClick = jest.fn();

const defaultProps = {
shipments,
onDownloadError,
onUploadClick,
};

Expand Down Expand Up @@ -254,11 +257,19 @@ describe('PPMSummaryList component', () => {
status: 200,
data: null,
};
downloadPPMPaymentPacket.mockImplementation(() => Promise.resolve(mockResponse));
// Setup a promise that will be resolved manually to check for the load mask
let resolveDownload;
const downloadPromise = new Promise((resolve) => {
resolveDownload = () => resolve(mockResponse);
});

downloadPPMPaymentPacket.mockImplementation(() => downloadPromise);

const onDownloadErrorNotCalled = jest.fn();

render(
<MockProviders>
<PPMSummaryList shipments={[shipments[3]]} />
<PPMSummaryList shipments={[shipments[3]]} onDownloadError={onDownloadErrorNotCalled} />
</MockProviders>,
);

Expand All @@ -269,16 +280,28 @@ describe('PPMSummaryList component', () => {

await userEvent.click(downloadPaymentButton);

// Check for the load mask after clicking the download button
expect(screen.getByText('Downloading Payment Packet (PDF)...')).toBeInTheDocument();

// Manually resolve the download
resolveDownload();

await waitFor(() => {
expect(downloadPPMPaymentPacket).toHaveBeenCalledTimes(1);
expect(onDownloadErrorNotCalled).toHaveBeenCalledTimes(0);
expect(screen.queryByText('Downloading Payment Packet (PDF)...')).not.toBeInTheDocument();
});
});

it('PPM Download Payment Packet - failure', async () => {
downloadPPMPaymentPacket.mockRejectedValue({
response: { body: { title: 'Error title', detail: 'Error detail' } },
// Create a promise we can reject manually
let rejectDownload;
const downloadPromise = new Promise((_, reject) => {
rejectDownload = () => reject(new Error('Error title: Error detail'));
});

downloadPPMPaymentPacket.mockReturnValue(downloadPromise);

const shipment = {
ppmShipment: {
status: ppmShipmentStatuses.CLOSEOUT_COMPLETE,
Expand All @@ -300,11 +323,11 @@ describe('PPMSummaryList component', () => {
},
},
};
const onErrorHandler = jest.fn();
const onDownloadErrorCalled = jest.fn();

render(
<MockProviders>
<PPMSummaryList shipments={[shipment]} onDownloadError={onErrorHandler} />
<PPMSummaryList shipments={[shipment]} onDownloadError={onDownloadErrorCalled} />
</MockProviders>,
);

Expand All @@ -314,9 +337,16 @@ describe('PPMSummaryList component', () => {
expect(downloadPaymentButton).toBeInTheDocument();
await userEvent.click(downloadPaymentButton);

// Check for the load mask after clicking the download button
expect(screen.getByText('Downloading Payment Packet (PDF)...')).toBeInTheDocument();

// Manually reject the download
rejectDownload();

await waitFor(() => {
expect(downloadPPMPaymentPacket).toHaveBeenCalledTimes(1);
expect(onErrorHandler).toHaveBeenCalledTimes(1);
expect(onDownloadErrorCalled).toHaveBeenCalledTimes(1);
expect(screen.queryByText('Downloading Payment Packet (PDF)...')).not.toBeInTheDocument();
});
});
});
Loading
Loading