Skip to content

Commit b8d97f4

Browse files
Merge remote-tracking branch 'origin/main' into PRMP-1058
# Conflicts: # .github/workflows/base-lambdas-reusable-deploy-all.yml # lambdas/handlers/report_orchestration_handler.py
2 parents 0e68690 + 5c2d3ce commit b8d97f4

File tree

145 files changed

+2234
-906
lines changed

Some content is hidden

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

145 files changed

+2234
-906
lines changed

.github/workflows/base-lambdas-reusable-deploy-all.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,4 +837,18 @@ jobs:
837837
lambda_aws_name: SesFeedbackMonitor
838838
lambda_layer_names: "core_lambda_layer,reports_lambda_layer"
839839
secrets:
840-
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}
840+
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}
841+
842+
deploy_concurrency_controller_lambda:
843+
name: Deploy Concurrency Controller Lambda
844+
uses: ./.github/workflows/base-lambdas-reusable-deploy.yml
845+
with:
846+
environment: ${{ inputs.environment }}
847+
python_version: ${{ inputs.python_version }}
848+
build_branch: ${{ inputs.build_branch }}
849+
sandbox: ${{ inputs.sandbox }}
850+
lambda_handler_name: concurrency_controller_handler
851+
lambda_aws_name: ConcurrencyController
852+
lambda_layer_names: "core_lambda_layer"
853+
secrets:
854+
AWS_ASSUME_ROLE: ${{ secrets.AWS_ASSUME_ROLE }}

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,16 @@ clean-test:
8181
find . -name '.cache' -exec rm -fr {} +
8282

8383
format:
84+
ifeq ($(CONTAINER), true)
85+
./.venv/bin/python3 -m isort --profile black lambdas/
86+
./.venv/bin/python3 -m black lambdas/
87+
./.venv/bin/ruff check lambdas/ --fix
88+
else
8489
./lambdas/venv/bin/python3 -m isort --profile black lambdas/
8590
./lambdas/venv/bin/python3 -m black lambdas/
8691
./lambdas/venv/bin/ruff check lambdas/ --fix
92+
endif
93+
8794

8895
sort-requirements:
8996
sort -o $(TEST_REQUIREMENTS) $(TEST_REQUIREMENTS)

app/cypress/e2e/0-ndr-core-tests/download_lloyd_george_summary.cy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('GP Workflow: Download Lloyd George summary report', () => {
3333

3434
cy.wait('@downloadReportFinished', { timeout: 20000 });
3535

36-
cy.url().should('contain', Cypress.config('baseUrl') + `${routes.createReportComplete}?reportType=0`);
36+
cy.url().should('contain', Cypress.config('baseUrl') + `${routes.createReportComplete}?reportType=PATIENT`);
3737
},
3838
);
3939
});

app/cypress/e2e/1-ndr-smoke-tests/gp_user_workflows/download_lloyd_george_summary_report_workflow.cy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('GP Workflow: Download Lloyd George summary report', () => {
3333

3434
cy.url().should(
3535
'contain',
36-
Cypress.config('baseUrl') + `${routes.createReportComplete}?reportType=0`,
36+
Cypress.config('baseUrl') + `${routes.createReportComplete}?reportType=PATIENT`,
3737
);
3838

3939
cy.getByTestId('logout-btn').click();

app/cypress/support/e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Cypress.Commands.add('navigateToDownloadReportPage', () => {
122122
cy.getByTestId('download-report-btn').should('exist');
123123
cy.getByTestId('download-report-btn').click();
124124

125-
cy.url().should('contain', baseUrl + `${routes.createReport}?reportType=0`);
125+
cy.url().should('contain', baseUrl + `${routes.createReport}?reportType=PATIENT`);
126126
});
127127

128128
declare global {

app/src/components/blocks/_admin/reviewsPage/ReviewsPage.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,4 +732,18 @@ describe('ReviewsPage', () => {
732732
});
733733
});
734734
});
735+
736+
describe('Report Download Link', () => {
737+
it('renders download report link with correct href', async () => {
738+
renderComponent();
739+
740+
await waitFor(() => {
741+
expect(screen.getByText('900 000 0001')).toBeInTheDocument();
742+
});
743+
744+
const downloadLink = screen.getByText('Download a report on this data');
745+
expect(downloadLink).toBeInTheDocument();
746+
expect(downloadLink).toHaveAttribute('href', '/create-report?reportType=REVIEW');
747+
});
748+
});
735749
});

app/src/components/blocks/_admin/reviewsPage/ReviewsPage.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import BackButton from '../../../generic/backButton/BackButton';
1919
import { Pagination } from '../../../generic/paginationV2/Pagination';
2020
import SpinnerButton from '../../../generic/spinnerButton/SpinnerButton';
2121
import SpinnerV2 from '../../../generic/spinnerV2/SpinnerV2';
22+
import { REPORT_TYPE } from '../../../../types/generic/reports';
2223
import { AxiosError } from 'axios';
2324
import { errorToParams } from '../../../../helpers/utils/errorToParams';
2425

@@ -292,6 +293,13 @@ export const ReviewsPage = ({ setReviewData }: ReviewsPageProps): React.JSX.Elem
292293
</p>
293294

294295
<Table.Panel heading="Documents to review" className="reviews-page" allowFullScreen>
296+
<div className="nhsuk-u-text-align-right">
297+
<a
298+
href={`${routes.REPORT_DOWNLOAD}?reportType=${REPORT_TYPE.ODS_REVIEW_SUMMARY}`}
299+
>
300+
Download a report on this data
301+
</a>
302+
</div>
295303
{/* Search box */}
296304
<form
297305
id="search-form"

app/src/components/blocks/_documentUpload/documentSelectStage/DocumentSelectStage.test.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,29 @@ describe('DocumentSelectStage', () => {
146146
const expectedDob = getFormattedDate(new Date(patientDetails.birthDate));
147147
expect(screen.getByText(expectedDob)).toBeInTheDocument();
148148
});
149+
150+
it('should show remove files error message when skip is clicked after selecting a file', async () => {
151+
const config = {
152+
...docConfig,
153+
stitched: false,
154+
};
155+
renderApp(history, {
156+
showSkipLink: true,
157+
documentConfig: config,
158+
});
159+
160+
await userEvent.upload(screen.getByTestId('button-input'), [
161+
buildLgFile(1),
162+
]);
163+
164+
await userEvent.click(await screen.findByTestId('skip-link'));
165+
166+
await waitFor(() => {
167+
expect(screen.getByTestId('error-box')).toHaveTextContent(
168+
'Remove files before you skip to the next step',
169+
);
170+
});
171+
});
149172
});
150173

151174
describe('Navigation', () => {

app/src/components/blocks/_documentUpload/documentSelectStage/DocumentSelectStage.tsx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const DocumentSelectStage = ({
6565
const fileInputAreaRef = useRef<HTMLFieldSetElement>(null);
6666
const [lastErrorsLength, setLastErrorsLength] = useState(0);
6767
const [tooManyFilesAdded, setTooManyFilesAdded] = useState<boolean>(false);
68+
const [removeFilesToSkip, setRemoveFilesToSkip] = useState<boolean>(false);
6869
const journey = getJourney();
6970

7071
const navigate = useEnhancedNavigate();
@@ -109,6 +110,7 @@ const DocumentSelectStage = ({
109110
}
110111

111112
if (!multifile && fileArray.length > 1) {
113+
resetErrors();
112114
setTooManyFilesAdded(true);
113115
return;
114116
}
@@ -199,6 +201,10 @@ const DocumentSelectStage = ({
199201
let updatedDocList: UploadDocument[] = [...documents];
200202
updatedDocList.splice(index, 1);
201203

204+
if (updatedDocList.filter((doc) => doc.docType === documentType).length === 0) {
205+
setRemoveFilesToSkip(false);
206+
}
207+
202208
updateDocuments(updatedDocList);
203209
};
204210

@@ -210,8 +216,6 @@ const DocumentSelectStage = ({
210216
position: index + 1,
211217
}));
212218

213-
setNoFilesSelected(sortedDocs.length === 0);
214-
215219
setDocuments((previousState) => {
216220
const docs = previousState.filter((doc) => doc.docType !== documentType);
217221
return [...docs, ...sortedDocs];
@@ -248,6 +252,8 @@ const DocumentSelectStage = ({
248252
};
249253

250254
const continueClicked = (): void => {
255+
resetErrors();
256+
251257
if (!validateDocuments()) {
252258
scrollToRef.current?.scrollIntoView({ behavior: 'smooth' });
253259
return;
@@ -263,10 +269,19 @@ const DocumentSelectStage = ({
263269
return;
264270
}
265271

266-
skipClicked();
272+
skipClicked(false);
267273
};
268274

269-
const skipClicked = (): void => {
275+
const skipClicked = (checkDocCount: boolean = true): void => {
276+
if (checkDocCount && documents.some(doc => doc.docType === documentType)) {
277+
resetErrors();
278+
setRemoveFilesToSkip(true);
279+
setTimeout(() => {
280+
scrollToRef.current?.scrollIntoView({ behavior: 'smooth' });
281+
}, 0);
282+
return;
283+
}
284+
270285
if (goToNextDocType) {
271286
goToNextDocType();
272287
window.scrollTo(0, 0);
@@ -337,6 +352,11 @@ const DocumentSelectStage = ({
337352
linkId: 'upload-files',
338353
error: UPLOAD_FILE_ERROR_TYPE.tooManyFiles,
339354
});
355+
} else if (removeFilesToSkip) {
356+
errors.push({
357+
linkId: 'upload-files',
358+
error: UPLOAD_FILE_ERROR_TYPE.removeFilesToSkip,
359+
});
340360
} else {
341361
errorDocs().forEach((doc) => {
342362
errors.push({
@@ -352,6 +372,7 @@ const DocumentSelectStage = ({
352372
const resetErrors = (): void => {
353373
setNoFilesSelected(false);
354374
setTooManyFilesAdded(false);
375+
setRemoveFilesToSkip(false);
355376
};
356377

357378
const backClicked = (): void => {
@@ -371,7 +392,7 @@ const DocumentSelectStage = ({
371392
Go back
372393
</BackLink>
373394

374-
{(errorDocs().length > 0 || noFilesSelected || tooManyFilesAdded) && (
395+
{(errorDocs().length > 0 || noFilesSelected || tooManyFilesAdded || removeFilesToSkip) && (
375396
<ErrorBox
376397
dataTestId="error-box"
377398
errorBoxSummaryId="failed-document-uploads-summary-title"
@@ -541,7 +562,7 @@ const DocumentSelectStage = ({
541562
Continue
542563
</Button>
543564
{showSkiplink && (
544-
<LinkButton data-testid="skip-link" onClick={skipClicked}>
565+
<LinkButton data-testid="skip-link" onClick={() => skipClicked()}>
545566
{documentConfig.content.skipDocumentLinkText}
546567
</LinkButton>
547568
)}

app/src/components/blocks/_downloadReport/downloadReportSelectStage/DownloadReportSelectStage.test.tsx

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { beforeEach, describe, expect, it, vi, MockedFunction, Mock } from 'vite
1212
const mockDownloadReport = downloadReport as MockedFunction<typeof downloadReport>;
1313
const mockUseConfig = vi.fn();
1414

15-
1615
const mockedUseNavigate = vi.fn();
1716
vi.mock('react-router-dom', async () => {
1817
const actual = await vi.importActual('react-router-dom');
@@ -46,7 +45,7 @@ describe('DownloadReportSelectStage', () => {
4645
const report = getReportByType(REPORT_TYPE.ODS_PATIENT_SUMMARY);
4746
render(<DownloadReportSelectStage report={report!} />);
4847

49-
expect(screen.getByTestId('return-to-home-button')).toBeInTheDocument();
48+
expect(screen.getByTestId('go-back-button')).toBeInTheDocument();
5049
const title = screen.getByTestId('title');
5150
expect(title).toBeInTheDocument();
5251
expect(title.innerHTML).toContain(report!.title);
@@ -56,7 +55,7 @@ describe('DownloadReportSelectStage', () => {
5655
).toBeInTheDocument();
5756
});
5857
expect(screen.queryByTestId('error-notification-banner')).not.toBeInTheDocument();
59-
expect(screen.getByText('Go to home')).toBeInTheDocument();
58+
expect(screen.getByText('Go back')).toBeInTheDocument();
6059
});
6160

6261
it('should render error notification when download fails', async () => {
@@ -107,33 +106,16 @@ describe('DownloadReportSelectStage', () => {
107106
});
108107
});
109108

110-
it('should navigate to home when clicking go to home link', async () => {
109+
it('should navigate to back when clicking go back link', async () => {
111110
const report = getReportByType(REPORT_TYPE.ODS_PATIENT_SUMMARY);
112111
render(<DownloadReportSelectStage report={report!} />);
113-
114-
await userEvent.click(screen.getByText('Go to home'));
115-
await waitFor(() => {
116-
expect(mockedUseNavigate).toHaveBeenCalledWith(routes.HOME);
117-
});
118-
});
119-
120-
it ('should navigate to admin hub, upload version 3 enabled', async () => {
121-
mockUseConfig.mockReturnValue({
122-
featureFlags: { uploadDocumentIteration3Enabled: true },
123-
});
124-
125-
const report = getReportByType(REPORT_TYPE.ODS_PATIENT_SUMMARY);
126-
render(<DownloadReportSelectStage report={report!} />);
127-
128112
let backLink: Element;
129-
backLink = screen.getByTestId('return-to-home-button');
130-
113+
backLink = screen.getByTestId('go-back-button');
131114
expect(backLink).toHaveTextContent('Go back');
132115

133116
await userEvent.click(backLink);
134-
135117
await waitFor(() => {
136-
expect(mockedUseNavigate).toHaveBeenCalledWith(routes.ADMIN_ROUTE);
137-
})
118+
expect(mockedUseNavigate).toHaveBeenCalledWith(-1);
119+
});
138120
});
139121
});

0 commit comments

Comments
 (0)