forked from nhs-england-tools/playwright-python-blueprint
-
Notifications
You must be signed in to change notification settings - Fork 2
Migrating scenario 7a #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
adrianoaru-nhs
merged 1 commit into
main
from
feature/BCSS-22019-surveillanceregressiontests-scenario-7a
Jan 5, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| from playwright.sync_api import Page | ||
| from pages.base_page import BasePage | ||
| from datetime import datetime | ||
| from utils.calendar_picker import CalendarPicker | ||
|
|
||
|
|
||
| class PostponeEpisodePage(BasePage): | ||
| """Postpone Episode Page locators, and methods for interacting with the page.""" | ||
|
|
||
| def __init__(self, page: Page): | ||
| super().__init__(page) | ||
| self.page = page | ||
|
|
||
| # Postpone Episode page - page locators | ||
| self.reason_dropwdown = self.page.locator("#CLOSE_REASON") | ||
| self.clinical_reason_dropwdown = self.page.locator( | ||
| "#UI_CLINICAL_REASON_FOR_CLOSURE" | ||
| ) | ||
| self.notes_field = self.page.locator("#UI_NOTES_TEXT") | ||
| self.reason_for_date_change_dropdown = self.page.locator( | ||
| "#A_C_SSDDReasonForChange" | ||
| ) | ||
| self.postpone_episode_button = self.page.get_by_role( | ||
| "button", name="Postpone Episode" | ||
| ) | ||
|
|
||
| def select_reason_dropdown_option(self, option: str) -> None: | ||
| """ | ||
| This method is designed to select an option from the Reason dropdown. | ||
| Args: | ||
| option (str): The option to select from the dropdown. | ||
| """ | ||
| self.reason_dropwdown.select_option(label=option) | ||
|
|
||
| def select_clinical_reason_dropdown_option(self, option: str) -> None: | ||
| """ | ||
| This method is designed to select an option from the Clinical Reason dropdown. | ||
| Args: | ||
| option (str): The option to select from the dropdown. | ||
| """ | ||
| self.clinical_reason_dropwdown.select_option(label=option) | ||
|
|
||
| def enter_notes(self, notes: str) -> None: | ||
| """ | ||
| Enters notes in the Notes field. | ||
| Args: | ||
| notes (str): The notes to enter in the field. | ||
| """ | ||
| self.notes_field.fill(notes) | ||
|
|
||
| def select_reason_for_date_change_dropdown_option(self, option: str) -> None: | ||
| """ | ||
| This method is designed to select an option from the Reason for Date Change dropdown. | ||
| Args: | ||
| option (str): The option to select from the dropdown. | ||
| """ | ||
| self.reason_for_date_change_dropdown.select_option(label=option) | ||
|
|
||
| def click_postpone_episode_button(self) -> None: | ||
| """Clicks the Postpone Episode button.""" | ||
| self.safe_accept_dialog(self.postpone_episode_button) | ||
49 changes: 49 additions & 0 deletions
49
pages/screening_subject_search/postpone_surveillance_episode_page.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| from playwright.sync_api import Page | ||
| from pages.screening_subject_search.postpone_episode_page import PostponeEpisodePage | ||
| from datetime import datetime | ||
| from utils.calendar_picker import CalendarPicker | ||
|
|
||
|
|
||
| class PostponeSurveillanceEpisodePage(PostponeEpisodePage): | ||
| """Postpone Surveillance Episode Page locators, and methods for interacting with the page.""" | ||
|
|
||
| def __init__(self, page: Page): | ||
| super().__init__(page) | ||
| self.page = page | ||
|
|
||
| # Postpone Surveillance Episode page - page locators | ||
| self.change_surveillance_due_date_field = self.page.locator( | ||
| "#A_C_SurveillanceScreeningDueDate" | ||
| ) | ||
|
|
||
| def enter_date_in_change_surveillance_due_date_field(self, date: datetime) -> None: | ||
| """ | ||
| Enters a date in the Change Surveillance Due Date field. | ||
| Args: | ||
| date (datetime): The date to enter in the field. | ||
| """ | ||
| CalendarPicker(self.page).calendar_picker_ddmmyyyy( | ||
| date, self.change_surveillance_due_date_field | ||
| ) | ||
|
|
||
| def postpone_surveillance_episode(self, criteria: dict) -> None: | ||
| """ | ||
| Postpone surveillance episode with given criteria. | ||
| Args: | ||
| criteria (dict): A dictionary containing the following keys: | ||
| - reason (str): The reason for postponing the episode. | ||
| - clinical reason (str): The clinical reason for postponing the episode. | ||
| - notes (str): Notes regarding the postponement. | ||
| - change surveillance due date (datetime): The new surveillance due date. | ||
| - reason for date change (str): The reason for changing the date. | ||
| """ | ||
| self.select_reason_dropdown_option(criteria["reason"]) | ||
| self.select_clinical_reason_dropdown_option(criteria["clinical reason"]) | ||
| self.enter_notes(criteria["notes"]) | ||
| self.enter_date_in_change_surveillance_due_date_field( | ||
| criteria["change surveillance due date"] | ||
| ) | ||
| self.select_reason_for_date_change_dropdown_option( | ||
| criteria["reason for date change"] | ||
| ) | ||
| self.click_postpone_episode_button() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
215 changes: 215 additions & 0 deletions
215
...egression/regression_tests/surveillance_regression_tests/test_surveillance_scenario_7a.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| import logging | ||
| import pytest | ||
| from datetime import datetime, timedelta | ||
| from playwright.sync_api import Page | ||
| from pages.datasets.colonoscopy_dataset_page import ( | ||
| ColonoscopyDatasetsPage, | ||
| FitForColonoscopySspOptions, | ||
| ) | ||
| from pages.datasets.subject_datasets_page import SubjectDatasetsPage | ||
| from pages.logout.log_out_page import LogoutPage | ||
| from pages.organisations.organisations_page import OrganisationSwitchPage | ||
| from pages.screening_subject_search.advance_surveillance_episode_page import ( | ||
| AdvanceSurveillanceEpisodePage, | ||
| ) | ||
| from pages.screening_subject_search.postpone_surveillance_episode_page import ( | ||
| PostponeSurveillanceEpisodePage, | ||
| ) | ||
| from pages.screening_subject_search.reopen_surveillance_episode_page import ( | ||
| ReopenSurveillanceEpisodePage, | ||
| ) | ||
| from pages.screening_subject_search.subject_screening_summary_page import ( | ||
| SubjectScreeningSummaryPage, | ||
| ) | ||
| from utils import screening_subject_page_searcher | ||
| from utils.generate_health_check_forms_util import GenerateHealthCheckFormsUtil | ||
| from utils.sspi_change_steps import SSPIChangeSteps | ||
| from utils.subject_assertion import subject_assertion | ||
| from utils.user_tools import UserTools | ||
|
|
||
|
|
||
| @pytest.mark.skip( | ||
| reason="Requires manual setup to create suitable subjects for surveillance postponement." | ||
| ) | ||
| @pytest.mark.vpn_required | ||
| @pytest.mark.regression | ||
| @pytest.mark.surveillance_regression_tests | ||
| def test_scenario_7a(page: Page, general_properties: dict) -> None: | ||
| """ | ||
| Scenario: 7a: Postpone from X500 | ||
|
|
||
| X500-X92-C203 [SSCL30] X900-A99 | ||
|
|
||
| This scenario does work, but only if you manage to invite a subject with a Surveillance due date that is in the past but less than a year ago, so we don't trip over the validation for the future date. These are not immediately available in a cloud dev/test database, so before it can be run, Surveillance invitations must be manually run to a date within the last year. Because this somewhat limits the usefulness of this scenario, it is flagged to be ignored by default. | ||
|
|
||
| Note that for a postpone, the calculated Surveillance due date and its reason for change are set to the values entered by the user. | ||
|
|
||
| Scenario summary: | ||
|
|
||
| > Run surveillance invitations for 1 subject > X500 (3.1) | ||
| > SSPI update changes subject to in-age at recall | ||
| > Postpone the episode > X92 | ||
| > Check recall [SSCL30] | ||
| > Reopen the episode > X900 (3.1) | ||
| > Complete the colonoscopy assessment dataset - fit for colonoscopy | ||
| > Suitable for colonoscopy > A99 (3.1) | ||
| """ | ||
| # Given I log in to BCSS "England" as user role "Specialist Screening Practitioner" | ||
| user_role = UserTools.user_login( | ||
| page, "Specialist Screening Practitioner at BCS009 & BCS001", True | ||
| ) | ||
|
|
||
| OrganisationSwitchPage(page).select_organisation_by_id("BCS001") | ||
| OrganisationSwitchPage(page).click_continue() | ||
adrianoaru-nhs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if user_role is None: | ||
| raise ValueError("User role is none") | ||
|
|
||
| # When I run surveillance invitations for 1 subject | ||
| org_id = general_properties["eng_screening_centre_id"] | ||
| nhs_no = GenerateHealthCheckFormsUtil(page).invite_surveillance_subjects_early( | ||
| org_id | ||
| ) | ||
| logging.info(f"[SUBJECT RETRIEVAL] Subject's NHS Number: {nhs_no}") | ||
|
|
||
| # Then my subject has been updated as follows: | ||
| subject_assertion( | ||
| nhs_no, | ||
| { | ||
| "latest episode status": "Open", | ||
| "latest episode type": "Surveillance", | ||
| "latest event status": "X500 Selected For Surveillance", | ||
| "responsible screening centre code": "User's screening centre", | ||
| "subject has unprocessed SSPI updates": "No", | ||
| "subject has user DOB updates": "No", | ||
| }, | ||
| user_role, | ||
| ) | ||
|
|
||
| # And I receive an SSPI update to change their date of birth to "72" years old | ||
| SSPIChangeSteps().sspi_update_to_change_dob_received(nhs_no, 72) | ||
|
|
||
| # Then my subject has been updated as follows: | ||
| subject_assertion(nhs_no, {"subject age": "72"}) | ||
|
|
||
| # When I view the subject | ||
| screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no) | ||
|
|
||
| # And I postpone the episode: | ||
| SubjectScreeningSummaryPage(page).click_postpone_surveillance_episode_button() | ||
| PostponeSurveillanceEpisodePage(page).postpone_surveillance_episode( | ||
| { | ||
| "reason": "Clinical Reason", | ||
| "clinical reason": "Unfit for further investigation", | ||
| "notes": "AUTO TEST: A Sufficiently long episode closure note, added by datatable.", | ||
| "change surveillance due date": datetime.today() + timedelta(days=1), | ||
| "reason for date change": "Patient Request", | ||
| } | ||
| ) | ||
|
|
||
| # Then my subject has been updated as follows: | ||
| subject_assertion( | ||
| nhs_no, | ||
| { | ||
| "calculated fobt due date": "Unchanged", | ||
| "calculated lynch due date": "Null", | ||
| "calculated surveillance due date": "Tomorrow", | ||
| "ceased confirmation date": "Null", | ||
| "ceased confirmation details": "Null", | ||
| "ceased confirmation user id": "Null", | ||
| "clinical reason for cease": "Null", | ||
| "latest episode accumulated result": "(Any) Surveillance non-participation", | ||
| "latest episode recall calculation method": "X92 Interrupt User Date", | ||
| "latest episode recall episode type": "Surveillance - High-risk findings", | ||
| "latest episode recall surveillance type": "High-risk findings", | ||
| "latest episode status": "Closed", | ||
| "latest episode status reason": "Clinical Reason", | ||
| "latest event status": "X92 Close Surveillance Episode via interrupt", | ||
| "lynch due date": "Null", | ||
| "lynch due date date of change": "Unchanged", | ||
| "lynch due date reason": "Unchanged", | ||
| "pre-interrupt event status": "X500 Selected For Surveillance", | ||
| "screening due date": "Null", | ||
| "screening due date date of change": "Unchanged", | ||
| "screening due date reason": "Unchanged", | ||
| "screening status": "Surveillance", | ||
| "screening status date of change": "Unchanged", | ||
| "screening status reason": "Unchanged", | ||
| "surveillance due date": "Calculated Surveillance due date", | ||
| "surveillance due date date of change": "Today", | ||
| "surveillance due date reason": "Patient Request", | ||
| }, | ||
| ) | ||
|
|
||
| # 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 episode for correction" | ||
| SubjectScreeningSummaryPage(page).click_reopen_surveillance_episode_button() | ||
| ReopenSurveillanceEpisodePage(page).click_reopen_episode_for_correction_button() | ||
|
|
||
| # 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": "As at episode start", | ||
| "ceased confirmation date": "Null", | ||
| "ceased confirmation details": "Null", | ||
| "ceased confirmation user id": "Null", | ||
| "clinical reason for cease": "Null", | ||
| "latest episode accumulated result": "Null", | ||
| "latest episode includes event code": "E63 Reopen episode for correction", | ||
| "latest episode recall calculation method": "X92 Interrupt User Date", | ||
| "latest episode recall episode type": "Null", | ||
| "latest episode recall surveillance type": "High-risk findings", | ||
| "latest episode status": "Open", | ||
| "latest episode status reason": "Null", | ||
| "latest event status": "X900 Surveillance Episode reopened", | ||
| "lynch due date": "Null", | ||
| "lynch due date date of change": "Unchanged", | ||
| "lynch due date reason": "Unchanged", | ||
| "screening due date": "Null", | ||
| "screening due date date of change": "Unchanged", | ||
| "screening due date reason": "Unchanged", | ||
| "screening status": "Surveillance", | ||
| "screening status date of change": "Unchanged", | ||
| "screening status reason": "Unchanged", | ||
| "surveillance due date": "Calculated surveillance due date", | ||
| "surveillance due date date of change": "Today", | ||
| "surveillance due date reason": "Reopened episode", | ||
| }, | ||
| ) | ||
|
|
||
| # 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_surveillance_episode_button() | ||
| AdvanceSurveillanceEpisodePage(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", | ||
| }, | ||
| ) | ||
|
|
||
| LogoutPage(page).log_out() | ||
adrianoaru-nhs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.