Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { render, screen } from '@testing-library/react';
import { Mock } from 'vitest';
import UserPatientRestrictionsCompleteStage from './UserPatientRestrictionsCompleteStage';
import { UserPatientRestrictionsSubRoute } from '../../../../types/generic/userPatientRestriction';
import usePatient from '../../../../helpers/hooks/usePatient';
import { buildPatientDetails } from '../../../../helpers/test/testBuilders';
import userEvent from '@testing-library/user-event';
import { routes } from '../../../../types/generic/routes';

vi.mock('react-router-dom', () => ({
...vi.importActual('react-router-dom'),
useNavigate: (): Mock => mockNavigate,
}));
vi.mock('../../../../helpers/hooks/usePatient');

const mockNavigate = vi.fn();
const mockUsePatient = usePatient as Mock;

describe('UserPatientRestrictionsCompleteStage', () => {
beforeEach(() => {
mockUsePatient.mockReturnValue(buildPatientDetails());
});

it('renders the correct title and patient details when a restriction is added', () => {
render(
<UserPatientRestrictionsCompleteStage route={UserPatientRestrictionsSubRoute.ADD} />,
);

expect(screen.getByTestId('page-title')).toHaveTextContent(
'A restriction has been added to this patient record:',
);
expect(screen.getByTestId('restriction-added-message')).toBeInTheDocument();
});

it('renders the correct title and patient details when a restriction is removed', () => {
render(
<UserPatientRestrictionsCompleteStage route={UserPatientRestrictionsSubRoute.REMOVE} />,
);

expect(screen.getByTestId('page-title')).toHaveTextContent(
'A restriction on accessing this patient record has been removed:',
);
expect(screen.getByTestId('restriction-removed-message')).toBeInTheDocument();
});

it('should navigate to user restrictions hub when the view restrictions button is clicked', async () => {
render(
<UserPatientRestrictionsCompleteStage route={UserPatientRestrictionsSubRoute.REMOVE} />,
);

const viewRestrictionsButton = screen.getByTestId('view-restrictions-button');
await userEvent.click(viewRestrictionsButton);

expect(mockNavigate).toHaveBeenCalledWith(routes.USER_PATIENT_RESTRICTIONS);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { useNavigate } from 'react-router-dom';
import useTitle from '../../../../helpers/hooks/useTitle';
import { UserPatientRestrictionsSubRoute } from '../../../../types/generic/userPatientRestriction';
import usePatient from '../../../../helpers/hooks/usePatient';
import { getFormattedPatientFullName } from '../../../../helpers/utils/formatPatientFullName';
import { formatNhsNumber } from '../../../../helpers/utils/formatNhsNumber';
import { getFormattedDateFromString } from '../../../../helpers/utils/formatDate';
import { Button } from 'nhsuk-react-components';
import { routes } from '../../../../types/generic/routes';

type Props = {
route: UserPatientRestrictionsSubRoute;
};

const UserPatientRestrictionsCompleteStage = ({ route }: Props): React.JSX.Element => {
const navigate = useNavigate();
const patientDetails = usePatient();

const pageTitle =
route === UserPatientRestrictionsSubRoute.ADD
? 'A restriction has been added to this patient record:'
: 'A restriction on accessing this patient record has been removed:';
useTitle({ pageTitle });

return (
<>
<div className="nhsuk-panel" data-testid="action-complete-card">
<h1 data-testid="page-title" className="nhsuk-panel__title">
{pageTitle}
</h1>
<br />
<div className="nhsuk-panel__body">
<strong data-testid="patient-name">
Patient name: {getFormattedPatientFullName(patientDetails)}
</strong>
<br />
<span data-testid="nhs-number">
NHS number: {formatNhsNumber(patientDetails!.nhsNumber)}
</span>
<br />
<span data-testid="dob">
Date of birth: {getFormattedDateFromString(patientDetails!.birthDate)}
</span>
</div>
</div>

{route === UserPatientRestrictionsSubRoute.ADD ? (
<p data-testid="restriction-added-message">
When you add a restriction, it will stay with this patient's record until it's
removed. If the patient moves practice, the new practice will see the name and
NHS smartcard number of the staff member you've restricted.
</p>
) : (
<p data-testid="restriction-removed-message">
The staff member can now access this patient's record.
</p>
)}

<h3>What happens next</h3>
<p>You can add, view and make changes to restrictions by going to the admin hub.</p>

<Button
data-testid="view-restrictions-button"
onClick={(): void => {
navigate(routes.USER_PATIENT_RESTRICTIONS);
}}
>
Go to view restrictions
</Button>
</>
);
};

export default UserPatientRestrictionsCompleteStage;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import userEvent from '@testing-library/user-event';
import { Mock } from 'vitest';
import { routeChildren } from '../../../../types/generic/routes';
import getUserPatientRestrictions from '../../../../helpers/requests/userPatientRestrictions/getUserPatientRestrictions';
import { buildUserRestrictions } from '../../../../helpers/test/testBuilders';
import { buildPatientDetails, buildUserRestrictions } from '../../../../helpers/test/testBuilders';
import { UserPatientRestrictionsSubRoute } from '../../../../types/generic/userPatientRestriction';
import { useState } from 'react';
import getPatientDetails from '../../../../helpers/requests/getPatientDetails';

vi.mock('react-router-dom', async () => {
const actual = await vi.importActual('react-router-dom');
Expand All @@ -27,29 +30,40 @@ vi.mock('react-router-dom', async () => {
};
});
vi.mock('../../../../helpers/requests/userPatientRestrictions/getUserPatientRestrictions');
vi.mock('../../../../helpers/requests/getPatientDetails');
vi.mock('../../../../helpers/hooks/useBaseAPIHeaders');
vi.mock('../../../../helpers/hooks/useBaseAPIUrl');
vi.mock('../../../../providers/patientProvider/PatientProvider', () => ({
usePatientDetailsContext: (): Mock => mockUsePatientDetailsContext(),
}));

const mockNavigate = vi.fn();
const mockGetUserPatientRestrictions = getUserPatientRestrictions as Mock;
const mockGetPatientDetails = getPatientDetails as Mock;
const mockUsePatientDetailsContext = vi.fn();
const mockSetPatientDetails = vi.fn();

describe('UserPatientRestrictionsListStage', () => {
const mockPatientDetails = buildPatientDetails();

beforeEach(() => {
mockGetUserPatientRestrictions.mockResolvedValue({
restrictions: buildUserRestrictions(),
});
mockUsePatientDetailsContext.mockReturnValue([mockPatientDetails, mockSetPatientDetails]);
mockGetPatientDetails.mockResolvedValue(mockPatientDetails);
});

it('renders correctly', () => {
render(<UserPatientRestrictionsListStage />);
renderPage();

expect(
screen.getByText('Manage restrictions on access to patient records'),
).toBeInTheDocument();
});

it('should navigate to add restrictions stage when add restriction button is clicked', async () => {
render(<UserPatientRestrictionsListStage />);
renderPage();

const addRestrictionButton = screen.getByRole('button', { name: 'Add a restriction' });
expect(addRestrictionButton).toBeInTheDocument();
Expand All @@ -65,7 +79,7 @@ describe('UserPatientRestrictionsListStage', () => {
restrictions,
});

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(async () => {
const viewRestrictionButton = screen.getByTestId(
Expand All @@ -77,10 +91,7 @@ describe('UserPatientRestrictionsListStage', () => {
});

expect(mockNavigate).toHaveBeenCalledWith(
routeChildren.USER_PATIENT_RESTRICTIONS_VIEW.replace(
':restrictionId',
restrictions[0].id,
),
routeChildren.USER_PATIENT_RESTRICTIONS_VERIFY_PATIENT,
);
});

Expand All @@ -89,7 +100,7 @@ describe('UserPatientRestrictionsListStage', () => {
new Error('Failed to load restrictions'),
);

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(() => {
expect(screen.getByTestId('failed-to-load-error')).toBeInTheDocument();
Expand All @@ -103,7 +114,7 @@ describe('UserPatientRestrictionsListStage', () => {
}),
);

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(() => {
expect(screen.getByText('Searching...')).toBeInTheDocument();
Expand All @@ -116,7 +127,7 @@ describe('UserPatientRestrictionsListStage', () => {
restrictions: [],
});

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(() => {
expect(screen.getByText('No user patient restrictions found')).toBeInTheDocument();
Expand All @@ -130,7 +141,7 @@ describe('UserPatientRestrictionsListStage', () => {
nextPageToken: 'next-page-token',
});

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(() => {
expect(screen.getByText('Next')).toBeInTheDocument();
Expand All @@ -144,7 +155,7 @@ describe('UserPatientRestrictionsListStage', () => {
nextPageToken: 'next-page-token',
});

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(async () => {
const nextButton = screen.getByTestId('next-page-link');
Expand All @@ -168,7 +179,7 @@ describe('UserPatientRestrictionsListStage', () => {
nextPageToken: 'next-page-token',
});

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(() => {
expect(screen.getByText('Next')).toBeInTheDocument();
Expand Down Expand Up @@ -197,7 +208,7 @@ describe('UserPatientRestrictionsListStage', () => {
nextPageToken: 'next-page-token',
});

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(async () => {
const nextButton = screen.getByText('Next');
Expand Down Expand Up @@ -230,7 +241,7 @@ describe('UserPatientRestrictionsListStage', () => {
nextPageToken: 'next-page-token',
});

render(<UserPatientRestrictionsListStage />);
renderPage();

await waitFor(async () => {
const nextButton = screen.getByText('Next');
Expand All @@ -257,7 +268,7 @@ describe('UserPatientRestrictionsListStage', () => {
});

it('should send nhsNumber parameter when searching by valid nhs number', async () => {
render(<UserPatientRestrictionsListStage />);
renderPage();

const nhsNumber = '2222222222';
await userEvent.click(screen.getByTestId('nhs-number-radio-button'));
Expand All @@ -275,7 +286,7 @@ describe('UserPatientRestrictionsListStage', () => {
});

it('should send smartcardNumber parameter when searching by valid smartcard number', async () => {
render(<UserPatientRestrictionsListStage />);
renderPage();

const smartcardNumber = '123456789012';
await userEvent.click(screen.getByTestId('smartcard-number-radio-button'));
Expand All @@ -295,7 +306,7 @@ describe('UserPatientRestrictionsListStage', () => {
it.each(['123', 'abc', '123456789', '12345678901', '1234567890'])(
'should show validation error when searching by invalid nhs number: %s',
async (invalidNhsNumber) => {
render(<UserPatientRestrictionsListStage />);
renderPage();

await userEvent.click(screen.getByTestId('nhs-number-radio-button'));
await userEvent.type(screen.getByTestId('search-input'), invalidNhsNumber);
Expand All @@ -312,7 +323,7 @@ describe('UserPatientRestrictionsListStage', () => {
it.each(['123', 'abc', '123456789', '12345678901', '1234567890', '12345678901a'])(
'should show validation error when searching by invalid smartcard number: %s',
async (invalidSmartcardNumber) => {
render(<UserPatientRestrictionsListStage />);
renderPage();

await userEvent.click(screen.getByTestId('smartcard-number-radio-button'));
await userEvent.type(screen.getByTestId('search-input'), invalidSmartcardNumber);
Expand All @@ -326,3 +337,12 @@ describe('UserPatientRestrictionsListStage', () => {
},
);
});

const TestApp = (): React.JSX.Element => {
const [, setSubRoute] = useState<UserPatientRestrictionsSubRoute | null>(null);
return <UserPatientRestrictionsListStage setSubRoute={setSubRoute} />;
};

const renderPage = (): void => {
render(<TestApp />);
};
Loading
Loading