Skip to content

Commit 7fa2488

Browse files
authored
[PRMP-811] Add API integration for reassign (#969)
1 parent d645825 commit 7fa2488

File tree

41 files changed

+4726
-1626
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+4726
-1626
lines changed

app/public/dev/testFile.zip

28.6 KB
Binary file not shown.

app/src/components/blocks/_admin/reviewDetailsAddMoreChoiceStage/ReviewDetailsAddMoreChoiceStage.test.tsx

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,99 @@ describe('ReviewDetailsAddMoreChoicePage', () => {
200200
});
201201
});
202202

203+
describe('Navigation', () => {
204+
it('navigates to add more files when yes is selected', async () => {
205+
render(<ReviewDetailsAddMoreChoiceStage reviewData={null} />);
206+
207+
const yesRadio = screen.getByRole('radio', {
208+
name: /Yes I have more scanned paper records to add for this patient/i,
209+
});
210+
await userEvent.click(yesRadio);
211+
212+
const continueButton = screen.getByRole('button', { name: 'Continue' });
213+
await userEvent.click(continueButton);
214+
215+
await waitFor(() => {
216+
expect(mockNavigate).toHaveBeenCalledWith(
217+
`/admin/reviews/${mockReviewId}/upload-additional-files`,
218+
undefined,
219+
);
220+
});
221+
});
222+
223+
it('navigates to upload file order when no is selected and multiple files exist', async () => {
224+
const mockReviewData = {
225+
id: 'review-123',
226+
files: [{ fileName: 'file1.pdf' }, { fileName: 'file2.pdf' }],
227+
} as any;
228+
229+
render(<ReviewDetailsAddMoreChoiceStage reviewData={mockReviewData} />);
230+
231+
const noRadio = screen.getByRole('radio', {
232+
name: /No, I don't have anymore scanned paper records to add for this patient/i,
233+
});
234+
await userEvent.click(noRadio);
235+
236+
const continueButton = screen.getByRole('button', { name: 'Continue' });
237+
await userEvent.click(continueButton);
238+
239+
await waitFor(() => {
240+
expect(mockNavigate).toHaveBeenCalledWith(
241+
`/admin/reviews/${mockReviewId}/upload-file-order`,
242+
undefined,
243+
);
244+
});
245+
});
246+
247+
it('navigates to upload directly when no is selected and single file exists', async () => {
248+
const mockReviewData = {
249+
id: 'review-123',
250+
files: [{ fileName: 'file1.pdf' }],
251+
} as any;
252+
253+
render(<ReviewDetailsAddMoreChoiceStage reviewData={mockReviewData} />);
254+
255+
const noRadio = screen.getByRole('radio', {
256+
name: /No, I don't have anymore scanned paper records to add for this patient/i,
257+
});
258+
await userEvent.click(noRadio);
259+
260+
const continueButton = screen.getByRole('button', { name: 'Continue' });
261+
await userEvent.click(continueButton);
262+
263+
await waitFor(() => {
264+
expect(mockNavigate).toHaveBeenCalledWith(
265+
`/admin/reviews/${mockReviewId}/upload`,
266+
undefined,
267+
);
268+
});
269+
});
270+
271+
it('navigates to upload directly when no is selected and no files exist', async () => {
272+
const mockReviewData = {
273+
id: 'review-123',
274+
files: [],
275+
} as any;
276+
277+
render(<ReviewDetailsAddMoreChoiceStage reviewData={mockReviewData} />);
278+
279+
const noRadio = screen.getByRole('radio', {
280+
name: /No, I don't have anymore scanned paper records to add for this patient/i,
281+
});
282+
await userEvent.click(noRadio);
283+
284+
const continueButton = screen.getByRole('button', { name: 'Continue' });
285+
await userEvent.click(continueButton);
286+
287+
await waitFor(() => {
288+
expect(mockNavigate).toHaveBeenCalledWith(
289+
`/admin/reviews/${mockReviewId}/upload`,
290+
undefined,
291+
);
292+
});
293+
});
294+
});
295+
203296
describe('Accessibility', () => {
204297
it('passes axe accessibility tests in initial state', async () => {
205298
const { container } = render(<ReviewDetailsAddMoreChoiceStage reviewData={null} />);

app/src/components/blocks/_admin/reviewDetailsAddMoreChoiceStage/ReviewDetailsAddMoreChoiceStage.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ const ReviewDetailsAddMoreChoiceStage: React.FC<ReviewDetailsAddMoreChoicePagePr
3232
navigate,
3333
);
3434
} else {
35-
navigateUrlParam(routeChildren.ADMIN_REVIEW_UPLOAD_FILE_ORDER, { reviewId }, navigate);
35+
navigateUrlParam(
36+
reviewData!.files!.length > 1
37+
? routeChildren.ADMIN_REVIEW_UPLOAD_FILE_ORDER
38+
: routeChildren.ADMIN_REVIEW_UPLOAD,
39+
{ reviewId },
40+
navigate
41+
);
3642
}
3743
};
3844

app/src/components/blocks/_admin/reviewDetailsAssessmentStage/ReviewDetailsAssessmentStage.test.tsx

Lines changed: 151 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { render, screen, waitFor } from '@testing-library/react';
22
import userEvent from '@testing-library/user-event';
33
import { act } from 'react';
4-
import { describe, expect, it, vi } from 'vitest';
4+
import { describe, expect, it, Mock, vi } from 'vitest';
55
import ReviewDetailsAssessmentStage from './ReviewDetailsAssessmentStage';
66
import { DOWNLOAD_STAGE } from '../../../../types/generic/downloadStage';
77
import {
@@ -24,7 +24,7 @@ vi.mock('../../../../helpers/utils/isLocal', () => ({
2424
}));
2525
vi.mock('react-router-dom', async () => ({
2626
...(await vi.importActual('react-router-dom')),
27-
useNavigate: (): typeof mockedUseNavigate => mockedUseNavigate,
27+
useNavigate: (): Mock => mockedUseNavigate,
2828
useParams: (): { reviewId: string } => ({ reviewId: 'test-review-id.v1' }),
2929
}));
3030

@@ -729,6 +729,155 @@ describe('ReviewDetailsAssessmentPage', () => {
729729
});
730730
});
731731

732+
describe('Error handling for file viewing', () => {
733+
it('navigates to SESSION_EXPIRED when getReviewById returns 403', async () => {
734+
const user = userEvent.setup();
735+
const mockGetReviewById = vi.spyOn(getReviewsModule, 'getReviewById');
736+
mockGetReviewById.mockRejectedValue({ code: '403' });
737+
738+
render(
739+
<ReviewDetailsAssessmentStage
740+
reviewData={createMockReviewData()}
741+
setReviewData={mockSetReviewData}
742+
uploadDocuments={createMockUploadDocuments()}
743+
downloadStage={DOWNLOAD_STAGE.SUCCEEDED}
744+
setDownloadStage={mockSetDownloadStage}
745+
hasExistingRecordInStorage={true}
746+
/>,
747+
);
748+
749+
const viewButtons = screen.getAllByRole('button', { name: /View/i });
750+
await act(async () => {
751+
await user.click(viewButtons[1]);
752+
});
753+
754+
await waitFor(() => {
755+
expect(mockedUseNavigate).toHaveBeenCalledWith('/session-expired');
756+
});
757+
});
758+
759+
it('navigates to SERVER_ERROR when getReviewById returns other error', async () => {
760+
const user = userEvent.setup();
761+
const mockGetReviewById = vi.spyOn(getReviewsModule, 'getReviewById');
762+
mockGetReviewById.mockRejectedValue(new Error('Server error'));
763+
764+
render(
765+
<ReviewDetailsAssessmentStage
766+
reviewData={createMockReviewData()}
767+
setReviewData={mockSetReviewData}
768+
uploadDocuments={createMockUploadDocuments()}
769+
downloadStage={DOWNLOAD_STAGE.SUCCEEDED}
770+
setDownloadStage={mockSetDownloadStage}
771+
hasExistingRecordInStorage={true}
772+
/>,
773+
);
774+
775+
const viewButtons = screen.getAllByRole('button', { name: /View/i });
776+
await act(async () => {
777+
await user.click(viewButtons[1]);
778+
});
779+
780+
await waitFor(() => {
781+
expect(mockedUseNavigate).toHaveBeenCalledWith(
782+
expect.stringContaining('/server-error'),
783+
);
784+
});
785+
});
786+
});
787+
788+
describe('Navigation with accept action and multifileReview', () => {
789+
it('navigates to UPLOAD when accept is selected with single file', async () => {
790+
const user = userEvent.setup();
791+
const singleFileReviewData = createMockReviewData(false, true, false, '24511000000107' as DOCUMENT_TYPE);
792+
singleFileReviewData.files = [{ fileName: 'single-file.pdf', uploadDate: '2024-01-15T09:00:00Z', presignedUrl: 'http://example.com' }];
793+
794+
const singleUploadDoc = [{
795+
id: 'new-1',
796+
file: new File(['test content'], 'single-file.pdf', { type: 'application/pdf' }),
797+
type: UploadDocumentType.REVIEW,
798+
state: DOCUMENT_UPLOAD_STATE.SELECTED,
799+
docType: '24511000000107' as DOCUMENT_TYPE,
800+
attempts: 0,
801+
}];
802+
803+
render(
804+
<ReviewDetailsAssessmentStage
805+
reviewData={singleFileReviewData}
806+
setReviewData={mockSetReviewData}
807+
uploadDocuments={singleUploadDoc}
808+
downloadStage={DOWNLOAD_STAGE.SUCCEEDED}
809+
setDownloadStage={mockSetDownloadStage}
810+
hasExistingRecordInStorage={false}
811+
/>,
812+
);
813+
814+
const acceptRadio = screen.getByLabelText(/Accept record/i);
815+
await user.click(acceptRadio);
816+
817+
const continueButton = screen.getByRole('button', { name: 'Continue' });
818+
await user.click(continueButton);
819+
820+
await waitFor(() => {
821+
expect(mockedUseNavigate).toHaveBeenCalledWith(
822+
'/admin/reviews/test-review-id.v1/upload',
823+
undefined,
824+
);
825+
});
826+
});
827+
828+
it('navigates to UPLOAD_FILE_ORDER when accept is selected with multiple files', async () => {
829+
const user = userEvent.setup();
830+
const multipleFileReviewData = createMockReviewData(false, true, false, '24511000000107' as DOCUMENT_TYPE);
831+
multipleFileReviewData.files = [
832+
{ fileName: 'file-1.pdf', uploadDate: '2024-01-15T09:00:00Z', presignedUrl: 'http://example.com/1' },
833+
{ fileName: 'file-2.pdf', uploadDate: '2024-01-16T09:00:00Z', presignedUrl: 'http://example.com/2' },
834+
];
835+
836+
const multiUploadDocs: ReviewUploadDocument[] = [
837+
{
838+
id: 'new-1',
839+
file: new File(['test content 1'], 'file-1.pdf', { type: 'application/pdf' }),
840+
type: UploadDocumentType.REVIEW,
841+
state: DOCUMENT_UPLOAD_STATE.SELECTED,
842+
docType: '24511000000107' as DOCUMENT_TYPE,
843+
attempts: 0,
844+
},
845+
{
846+
id: 'new-2',
847+
file: new File(['test content 2'], 'file-2.pdf', { type: 'application/pdf' }),
848+
type: UploadDocumentType.REVIEW,
849+
state: DOCUMENT_UPLOAD_STATE.SELECTED,
850+
docType: '24511000000107' as DOCUMENT_TYPE,
851+
attempts: 0,
852+
},
853+
];
854+
855+
render(
856+
<ReviewDetailsAssessmentStage
857+
reviewData={multipleFileReviewData}
858+
setReviewData={mockSetReviewData}
859+
uploadDocuments={multiUploadDocs}
860+
downloadStage={DOWNLOAD_STAGE.SUCCEEDED}
861+
setDownloadStage={mockSetDownloadStage}
862+
hasExistingRecordInStorage={false}
863+
/>,
864+
);
865+
866+
const acceptRadio = screen.getByLabelText(/Accept record/i);
867+
await user.click(acceptRadio);
868+
869+
const continueButton = screen.getByRole('button', { name: 'Continue' });
870+
await user.click(continueButton);
871+
872+
await waitFor(() => {
873+
expect(mockedUseNavigate).toHaveBeenCalledWith(
874+
'/admin/reviews/test-review-id.v1/upload-file-order',
875+
undefined,
876+
);
877+
});
878+
});
879+
});
880+
732881
describe('Back button', () => {
733882
it('renders back button', () => {
734883
render(

0 commit comments

Comments
 (0)