Skip to content

Commit

Permalink
Merge pull request #13942 from transcom/B-21077-Move-Shipment-Button-…
Browse files Browse the repository at this point in the history
…MAIN

B 21077 move shipment button main
  • Loading branch information
taeJungCaci authored Oct 21, 2024
2 parents 51f5619 + 4d482ab commit 942fd9a
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import * as PropTypes from 'prop-types';
import { generatePath } from 'react-router-dom';
import { generatePath, useParams, useNavigate } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import styles from './RequestedShipments.module.scss';
Expand All @@ -14,6 +14,10 @@ import shipmentCardsStyles from 'styles/shipmentCards.module.scss';
import { MTOServiceItemShape, OrdersInfoShape } from 'types/order';
import { ShipmentShape } from 'types/shipment';
import { formatDateFromIso } from 'utils/formatters';
import ButtonDropdown from 'components/ButtonDropdown/ButtonDropdown';
import { SHIPMENT_OPTIONS_URL } from 'shared/constants';
import Restricted from 'components/Restricted/Restricted';
import { permissionTypes } from 'constants/permissions';

// nts defaults show preferred pickup date and pickup address, flagged items when collapsed
// ntsr defaults shows preferred delivery date, storage facility address, destination address, flagged items when collapsed
Expand Down Expand Up @@ -66,11 +70,54 @@ const ApprovedRequestedShipments = ({
};
};

const { moveCode } = useParams();
const navigate = useNavigate();
const handleButtonDropdownChange = (e) => {
const selectedOption = e.target.value;

const addShipmentPath = `${generatePath(tooRoutes.SHIPMENT_ADD_PATH, {
moveCode,
shipmentType: selectedOption,
})}`;

navigate(addShipmentPath);
};

const dutyLocationPostal = { postalCode: ordersInfo.newDutyLocation?.address?.postalCode };

return (
<div className={styles.RequestedShipments} data-testid="requested-shipments">
<h2>Approved Shipments</h2>
<div className={styles.sectionHeader}>
<h2>Approved Shipments</h2>
<div className={styles.buttonDropdown}>
{!isMoveLocked && (
<Restricted to={permissionTypes.createTxoShipment}>
<ButtonDropdown
ariaLabel="Add a new shipment"
data-testid="addShipmentButton"
onChange={handleButtonDropdownChange}
>
<option value="" label="Add a new shipment">
Add a new shipment
</option>
<option data-testid="hhgOption" value={SHIPMENT_OPTIONS_URL.HHG}>
HHG
</option>
<option value={SHIPMENT_OPTIONS_URL.PPM}>PPM</option>
<option value={SHIPMENT_OPTIONS_URL.NTS}>NTS</option>
<option value={SHIPMENT_OPTIONS_URL.NTSrelease}>NTS-release</option>
<option data-testid="boatOption" value={SHIPMENT_OPTIONS_URL.BOAT}>
Boat
</option>
<option data-testid="mobileHomeOption" value={SHIPMENT_OPTIONS_URL.MOBILE_HOME}>
Mobile Home
</option>
</ButtonDropdown>
</Restricted>
)}
</div>
</div>

<div className={shipmentCardsStyles.shipmentCards}>
{mtoShipments &&
mtoShipments.map((shipment) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@
@include u-padding-x(4);
@include u-padding-y(2);

.sectionHeader {
display: flex;
justify-content: center;
align-items: center;
h2 {
margin-right: auto;
}

.buttonDropdown {
margin-left: auto
}
}

h4 {
@include u-margin(0);
font-weight: bold;
Expand Down
144 changes: 121 additions & 23 deletions src/components/Office/RequestedShipments/RequestedShipments.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { act } from 'react-dom/test-utils';
import { render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { generatePath } from 'react-router-dom';

import {
shipments,
Expand All @@ -19,12 +20,15 @@ import {
import ApprovedRequestedShipments from './ApprovedRequestedShipments';
import SubmittedRequestedShipments from './SubmittedRequestedShipments';

import { SHIPMENT_OPTIONS_URL } from 'shared/constants';
import { tooRoutes } from 'constants/routes';
import { MockProviders } from 'testUtils';
import { permissionTypes } from 'constants/permissions';

const mockNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => jest.fn(),
useNavigate: () => mockNavigate,
}));

const moveTaskOrder = {
Expand Down Expand Up @@ -115,7 +119,7 @@ const submittedRequestedShipmentsComponentServicesCounselingCompleted = (
);

const submittedRequestedShipmentsComponentMissingRequiredInfo = (
<MockProviders permissions={[permissionTypes.updateShipment]}>
<MockProviders permissions={[permissionTypes.updateShipment, permissionTypes.createTxoShipment]}>
<SubmittedRequestedShipments
ordersInfo={ordersInfo}
allowancesInfo={allowancesInfo}
Expand All @@ -129,6 +133,31 @@ const submittedRequestedShipmentsComponentMissingRequiredInfo = (
</MockProviders>
);

const submittedRequestedShipmentsCanCreateNewShipment = (
<MockProviders permissions={[permissionTypes.createTxoShipment]}>
<SubmittedRequestedShipments
ordersInfo={ordersInfo}
allowancesInfo={allowancesInfo}
customerInfo={customerInfo}
mtoShipments={shipments}
closeoutOffice={closeoutOffice}
approveMTO={approveMTO}
moveTaskOrder={moveTaskOrderServicesCounselingCompleted}
moveCode="TE5TC0DE"
/>
</MockProviders>
);

const testProps = {
ordersInfo,
allowancesInfo,
customerInfo,
mtoShipments: shipments,
approveMTO,
mtoServiceItems: [],
moveCode: 'TE5TC0DE',
};

describe('RequestedShipments', () => {
describe('Prime-handled shipments', () => {
it('renders the container successfully without services counseling completed', () => {
Expand Down Expand Up @@ -215,6 +244,12 @@ describe('RequestedShipments', () => {
expect(container.querySelector('#approvalConfirmationModal')).toHaveStyle('display: block');
});

it('renders Add a new shjipment Button', async () => {
render(submittedRequestedShipmentsCanCreateNewShipment);

expect(await screen.getByRole('combobox', { name: 'Add a new shipment' })).toBeInTheDocument();
});

it('disables the Approve selected button when there is missing required information', async () => {
const { container } = render(submittedRequestedShipmentsComponentMissingRequiredInfo);

Expand All @@ -226,6 +261,8 @@ describe('RequestedShipments', () => {
);
});

expect(await screen.getByRole('combobox', { name: 'Add a new shipment' })).toBeInTheDocument();

expect(screen.getByRole('button', { name: 'Approve selected' })).toBeDisabled();

await act(async () => {
Expand Down Expand Up @@ -417,15 +454,6 @@ describe('RequestedShipments', () => {
});

describe('Permission dependent rendering', () => {
const testProps = {
ordersInfo,
allowancesInfo,
customerInfo,
mtoShipments: shipments,
approveMTO,
mtoServiceItems: [],
moveCode: 'TE5TC0DE',
};
it('renders the "Add service items to move" section when user has permission', () => {
render(
<MockProviders permissions={[permissionTypes.updateShipment]}>
Expand All @@ -449,6 +477,76 @@ describe('RequestedShipments', () => {
});
});

describe('shows the dropdown and navigates to each option when mtoshipments are submitted', () => {
it.each([
[
SHIPMENT_OPTIONS_URL.HHG,
SHIPMENT_OPTIONS_URL.NTS,
SHIPMENT_OPTIONS_URL.NTSrelease,
SHIPMENT_OPTIONS_URL.MOBILE_HOME,
SHIPMENT_OPTIONS_URL.BOAT,
],
])('selects the %s option and navigates to the matching form for that shipment type', async (shipmentType) => {
render(
<MockProviders
permissions={[permissionTypes.createTxoShipment]}
path={tooRoutes.SHIPMENT_ADD_PATH}
params={{ moveCode: 'TE5TC0DE', shipmentType }}
>
<SubmittedRequestedShipments {...testProps} />,
</MockProviders>,
);

const path = `${generatePath(tooRoutes.SHIPMENT_ADD_PATH, {
moveCode: 'TE5TC0DE',
shipmentType,
})}`;

const buttonDropdown = await screen.findByRole('combobox');

expect(buttonDropdown).toBeInTheDocument();

await userEvent.selectOptions(buttonDropdown, shipmentType);

expect(mockNavigate).toHaveBeenCalledWith(path);
});
});

describe('shows the dropdown and navigates to each option when mtoshipments are approved', () => {
it.each([
[
SHIPMENT_OPTIONS_URL.HHG,
SHIPMENT_OPTIONS_URL.NTS,
SHIPMENT_OPTIONS_URL.NTSrelease,
SHIPMENT_OPTIONS_URL.MOBILE_HOME,
SHIPMENT_OPTIONS_URL.BOAT,
],
])('selects the %s option and navigates to the matching form for that shipment type', async (shipmentType) => {
render(
<MockProviders
permissions={[permissionTypes.createTxoShipment]}
path={tooRoutes.SHIPMENT_ADD_PATH}
params={{ moveCode: 'TE5TC0DE', shipmentType }}
>
<ApprovedRequestedShipments {...testProps} />,
</MockProviders>,
);

const path = `${generatePath(tooRoutes.SHIPMENT_ADD_PATH, {
moveCode: 'TE5TC0DE',
shipmentType,
})}`;

const buttonDropdown = await screen.findByRole('combobox');

expect(buttonDropdown).toBeInTheDocument();

await userEvent.selectOptions(buttonDropdown, shipmentType);

expect(mockNavigate).toHaveBeenCalledWith(path);
});
});

describe('Conditional form display', () => {
const renderComponent = (props) => {
render(
Expand All @@ -465,36 +563,36 @@ describe('RequestedShipments', () => {
moveCode: 'TE5TC0DE',
};
it('does not render the "Add service items to move" section when both service items are present', () => {
const testProps = {
const testPropsMsCs = {
mtoServiceItems: serviceItemsMSandCS,
mtoShipments: shipments,
...conditionalFormTestProps,
};
renderComponent(testProps);
renderComponent(testPropsMsCs);

expect(screen.queryByText('Add service items to this move')).not.toBeInTheDocument();
expect(screen.getByText('Approve selected')).toBeInTheDocument();
});

it('does not render the "Add service items to move" section when counseling is present and all shipments are PPM', () => {
const testProps = {
const testPropsCS = {
mtoServiceItems: serviceItemsCS,
mtoShipments: ppmOnlyShipments,
...conditionalFormTestProps,
};
renderComponent(testProps);
renderComponent(testPropsCS);

expect(screen.queryByText('Add service items to this move')).not.toBeInTheDocument();
expect(screen.getByText('Approve selected')).toBeInTheDocument();
});

it('renders the "Add service items to move" section with only counseling when only move management is present in service items', () => {
const testProps = {
const testPropsMS = {
mtoServiceItems: serviceItemsMS,
mtoShipments: shipments,
...conditionalFormTestProps,
};
renderComponent(testProps);
renderComponent(testPropsMS);

expect(screen.getByText('Add service items to this move')).toBeInTheDocument();
expect(screen.getByText('Approve selected')).toBeInTheDocument();
Expand All @@ -503,12 +601,12 @@ describe('RequestedShipments', () => {
});

it('renders the "Add service items to move" section with only move management when only counseling is present in service items', () => {
const testProps = {
const testPropsCS = {
mtoServiceItems: serviceItemsCS,
mtoShipments: shipments,
...conditionalFormTestProps,
};
renderComponent(testProps);
renderComponent(testPropsCS);

expect(screen.getByText('Add service items to this move')).toBeInTheDocument();
expect(screen.getByText('Approve selected')).toBeInTheDocument();
Expand All @@ -517,12 +615,12 @@ describe('RequestedShipments', () => {
});

it('renders the "Add service items to move" section with all fields when neither counseling nor move management is present in service items', () => {
const testProps = {
const testPropsServiceItemsEmpty = {
mtoServiceItems: serviceItemsEmpty,
mtoShipments: shipments,
...conditionalFormTestProps,
};
renderComponent(testProps);
renderComponent(testPropsServiceItemsEmpty);

expect(screen.getByText('Add service items to this move')).toBeInTheDocument();
expect(screen.getByText('Approve selected')).toBeInTheDocument();
Expand All @@ -531,12 +629,12 @@ describe('RequestedShipments', () => {
});

it('renders the "Add service items to move" section with only counseling when all shipments are PPM', () => {
const testProps = {
const testPropsServiceItemsEmpty = {
mtoServiceItems: serviceItemsEmpty,
mtoShipments: ppmOnlyShipments,
...conditionalFormTestProps,
};
renderComponent(testProps);
renderComponent(testPropsServiceItemsEmpty);

expect(screen.getByText('Add service items to this move')).toBeInTheDocument();
expect(screen.getByText('Approve selected')).toBeInTheDocument();
Expand Down
Loading

0 comments on commit 942fd9a

Please sign in to comment.