Skip to content

Commit

Permalink
Merge branch 'main' into PRMDR-809
Browse files Browse the repository at this point in the history
  • Loading branch information
SRAlexander authored May 13, 2024
2 parents f096392 + 7c29ffc commit f865f23
Show file tree
Hide file tree
Showing 26 changed files with 608 additions and 351 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,18 @@ import { render, screen } from '@testing-library/react';
import LgRecordDetails, { Props } from './LloydGeorgeRecordDetails';
import { buildLgSearchResult } from '../../../../helpers/test/testBuilders';
import formatFileSize from '../../../../helpers/utils/formatFileSize';
import { REPOSITORY_ROLE } from '../../../../types/generic/authRole';
import useRole from '../../../../helpers/hooks/useRole';
import { lloydGeorgeRecordLinks } from '../../../../types/blocks/lloydGeorgeActions';
import { LinkProps } from 'react-router-dom';
import useIsBSOL from '../../../../helpers/hooks/useIsBSOL';

jest.mock('../../../../helpers/hooks/useRole');
jest.mock('../../../../helpers/hooks/useIsBSOL');

const mockedUseNavigate = jest.fn();
const mockPdf = buildLgSearchResult();
const mockSetDownloadRemoveButtonClicked = jest.fn();
const mockSetError = jest.fn();
const mockSetFocus = jest.fn();
const mockedUseRole = useRole as jest.Mock;
const mockedUseIsBSOL = useIsBSOL as jest.Mock;

jest.mock('react-router', () => ({
useNavigate: () => mockedUseNavigate,
}));
jest.mock('react-router-dom', () => ({
__esModule: true,
Link: (props: LinkProps) => <a {...props} role="link" />,
}));

describe('LloydGeorgeRecordDetails', () => {
beforeEach(() => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.PCSE);
process.env.REACT_APP_ENVIRONMENT = 'jest';
});

afterEach(() => {
jest.clearAllMocks();
});

describe('Rendering', () => {
it('renders the record details component', () => {
renderComponent();
Expand All @@ -47,105 +26,14 @@ describe('LloydGeorgeRecordDetails', () => {
expect(screen.getByText('File format: PDF')).toBeInTheDocument();
});
});

describe('Unauthorised', () => {
const unauthorisedLinks = lloydGeorgeRecordLinks.filter((a) =>
Array.isArray(a.unauthorised),
);

it.each(unauthorisedLinks)(
"does not render actionLink '$label' if role is unauthorised",
async (action) => {
const [unauthorisedRole] = action.unauthorised ?? [];
mockedUseRole.mockReturnValue(unauthorisedRole);

renderComponent();

expect(screen.queryByText(`Select an action...`)).not.toBeInTheDocument();
expect(screen.queryByTestId('actions-menu')).not.toBeInTheDocument();
},
);

it.each(unauthorisedLinks)(
"does not render actionLink '$label' for GP Clinical Role",
async (action) => {
expect(action.unauthorised).toContain(REPOSITORY_ROLE.GP_CLINICAL);
},
);
});

describe('GP admin non BSOL user', () => {
it('renders the record details component with button', () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_ADMIN);
mockedUseIsBSOL.mockReturnValue(false);
renderComponent();

expect(screen.getByText(`Last updated: ${mockPdf.last_updated}`)).toBeInTheDocument();
expect(screen.getByText(`${mockPdf.number_of_files} files`)).toBeInTheDocument();
expect(
screen.getByText(`File size: ${formatFileSize(mockPdf.total_file_size_in_byte)}`),
).toBeInTheDocument();
expect(screen.getByText('File format: PDF')).toBeInTheDocument();
expect(
screen.getByRole('button', { name: 'Download and remove record' }),
).toBeInTheDocument();

expect(screen.queryByText(`Select an action...`)).not.toBeInTheDocument();
expect(screen.queryByTestId('actions-menu')).not.toBeInTheDocument();
});

it('set downloadRemoveButtonClicked to true when button is clicked', () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_ADMIN);
mockedUseIsBSOL.mockReturnValue(false);
renderComponent();

const button = screen.getByRole('button', { name: 'Download and remove record' });

button.click();

expect(mockSetDownloadRemoveButtonClicked).toHaveBeenCalledWith(true);
});

it('calls setFocus and setError when the button is clicked again after warning box shown up', () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_ADMIN);
mockedUseIsBSOL.mockReturnValue(false);
renderComponent({ downloadRemoveButtonClicked: true });

const button = screen.getByRole('button', { name: 'Download and remove record' });

button.click();

expect(mockSetError).toHaveBeenCalledWith('confirmDownloadRemove', {
type: 'custom',
message: 'true',
});
expect(mockSetFocus).toHaveBeenCalledWith('confirmDownloadRemove');
});
});
});

type mockedProps = Omit<
Props,
'setStage' | 'stage' | 'setDownloadRemoveButtonClicked' | 'setError' | 'setFocus'
>;
const TestApp = (props: mockedProps) => {
return (
<LgRecordDetails
{...props}
setDownloadRemoveButtonClicked={mockSetDownloadRemoveButtonClicked}
setError={mockSetError}
setFocus={mockSetFocus}
/>
);
};

const renderComponent = (propsOverride?: Partial<Props>) => {
const props: mockedProps = {
const props: Props = {
lastUpdated: mockPdf.last_updated,
numberOfFiles: mockPdf.number_of_files,
totalFileSizeInByte: mockPdf.total_file_size_in_byte,
downloadRemoveButtonClicked: false,
...propsOverride,
};
return render(<TestApp {...props} />);
return render(<LgRecordDetails {...props} />);
};
Original file line number Diff line number Diff line change
@@ -1,42 +1,13 @@
import React, { Dispatch, SetStateAction } from 'react';
import React from 'react';
import formatFileSize from '../../../../helpers/utils/formatFileSize';
import { Button } from 'nhsuk-react-components';
import useRole from '../../../../helpers/hooks/useRole';
import { FieldValues, UseFormSetError, UseFormSetFocus } from 'react-hook-form';
import useIsBSOL from '../../../../helpers/hooks/useIsBSOL';
import { REPOSITORY_ROLE } from '../../../../types/generic/authRole';

export type Props = {
lastUpdated: string;
numberOfFiles: number;
totalFileSizeInByte: number;
setDownloadRemoveButtonClicked: Dispatch<SetStateAction<boolean>>;
downloadRemoveButtonClicked: boolean;
setError: UseFormSetError<FieldValues>;
setFocus: UseFormSetFocus<FieldValues>;
};

function LloydGeorgeRecordDetails({
lastUpdated,
numberOfFiles,
totalFileSizeInByte,
setDownloadRemoveButtonClicked,
downloadRemoveButtonClicked,
setError,
setFocus,
}: Props) {
const role = useRole();
const isBSOL = useIsBSOL();
const userIsGpAdminNonBSOL = role === REPOSITORY_ROLE.GP_ADMIN && !isBSOL;

const handleDownloadAndRemoveRecordButton = () => {
if (downloadRemoveButtonClicked) {
setError('confirmDownloadRemove', { type: 'custom', message: 'true' });
}
setFocus('confirmDownloadRemove');
setDownloadRemoveButtonClicked(true);
};

function LloydGeorgeRecordDetails({ lastUpdated, numberOfFiles, totalFileSizeInByte }: Props) {
return (
<div className="lloydgeorge_record-details">
<div className="lloydgeorge_record-details_details">
Expand All @@ -52,17 +23,6 @@ function LloydGeorgeRecordDetails({
{' |'}
</div>
</div>
{userIsGpAdminNonBSOL && (
<div className="lloydgeorge_record-details_download-remove-button">
<Button
data-testid="download-and-remove-record-btn"
onClick={handleDownloadAndRemoveRecordButton}
className="lloydgeorge_record-details_download-remove-button-content"
>
Download and remove record
</Button>
</div>
)}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,12 @@ describe('LloydGeorgeRecordStage', () => {
};

const showConfirmationMessage = async () => {
const greenDownloadButton = screen.getByRole('button', {
name: 'Download and remove record',
const sideMenuDownloadButton = screen.getByRole('button', {
name: 'Download and remove files',
});

act(() => {
userEvent.click(greenDownloadButton);
userEvent.click(sideMenuDownloadButton);
});
await waitFor(() => {
expect(
Expand All @@ -168,15 +168,15 @@ describe('LloydGeorgeRecordStage', () => {
expect(screen.getByText('Before downloading')).toBeInTheDocument();
expect(screen.getByText('Available records')).toBeInTheDocument();
expect(
screen.getByRole('button', { name: 'Download and remove record' }),
screen.getByRole('button', { name: 'Download and remove files' }),
).toBeInTheDocument();
});

it('clicking the green download button should show confirmation message, checkbox, red download button and cancel button', async () => {
it('clicking the side menu download button should show confirmation message, checkbox, red download button and cancel button', async () => {
renderComponentForNonBSOLGPAdmin();

const downloadButton = screen.getByRole('button', {
name: 'Download and remove record',
name: 'Download and remove files',
});

act(() => {
Expand Down Expand Up @@ -224,6 +224,27 @@ describe('LloydGeorgeRecordStage', () => {
expect(mockSetStage).not.toBeCalled();
});

it('when checkbox is unchecked, clicking "Download and remove" button twice will bring up a warning callout message', async () => {
renderComponentForNonBSOLGPAdmin();
await showConfirmationMessage();

act(() => {
userEvent.click(
screen.getByRole('button', {
name: 'Download and remove files',
}),
);
});

expect(
screen.getByText('You must confirm if you want to download and remove this record'),
).toBeInTheDocument();
expect(
screen.getByText('Confirm if you want to download and remove this record'),
).toBeInTheDocument();
expect(mockSetStage).not.toBeCalled();
});

it('when checkbox is checked, clicking red download button should proceed to download and delete process', async () => {
renderComponentForNonBSOLGPAdmin();
await showConfirmationMessage();
Expand Down Expand Up @@ -309,42 +330,39 @@ describe('LloydGeorgeRecordStage', () => {
});
});

it('does not render warning callout, header and button when user is GP admin and BSOL', async () => {
it('does not render warning callout or button when user is GP admin and BSOL', async () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_ADMIN);
mockedIsBSOL.mockReturnValue(true);

renderComponent();

expect(screen.queryByText('Before downloading')).not.toBeInTheDocument();
expect(screen.queryByText('Available records')).not.toBeInTheDocument();
expect(
screen.queryByRole('button', { name: 'Download and remove record' }),
screen.queryByRole('button', { name: 'Download and remove files' }),
).not.toBeInTheDocument();
});

it('does not render warning callout, header and button when user is GP clinical and non BSOL', async () => {
it('does not render warning callout or button when user is GP clinical and non BSOL', async () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_CLINICAL);
mockedIsBSOL.mockReturnValue(false);

renderComponent();

expect(screen.queryByText('Before downloading')).not.toBeInTheDocument();
expect(screen.queryByText('Available records')).not.toBeInTheDocument();
expect(
screen.queryByRole('button', { name: 'Download and remove record' }),
screen.queryByRole('button', { name: 'Download and remove files' }),
).not.toBeInTheDocument();
});

it('does not render warning callout, header and button when user is GP clinical and BSOL', async () => {
it('does not render warning callout or button when user is GP clinical and BSOL', async () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_CLINICAL);
mockedIsBSOL.mockReturnValue(true);

renderComponent();

expect(screen.queryByText('Before downloading')).not.toBeInTheDocument();
expect(screen.queryByText('Available records')).not.toBeInTheDocument();
expect(
screen.queryByRole('button', { name: 'Download and remove record' }),
screen.queryByRole('button', { name: 'Download and remove files' }),
).not.toBeInTheDocument();
});

Expand Down
Loading

0 comments on commit f865f23

Please sign in to comment.