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

PRMDR-417 Download UI and functionality for non BSOL #226

Merged
merged 46 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e6e772a
[PRMDR-414] add warning callout and text
RachelHowellNHS Jan 4, 2024
d54d190
[PRMDR-414] add download and remove record button
RachelHowellNHS Jan 4, 2024
90b2bc0
[PRMDR-414] increase space above button
RachelHowellNHS Jan 4, 2024
8e667be
[PRMDR-414] wrap button in div
RachelHowellNHS Jan 4, 2024
de38930
[PRMDR-414] remove unused id
RachelHowellNHS Jan 4, 2024
8460f94
[PRMDR-414] change role to gp clinical for testing and create useIsBS…
RachelHowellNHS Jan 4, 2024
a87c545
[PRMDR-414] fix tests
RachelHowellNHS Jan 4, 2024
c7e6918
[PRMDR-414] change role back to gp admin
RachelHowellNHS Jan 4, 2024
190b631
[PRMDR-414] unit tests
RachelHowellNHS Jan 5, 2024
07294cc
[PRMDR-414] remove unused import
RachelHowellNHS Jan 5, 2024
4d95d14
[PRMDR-414] fix e2e tests
RachelHowellNHS Jan 5, 2024
82c6dc4
[PRMDR-417] add state for download and remove record button and inset…
RachelHowellNHS Jan 5, 2024
9e4852f
[PRMDR-417] fix unit tests props
RachelHowellNHS Jan 5, 2024
cf1065b
[PRMDR-417] add content to inset text
RachelHowellNHS Jan 8, 2024
be54855
[PRMDR-417] fix checkbox
RachelHowellNHS Jan 8, 2024
38275b2
[PRMDR-417] amend styling
RachelHowellNHS Jan 8, 2024
6752210
[PRMDR-417] amend styling
RachelHowellNHS Jan 8, 2024
ef75284
[PRMDR-417] rebase with main
RachelHowellNHS Jan 8, 2024
56e1ed1
[PRMDR-417] add warning icon
RachelHowellNHS Jan 8, 2024
35baba6
[PRMDR-417] fix button colour
RachelHowellNHS Jan 8, 2024
46d30fd
[PRMDR-417] rebase with main
RachelHowellNHS Jan 8, 2024
9c6f42d
[PRMDR-417] amend button submit, change id
RachelHowellNHS Jan 8, 2024
5630cd2
[PRMDR-417] update download and remove submit
RachelHowellNHS Jan 9, 2024
732e864
[PRMDR-417] add functionality to cancel button
RachelHowellNHS Jan 9, 2024
6be1164
[PRMDR-417] add condition to stop error showing after cancel button h…
RachelHowellNHS Jan 9, 2024
131443a
[PRMDR-417] add clearErrors hook
RachelHowellNHS Jan 9, 2024
832678a
[PRMDR-417] add setError hook
RachelHowellNHS Jan 9, 2024
bb0ef48
[PRMDR-417] add setError hook
RachelHowellNHS Jan 9, 2024
193d4a5
[PRMDR-417] add setFocus hook
RachelHowellNHS Jan 9, 2024
d984672
[PRMDR-417] add setFocus hook
RachelHowellNHS Jan 9, 2024
3b9f81b
[PRMDR-417] styling
RachelHowellNHS Jan 9, 2024
c03705a
[PRMDR-417] styling
RachelHowellNHS Jan 9, 2024
43c2369
[PRMDR-417] Add unit tests for download and remove button at LloydGeo…
joefong-nhs Jan 9, 2024
4aedb6e
[PRMDR-417] Fix the issue of checkbox not working right when clicked …
joefong-nhs Jan 9, 2024
347d20e
[PRMDR-417] merge with main
RachelHowellNHS Jan 9, 2024
721967d
[PRMDR-417] move set focus outside of if block
RachelHowellNHS Jan 9, 2024
eedaf49
[PRMDR-417] remove unused imports
RachelHowellNHS Jan 9, 2024
d9b7a9f
[PRMDR-417] add active button colour
RachelHowellNHS Jan 9, 2024
c242e68
[PRMDR-417] increase margin
RachelHowellNHS Jan 9, 2024
49339fa
[PRMDR-417] change focus to input ref
RachelHowellNHS Jan 9, 2024
71816c0
[PRMDR-417] fix test
RachelHowellNHS Jan 9, 2024
fb3ced6
[PRMDR-417] spacing
RachelHowellNHS Jan 9, 2024
eeaf301
[PRMDR-417] spacing
RachelHowellNHS Jan 9, 2024
2e48368
[PRMDR-417] WIP adding unit tests around download and remove record c…
joefong-nhs Jan 9, 2024
c7dfedc
[PRMDR-417] Add unit tests for red download button and cancel button
joefong-nhs Jan 10, 2024
6da3816
[PRMDR-417] remove comment and text mistake
RachelHowellNHS Jan 10, 2024
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
Expand Up @@ -8,11 +8,15 @@ import { REPOSITORY_ROLE } from '../../../types/generic/authRole';
import useRole from '../../../helpers/hooks/useRole';
import { actionLinks } from '../../../types/blocks/lloydGeorgeActions';
import { LinkProps } from 'react-router-dom';

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

const mockedUseNavigate = jest.fn();
const mockPdf = buildLgSearchResult();
const mockSetStage = jest.fn();
const mockSetDownloadRemoveButtonClicked = jest.fn();
const mockSetError = jest.fn();
const mockSetFocus = jest.fn();
const mockedUseRole = useRole as jest.Mock;
jest.mock('react-router', () => ({
useNavigate: () => mockedUseNavigate,
Expand Down Expand Up @@ -128,15 +132,7 @@ describe('LloydGeorgeRecordDetails', () => {

describe('GP admin non BSOL user', () => {
it('renders the record details component with button', () => {
render(
<LgRecordDetails
lastUpdated={mockPdf.last_updated}
numberOfFiles={mockPdf.number_of_files}
totalFileSizeInByte={mockPdf.total_file_size_in_byte}
setStage={mockSetStage}
userIsGpAdminNonBSOL={true}
/>,
);
renderComponent({ userIsGpAdminNonBSOL: true });

expect(screen.getByText(`Last updated: ${mockPdf.last_updated}`)).toBeInTheDocument();
expect(screen.getByText(`${mockPdf.number_of_files} files`)).toBeInTheDocument();
Expand All @@ -151,19 +147,55 @@ describe('LloydGeorgeRecordDetails', () => {
expect(screen.queryByText(`Select an action...`)).not.toBeInTheDocument();
expect(screen.queryByTestId('actions-menu')).not.toBeInTheDocument();
});

it('set downloadRemoveButtonClicked to true when button is clicked', () => {
renderComponent({ userIsGpAdminNonBSOL: true });

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', () => {
renderComponent({ userIsGpAdminNonBSOL: true, 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');
});
});
});

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

const renderComponent = (propsOverride?: Partial<Props>) => {
const props: Omit<Props, 'setStage' | 'stage'> = {
const props: mockedProps = {
lastUpdated: mockPdf.last_updated,
numberOfFiles: mockPdf.number_of_files,
totalFileSizeInByte: mockPdf.total_file_size_in_byte,

downloadRemoveButtonClicked: false,
...propsOverride,
};
return render(<TestApp {...props} />);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Link } from 'react-router-dom';
import useRole from '../../../helpers/hooks/useRole';
import { actionLinks } from '../../../types/blocks/lloydGeorgeActions';
import { LG_RECORD_STAGE } from '../../../types/blocks/lloydGeorgeStages';
import { FieldValues, UseFormSetError, UseFormSetFocus } from 'react-hook-form';
import { REPOSITORY_ROLE } from '../../../types/generic/authRole';

export type Props = {
Expand All @@ -15,6 +16,10 @@ export type Props = {
totalFileSizeInByte: number;
setStage: Dispatch<SetStateAction<LG_RECORD_STAGE>>;
userIsGpAdminNonBSOL?: boolean;
setDownloadRemoveButtonClicked: Dispatch<SetStateAction<boolean>>;
downloadRemoveButtonClicked: boolean;
setError: UseFormSetError<FieldValues>;
setFocus: UseFormSetFocus<FieldValues>;
};

function LloydGeorgeRecordDetails({
Expand All @@ -23,6 +28,10 @@ function LloydGeorgeRecordDetails({
totalFileSizeInByte,
setStage,
userIsGpAdminNonBSOL,
setDownloadRemoveButtonClicked,
downloadRemoveButtonClicked,
setError,
setFocus,
}: Props) {
const [showActionsMenu, setShowActionsMenu] = useState(false);
const actionsRef = useRef(null);
Expand All @@ -33,6 +42,15 @@ function LloydGeorgeRecordDetails({
useOnClickOutside(actionsRef, (e) => {
setShowActionsMenu(false);
});

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

return (
<div className="lloydgeorge_record-details">
<div className="lloydgeorge_record-details_details">
Expand All @@ -50,7 +68,10 @@ function LloydGeorgeRecordDetails({
</div>
{userIsGpAdminNonBSOL ? (
<div className="lloydgeorge_record-details_download-remove-button">
<Button className="lloydgeorge_record-details_download-remove-button-content">
<Button
onClick={handleDownloadAndRemoveRecordButton}
className="lloydgeorge_record-details_download-remove-button-content"
>
Download and remove record
</Button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import usePatient from '../../../helpers/hooks/usePatient';
import useRole from '../../../helpers/hooks/useRole';
import useIsBSOL from '../../../helpers/hooks/useIsBSOL';
import { REPOSITORY_ROLE } from '../../../types/generic/authRole';

const mockPdf = buildLgSearchResult();
const mockPatientDetails = buildPatientDetails();

Expand All @@ -22,6 +23,7 @@ const mockedUsePatient = usePatient as jest.Mock;
const mockNavigate = jest.fn();
const mockedUseRole = useRole as jest.Mock;
const mockedIsBSOL = useIsBSOL as jest.Mock;
const mockSetStage = jest.fn();

jest.mock('react-router', () => ({
useNavigate: () => mockNavigate,
Expand Down Expand Up @@ -113,18 +115,149 @@ describe('LloydGeorgeRecordStage', () => {
expect(screen.getByText('Lloyd George record')).toBeInTheDocument();
});
});
describe('User is GP admin and non BSOL', () => {
const renderComponentForNonBSOLGPAdmin = () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_ADMIN);
mockedIsBSOL.mockReturnValue(false);
renderComponent();
};

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

act(() => {
userEvent.click(greenDownloadButton);
});
await waitFor(() => {
expect(
screen.getByText('Are you sure you want to download and remove this record?'),
).toBeInTheDocument();
});
};

const clickRedDownloadButton = () => {
const redDownloadButton = screen.getByRole('button', {
name: 'Yes, download and remove',
});

act(() => {
userEvent.click(redDownloadButton);
});
};

it('renders warning callout, header and button', async () => {
renderComponentForNonBSOLGPAdmin();

expect(screen.getByText('Before downloading')).toBeInTheDocument();
expect(screen.getByText('Available records')).toBeInTheDocument();
expect(
screen.getByRole('button', { name: 'Download and remove record' }),
).toBeInTheDocument();
});

it('renders warning callout, header and button when user is GP admin and non BSOL', async () => {
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_ADMIN);
mockedIsBSOL.mockReturnValue(false);
it('clicking the green 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',
});

act(() => {
userEvent.click(downloadButton);
});

await waitFor(() => {
expect(
screen.getByText('Are you sure you want to download and remove this record?'),
).toBeInTheDocument();
});
expect(
screen.getByText(
"If you download this record, it removes from our storage. You must keep the patient's record safe.",
),
).toBeInTheDocument();
expect(
screen.getByRole('checkbox', {
name: 'I understand that downloading this record removes it from storage.',
}),
).toBeInTheDocument();
expect(
screen.getByRole('button', { name: 'Yes, download and remove' }),
).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
});

renderComponent();
it('when checkbox is unchecked, clicking red download button should show an alert and not allowing download', async () => {
renderComponentForNonBSOLGPAdmin();
await showConfirmationMessage();

clickRedDownloadButton();

await waitFor(() => {
expect(
screen.getByRole('alert', { name: 'There is a problem' }),
).toBeInTheDocument();
});
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();
});

expect(screen.getByText('Before downloading')).toBeInTheDocument();
expect(screen.getByText('Available records')).toBeInTheDocument();
expect(
screen.getByRole('button', { name: 'Download and remove record' }),
).toBeInTheDocument();
it('when checkbox is checked, clicking red download button should proceed to download and delete process', async () => {
renderComponentForNonBSOLGPAdmin();
await showConfirmationMessage();

act(() => {
userEvent.click(screen.getByRole('checkbox'));
});

clickRedDownloadButton();

await waitFor(() => {
expect(mockSetStage).toBeCalledWith(LG_RECORD_STAGE.DOWNLOAD_ALL);
});
});

it('when checkbox is toggled 2 times ( = unchecked), red download button should not proceed to download', async () => {
renderComponentForNonBSOLGPAdmin();
await showConfirmationMessage();

const checkBox = screen.getByRole('checkbox');
act(() => {
userEvent.click(checkBox);
userEvent.click(checkBox);
});

clickRedDownloadButton();

await waitFor(() => {
expect(
screen.getByRole('alert', { name: 'There is a problem' }),
).toBeInTheDocument();
});
expect(mockSetStage).not.toBeCalled();
});

it('clicking cancel button will hide the confirmation message', async () => {
renderComponentForNonBSOLGPAdmin();
await showConfirmationMessage();

act(() => {
userEvent.click(screen.getByRole('button', { name: 'Cancel' }));
});

await waitFor(() => {
expect(
screen.queryByText('Are you sure you want to download and remove this record?'),
).not.toBeInTheDocument();
});
});
});

it('does not render warning callout, header and button when user is GP admin and BSOL', async () => {
Expand Down Expand Up @@ -167,8 +300,7 @@ describe('LloydGeorgeRecordStage', () => {
});
});
const TestApp = (props: Omit<Props, 'setStage' | 'stage'>) => {
const [stage, setStage] = useState(LG_RECORD_STAGE.RECORD);
return <LgRecordStage {...props} setStage={setStage} stage={stage} />;
return <LgRecordStage {...props} setStage={mockSetStage} stage={LG_RECORD_STAGE.RECORD} />;
};

const renderComponent = (propsOverride?: Partial<Props>) => {
Expand Down
Loading
Loading