diff --git a/pages/screening_subject_search/advance_episode_page.py b/pages/screening_subject_search/advance_episode_page.py index 506a6efa..2e57a5e3 100644 --- a/pages/screening_subject_search/advance_episode_page.py +++ b/pages/screening_subject_search/advance_episode_page.py @@ -538,3 +538,18 @@ def click_high_risk_findings_result_from_symptomatic_procedure_button( def click_other_post_investigation_contact_required_button(self) -> None: """Click the 'Other Post Investigation Contact Required' button.""" self.safe_accept_dialog(self.other_post_investigation_contact_required_button) + + def can_advance_episode(self, advance_option: str, can_or_cannot: bool) -> None: + """ + Asserted whether a subject's episode can be advanced using a specified option + Args: + advance_option (str): The advance episode option to check + can_or_cannot (bool): True if the option should be visible, False otherwise + Raises: + AssertionError: If the visibility of the option does not match the expected value + """ + advance_option_locator = self.page.get_by_role("button", name=advance_option) + if can_or_cannot: + assert advance_option_locator.is_visible() + else: + assert advance_option_locator.is_hidden() diff --git a/pages/screening_subject_search/reopen_lynch_surveillance_episode_page.py b/pages/screening_subject_search/reopen_lynch_surveillance_episode_page.py new file mode 100644 index 00000000..46423e80 --- /dev/null +++ b/pages/screening_subject_search/reopen_lynch_surveillance_episode_page.py @@ -0,0 +1,9 @@ +from playwright.sync_api import Page +from pages.screening_subject_search.reopen_episode_page import ReopenEpisodePage + + +class ReopenLynchSurveillanceEpisodePage(ReopenEpisodePage): + """Reopen Lynch Surveillance Episode Page locators, and methods for interacting with the page.""" + + def __init__(self, page: Page): + super().__init__(page) diff --git a/pages/screening_subject_search/subject_screening_summary_page.py b/pages/screening_subject_search/subject_screening_summary_page.py index 3982bf2a..ffcfd76e 100644 --- a/pages/screening_subject_search/subject_screening_summary_page.py +++ b/pages/screening_subject_search/subject_screening_summary_page.py @@ -118,6 +118,9 @@ def __init__(self, page: Page): self.reopen_surveillance_episode_button = self.page.get_by_role( "button", name="Reopen Surveillance Episode" ) + self.reopen_lynch_surveillance_episode_button = self.page.get_by_role( + "button", name="Reopen Lynch Surveillance Episode" + ) self.reopen_for_correction_button = self.page.get_by_role( "button", name="Reopen episode for correction" ) @@ -465,6 +468,10 @@ def click_reopen_surveillance_episode_button(self) -> None: """Click on the 'Reopen Surveillance Episode' button""" self.click(self.reopen_surveillance_episode_button) + def click_reopen_lynch_surveillance_episode_button(self) -> None: + """Click on the 'Reopen Lynch Surveillance Episode' button""" + self.click(self.reopen_lynch_surveillance_episode_button) + def reopen_fobt_screening_episode(self) -> None: """ Reopen a previously closed FOBT screening episode, including confirmation modal. diff --git a/tests/regression/regression_tests/lynch_regression_tests/test_lynch_scenario_16.py b/tests/regression/regression_tests/lynch_regression_tests/test_lynch_scenario_16.py new file mode 100644 index 00000000..4e1511f2 --- /dev/null +++ b/tests/regression/regression_tests/lynch_regression_tests/test_lynch_scenario_16.py @@ -0,0 +1,881 @@ +import logging +import pytest +from datetime import datetime, timedelta +from playwright.sync_api import Page +from classes.repositories.episode_repository import EpisodeRepository +from classes.repositories.general_repository import GeneralRepository +from pages.base_page import BasePage +from pages.datasets.colonoscopy_dataset_page import ( + ColonoscopyDatasetsPage, + FitForColonoscopySspOptions, +) +from pages.datasets.investigation_dataset_page import ( + BowelPreparationQualityOptions, + ComfortOptions, + DrugTypeOptions, + EndoscopyLocationOptions, + FailureReasonsOptions, + InsufflationOptions, + InvestigationDatasetsPage, + LateOutcomeOptions, + OutcomeAtTimeOfProcedureOptions, + YesNoOptions, +) +from pages.datasets.subject_datasets_page import SubjectDatasetsPage +from pages.logout.log_out_page import LogoutPage +from pages.screening_practitioner_appointments.appointment_detail_page import ( + AppointmentDetailPage, +) +from pages.screening_subject_search.advance_lynch_surveillance_episode_page import ( + AdvanceLynchSurveillanceEpisodePage, +) +from pages.screening_subject_search.attend_diagnostic_test_page import ( + AttendDiagnosticTestPage, +) +from pages.screening_subject_search.contact_with_patient_page import ( + ContactWithPatientPage, +) +from pages.screening_subject_search.diagnostic_test_outcome_page import ( + DiagnosticTestOutcomePage, + OutcomeOfDiagnosticTest, + ReasonForSymptomaticReferral, +) +from pages.screening_subject_search.episode_events_and_notes_page import ( + EpisodeEventsAndNotesPage, +) +from pages.screening_subject_search.lnpcp_result_from_symptomatic_procedure_page import ( + LnpcpResultFromSymptomaticProcedure, +) +from pages.screening_subject_search.subject_screening_summary_page import ( + SubjectScreeningSummaryPage, +) +from pages.screening_subject_search.reopen_lynch_surveillance_episode_page import ( + ReopenLynchSurveillanceEpisodePage, +) +from pages.screening_subject_search.return_from_symptomatic_referral_page import ( + ReturnFromSymptomaticReferralPage, +) +from utils import screening_subject_page_searcher +from utils.appointments import book_appointments, book_post_investigation_appointment +from utils.batch_processing import batch_processing +from utils.calendar_picker import CalendarPicker +from utils.investigation_dataset import InvestigationDatasetCompletion +from utils.lynch_utils import LynchUtils +from utils.oracle.oracle import OracleDB +from utils.sspi_change_steps import SSPIChangeSteps +from utils.subject_assertion import subject_assertion +from utils.user_tools import UserTools + + +@pytest.mark.usefixtures("setup_org_and_appointments") +@pytest.mark.vpn_required +@pytest.mark.regression +@pytest.mark.lynch_regression_tests +def test_lynch_scenario_16(page: Page) -> None: + """ + Scenario: 16 - LNPCP result from symptomatic procedure, then refer another diagnostic test + + G1-G2-G3-A183-A25-J10-A99-A59-A259-A315-A361-A323-A317-A353-A372-A373-A377-A157-Lynch in age [SSCL52c] A372-A373-A389-A360-A410-A415-A416-A316-A319-A395 + + In this scenario, the subject is referred for a symptomatic procedure following a diagnostic test which gives no result. The result of the symptomatic procedure is LNPCP. + + BCSS-17906 NOTE: The pathway for referring for another diagnostic test following symptomatic procedure is currently incomplete, so stopping at A360 + + Scenario summary: + + > Process Lynch diagnosis for a new in-age subject suitable for immediate invitation + > Run Lynch invitations > G1 (5.1) + > Process G1 letter batch > G2 (5.1) + > Run timed events > G3 (5.1) + > Book appointment > A183 (1.11) + > Process A183 letter batch > A25 (1.11) + > Attend appointment > J10 (1.12) + > Suitable for Endoscopic Test > A99 (2.1) + > Invite for Diagnostic Test > A59 (2.1) + > Attend test > A259 (2.1) + > Diagnostic Test Outcome Entered (Refer to Symptomatic) > A315 (2.1) + > Other Post-investigation Contact Required > A361 (2.1) + > Post-investigation Appointment Not Required > A317 (2.1) + > MDT Referral Not Required > A353 (2.6) + > Process A353 letter batch > A372 (2.7) + > LNPCP Result from Symptomatic Procedure > A373 (2.7) + > Refer Lynch > A377 (2.7) + > Process A377 letter batch > A157 (2.1) + > Check recall [SSCL52c] + > Post-investigation appointment required > A360 (2.1) + > Book post-investigation appointment > A410 (2.4) + > Process A410 letter batch > A415 (2.4) + > Attend post-investigation appointment > A416 > A316 > A319 (2.4) + > Process A319 letter batch > A395 (2.4) + """ + # Given I log in to BCSS "England" as user role "Hub Manager" + user_role = UserTools.user_login( + page, "Hub Manager State Registered at BCS01", return_role_type=True + ) + if user_role is None: + raise ValueError("User cannot be assigned to a UserRoleType") + + # When I receive Lynch diagnosis "EPCAM" for a new subject in my hub aged "25" with diagnosis date "1 year ago" and no last colonoscopy date + nhs_no = LynchUtils(page).insert_validated_lynch_patient_from_new_subject_with_age( + age="25", + gene="EPCAM", + when_diagnosis_took_place="1 year ago", + when_last_colonoscopy_took_place="unknown", + user_role=user_role, + ) + + # Then Comment: NHS number + assert nhs_no is not None + logging.info(f"[SUBJECT CREATION] Created Lynch subject with NHS number: {nhs_no}") + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "Calculated FOBT due date": "Null", + "Calculated lynch due date": "Null", + "Calculated surveillance due date": "Null", + "Lynch due date": "Null", + "Lynch due date date of change": "Null", + "Lynch due date reason": "Null", + "Previous screening status": "Null", + "Screening due date": "Null", + "Screening due date date of change": "Null", + "Screening due date reason": "Null", + "Subject has lynch diagnosis": "Yes", + "Subject lower FOBT age": "Default", + "Subject lower lynch age": "25", + "Screening status": "Lynch Surveillance", + "Screening status date of change": "Today", + "Screening status reason": "Eligible for Lynch Surveillance", + "Subject age": "25", + "Surveillance due date": "Null", + "Surveillance due date date of change": "Null", + "Surveillance due date reason": "Null", + }, + user_role, + ) + + # When I set the Lynch invitation rate for all screening centres to 50 + LynchUtils(page).set_lynch_invitation_rate(rate=50) + + # And I run the Lynch invitations process + GeneralRepository().run_lynch_invitations() + + # And my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "Calculated FOBT due date": "Null", + "Calculated lynch due date": "Unchanged", + "Calculated surveillance due date": "Null", + "Lynch due date": "25th birthday", + "Lynch due date date of change": "Today", + "Lynch due date reason": "Selected for Lynch Surveillance", + "Previous screening status": "Null", + "Screening due date": "Null", + "Screening due date date of change": "Null", + "Screening due date reason": "Null", + "Subject has an open episode": "Yes", + "Subject has lynch diagnosis": "Yes", + "Subject lower FOBT age": "Default", + "Subject lower lynch age": "25", + "Screening status": "Lynch Surveillance", + "Screening status date of change": "Today", + "Screening status reason": "Eligible for Lynch Surveillance", + "Subject age": "25", + "Surveillance due date": "Null", + "Surveillance due date date of change": "Null", + "Surveillance due date reason": "Null", + }, + ) + + # And there is a "G1" letter batch for my subject with the exact title "Lynch Surveillance Pre-invitation" + # When I process the open "G1" letter batch for my subject + batch_processing(page, "G1", "Lynch Surveillance Pre-invitation") + + # Then my subject has been updated as follows: + subject_assertion(nhs_no, {"latest event status": "G2 Lynch Pre-invitation Sent"}) + + # When I run Timed Events for my subject + OracleDB().exec_bcss_timed_events(nhs_number=nhs_no) + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "G3 Lynch Surveillance Colonoscopy Assessment Appointment Required" + }, + ) + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I receive an SSPI update to change their date of birth to "65" years old + SSPIChangeSteps().sspi_update_to_change_dob_received(nhs_no, 65) + + logging.info("Progress the episode through to closure") + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I view the practitioner appointment booking screen + SubjectScreeningSummaryPage(page).click_book_practitioner_clinic_button() + + # And I select "BCS001" as the screening centre where the practitioner appointment will be held + # And I set the practitioner appointment date to "today" + # And I book the "earliest" available practitioner appointment on this date + book_appointments( + page, + "BCS001 - Wolverhampton Bowel Cancer Screening Centre", + "The Royal Hospital (Wolverhampton)", + ) + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A183 1st Colonoscopy Assessment Appointment Requested", + }, + ) + + # And there is a "A183" letter batch for my subject with the exact title "Practitioner Clinic 1st Appointment (Lynch)" + # When I process the open "A183" letter batch for my subject + batch_processing(page, "A183", "Practitioner Clinic 1st Appointment (Lynch)") + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A25 1st Colonoscopy Assessment Appointment Booked, letter sent", + }, + ) + + # When I switch users to BCSS "England" as user role "Screening Centre Manager" + LogoutPage(page).log_out(close_page=False) + BasePage(page).go_to_log_in_page() + user_role = UserTools.user_login(page, "Screening Centre Manager at BCS001", True) + if user_role is None: + raise ValueError("User cannot be assigned to a UserRoleType") + + # And I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I view the event history for the subject's latest episode + SubjectScreeningSummaryPage(page).expand_episodes_list() + SubjectScreeningSummaryPage(page).click_first_lynch_surveillance_episode_link() + + # And I view the latest practitioner appointment in the subject's episode + EpisodeEventsAndNotesPage(page).click_most_recent_view_appointment_link() + + # And I attend the subject's practitioner appointment "yesterday" + AppointmentDetailPage(page).mark_appointment_as_attended( + datetime.today() - timedelta(days=1) + ) + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "J10 Attended Colonoscopy Assessment Appointment", + }, + ) + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I edit the Colonoscopy Assessment Dataset for this subject + SubjectScreeningSummaryPage(page).click_datasets_link() + SubjectDatasetsPage(page).click_colonoscopy_show_datasets() + + # And I update the Colonoscopy Assessment Dataset with the following values: + ColonoscopyDatasetsPage(page).select_fit_for_colonoscopy_option( + FitForColonoscopySspOptions.YES + ) + ColonoscopyDatasetsPage(page).click_dataset_complete_radio_button_yes() + + # And I save the Colonoscopy Assessment Dataset + ColonoscopyDatasetsPage(page).save_dataset() + + # And I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I advance the subject's episode for "Suitable for Endoscopic Test" + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_suitable_for_endoscopic_test_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A99 Suitable for Endoscopic Test", + }, + ) + + logging.info("Invite them for diagnostic test and attend the test") + + # When I view the advance episode options + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + + # And I select Diagnostic Test Type "Colonoscopy" + AdvanceLynchSurveillanceEpisodePage(page).select_test_type_dropdown_option( + "Colonoscopy" + ) + + # And I enter a Diagnostic Test First Offered Appointment Date of "today" + AdvanceLynchSurveillanceEpisodePage(page).click_calendar_button() + CalendarPicker(page).v1_calender_picker(datetime.today()) + + # And I advance the subject's episode for "Invite for Diagnostic Test >>" + AdvanceLynchSurveillanceEpisodePage(page).click_invite_for_diagnostic_test_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "which diagnostic test": "Latest test in latest episode", + "diagnostic test proposed type": "Colonoscopy", + "diagnostic test confirmed type": "Null", + "diagnostic test intended extent": "Null", + "latest event status": "A59 Invited for Diagnostic Test", + }, + ) + + # When I select the advance episode option for "Attend Diagnostic Test" + AdvanceLynchSurveillanceEpisodePage(page).click_attend_diagnostic_test_button() + + # Then I confirm the value of the diagnostic test attendance field "Proposed Type of Test" is "Colonoscopy" + AttendDiagnosticTestPage(page).confirm_proposed_type_of_test( + "Proposed Type of Test", "Colonoscopy" + ) + + # And I confirm the value of the diagnostic test attendance field "Actual Type of Test" is "Colonoscopy" + AttendDiagnosticTestPage(page).confirm_proposed_type_of_test( + "Actual Type of Test", "Colonoscopy" + ) + + # When I attend the subject's diagnostic test + AttendDiagnosticTestPage(page).click_calendar_button() + CalendarPicker(page).v1_calender_picker(datetime.today()) + AttendDiagnosticTestPage(page).click_save_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "which diagnostic test": "Latest test in latest episode", + "diagnostic test proposed type": "Colonoscopy", + "diagnostic test confirmed type": "Colonoscopy", + "diagnostic test intended extent": "Null", + "latest event status": "A259 Attended Diagnostic Test", + }, + ) + + logging.info("Complete the investigation dataset to give a result of No Result") + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I edit the Investigation Dataset for this subject + SubjectScreeningSummaryPage(page).click_datasets_link() + SubjectDatasetsPage(page).click_investigation_show_datasets() + + # Confirm on the investigation Datasets Page + InvestigationDatasetsPage(page).bowel_cancer_screening_page_title_contains_text( + "Investigation Datasets" + ) + + # Then message "WARNING - Resect & Discard is not appropriate for a Lynch patient." is displayed at the top of the investigation dataset + InvestigationDatasetsPage(page).message_is_displayed( + "WARNING - Resect & Discard is not appropriate for a Lynch patient." + ) + + # And I open all minimized sections on the dataset + InvestigationDatasetsPage(page).open_all_minimized_sections() + + # When I set the following fields and values within the "Investigation Dataset" section of the investigation dataset: + InvestigationDatasetCompletion(page).fill_out_general_information( + { + "practitioner": 1, + "site": 1, + "testing clinician": 1, + "aspirant endoscopist": None, + } + ) + + # And I add the following "Bowel Preparation Administered" drugs and doses within the Investigation Dataset for this subject: + InvestigationDatasetCompletion(page).fill_out_drug_information( + { + "drug_dose1": "3", + "drug_type1": DrugTypeOptions.MANNITOL, + } + ) + + # And I set the following fields and values within the "Endoscopy Information" section of the investigation dataset: + InvestigationDatasetCompletion(page).fill_endoscopy_information( + { + "endoscope inserted": "yes", + "procedure type": "diagnostic", + "bowel preparation quality": BowelPreparationQualityOptions.GOOD, + "comfort during recovery": ComfortOptions.NO_DISCOMFORT, + "comfort during examination": ComfortOptions.NO_DISCOMFORT, + "endoscopist defined extent": EndoscopyLocationOptions.DESCENDING_COLON, + "scope imager used": YesNoOptions.YES, + "retroverted view": YesNoOptions.NO, + "start of intubation time": "09:00", + "start of extubation time": "09:30", + "end time of procedure": "10:00", + "scope id": "Autotest", + "insufflation": InsufflationOptions.AIR, + "outcome at time of procedure": OutcomeAtTimeOfProcedureOptions.LEAVE_DEPARTMENT, + "late outcome": LateOutcomeOptions.NO_COMPLICATIONS, + } + ) + + InvestigationDatasetCompletion(page).fill_out_failure_information( + {"failure reasons": FailureReasonsOptions.PAIN} + ) + + # And I mark the Investigation Dataset as completed + InvestigationDatasetsPage(page).check_dataset_complete_checkbox() + + # Then the Investigation Dataset result message, which I will cancel, is "No Result" + InvestigationDatasetsPage(page).click_save_dataset_button_assert_dialog("No Result") + + # And I press the save Investigation Dataset button + InvestigationDatasetsPage(page).click_save_dataset_button() + + # Then I confirm the Episode Result is "No result" + EpisodeRepository().confirm_episode_result(nhs_no, "No Result") + + logging.info( + "Progress the episode via post-investigation appointment and referral to symptomatic to closure on A157 LNPCP" + ) + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I select the advance episode option for "Enter Diagnostic Test Outcome" + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_enter_diagnostic_test_outcome_button() + + # Then I confirm the Outcome Of Diagnostic Test dropdown has the following options: + DiagnosticTestOutcomePage(page).test_outcome_dropdown_contains_options( + [ + "Failed Test - Refer Another", + "Refer Symptomatic", + ], + ) + + # When I select Outcome of Diagnostic Test "Refer Symptomatic" + DiagnosticTestOutcomePage(page).select_test_outcome_option( + OutcomeOfDiagnosticTest.REFER_SYMPTOMATIC + ) + + # Then the text "Diagnostic Test Date resulting in a recall due date" is not visible + DiagnosticTestOutcomePage(page).text_is_visible( + "Diagnostic Test Date resulting in a recall due date", False + ) + + # When I select Reason for Symptomatic Referral value "Suspected Cancer Surgery" + DiagnosticTestOutcomePage(page).select_reason_for_symptomatic_referral_option( + ReasonForSymptomaticReferral.SUSPECTED_CANCER_SURGERY + ) + + # And I save the Diagnostic Test Outcome + DiagnosticTestOutcomePage(page).click_save_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A315 Diagnostic Test Outcome Entered", + }, + ) + + # When I advance the subject's episode for "Other Post-investigation Contact Required" + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_other_post_investigation_contact_required_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A361 Other Post-investigation Contact Required", + }, + ) + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I select the advance episode option for "Record other post-investigation contact" + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_record_other_post_investigation_contact_button() + + # Then I confirm the patient outcome dropdown has the following options: + ContactWithPatientPage(page).patient_outcome_dropdown_contains_options( + [ + "Post-investigation Appointment Not Required", + "Post-investigation Appointment Required", + "No outcome", + ] + ) + + # When I record contact with the subject with outcome "Post-investigation Appointment Not Required" + ContactWithPatientPage(page).record_post_investigation_appointment_not_required() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest episode includes event status": "A323 Post-investigation Appointment NOT Required", + "latest event status": "A317 Post-investigation Contact Made", + }, + ) + + # When I view the advance episode options + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + + # And I advance the subject's episode for "MDT Referral Not Required" + AdvanceLynchSurveillanceEpisodePage(page).click_mdt_referral_not_required_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A353 MDT Referral Not Required", + }, + ) + + # And there is a "A353" letter batch for my subject with the exact title "GP Letter Indicating Referral to Symptomatic (Lynch)" + # When I process the open "A353" letter batch for my subject + batch_processing( + page, "A353", "GP Letter Indicating Referral to Symptomatic (Lynch)" + ) + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A372 Refer Symptomatic, GP Letter Printed", + }, + ) + + # When I view the advance episode options + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + + # Then I "can" advance the subject's episode for "LNPCP Result from Symptomatic Procedure" + AdvanceLynchSurveillanceEpisodePage(page).can_advance_episode( + "LNPCP Result from Symptomatic Procedure", True + ) + + # When I select the advance episode option for "LNPCP Result from Symptomatic Procedure" + AdvanceLynchSurveillanceEpisodePage( + page + ).click_lnpcp_result_from_symptomatic_procedure_button() + + # And I set the Date of Symptomatic Procedure to "2 days ago" + LnpcpResultFromSymptomaticProcedure(page).enter_date_of_symptomatic_procedure( + datetime.today() - timedelta(days=2) + ) + + # And the Screening Interval is 24 months + LnpcpResultFromSymptomaticProcedure(page).assert_text_in_alert_textbox( + "recall interval of 24 months" + ) + + # And I select test number 1 + LnpcpResultFromSymptomaticProcedure(page).select_test_number(1) + + # And I save the Result from Symptomatic Procedure + LnpcpResultFromSymptomaticProcedure(page).click_save_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "which diagnostic test": "Latest not-void test in latest episode", + "latest episode accumulated result": "LNPCP", + "latest event status": "A373 Symptomatic result recorded", + "symptomatic procedure date": "2 days ago", + "symptomatic procedure result": "LNPCP", + }, + ) + + # When I advance the subject's episode for "Return to Lynch after symptomatic referral" + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_return_to_lynch_after_symptomatic_referral_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A377 Return to Lynch after symptomatic referral", + }, + ) + + logging.info("Check the subject's data after episode closure") + + # And there is a "A377" letter batch for my subject with the exact title "Return to Lynch after symptomatic referral" + # When I process the open "A377" letter batch for my subject + batch_processing(page, "A377", "Return to Lynch after symptomatic referral") + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "which diagnostic test": "Latest not-void test in latest episode", + "calculated fobt due date": "Null", + "calculated lynch due date": "2 years from Symptomatic Procedure", + "calculated surveillance due date": "Null", + "ceased confirmation date": "Null", + "ceased confirmation details": "Null", + "ceased confirmation user id": "Null", + "clinical reason for cease": "Null", + "latest episode accumulated result": "LNPCP", + "latest episode recall calculation method": "Symptomatic Procedure Date", + "latest episode recall episode type": "Lynch Surveillance", + "latest episode recall surveillance type": "Null", + "latest episode status": "Closed", + "latest episode status reason": "Episode Complete", + "latest event status": "A157 LNPCP", + "lynch due date": "Calculated Lynch due date", + "lynch due date reason": "Lynch Surveillance", + "lynch due date date of change": "Today", + "screening due date": "Null", + "screening due date date of change": "Unchanged", + "screening due date reason": "Unchanged", + "screening referral type": "Null", + "screening status": "Lynch Surveillance", + "screening status date of change": "Unchanged", + "screening status reason": "Lynch Surveillance", + "surveillance due date": "Null", + "surveillance due date reason": "Unchanged", + "surveillance due date date of change": "Unchanged", + "symptomatic procedure date": "2 days ago", + "symptomatic procedure result": "LNPCP", + }, + ) + + logging.info( + "Now reopen the episode to re-record the symptomatic result, and this time refer for another diagnostic test" + ) + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I reopen the subject's episode for "Reopen to Re-record Outcome from Symptomatic Referral" + SubjectScreeningSummaryPage(page).click_reopen_lynch_surveillance_episode_button() + ReopenLynchSurveillanceEpisodePage( + page + ).click_reopen_to_rerecord_outcome_from_symptomatic_referral_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "which diagnostic test": "Latest not-void test in latest episode", + "calculated fobt due date": "Null", + "calculated lynch due date": "As at episode start", + "calculated surveillance due date": "Null", + "ceased confirmation date": "Null", + "ceased confirmation details": "Null", + "ceased confirmation user id": "Null", + "clinical reason for cease": "Null", + "latest episode accumulated result": "No Result", + "latest episode includes event code": "E372 Reopen to Re-record Outcome from Symptomatic Referral", + "latest episode recall calculation method": "Symptomatic Procedure Date", + "latest episode recall episode type": "Null", + "latest episode recall surveillance type": "Null", + "latest episode status": "Open", + "latest episode status reason": "Null", + "latest event status": "A372 Refer Symptomatic, GP Letter Printed", + "screening due date": "Null", + "screening due date date of change": "Unchanged", + "screening due date reason": "Unchanged", + "screening status": "Lynch Surveillance", + "screening status date of change": "Unchanged", + "screening status reason": "Lynch Surveillance", + "surveillance due date": "Null", + "surveillance due date reason": "Unchanged", + "surveillance due date date of change": "Unchanged", + "symptomatic procedure date": "Null", + "symptomatic procedure result": "Null", + "screening referral type": "Null", + }, + ) + + # When I select the advance episode option for "LNPCP Result from Symptomatic Procedure" + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_lnpcp_result_from_symptomatic_procedure_button() + + # And I set the Date of Symptomatic Procedure to "yesterday" + LnpcpResultFromSymptomaticProcedure(page).enter_date_of_symptomatic_procedure( + datetime.today() - timedelta(days=1) + ) + + # And the Screening Interval is 24 months + LnpcpResultFromSymptomaticProcedure(page).assert_text_in_alert_textbox( + "recall interval of 24 months" + ) + + # And I select test number 1 + LnpcpResultFromSymptomaticProcedure(page).select_test_number(1) + + # And I save the Result from Symptomatic Procedure + LnpcpResultFromSymptomaticProcedure(page).click_save_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "which diagnostic test": "Latest not-void test in latest episode", + "latest episode accumulated result": "LNPCP", + "latest event status": "A373 Symptomatic result recorded", + "symptomatic procedure date": "Yesterday", + "symptomatic procedure result": "LNPCP", + }, + ) + + # When I select the advance episode option for "Refer Another Diagnostic Test after return from Symptomatic Referral" + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_refer_another_diagnostic_test_after_return_from_symptomatic_referral_button() + + # And I select Referral Type of "Radiological" for the Diagnostic Test Referral Following Symptomatic Procedure + ReturnFromSymptomaticReferralPage( + page + ).select_radiological_or_endoscopic_referral_option("Radiological") + + # And I select Reason for Onward Referral of "Further Clinical Assessment" for the Diagnostic Test Referral Following Symptomatic Procedure + ReturnFromSymptomaticReferralPage(page).select_reason_for_onward_referral_option( + "Further Clinical Assessment" + ) + + # And I save the Diagnostic Test Referral Following Symptomatic Procedure + ReturnFromSymptomaticReferralPage(page).click_save_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A389 Refer Another Diagnostic Test after return from Symptomatic Referral" + }, + ) + + logging.info( + "Temporary pathway until the Return from Symptomatic Referral - Refer Another Diagnostic Test screen is built in BCSS-16246" + ) + + # When I advance the subject's episode for "Post-investigation Appointment Required" + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + SubjectScreeningSummaryPage(page).click_advance_lynch_surveillance_episode_button() + AdvanceLynchSurveillanceEpisodePage( + page + ).click_post_investigation_appointment_required_button() + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + {"latest event status": "A360 Post-investigation Appointment Required"}, + ) + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I choose to book a practitioner clinic for my subject + SubjectScreeningSummaryPage(page).click_book_practitioner_clinic_button() + + # And I set the practitioner appointment date to "today" + # And I book the earliest available post investigation appointment on this date + book_post_investigation_appointment(page, "The Royal Hospital (Wolverhampton)") + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A410 Post-investigation Appointment Made", + }, + ) + + # And there is a "A410" letter batch for my subject with the exact title "Post-Investigation Appointment Invitation Letter (Lynch)" + # When I process the open "A410" letter batch for my subject + batch_processing( + page, "A410", "Post-Investigation Appointment Invitation Letter (Lynch)" + ) + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A415 Post-investigation Appointment Invitation Letter Printed", + }, + ) + + # When I view the subject + screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) + + # And I view the event history for the subject's latest episode + SubjectScreeningSummaryPage(page).expand_episodes_list() + SubjectScreeningSummaryPage(page).click_first_lynch_surveillance_episode_link() + + # And I view the latest practitioner appointment in the subject's episode + EpisodeEventsAndNotesPage(page).click_most_recent_view_appointment_link() + + # And I attend the subject's practitioner appointment "today" + AppointmentDetailPage(page).mark_appointment_as_attended(datetime.today()) + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest episode includes event status": "A416 Post-investigation Appointment Attended", + }, + ) + + # TheAndn my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest episode includes event status": "A316 Post-investigation Appointment Attended", + "latest event status": "A319 Refer follow-up test after return from symptomatic referral letter (Patient & GP)", + }, + ) + + # And there is a "A319" letter batch for my subject with the exact title "Result Letters - Refer another test after symptomatic referral (Lynch)" + # When I process the open "A319" letter batch for my subject + batch_processing( + page, + "A319", + "Result Letters - Refer another test after symptomatic referral (Lynch)", + ) + + # Then my subject has been updated as follows: + subject_assertion( + nhs_no, + { + "latest event status": "A395 Refer Another Diagnostic Test", + }, + ) + + LogoutPage(page).log_out() diff --git a/utils/appointments.py b/utils/appointments.py index 013ff923..344a4034 100644 --- a/utils/appointments.py +++ b/utils/appointments.py @@ -133,7 +133,7 @@ def book_appointments(page: Page, screening_centre: str, site: str) -> None: def book_post_investigation_appointment( - page: Page, site: str, appointment_date:datetime=datetime.today() + page: Page, site: str, appointment_date: datetime = datetime.today() ) -> None: """ Book a post-investigation appointment for a subject. @@ -159,6 +159,7 @@ def book_post_investigation_appointment( ) overlap_message = "Overlaps a Post Investigation, Surveillance appointment or Colonoscopy Assessment appointment" + appointment_too_early_message = "Appointment before earliest start time" screening_practitioner_index = 1 # Start with the first practitioner appointment_start_time = "08:00" @@ -176,7 +177,10 @@ def book_post_investigation_appointment( dialog_message = ( book_appointments_page.click_save_button_and_return_message() ) - if dialog_message is None or overlap_message not in dialog_message: + if dialog_message is None or ( + overlap_message not in dialog_message + and appointment_too_early_message not in dialog_message + ): # Success or no overlap dialog page.wait_for_timeout( 500