diff --git a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/patient_search_and_verify_workflow.cy.js b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/patient_search_and_verify_workflow.cy.js index 7e39cd0d0..2ce0eda50 100644 --- a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/patient_search_and_verify_workflow.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/patient_search_and_verify_workflow.cy.js @@ -20,8 +20,18 @@ describe('GP Workflow: Patient search and verify', () => { active: false, }; + const featureFlags = { + uploadArfWorkflowEnabled: 'true', + uploadLambdaEnabled: 'true', + }; + gpRoles.forEach((role) => { beforeEach(() => { + cy.intercept('GET', '/FeatureFlags*', { + statusCode: 200, + body: featureFlags, + }).as('featureFlags'); + cy.login(role); cy.visit(searchPatientUrl); }); diff --git a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/upload_workflow.cy.js b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/upload_workflow.cy.js index 9a3072793..08c2e4342 100644 --- a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/upload_workflow.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/upload_workflow.cy.js @@ -21,6 +21,11 @@ const patient = { active: false, }; +const featureFlags = { + uploadArfWorkflowEnabled: 'true', + uploadLambdaEnabled: 'true', +}; + const bucketUrlIdentifer = 'document-store.s3.amazonaws.com'; const serverError = 500; const successNoContent = 204; @@ -91,6 +96,11 @@ const gpRoles = [Roles.GP_ADMIN, Roles.GP_CLINICAL]; describe('GP Workflow: Upload docs and verify', () => { gpRoles.forEach((role) => { beforeEach(() => { + cy.intercept('GET', '**/FeatureFlags**', { + statusCode: 200, + body: featureFlags, + }).as('featureFlags'); + cy.login(role); navigateToUploadPage(); }); diff --git a/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.test.tsx b/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.test.tsx index 5656aa368..7294c03bc 100644 --- a/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.test.tsx +++ b/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.test.tsx @@ -1,17 +1,19 @@ -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import UploadDocumentsPage from './UploadDocumentsPage'; -import usePatient from '../../helpers/hooks/usePatient'; -import { buildPatientDetails } from '../../helpers/test/testBuilders'; +import { buildConfig } from '../../helpers/test/testBuilders'; import { UPLOAD_STAGE } from '../../types/pages/UploadDocumentsPage/types'; import { useState } from 'react'; -jest.mock('../../helpers/hooks/useBaseAPIHeaders'); -jest.mock('../../helpers/hooks/useBaseAPIUrl'); -jest.mock('../../helpers/hooks/usePatient'); -jest.mock('react-router'); -const mockedUsePatient = usePatient as jest.Mock; +import useConfig from '../../helpers/hooks/useConfig'; +import { routes } from '../../types/generic/routes'; + const mockUseState = useState as jest.Mock; +const mockConfigContext = useConfig as jest.Mock; +const mockedUseNavigate = jest.fn(); -const mockPatient = buildPatientDetails(); +jest.mock('react-router', () => ({ + useNavigate: () => mockedUseNavigate, + useLocation: () => jest.fn(), +})); jest.mock('react', () => ({ ...jest.requireActual('react'), useState: jest.fn(), @@ -25,39 +27,91 @@ jest.mock('../../components/blocks/_arf/uploadingStage/UploadingStage', () => () jest.mock('../../components/blocks/_arf/completeStage/CompleteStage', () => () => (

Mock complete stage

)); +jest.mock('../../helpers/hooks/useConfig'); describe('UploadDocumentsPage', () => { beforeEach(() => { process.env.REACT_APP_ENVIRONMENT = 'jest'; - mockedUsePatient.mockReturnValue(mockPatient); + mockConfigContext.mockReturnValue( + buildConfig({}, { uploadArfWorkflowEnabled: true, uploadLambdaEnabled: true }), + ); mockUseState.mockImplementation(() => [UPLOAD_STAGE.Selecting, jest.fn()]); }); afterEach(() => { jest.clearAllMocks(); }); describe('Rendering', () => { - it('renders initial file input stage', () => { + it('renders initial file input stage', async () => { render(); + expect( screen.getByRole('heading', { name: 'Mock file input stage' }), ).toBeInTheDocument(); + await waitFor(() => { + expect(mockedUseNavigate).not.toHaveBeenCalledWith(routes.UNAUTHORISED); + }); }); - it('renders uploading stage when state is set', () => { + it('renders uploading stage when state is set', async () => { mockUseState.mockImplementation(() => [UPLOAD_STAGE.Uploading, jest.fn()]); + render(); + expect( screen.getByRole('heading', { name: 'Mock files are uploading stage' }), ).toBeInTheDocument(); + await waitFor(() => { + expect(mockedUseNavigate).not.toHaveBeenCalledWith(routes.UNAUTHORISED); + }); }); - it('renders upload complete stage when state is set', () => { + it('renders upload complete stage when state is set', async () => { mockUseState.mockImplementation(() => [UPLOAD_STAGE.Complete, jest.fn()]); + render(); + expect( screen.getByRole('heading', { name: 'Mock complete stage' }), ).toBeInTheDocument(); + await waitFor(() => { + expect(mockedUseNavigate).not.toHaveBeenCalledWith(routes.UNAUTHORISED); + }); + }); + }); + + describe('Navigation', () => { + it('redirects to unauthorised page if arf workflow feature toggled off', async () => { + mockConfigContext.mockReturnValue( + buildConfig({}, { uploadArfWorkflowEnabled: true, uploadLambdaEnabled: false }), + ); + + render(); + + await waitFor(() => { + expect(mockedUseNavigate).toHaveBeenCalledWith(routes.UNAUTHORISED); + }); + }); + it('redirects to unauthorised page if upload lambda feature toggled off', async () => { + mockConfigContext.mockReturnValue( + buildConfig({}, { uploadArfWorkflowEnabled: true, uploadLambdaEnabled: false }), + ); + + render(); + + await waitFor(() => { + expect(mockedUseNavigate).toHaveBeenCalledWith(routes.UNAUTHORISED); + }); + }); + it('redirects to unauthorised page if both features toggled off', async () => { + mockConfigContext.mockReturnValue( + buildConfig({}, { uploadArfWorkflowEnabled: false, uploadLambdaEnabled: false }), + ); + + render(); + + await waitFor(() => { + expect(mockedUseNavigate).toHaveBeenCalledWith(routes.UNAUTHORISED); + }); }); }); - describe('Navigation', () => {}); }); diff --git a/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx b/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx index 70eb0d25e..aab9a2b29 100644 --- a/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx +++ b/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx @@ -1,12 +1,34 @@ -import React, { useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { UPLOAD_STAGE, UploadDocument } from '../../types/pages/UploadDocumentsPage/types'; import SelectStage from '../../components/blocks/_arf/selectStage/SelectStage'; import UploadingStage from '../../components/blocks/_arf/uploadingStage/UploadingStage'; import CompleteStage from '../../components/blocks/_arf/completeStage/CompleteStage'; +import { routes } from '../../types/generic/routes'; +import { useNavigate } from 'react-router'; +import useConfig from '../../helpers/hooks/useConfig'; function UploadDocumentsPage() { const [stage, setStage] = useState(UPLOAD_STAGE.Selecting); const [documents, setDocuments] = useState>([]); + const config = useConfig(); + const navigate = useNavigate(); + + const mounted = useRef(false); + useEffect(() => { + const onPageLoad = () => { + if ( + !config.featureFlags.uploadArfWorkflowEnabled || + !config.featureFlags.uploadLambdaEnabled + ) { + navigate(routes.UNAUTHORISED); + } + }; + + if (!mounted.current) { + mounted.current = true; + onPageLoad(); + } + }, [navigate, config]); if (stage === UPLOAD_STAGE.Selecting) { return (