From 2bc003e16eba996a58949f655b267175fbdfc572 Mon Sep 17 00:00:00 2001 From: NogaNHS <127490765+NogaNHS@users.noreply.github.com> Date: Thu, 19 Dec 2024 10:03:01 +0000 Subject: [PATCH 1/8] [PRMP-1360] - Update to nrl pointer request (#488) * [PRMP-1360] add missing fields in NRL request * [PRMP-1360] fix typo * [PRMP-1360] change to snomedcode --- lambdas/enums/snomed_codes.py | 19 +++++++++---- lambdas/models/nrl_fhir_document_reference.py | 27 ++++++++++++++----- lambdas/models/nrl_sqs_message.py | 12 ++++++--- lambdas/services/document_deletion_service.py | 8 +++--- lambdas/services/nrl_api_service.py | 13 +++++---- .../test_manage_nrl_pointer_handler.py | 26 +++++++++--------- .../test_document_deletion_service.py | 13 +++++---- .../unit/services/test_nrl_api_service.py | 23 ++++++++-------- 8 files changed, 88 insertions(+), 53 deletions(-) diff --git a/lambdas/enums/snomed_codes.py b/lambdas/enums/snomed_codes.py index 9b1f3f995..299441fa5 100644 --- a/lambdas/enums/snomed_codes.py +++ b/lambdas/enums/snomed_codes.py @@ -1,9 +1,18 @@ -from enum import StrEnum +from enum import Enum +from pydantic import BaseModel -class SnomedCodesType(StrEnum): - LLOYD_GEORGE = "16521000000101" +class SnomedCode(BaseModel): + code: str + display_name: str -class SnomedCodesCategory(StrEnum): - CARE_PLAN = "734163000" + +class SnomedCodes(Enum): + LLOYD_GEORGE = SnomedCode( + code="16521000000101", display_name="Lloyd George record folder" + ) + CARE_PLAN = SnomedCode(code="734163000", display_name="Care plan") + GENERAL_MEDICAL_PRACTICE = SnomedCode( + code="1060971000000108", display_name="General practice service" + ) diff --git a/lambdas/models/nrl_fhir_document_reference.py b/lambdas/models/nrl_fhir_document_reference.py index ed1f67901..196d03ecf 100644 --- a/lambdas/models/nrl_fhir_document_reference.py +++ b/lambdas/models/nrl_fhir_document_reference.py @@ -1,5 +1,6 @@ from typing import Optional +from enums.snomed_codes import SnomedCode, SnomedCodes from fhir.resources.R4B.documentreference import DocumentReference from models.nrl_sqs_message import NrlAttachment from pydantic import BaseModel, ConfigDict @@ -10,9 +11,11 @@ class FhirDocumentReference(BaseModel): model_config = ConfigDict(alias_generator=to_camel) nhs_number: str custodian: str - snomed_code_doc_type: str = "None" - snomed_code_category: str = "None" - snomed_code_category_display: str = "Care plan" + snomed_code_doc_type: SnomedCode = SnomedCodes.LLOYD_GEORGE.value + snomed_code_category: SnomedCode = SnomedCodes.CARE_PLAN.value + snomed_code_practice_setting: SnomedCode = ( + SnomedCodes.GENERAL_MEDICAL_PRACTICE.value + ) attachment: Optional[NrlAttachment] = NrlAttachment() def build_fhir_dict(self): @@ -36,7 +39,8 @@ def build_fhir_dict(self): "coding": [ { "system": snomed_url, - "code": self.snomed_code_doc_type, + "code": self.snomed_code_doc_type.code, + "display": self.snomed_code_doc_type.display_name, } ] }, @@ -45,8 +49,8 @@ def build_fhir_dict(self): "coding": [ { "system": snomed_url, - "code": self.snomed_code_category, - "display": self.snomed_code_category_display, + "code": self.snomed_code_category.code, + "display": self.snomed_code_category.display_name, } ] } @@ -71,5 +75,16 @@ def build_fhir_dict(self): }, } ], + "context": { + "practiceSetting": { + "coding": [ + { + "system": snomed_url, + "code": self.snomed_code_practice_setting.code, + "display": self.snomed_code_practice_setting.display_name, + } + ] + } + }, } return DocumentReference(**structure_json) diff --git a/lambdas/models/nrl_sqs_message.py b/lambdas/models/nrl_sqs_message.py index c6c82c22d..aa3b9dbdd 100644 --- a/lambdas/models/nrl_sqs_message.py +++ b/lambdas/models/nrl_sqs_message.py @@ -1,6 +1,6 @@ from typing import Optional -from enums.snomed_codes import SnomedCodesCategory, SnomedCodesType +from enums.snomed_codes import SnomedCode, SnomedCodes from pydantic import AliasGenerator, BaseModel, ConfigDict from pydantic.alias_generators import to_camel @@ -17,12 +17,16 @@ class NrlAttachment(BaseModel): class NrlSqsMessage(BaseModel): model_config = ConfigDict( - alias_generator=AliasGenerator(serialization_alias=to_camel) + alias_generator=AliasGenerator(serialization_alias=to_camel), + use_enum_values=True, ) nhs_number: str - snomed_code_doc_type: str = SnomedCodesType.LLOYD_GEORGE - snomed_code_category: str = SnomedCodesCategory.CARE_PLAN + snomed_code_doc_type: SnomedCode = SnomedCodes.LLOYD_GEORGE.value + snomed_code_category: SnomedCode = SnomedCodes.CARE_PLAN.value + snomed_code_practice_setting: SnomedCode = ( + SnomedCodes.GENERAL_MEDICAL_PRACTICE.value + ) description: str = "" attachment: Optional[NrlAttachment] = None action: str diff --git a/lambdas/services/document_deletion_service.py b/lambdas/services/document_deletion_service.py index 09ba07e2d..8f634d780 100644 --- a/lambdas/services/document_deletion_service.py +++ b/lambdas/services/document_deletion_service.py @@ -6,7 +6,7 @@ from enums.lambda_error import LambdaError from enums.nrl_sqs_upload import NrlActionTypes from enums.s3_lifecycle_tags import S3LifecycleTags -from enums.snomed_codes import SnomedCodesCategory, SnomedCodesType +from enums.snomed_codes import SnomedCodes from enums.supported_document_types import SupportedDocumentTypes from models.document_reference import DocumentReference from models.nrl_sqs_message import NrlSqsMessage @@ -91,13 +91,13 @@ def send_sqs_message_to_remove_pointer(self, nhs_number: str): delete_nrl_message = NrlSqsMessage( nhs_number=nhs_number, action=NrlActionTypes.DELETE, - snomed_code_doc_type=SnomedCodesType.LLOYD_GEORGE, - snomed_code_category=SnomedCodesCategory.CARE_PLAN, + snomed_code_doc_type=SnomedCodes.LLOYD_GEORGE.value, + snomed_code_category=SnomedCodes.CARE_PLAN.value, ) sqs_group_id = f"NRL_delete_{uuid.uuid4()}" nrl_queue_url = os.environ["NRL_SQS_QUEUE_URL"] self.sqs_service.send_message_fifo( queue_url=nrl_queue_url, - message_body=delete_nrl_message.model_dump_json(), + message_body=delete_nrl_message.model_dump_json(exclude_unset=True), group_id=sqs_group_id, ) diff --git a/lambdas/services/nrl_api_service.py b/lambdas/services/nrl_api_service.py index 9e33d01bd..52f3ed5bb 100644 --- a/lambdas/services/nrl_api_service.py +++ b/lambdas/services/nrl_api_service.py @@ -2,8 +2,9 @@ import uuid import requests -from requests import HTTPError +from enums.snomed_codes import SnomedCode from requests.adapters import HTTPAdapter +from requests.exceptions import ConnectionError, HTTPError, Timeout from urllib3 import Retry from utils.audit_logging_setup import LoggingService from utils.exceptions import NrlApiException @@ -46,7 +47,7 @@ def create_new_pointer(self, body, retry_on_expired: bool = True): ) response.raise_for_status() logger.info("Successfully created new pointer") - except HTTPError as e: + except (ConnectionError, Timeout, HTTPError) as e: logger.error(e.response.content) if e.response.status_code == 401 and retry_on_expired: self.headers["Authorization"] = ( @@ -56,14 +57,16 @@ def create_new_pointer(self, body, retry_on_expired: bool = True): else: raise NrlApiException("Error while creating new NRL Pointer") - def get_pointer(self, nhs_number, record_type=None, retry_on_expired: bool = True): + def get_pointer( + self, nhs_number, record_type: SnomedCode = None, retry_on_expired: bool = True + ): try: self.set_x_request_id() params = { "subject:identifier": f"https://fhir.nhs.uk/Id/nhs-number|{nhs_number}" } if record_type: - params["type"] = f"http://snomed.info/sct|{record_type}" + params["type"] = f"http://snomed.info/sct|{record_type.code}" response = self.session.get( url=self.endpoint, params=params, headers=self.headers ) @@ -79,7 +82,7 @@ def get_pointer(self, nhs_number, record_type=None, retry_on_expired: bool = Tru else: raise NrlApiException("Error while getting NRL Pointer") - def delete_pointer(self, nhs_number, record_type): + def delete_pointer(self, nhs_number, record_type: SnomedCode = None): search_results = self.get_pointer(nhs_number, record_type).get("entry", []) for entry in search_results: self.set_x_request_id() diff --git a/lambdas/tests/unit/handlers/test_manage_nrl_pointer_handler.py b/lambdas/tests/unit/handlers/test_manage_nrl_pointer_handler.py index c115a2202..b7a91c5c0 100644 --- a/lambdas/tests/unit/handlers/test_manage_nrl_pointer_handler.py +++ b/lambdas/tests/unit/handlers/test_manage_nrl_pointer_handler.py @@ -1,7 +1,7 @@ -import json - import pytest +from enums.snomed_codes import SnomedCodes from handlers.manage_nrl_pointer_handler import lambda_handler +from models.nrl_sqs_message import NrlAttachment, NrlSqsMessage from utils.exceptions import NrlApiException @@ -14,18 +14,18 @@ def mock_service(mocker): def build_test_sqs_message(action="create"): - SQS_Message = { - "nhs_number": "123456789", - "snomed_code_doc_type": "16521000000101", - "snomed_code_category": "734163000", - "action": action, - "attachment": { - "contentType": "application/pdf", - "url": "https://example.org/my-doc.pdf", - }, - } + doc_details = NrlAttachment( + url="https://example.org/my-doc.pdf", + ) + sqs_message = NrlSqsMessage( + nhs_number="123456789", + action=action, + snomed_code_doc_type=SnomedCodes.LLOYD_GEORGE.value, + snomed_code_category=SnomedCodes.CARE_PLAN.value, + attachment=doc_details, + ).model_dump_json() return { - "body": json.dumps(SQS_Message), + "body": sqs_message, "eventSource": "aws:sqs", } diff --git a/lambdas/tests/unit/services/test_document_deletion_service.py b/lambdas/tests/unit/services/test_document_deletion_service.py index e68c7e1a4..4a690c443 100644 --- a/lambdas/tests/unit/services/test_document_deletion_service.py +++ b/lambdas/tests/unit/services/test_document_deletion_service.py @@ -2,6 +2,7 @@ import pytest from enums.s3_lifecycle_tags import S3LifecycleTags +from enums.snomed_codes import SnomedCodes from enums.supported_document_types import SupportedDocumentTypes from services.document_deletion_service import DocumentDeletionService from tests.unit.conftest import ( @@ -227,12 +228,14 @@ def test_send_sqs_message_to_remove_pointer(mocker, mock_deletion_service): expected_message_body = ( '{{"nhs_number":"{}",' - '"snomed_code_doc_type":"16521000000101",' - '"snomed_code_category":"734163000",' - '"description":"",' - '"attachment":null,' + '"snomed_code_doc_type":{},' + '"snomed_code_category":{},' '"action":"delete"}}' - ).format(TEST_NHS_NUMBER) + ).format( + TEST_NHS_NUMBER, + SnomedCodes.LLOYD_GEORGE.value.model_dump_json(), + SnomedCodes.CARE_PLAN.value.model_dump_json(), + ) mock_deletion_service.send_sqs_message_to_remove_pointer(TEST_NHS_NUMBER) diff --git a/lambdas/tests/unit/services/test_nrl_api_service.py b/lambdas/tests/unit/services/test_nrl_api_service.py index 997a3d839..0c0241bd4 100644 --- a/lambdas/tests/unit/services/test_nrl_api_service.py +++ b/lambdas/tests/unit/services/test_nrl_api_service.py @@ -1,4 +1,5 @@ import pytest +from enums.snomed_codes import SnomedCodes from requests import Response from services.nrl_api_service import NrlApiService from tests.unit.conftest import FAKE_URL, TEST_NHS_NUMBER @@ -43,12 +44,12 @@ def test_get_end_user_ods_code(nrl_service): def test_get_pointer_with_record_type(mocker, nrl_service): - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value mocker.patch("uuid.uuid4", return_value="test_uuid") mock_params = { "subject:identifier": f"https://fhir.nhs.uk/Id/nhs-number|{TEST_NHS_NUMBER}", - "type": f"http://snomed.info/sct|{mock_type}", + "type": f"http://snomed.info/sct|{mock_type.code}", } mock_headers = { "Authorization": f"Bearer {ACCESS_TOKEN}", @@ -64,11 +65,11 @@ def test_get_pointer_with_record_type(mocker, nrl_service): def test_get_pointer_with_record_type_no_retry(mocker, nrl_service): - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value mocker.patch("uuid.uuid4", return_value="test_uuid") mock_params = { "subject:identifier": f"https://fhir.nhs.uk/Id/nhs-number|{TEST_NHS_NUMBER}", - "type": f"http://snomed.info/sct|{mock_type}", + "type": f"http://snomed.info/sct|{mock_type.code}", } mock_headers = { "Authorization": f"Bearer {ACCESS_TOKEN}", @@ -90,11 +91,11 @@ def test_get_pointer_with_record_type_no_retry(mocker, nrl_service): def test_get_pointer_with_record_type_with_retry(mocker, nrl_service): - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value mocker.patch("uuid.uuid4", return_value="test_uuid") mock_params = { "subject:identifier": f"https://fhir.nhs.uk/Id/nhs-number|{TEST_NHS_NUMBER}", - "type": f"http://snomed.info/sct|{mock_type}", + "type": f"http://snomed.info/sct|{mock_type.code}", } mock_headers = { "Authorization": f"Bearer {ACCESS_TOKEN}", @@ -120,7 +121,7 @@ def test_get_pointer_raise_error(nrl_service): response.status_code = 400 response._content = b"{}" - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value nrl_service.session.get.return_value = response pytest.raises(NrlApiException, nrl_service.get_pointer, TEST_NHS_NUMBER, mock_type) @@ -129,7 +130,7 @@ def test_get_pointer_raise_error(nrl_service): def test_delete_pointer_with_record_type_no_record(mocker, nrl_service): - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value mocker.patch("uuid.uuid4", return_value="test_uuid") nrl_response = { @@ -145,7 +146,7 @@ def test_delete_pointer_with_record_type_no_record(mocker, nrl_service): def test_delete_pointer_with_record_type_one_record(mocker, nrl_service): - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value mocker.patch("uuid.uuid4", return_value="test_uuid") mock_pointer_id = "ODSCODE-1111bfb1-1111-2222-3333-4444555c666f" mock_headers = { @@ -176,7 +177,7 @@ def test_delete_pointer_with_record_type_one_record(mocker, nrl_service): def test_delete_pointer_with_record_type_more_than_one_record(mocker, nrl_service): - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value mocker.patch("uuid.uuid4", return_value="test_uuid") mock_pointer_id = "ODSCODE-1111bfb1-1111-2222-3333-4444555c666" @@ -209,7 +210,7 @@ def test_delete_pointer_not_raise_error(mocker, nrl_service): response = Response() response.status_code = 400 response._content = b"{}" - mock_type = 11111111 + mock_type = SnomedCodes.LLOYD_GEORGE.value nrl_response = { "resourceType": "Bundle", "type": "searchset", From 735f57426f8141575fcb83ef41de9de77c2ac30f Mon Sep 17 00:00:00 2001 From: MohammadIqbalAD-NHS <127403145+MohammadIqbalAD-NHS@users.noreply.github.com> Date: Thu, 19 Dec 2024 17:00:33 +0000 Subject: [PATCH 2/8] [PRMP-1334] - Replace 'Crown copyright' with 'NHS England' in footer (#486) * [PRMP-1334] - Replace 'Crown copyright' to 'NHS England' in footer * [PRMP-1334] - Hardcode text colour in NHSFooter.Copyright --- app/src/components/layout/footer/Footer.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/components/layout/footer/Footer.tsx b/app/src/components/layout/footer/Footer.tsx index f1a0e46e4..f7a961127 100644 --- a/app/src/components/layout/footer/Footer.tsx +++ b/app/src/components/layout/footer/Footer.tsx @@ -16,7 +16,10 @@ function Footer() { Privacy notice - © {'Crown copyright'} + {/* TODO - PRMP-1348: Remove hardcoded styling below if no longer required */} + + © {'NHS England'} + ); } From 6b29964ca127d5f33ffb96c04bfcb9cf72e8adfa Mon Sep 17 00:00:00 2001 From: jack-nhs Date: Fri, 20 Dec 2024 09:35:18 +0000 Subject: [PATCH 3/8] Prmp 1182 - Remove number of files line from available records page (#485) * removes number of files and size of files from within record card * adds number of files downloading back * fixes tests * remove unnessecary import * remove unnessecary import * remove unnessecary import * remove unnessecary import --------- Co-authored-by: Jack Sutton Co-authored-by: steph-torres-nhs --- .../download_lloyd_george_workflow.cy.js | 6 ------ .../view_lloyd_george_is_bsol_workflow.cy.js | 3 +-- .../LloydGeorgeDownloadStage.test.tsx | 2 +- .../LloydGeorgeDownloadStage.tsx | 5 +---- .../LloydGeorgeRecordDetails.test.tsx | 8 ------- .../LloydGeorgeRecordDetails.tsx | 13 +----------- .../LloydGeorgeViewRecordStage.test.tsx | 6 ------ .../LloydGeorgeViewRecordStage.tsx | 16 ++------------ .../LloydGeorgeRecordPage.test.tsx | 21 ------------------- 9 files changed, 6 insertions(+), 74 deletions(-) diff --git a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js index 972cf3c4a..802440d69 100644 --- a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js @@ -171,9 +171,6 @@ describe('GP Workflow: View Lloyd George record', () => { // Assert contents of page when downloading cy.getByTestId('lloyd-george-download-header').should('exist'); cy.getByTestId('cancel-download-link').should('exist'); - cy.getByTestId('download-file-header-' + testFiles.length + '-files').should( - 'exist', - ); // Assert contents of page after download cy.wait('@documentManifestCompleted'); @@ -225,7 +222,6 @@ describe('GP Workflow: View Lloyd George record', () => { cy.title().should('eq', downloadingPageTitle); // Assert contents of page when downloading cy.getByTestId('lloyd-george-download-header').should('exist'); - cy.getByTestId('download-file-header-2-files').should('exist'); cy.getByTestId('cancel-download-link').should('exist'); @@ -289,8 +285,6 @@ describe('GP Workflow: View Lloyd George record', () => { cy.title().should('eq', downloadingPageTitle); // Assert contents of page when downloading cy.getByTestId('lloyd-george-download-header').should('exist'); - cy.getByTestId('download-file-header-1-files').should('exist'); - cy.getByTestId('cancel-download-link').should('exist'); // Assert contents of page after download diff --git a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/view_lloyd_george_is_bsol_workflow.cy.js b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/view_lloyd_george_is_bsol_workflow.cy.js index d60e248df..f9f13127f 100644 --- a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/view_lloyd_george_is_bsol_workflow.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/view_lloyd_george_is_bsol_workflow.cy.js @@ -95,8 +95,7 @@ describe('GP Workflow: View Lloyd George record', () => { assertPatientInfo(); cy.getByTestId('pdf-card') .should('include.text', 'Lloyd George record') - .should('include.text', 'Last updated: 09 October 2023 at 15:41:38') - .should('include.text', '12 files | File size: 502 KB | File format: PDF'); + .should('include.text', 'Last updated: 09 October 2023 at 15:41:38'); cy.getByTestId('pdf-viewer').should('be.visible'); // Act - open full screen view diff --git a/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.test.tsx b/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.test.tsx index 98869324b..92712f6d7 100644 --- a/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.test.tsx +++ b/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.test.tsx @@ -220,9 +220,9 @@ describe('LloydGeorgeDownloadStage', () => { const renderComponent = (history: MemoryHistory, propsOverride?: Partial) => { const props: Omit = { - numberOfFiles: mockPdf.numberOfFiles, deleteAfterDownload: false, ...propsOverride, + numberOfFiles: mockPdf.numberOfFiles, }; return render( diff --git a/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.tsx b/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.tsx index ae802cba1..d43a23340 100644 --- a/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.tsx +++ b/app/src/components/blocks/_lloydGeorge/lloydGeorgeDownloadStage/LloydGeorgeDownloadStage.tsx @@ -41,7 +41,7 @@ function LloydGeorgeDownloadStage({ filename: '', }); const linkRef = useRef(null); - + const pageDownloadCountId = 'download-file-header-' + numberOfFiles + '-files'; const mounted = useRef(false); const navigate = useNavigate(); const { mockLocal } = useConfig(); @@ -49,8 +49,6 @@ function LloydGeorgeDownloadStage({ const nhsNumber = patientDetails?.nhsNumber ?? ''; const [delayTimer, setDelayTimer] = useState(); - const pageDownloadCountId = 'download-file-header-' + numberOfFiles + '-files'; - const progressTimer = useMemo(() => { return new FakeProgress({ timeConstant: timeToComplete, @@ -145,7 +143,6 @@ function LloydGeorgeDownloadStage({ navigate, mockLocal, selectedDocuments, - numberOfFiles, ]); const pageHeader = 'Downloading documents'; diff --git a/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.test.tsx b/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.test.tsx index 8f095c460..d25188220 100644 --- a/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.test.tsx +++ b/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.test.tsx @@ -1,7 +1,6 @@ import { render, screen } from '@testing-library/react'; import LgRecordDetails, { Props } from './LloydGeorgeRecordDetails'; import { buildLgSearchResult } from '../../../../helpers/test/testBuilders'; -import formatFileSize from '../../../../helpers/utils/formatFileSize'; const mockPdf = buildLgSearchResult(); @@ -19,11 +18,6 @@ describe('LloydGeorgeRecordDetails', () => { renderComponent(); expect(screen.getByText(`Last updated: ${mockPdf.lastUpdated}`)).toBeInTheDocument(); - expect(screen.getByText(`${mockPdf.numberOfFiles} files`)).toBeInTheDocument(); - expect( - screen.getByText(`File size: ${formatFileSize(mockPdf.totalFileSizeInBytes)}`), - ).toBeInTheDocument(); - expect(screen.getByText('File format: PDF')).toBeInTheDocument(); }); }); }); @@ -31,8 +25,6 @@ describe('LloydGeorgeRecordDetails', () => { const renderComponent = (propsOverride?: Partial) => { const props: Props = { lastUpdated: mockPdf.lastUpdated, - numberOfFiles: mockPdf.numberOfFiles, - totalFileSizeInBytes: mockPdf.totalFileSizeInBytes, ...propsOverride, }; return render(); diff --git a/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.tsx b/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.tsx index 9105d05e0..3042f63d0 100644 --- a/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.tsx +++ b/app/src/components/blocks/_lloydGeorge/lloydGeorgeRecordDetails/LloydGeorgeRecordDetails.tsx @@ -1,27 +1,16 @@ import React from 'react'; -import formatFileSize from '../../../../helpers/utils/formatFileSize'; export type Props = { lastUpdated: string; - numberOfFiles: number; - totalFileSizeInBytes: number; }; -function LloydGeorgeRecordDetails({ lastUpdated, numberOfFiles, totalFileSizeInBytes }: Props) { +function LloydGeorgeRecordDetails({ lastUpdated }: Props) { return (
Last updated: {lastUpdated}
-
- {numberOfFiles} files - {' | '} - File size: {formatFileSize(totalFileSizeInBytes)} - {' | '} - File format: PDF - {' |'} -
); diff --git a/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.test.tsx b/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.test.tsx index 7b3edf11f..607f541db 100644 --- a/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.test.tsx +++ b/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.test.tsx @@ -9,7 +9,6 @@ import useRole from '../../../../helpers/hooks/useRole'; import useIsBSOL from '../../../../helpers/hooks/useIsBSOL'; import useConfig from '../../../../helpers/hooks/useConfig'; import { act, render, screen, waitFor } from '@testing-library/react'; -import formatFileSize from '../../../../helpers/utils/formatFileSize'; import { DOWNLOAD_STAGE } from '../../../../types/generic/downloadStage'; import { getFormattedDate } from '../../../../helpers/utils/formatDate'; import userEvent from '@testing-library/user-event'; @@ -62,11 +61,6 @@ describe('LloydGeorgeViewRecordStage', () => { expect(screen.getByText('View in full screen')).toBeInTheDocument(); expect(screen.getByText('Lloyd George record')).toBeInTheDocument(); expect(screen.getByText(`Last updated: ${mockPdf.lastUpdated}`)).toBeInTheDocument(); - expect(screen.getByText(`${mockPdf.numberOfFiles} files`)).toBeInTheDocument(); - expect( - screen.getByText(`File size: ${formatFileSize(mockPdf.totalFileSizeInBytes)}`), - ).toBeInTheDocument(); - expect(screen.getByText('File format: PDF')).toBeInTheDocument(); expect( screen.queryByText('No documents are available for this patient.'), diff --git a/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx b/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx index eec37f8ab..9d30b156d 100644 --- a/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx +++ b/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx @@ -97,8 +97,6 @@ function LloydGeorgeViewRecordStage({ const recordDetailsProps: RecordDetailsProps = { downloadStage, lastUpdated, - numberOfFiles, - totalFileSizeInBytes, }; const pageHeader = 'Available records'; @@ -258,17 +256,9 @@ function LloydGeorgeViewRecordStage({ ); } -type RecordDetailsProps = Pick< - Props, - 'downloadStage' | 'lastUpdated' | 'numberOfFiles' | 'totalFileSizeInBytes' ->; +type RecordDetailsProps = Pick; -const RecordDetails = ({ - downloadStage, - lastUpdated, - numberOfFiles, - totalFileSizeInBytes, -}: RecordDetailsProps) => { +const RecordDetails = ({ downloadStage, lastUpdated }: RecordDetailsProps) => { switch (downloadStage) { case DOWNLOAD_STAGE.INITIAL: case DOWNLOAD_STAGE.PENDING: @@ -277,8 +267,6 @@ const RecordDetails = ({ case DOWNLOAD_STAGE.SUCCEEDED: { const detailsProps = { lastUpdated, - numberOfFiles, - totalFileSizeInBytes, }; return ; } diff --git a/app/src/pages/lloydGeorgeRecordPage/LloydGeorgeRecordPage.test.tsx b/app/src/pages/lloydGeorgeRecordPage/LloydGeorgeRecordPage.test.tsx index 6fc97a136..0872260b1 100644 --- a/app/src/pages/lloydGeorgeRecordPage/LloydGeorgeRecordPage.test.tsx +++ b/app/src/pages/lloydGeorgeRecordPage/LloydGeorgeRecordPage.test.tsx @@ -7,7 +7,6 @@ import { } from '../../helpers/test/testBuilders'; import { getFormattedDate } from '../../helpers/utils/formatDate'; import axios from 'axios'; -import formatFileSize from '../../helpers/utils/formatFileSize'; import usePatient from '../../helpers/hooks/usePatient'; import useConfig from '../../helpers/hooks/useConfig'; import useRole from '../../helpers/hooks/useRole'; @@ -99,20 +98,6 @@ describe('LloydGeorgeRecordPage', () => { }); }); - it('calls refreshRecord and updates state when successful', async () => { - const lgResult = buildLgSearchResult(); - mockAxios.post.mockResolvedValue({ data: { jobStatus: 'Complete' } }); - mockAxios.get.mockResolvedValue({ data: lgResult }); - - renderPage(history); - - await waitFor(async () => { - expect(screen.getByText(`${lgResult.numberOfFiles} files`)).toBeInTheDocument(); - }); - - expect(screen.getByText('File format: PDF')).toBeInTheDocument(); - }); - it('renders initial lg record view with no docs available text if lambda return records status is uploading for more than 3 min', async () => { const errorResponse = { response: { @@ -199,12 +184,6 @@ describe('LloydGeorgeRecordPage', () => { expect(screen.getByText('Lloyd George record')).toBeInTheDocument(); expect(screen.queryByText('No documents are available')).not.toBeInTheDocument(); - - expect(screen.getByText(`${lgResult.numberOfFiles} files`)).toBeInTheDocument(); - expect( - screen.getByText(`File size: ${formatFileSize(lgResult.totalFileSizeInBytes)}`), - ).toBeInTheDocument(); - expect(screen.getByText('File format: PDF')).toBeInTheDocument(); }); describe('Accessibility', () => { From 3dd0d78f77ffa73c1f725a8cda83d8af6942730b Mon Sep 17 00:00:00 2001 From: mark-start-nhs Date: Fri, 20 Dec 2024 09:36:23 +0000 Subject: [PATCH 4/8] [PRMP-1239] NEW SERVICE updated to be New service (#495) * PRMP-1239 * for pr --- app/cypress/e2e/0-ndr-core-tests/homepage.cy.js | 2 +- app/src/components/layout/phaseBanner/PhaseBanner.test.tsx | 2 +- app/src/components/layout/phaseBanner/PhaseBanner.tsx | 2 +- app/src/styles/App.scss | 4 ++++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js b/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js index 3472e96df..ba635d03e 100644 --- a/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/homepage.cy.js @@ -34,7 +34,7 @@ describe('Home Page', () => { }); it('displays service banner', { tags: 'regression' }, () => { - cy.get('.govuk-phase-banner__content__tag').should('have.text', 'New Service'); + cy.get('.govuk-phase-banner__content__tag').should('have.text', 'New service'); cy.get('.govuk-phase-banner__text').should( 'have.text', 'Your feedback will help us to improve this service.', diff --git a/app/src/components/layout/phaseBanner/PhaseBanner.test.tsx b/app/src/components/layout/phaseBanner/PhaseBanner.test.tsx index 685fb953d..5be57d777 100644 --- a/app/src/components/layout/phaseBanner/PhaseBanner.test.tsx +++ b/app/src/components/layout/phaseBanner/PhaseBanner.test.tsx @@ -20,7 +20,7 @@ describe('PhaseBanner', () => { it('renders PhaseBanner with content', () => { renderComponent(); - expect(screen.getByText('New Service')).toBeInTheDocument(); + expect(screen.getByText('New service')).toBeInTheDocument(); expect(screen.getByText(/Your/i)).toBeInTheDocument(); expect(screen.getByText(/feedback/i)).toBeInTheDocument(); diff --git a/app/src/components/layout/phaseBanner/PhaseBanner.tsx b/app/src/components/layout/phaseBanner/PhaseBanner.tsx index 61b66c048..fd24c6b8a 100644 --- a/app/src/components/layout/phaseBanner/PhaseBanner.tsx +++ b/app/src/components/layout/phaseBanner/PhaseBanner.tsx @@ -24,7 +24,7 @@ function PhaseBanner() {
- New Service + New service

Your {linkToFeedbackPage} will help us to improve this service. diff --git a/app/src/styles/App.scss b/app/src/styles/App.scss index 096f72080..945b40c1d 100644 --- a/app/src/styles/App.scss +++ b/app/src/styles/App.scss @@ -793,6 +793,10 @@ $hunit: '%'; border: none; } +.govuk-phase-banner__content__tag { + text-transform: none; +} + .govuk-warning-text__icon { border: 3px solid $color_nhsuk-yellow; background: $color_nhsuk-yellow; From f87cbc5c1fdde359dbfe3447823457b6e826ecaa Mon Sep 17 00:00:00 2001 From: steph-torres-nhs Date: Fri, 20 Dec 2024 11:29:26 +0000 Subject: [PATCH 5/8] Update subscribe-to-mns.yml (#496) --- .github/workflows/subscribe-to-mns.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/subscribe-to-mns.yml b/.github/workflows/subscribe-to-mns.yml index c49f68eae..cd8e8a02a 100644 --- a/.github/workflows/subscribe-to-mns.yml +++ b/.github/workflows/subscribe-to-mns.yml @@ -12,15 +12,12 @@ on: sandbox: required: true type: string - secrets: - AWS_ASSUME_ROLE: - required: true permissions: pull-requests: write id-token: write # This is required for requesting the JWT contents: read # This is required for actions/checkout jobs: - batch_update_build_docker_image: + placeholder: runs-on: ubuntu-latest environment: ${{ inputs.environment }} defaults: @@ -28,6 +25,6 @@ jobs: working-directory: lambdas steps: - name: Placeholder - run: | - echo "Running placeholder job on ${inputs.sandbox}" + run: | + echo "Running placeholder job on ${inputs.sandbox}" From 9c5628721535a164b818672ed34030889af1cf16 Mon Sep 17 00:00:00 2001 From: mark-start-nhs Date: Thu, 2 Jan 2025 15:21:39 +0000 Subject: [PATCH 6/8] [PRMP-1237] Underline nav bar links in the nav bar --- app/src/styles/App.scss | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/src/styles/App.scss b/app/src/styles/App.scss index 945b40c1d..7b230425b 100644 --- a/app/src/styles/App.scss +++ b/app/src/styles/App.scss @@ -678,9 +678,16 @@ $hunit: '%'; } &_item { - a, - a:hover { + + a { color: $color_nhsuk-white; + text-decoration: underline; + text-decoration-color: $color_nhsuk-white; + text-underline-offset: 2px; + } + + a:hover { + text-decoration: none; } a:visited { @@ -690,7 +697,9 @@ $hunit: '%'; &--desktop { margin: 0 2rem; } + } + } // Generic From 037723fd43440d8babe3d5fa0c41d64334e64c9f Mon Sep 17 00:00:00 2001 From: mark-start-nhs Date: Thu, 2 Jan 2025 15:23:04 +0000 Subject: [PATCH 7/8] [PRMP-1321][PRMP-1041] Patient Details screen updates --- app/README.md | 2 +- .../lloyd_george_workflow.cy.js | 2 +- .../download_lloyd_george_workflow.cy.js | 2 +- .../patient_search_and_verify_workflow.cy.js | 4 +- .../LloydGeorgeViewRecordStage.tsx | 7 +++- .../generic/backButton/BackButton.story.ts | 13 ++++++ .../generic/backButton/BackButton.test.tsx | 26 ++++++++++++ .../generic/backButton/BackButton.tsx | 13 ++++-- .../PatientResultPage.test.tsx | 42 ++++++++----------- .../patientResultPage/PatientResultPage.tsx | 16 +++---- 10 files changed, 83 insertions(+), 44 deletions(-) diff --git a/app/README.md b/app/README.md index 8d9eb6d36..d3b5596d4 100644 --- a/app/README.md +++ b/app/README.md @@ -22,7 +22,7 @@ The National Document Repository user interface (UI) has been developed with Rea ### 1. Set Env Variables -Create a `.env` file by duplicating [.env.template](.env.template) and adding any missing values. This file is sourced to +In the app/ directory create a `.env` file by duplicating the [.env.template](.env.template) and adding any missing values. This file is sourced to your shell env so make sure it doesn't have any extra whitespace, comments etc. The `local` environment variable will allow your local app to bypass auth and mock most lambda requests. diff --git a/app/cypress/e2e/0-ndr-core-tests/feature_flag_workflows/lloyd_george_workflow.cy.js b/app/cypress/e2e/0-ndr-core-tests/feature_flag_workflows/lloyd_george_workflow.cy.js index 56b1a5be1..275130a64 100644 --- a/app/cypress/e2e/0-ndr-core-tests/feature_flag_workflows/lloyd_george_workflow.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/feature_flag_workflows/lloyd_george_workflow.cy.js @@ -28,7 +28,7 @@ describe('Feature flags - Lloyd George Workflow', () => { }); cy.title().should( 'eq', - 'Verify patient details - Access and store digital patient documents', + 'Patient details - Access and store digital patient documents', ); cy.get('#verify-submit').click(); diff --git a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js index 802440d69..8aa60367b 100644 --- a/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js +++ b/app/cypress/e2e/0-ndr-core-tests/gp_user_workflows/download_lloyd_george_workflow.cy.js @@ -11,7 +11,7 @@ const downloadPageTitle = const downloadingPageTitle = 'Downloading documents - Access and store digital patient documents'; const downloadCompletePageTitle = 'Download complete - Access and store digital patient documents'; const verifyPatientPageTitle = - 'Verify patient details - Access and store digital patient documents'; + 'Patient details - Access and store digital patient documents'; const lloydGeorgeRecordPageTitle = 'Available records - Access and store digital patient documents'; const testFiles = [ { 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 651588015..402d35791 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 @@ -65,7 +65,7 @@ describe('GP Workflow: Patient search and verify', () => { cy.wait('@search'); cy.title().should( 'eq', - 'Verify patient details - Access and store digital patient documents', + 'Patient details - Access and store digital patient documents', ); cy.url().should('include', 'verify'); @@ -73,7 +73,7 @@ describe('GP Workflow: Patient search and verify', () => { cy.get('#gp-message').should('be.visible'); cy.get('#gp-message').should( 'have.text', - 'Check these patient details match the records or attachments you plan to use', + 'This page displays the current data recorded in the Patient Demographic Service for this patient.', ); cy.get('#verify-submit').click(); diff --git a/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx b/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx index 9d30b156d..e65fc263d 100644 --- a/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx +++ b/app/src/components/blocks/_lloydGeorge/lloydGeorgeViewRecordStage/LloydGeorgeViewRecordStage.tsx @@ -26,7 +26,7 @@ import { import RecordCard from '../../../generic/recordCard/RecordCard'; import RecordMenuCard from '../../../generic/recordMenuCard/RecordMenuCard'; import useTitle from '../../../../helpers/hooks/useTitle'; -import { routeChildren } from '../../../../types/generic/routes'; +import { routes, routeChildren } from '../../../../types/generic/routes'; import { useNavigate } from 'react-router-dom'; import PatientSimpleSummary from '../../../generic/patientSimpleSummary/PatientSimpleSummary'; import ProgressBar from '../../../generic/progressBar/ProgressBar'; @@ -126,7 +126,10 @@ function LloydGeorgeViewRecordStage({ Exit full screen ) : ( - + )} {!fullScreen && userIsGpAdminNonBSOL && (

diff --git a/app/src/components/generic/backButton/BackButton.story.ts b/app/src/components/generic/backButton/BackButton.story.ts index 402090f1b..51a1efe04 100644 --- a/app/src/components/generic/backButton/BackButton.story.ts +++ b/app/src/components/generic/backButton/BackButton.story.ts @@ -18,4 +18,17 @@ export const BackButton: Story = { args: {}, }; +export const WithCustomText: Story = { + args: { + backLinkText: 'navigate to ...', + }, +}; + +export const WithCustomToLocationAndText: Story = { + args: { + toLocation: '/specified-location', + backLinkText: 'navigate to /specified-location', + }, +}; + export default meta; diff --git a/app/src/components/generic/backButton/BackButton.test.tsx b/app/src/components/generic/backButton/BackButton.test.tsx index 130a87a02..a320cf206 100644 --- a/app/src/components/generic/backButton/BackButton.test.tsx +++ b/app/src/components/generic/backButton/BackButton.test.tsx @@ -32,4 +32,30 @@ describe('BackButton', () => { expect(mockUseNavigate).toHaveBeenCalledWith(-1); }); }); + + it('navigates to specified location when the "toLocation" property is defined' , async () => { + + render(); + userEvent.click( screen.getByText('Go back')); + + await waitFor(() => { + expect(mockUseNavigate).toHaveBeenCalledWith('/specified-location'); + }); + + }); + + it('displays default back link text when "backLinkText" is not provided', async () => { + + render(); + expect(screen.getByText('Go back')).toBeInTheDocument(); + + }); + + it('displays custom back link text when "backLinkText" is defined', async () => { + + render(); + expect(screen.getByText('navigate to ...')).toBeInTheDocument(); + + }); + }); diff --git a/app/src/components/generic/backButton/BackButton.tsx b/app/src/components/generic/backButton/BackButton.tsx index 7b0e4d98a..e25b57a00 100644 --- a/app/src/components/generic/backButton/BackButton.tsx +++ b/app/src/components/generic/backButton/BackButton.tsx @@ -3,17 +3,24 @@ import React from 'react'; import type { MouseEvent } from 'react'; import { useNavigate } from 'react-router-dom'; -const BackButton = () => { +interface BackButtonProps { + toLocation?: string; + backLinkText?: string; +} + +const BackButton = ({ toLocation, backLinkText = 'Go back' }: BackButtonProps) => { const navigate = useNavigate(); const onBack = (e: MouseEvent) => { e.preventDefault(); - navigate(-1); + + if (toLocation) navigate(toLocation); + else navigate(-1); }; return ( - Go back + {backLinkText} ); }; diff --git a/app/src/pages/patientResultPage/PatientResultPage.test.tsx b/app/src/pages/patientResultPage/PatientResultPage.test.tsx index 34833c446..b92b1117a 100644 --- a/app/src/pages/patientResultPage/PatientResultPage.test.tsx +++ b/app/src/pages/patientResultPage/PatientResultPage.test.tsx @@ -19,6 +19,10 @@ jest.mock('../../helpers/hooks/usePatient'); const mockedUseRole = useRole as jest.Mock; const mockedUsePatient = usePatient as jest.Mock; +const PAGE_HEADER_TEXT = 'Patient details' +const PAGE_TEXT = "This page displays the current data recorded in the Patient Demographic Service for this patient." +const CONFIRM_BUTTON_TEXT = 'Confirm patient details and continue' + describe('PatientResultPage', () => { beforeEach(() => { process.env.REACT_APP_ENVIRONMENT = 'jest'; @@ -32,7 +36,7 @@ describe('PatientResultPage', () => { it('displays component', () => { render(); - expect(screen.getByText('Verify patient details')).toBeInTheDocument(); + expect(screen.getByText(PAGE_HEADER_TEXT)).toBeInTheDocument(); }); it.each(authorisedRoles)( @@ -47,23 +51,13 @@ describe('PatientResultPage', () => { render(); expect( - screen.getByRole('heading', { name: 'Verify patient details' }), + screen.getByRole('heading', { name: PAGE_HEADER_TEXT }), ).toBeInTheDocument(); expect(screen.getByText(familyName)).toBeInTheDocument(); expect( - screen.getByRole('button', { name: 'Accept details are correct' }), + screen.getByRole('button', { name: CONFIRM_BUTTON_TEXT }), ).toBeInTheDocument(); - expect(screen.getByText(/If patient details are incorrect/)).toBeInTheDocument(); - - const nationalServiceDeskLink = screen.getByRole('link', { - name: /National Service Desk/, - }); - expect(nationalServiceDeskLink).toHaveAttribute( - 'href', - 'https://digital.nhs.uk/about-nhs-digital/contact-us#nhs-digital-service-desks', - ); - expect(nationalServiceDeskLink).toHaveAttribute('target', '_blank'); }, ); @@ -79,11 +73,11 @@ describe('PatientResultPage', () => { render(); expect( - screen.getByRole('heading', { name: 'Verify patient details' }), + screen.getByRole('heading', { name: PAGE_HEADER_TEXT }), ).toBeInTheDocument(); expect( screen.getByText( - 'Check these patient details match the records or attachments you plan to use', + PAGE_TEXT , ), ).toBeInTheDocument(); }, @@ -100,7 +94,7 @@ describe('PatientResultPage', () => { render(); expect( - screen.getByRole('heading', { name: 'Verify patient details' }), + screen.getByRole('heading', { name: PAGE_HEADER_TEXT }), ).toBeInTheDocument(); expect(screen.queryByText('Select patient status')).not.toBeInTheDocument(); @@ -110,7 +104,7 @@ describe('PatientResultPage', () => { ).not.toBeInTheDocument(); expect( screen.queryByText( - 'Check these patient details match the records or attachments you plan to use', + PAGE_TEXT, ), ).not.toBeInTheDocument(); }); @@ -127,7 +121,7 @@ describe('PatientResultPage', () => { act(() => { userEvent.click( screen.getByRole('button', { - name: 'Accept details are correct', + name: CONFIRM_BUTTON_TEXT, }), ); }); @@ -148,7 +142,7 @@ describe('PatientResultPage', () => { render(); expect( - screen.getByRole('heading', { name: 'Verify patient details' }), + screen.getByRole('heading', { name: PAGE_HEADER_TEXT }), ).toBeInTheDocument(); expect( screen.getByText('The NHS number for this patient has changed.'), @@ -167,7 +161,7 @@ describe('PatientResultPage', () => { render(); expect( - screen.getByRole('heading', { name: 'Verify patient details' }), + screen.getByRole('heading', { name: PAGE_HEADER_TEXT }), ).toBeInTheDocument(); expect( screen.getByText( @@ -190,7 +184,7 @@ describe('PatientResultPage', () => { render(); expect( - screen.getByRole('heading', { name: 'Verify patient details' }), + screen.getByRole('heading', { name: PAGE_HEADER_TEXT }), ).toBeInTheDocument(); const results = await runAxeTest(document.body); @@ -237,7 +231,7 @@ describe('PatientResultPage', () => { act(() => { userEvent.click( screen.getByRole('button', { - name: 'Accept details are correct', + name: CONFIRM_BUTTON_TEXT, }), ); }); @@ -259,7 +253,7 @@ describe('PatientResultPage', () => { act(() => { userEvent.click( - screen.getByRole('button', { name: 'Accept details are correct' }), + screen.getByRole('button', { name: CONFIRM_BUTTON_TEXT }), ); }); @@ -275,7 +269,7 @@ describe('PatientResultPage', () => { render(); - userEvent.click(screen.getByRole('button', { name: 'Accept details are correct' })); + userEvent.click(screen.getByRole('button', { name: CONFIRM_BUTTON_TEXT })); await waitFor(() => { expect(mockedUseNavigate).toHaveBeenCalledWith(routes.ARF_OVERVIEW); diff --git a/app/src/pages/patientResultPage/PatientResultPage.tsx b/app/src/pages/patientResultPage/PatientResultPage.tsx index 9bf56689b..4ba8ce98e 100644 --- a/app/src/pages/patientResultPage/PatientResultPage.tsx +++ b/app/src/pages/patientResultPage/PatientResultPage.tsx @@ -8,7 +8,6 @@ import ErrorBox from '../../components/layout/errorBox/ErrorBox'; import { REPOSITORY_ROLE } from '../../types/generic/authRole'; import useRole from '../../helpers/hooks/useRole'; import usePatient from '../../helpers/hooks/usePatient'; -import ServiceDeskLink from '../../components/generic/serviceDeskLink/ServiceDeskLink'; import useTitle from '../../helpers/hooks/useTitle'; import PatientSummary from '../../components/generic/patientSummary/PatientSummary'; @@ -44,11 +43,11 @@ function PatientResultPage() { }; const showWarning = patientDetails?.superseded || patientDetails?.restricted; const isGp = userIsGPAdmin || userIsGPClinical; - const pageHeader = 'Verify patient details'; + const pageHeader = 'Patient details'; useTitle({ pageTitle: pageHeader }); return (
- + {inputError && (

- Check these patient details match the records or attachments you plan to - use + This page displays the current data recorded in the Patient Demographic + Service for this patient.

)} - -

- If patient details are incorrect, please contact the -

); } From 018cc07dc7117e41b06a9080d4236592d9a7b53e Mon Sep 17 00:00:00 2001 From: jack-nhs Date: Fri, 3 Jan 2025 10:06:44 +0000 Subject: [PATCH 8/8] PRMP-1332 - single element are being placed in groups/lists (#482) * [PRMP-1332] Updated download and remove options to not be list items on view document page * moves update and delete links from within a list * removes fieldset from search for patient screen * remove unnessecary import * [PRMP-1332] use css to create margin between link items --------- Co-authored-by: Ollie Beumkes Co-authored-by: Jack Sutton Co-authored-by: Steph Torres --- .../generic/recordMenuCard/RecordMenuCard.tsx | 10 ++-- .../patientSearchPage/PatientSearchPage.tsx | 49 +++++++++---------- app/src/styles/App.scss | 10 ++-- 3 files changed, 29 insertions(+), 40 deletions(-) diff --git a/app/src/components/generic/recordMenuCard/RecordMenuCard.tsx b/app/src/components/generic/recordMenuCard/RecordMenuCard.tsx index 1de5fdefb..06a4f5de0 100644 --- a/app/src/components/generic/recordMenuCard/RecordMenuCard.tsx +++ b/app/src/components/generic/recordMenuCard/RecordMenuCard.tsx @@ -61,13 +61,9 @@ const SideMenuSubSection = ({ actionLinks, heading, setStage }: SubSectionProps) return ( <>

{heading}

-
    - {actionLinks.map((link) => ( -
  1. - -
  2. - ))} -
+ {actionLinks.map((link) => ( + + ))} ); }; diff --git a/app/src/pages/patientSearchPage/PatientSearchPage.tsx b/app/src/pages/patientSearchPage/PatientSearchPage.tsx index 0f2b6f426..8fff917dd 100644 --- a/app/src/pages/patientSearchPage/PatientSearchPage.tsx +++ b/app/src/pages/patientSearchPage/PatientSearchPage.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { routes } from '../../types/generic/routes'; import { FieldValues, useForm } from 'react-hook-form'; import ErrorBox from '../../components/layout/errorBox/ErrorBox'; -import { Button, Fieldset, Input } from 'nhsuk-react-components'; +import { Button, Input } from 'nhsuk-react-components'; import SpinnerButton from '../../components/generic/spinnerButton/SpinnerButton'; import { InputRef } from '../../types/generic/inputRef'; import { useNavigate } from 'react-router-dom'; @@ -107,32 +107,29 @@ function PatientSearchPage() { )} )} +

{pageTitle}

-
- - {pageTitle} - - -
+ + {submissionState === SEARCH_STATES.SEARCHING ? (