Skip to content

Commit

Permalink
Merge branch 'main' into PRMDR-556
Browse files Browse the repository at this point in the history
  • Loading branch information
carlsmith101 authored Jan 24, 2024
2 parents 4971118 + 62b3d6a commit 4a1e8aa
Show file tree
Hide file tree
Showing 30 changed files with 521 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,15 @@ describe('GP Workflow: View Lloyd George record', () => {
cy.get('#verify-submit').click();

//Assert
assertPatientInfo();
assertFailedLloydGeorgeLoad();
cy.contains('Sorry, there is a problem with the service').should('be.visible');
},
);
});
});

context('View Lloyd George document with specific role tests', () => {
it(
'It displays an error with a download link when a Lloyd George stitching timeout occures via the API Gatway for a GP_ADMIN',
'It displays an error with a download link when a Lloyd George stitching timeout occurs via the API Gateway for a GP_ADMIN',
{ tags: 'regression' },
() => {
beforeEachConfiguration(Roles.GP_ADMIN);
Expand All @@ -151,7 +150,7 @@ describe('GP Workflow: View Lloyd George record', () => {
);

it(
'It displays an error with download link when a Lloyd George stitching timeout occures via the API Gatway for a GP_CLINICAL but link access is denied',
'It displays an error with download link when a Lloyd George stitching timeout occurs via the API Gateway for a GP_CLINICAL but link access is denied',
{ tags: 'regression' },
() => {
beforeEachConfiguration(Roles.GP_CLINICAL);
Expand Down Expand Up @@ -287,7 +286,7 @@ describe('GP Workflow: View Lloyd George record', () => {
cy.wait('@documentDelete');

// assert
cy.getByTestId('service-error').should('be.visible');
cy.contains('Sorry, there is a problem with the service').should('be.visible');
},
);

Expand Down Expand Up @@ -346,7 +345,7 @@ describe('GP Workflow: View Lloyd George record', () => {
cy.wait('@documentManifest');

// Assert
cy.contains('An error has occurred while preparing your download').should('be.visible');
cy.contains('Sorry, there is a problem with the service').should('be.visible');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ describe('GP Workflow: View Lloyd George record', () => {
cy.get('#verify-submit').click();

//Assert
assertPatientInfo();
assertFailedLloydGeorgeLoad();
cy.contains('Sorry, there is a problem with the service').should(
'be.visible',
);
},
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ describe('PCSE Workflow: Access and download found files', () => {

navigateToDownload(roles.PCSE);

cy.get('#service-error').should('exist');
cy.contains('Sorry, there is a problem with the service').should('be.visible');
},
);

Expand Down Expand Up @@ -307,7 +307,7 @@ describe('PCSE Workflow: Access and download found files', () => {
cy.getByTestId('delete-submit-btn').click();

// assert
cy.getByTestId('service-error').should('be.visible');
cy.contains('Sorry, there is a problem with the service').should('be.visible');
},
);

Expand All @@ -330,7 +330,7 @@ describe('PCSE Workflow: Access and download found files', () => {
cy.getByTestId('delete-submit-btn').click();

// assert
cy.getByTestId('service-error').should('be.visible');
cy.contains('Sorry, there is a problem with the service').should('be.visible');
},
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ describe('DeleteDocumentsStage', () => {
const errorResponse = {
response: {
status: 500,
message: 'Client Error.',
data: { message: 'Client Error', err_code: 'SP_1001' },
},
};
mockedAxios.delete.mockImplementation(() => Promise.reject(errorResponse));
Expand All @@ -182,6 +182,12 @@ describe('DeleteDocumentsStage', () => {
screen.getByText('Sorry, the service is currently unavailable.'),
).toBeInTheDocument();
});

await waitFor(() => {
expect(mockedUseNavigate).toHaveBeenCalledWith(
routes.SERVER_ERROR + '?errorCode=SP_1001',
);
});
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { REPOSITORY_ROLE } from '../../../types/generic/authRole';
import { LG_RECORD_STAGE } from '../../../types/blocks/lloydGeorgeStages';
import useBaseAPIUrl from '../../../helpers/hooks/useBaseAPIUrl';
import usePatient from '../../../helpers/hooks/usePatient';
import { errorToParams } from '../../../helpers/utils/errorToParams';

export type Props = {
docType: DOCUMENT_TYPE;
Expand Down Expand Up @@ -80,7 +81,6 @@ function DeleteDocumentsStage({

if (response.status === 200) {
setDeletionStage(SUBMISSION_STATE.SUCCEEDED);

if (setDownloadStage) {
setDownloadStage(DOWNLOAD_STAGE.FAILED);
}
Expand All @@ -89,6 +89,8 @@ function DeleteDocumentsStage({
const error = e as AxiosError;
if (error.response?.status === 403) {
navigate(routes.START);
} else {
navigate(routes.SERVER_ERROR + errorToParams(error));
}
setDeletionStage(SUBMISSION_STATE.FAILED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('DocumentSearchResultsOptions', () => {
const errorResponse = {
response: {
status: 400,
message: 'Error',
data: { message: 'Error', err_code: 'SP_1001' },
},
};
mockedAxios.get.mockImplementation(() => Promise.reject(errorResponse));
Expand Down Expand Up @@ -154,6 +154,24 @@ describe('DocumentSearchResultsOptions', () => {
expect(mockedUseNavigate).toHaveBeenCalledWith(routes.START);
});
});
it('navigates to error page when API returns 5XX', async () => {
const errorResponse = {
response: {
status: 500,
data: { message: 'Server error', err_code: 'SP_1001' },
},
};
mockedAxios.get.mockImplementation(() => Promise.reject(errorResponse));

renderDocumentSearchResultsOptions(SUBMISSION_STATE.INITIAL);
userEvent.click(screen.getByRole('button', { name: 'Download All Documents' }));

await waitFor(() => {
expect(mockedUseNavigate).toHaveBeenCalledWith(
routes.SERVER_ERROR + '?errorCode=SP_1001',
);
});
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react';
import useBaseAPIHeaders from '../../../helpers/hooks/useBaseAPIHeaders';
import { DOCUMENT_TYPE } from '../../../types/pages/UploadDocumentsPage/types';
import useBaseAPIUrl from '../../../helpers/hooks/useBaseAPIUrl';
import { errorToParams } from '../../../helpers/utils/errorToParams';

type Props = {
nhsNumber: string;
Expand Down Expand Up @@ -58,6 +59,8 @@ const DocumentSearchResultsOptions = (props: Props) => {
const error = e as AxiosError;
if (error.response?.status === 403) {
navigate(routes.START);
} else {
navigate(routes.SERVER_ERROR + errorToParams(error));
}
props.updateDownloadState(SUBMISSION_STATE.FAILED);
}
Expand Down
5 changes: 4 additions & 1 deletion app/src/components/blocks/feedbackForm/FeedbackForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import FeedbackForm, { Props } from './FeedbackForm';
import { fillInForm } from '../../../helpers/test/formUtils';

jest.mock('../../../helpers/requests/sendEmail');
const mockedUseNavigate = jest.fn();
const mockSendEmail = sendEmail as jest.Mock;
const mockSetStage = jest.fn();

jest.mock('react-router', () => ({
useNavigate: () => mockedUseNavigate,
}));
const clickSubmitButton = () => {
userEvent.click(screen.getByRole('button', { name: 'Send feedback' }));
};
Expand Down
21 changes: 13 additions & 8 deletions app/src/components/blocks/feedbackForm/FeedbackForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import isEmail from 'validator/lib/isEmail';
import sendEmail from '../../../helpers/requests/sendEmail';
import { Button, Fieldset, Input, Radios, Textarea } from 'nhsuk-react-components';
import SpinnerButton from '../../generic/spinnerButton/SpinnerButton';
import { routes } from '../../../types/generic/routes';
import { useNavigate } from 'react-router-dom';
import { errorToParams } from '../../../helpers/utils/errorToParams';
import { AxiosError } from 'axios/index';

export type Props = {
stage: SUBMISSION_STAGE;
Expand All @@ -25,17 +29,18 @@ function FeedbackForm({ stage, setStage }: Props) {
} = useForm<FormData>({
reValidateMode: 'onSubmit',
});
const navigate = useNavigate();

const submit: SubmitHandler<FormData> = async (formData) => {
setStage(SUBMISSION_STAGE.Submitting);

sendEmail(formData)
.then(() => {
setStage(SUBMISSION_STAGE.Successful);
})
.catch((e) => {
setStage(SUBMISSION_STAGE.Failure);
});
// add tests for failing and passing cases when real email service is implemented
try {
await sendEmail(formData);
setStage(SUBMISSION_STAGE.Successful);
} catch (e) {
const error = e as AxiosError;
navigate(routes.SERVER_ERROR + errorToParams(error));
}
};

const renameRefKey = (props: UseFormRegisterReturn, newRefKey: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,25 @@ import { act } from 'react-dom/test-utils';
import userEvent from '@testing-library/user-event';
import usePatient from '../../../helpers/hooks/usePatient';
import { LinkProps } from 'react-router-dom';
import { routes } from '../../../types/generic/routes';
import mock = jest.mock;

const mockedUseNavigate = jest.fn();
jest.mock('react-router', () => ({
useNavigate: () => mockedUseNavigate,
}));
const mockedAxios = axios as jest.Mocked<typeof axios>;
const mockedUsePatient = usePatient as jest.Mock;
const mockPdf = buildLgSearchResult();
const mockPatient = buildPatientDetails();
const mockSetStage = jest.fn();
const mockDownloadStage = jest.fn();
jest.mock('react-router-dom', () => ({
__esModule: true,
Link: (props: LinkProps) => <a {...props} role="link" />,
useNavigate: () => mockedUseNavigate,
}));
jest.mock('axios');
jest.mock('../../../helpers/hooks/useBaseAPIHeaders');
jest.mock('../../../helpers/hooks/usePatient');

const mockedAxios = axios as jest.Mocked<typeof axios>;
const mockedUsePatient = usePatient as jest.Mock;

const mockPdf = buildLgSearchResult();
const mockPatient = buildPatientDetails();
const mockSetStage = jest.fn();
const mockDownloadStage = jest.fn();

describe('LloydGeorgeDownloadAllStage', () => {
beforeEach(() => {
process.env.REACT_APP_ENVIRONMENT = 'jest';
Expand Down Expand Up @@ -97,6 +95,60 @@ describe('LloydGeorgeDownloadAllStage', () => {
});
expect(screen.getByRole('heading', { name: 'Download complete' })).toBeInTheDocument();
});

it('navigates to Error page when zip lg record view complete but fail on delete', async () => {
window.HTMLAnchorElement.prototype.click = jest.fn();
mockedAxios.get.mockImplementation(() => Promise.resolve({ data: mockPdf.presign_url }));
const errorResponse = {
response: {
status: 500,
data: { message: 'An error occurred', err_code: 'SP_1001' },
},
};
mockedAxios.delete.mockImplementation(() => Promise.reject(errorResponse));

jest.useFakeTimers();

renderComponent({ deleteAfterDownload: true });

expect(screen.getByText('0% downloaded...')).toBeInTheDocument();
expect(screen.queryByText('100% downloaded...')).not.toBeInTheDocument();

act(() => {
jest.advanceTimersByTime(500);
});

await waitFor(() => {
expect(screen.getByText('100% downloaded...')).toBeInTheDocument();
});
expect(screen.queryByText('0% downloaded...')).not.toBeInTheDocument();

await waitFor(() => {
expect(mockedUseNavigate).toHaveBeenCalledWith(
routes.SERVER_ERROR + '?errorCode=SP_1001',
);
});
});

it('navigates to Error page when zip lg record view return 500', async () => {
const errorResponse = {
response: {
status: 500,
data: { message: 'An error occurred', err_code: 'SP_1001' },
},
};
mockedAxios.get.mockImplementation(() => Promise.reject(errorResponse));
jest.useFakeTimers();
renderComponent();
act(() => {
jest.advanceTimersByTime(500);
});
await waitFor(() => {
expect(mockedUseNavigate).toHaveBeenCalledWith(
routes.SERVER_ERROR + '?errorCode=SP_1001',
);
});
});
});

const renderComponent = (propsOverride?: Partial<Props>) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import React, {
useState,
} from 'react';
import { Card } from 'nhsuk-react-components';
import { Link } from 'react-router-dom';
import useBaseAPIHeaders from '../../../helpers/hooks/useBaseAPIHeaders';
import getPresignedUrlForZip from '../../../helpers/requests/getPresignedUrlForZip';
import { DOCUMENT_TYPE } from '../../../types/pages/UploadDocumentsPage/types';
Expand All @@ -18,6 +17,10 @@ import useBaseAPIUrl from '../../../helpers/hooks/useBaseAPIUrl';
import usePatient from '../../../helpers/hooks/usePatient';
import deleteAllDocuments from '../../../helpers/requests/deleteAllDocuments';
import { DOWNLOAD_STAGE } from '../../../types/generic/downloadStage';
import { routes } from '../../../types/generic/routes';
import { useNavigate, Link } from 'react-router-dom';
import { errorToParams } from '../../../helpers/utils/errorToParams';
import { AxiosError } from 'axios/index';

const FakeProgress = require('fake-progress');

Expand Down Expand Up @@ -50,6 +53,7 @@ function LloydGeorgeDownloadAllStage({
const [inProgress, setInProgress] = useState(true);
const linkRef = useRef<HTMLAnchorElement | null>(null);
const mounted = useRef(false);
const navigate = useNavigate();

const patientDetails = usePatient();
const nhsNumber = patientDetails?.nhsNumber ?? '';
Expand Down Expand Up @@ -102,10 +106,14 @@ function LloydGeorgeDownloadAllStage({
baseUrl,
baseHeaders,
});
} catch (e) {} // This is fail and forget at this point in time.
} catch (e) {
navigate(routes.SERVER_ERROR + errorToParams(e as AxiosError));
} // This is fail and forget at this point in time.
}
setLinkAttributes({ url: preSignedUrl, filename: filename });
} catch (e) {}
} catch (e) {
navigate(routes.SERVER_ERROR + errorToParams(e as AxiosError));
}
};

if (!mounted.current) {
Expand All @@ -116,7 +124,15 @@ function LloydGeorgeDownloadAllStage({
const delayTimer = setTimeout(onPageLoad, timeToComplete + delay);
setDelayTimer(delayTimer);
}
}, [baseHeaders, baseUrl, intervalTimer, nhsNumber, progressTimer, deleteAfterDownload]);
}, [
baseHeaders,
baseUrl,
intervalTimer,
nhsNumber,
progressTimer,
deleteAfterDownload,
navigate,
]);

return inProgress ? (
<div className="lloydgeorge_downloadall-stage" data-testid="lloydgeorge_downloadall-stage">
Expand Down
Loading

0 comments on commit 4a1e8aa

Please sign in to comment.