Skip to content

Commit bc6b4d3

Browse files
Merge branch 'main' of github.com:NHSDigital/bcss-playwright into feature/BCSS-20606-new-regression-release-seek-further-data
2 parents 32a4dc9 + 5c2fbf5 commit bc6b4d3

File tree

10 files changed

+1266
-29
lines changed

10 files changed

+1266
-29
lines changed

classes/event/event_status_type.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ class EventStatusType(Enum):
8686
"A318",
8787
"Post-investigation Appointment NOT Required - Result Letter Created",
8888
)
89+
A319 = (
90+
305787,
91+
"A319",
92+
"Refer follow-up test after return from symptomatic referral letter (Patient & GP)",
93+
)
8994
A320 = (160160, "A320", "Refer Another Test")
9095
A321 = (203141, "A321", "Manual Patient Result Letter Created")
9196
A322 = (203142, "A322", "GP Copy of Manual Patient Result Letter on Queue")
@@ -174,6 +179,7 @@ class EventStatusType(Enum):
174179
A370 = (160161, "A370", "Diagnostic Test Result Letter sent to GP")
175180
A371 = (20080, "A371", "Surgery Patient Result letter Printed")
176181
A372 = (20081, "A372", "Refer Symptomatic, GP Letter Printed")
182+
A373 = (305780, "A373", "Symptomatic result recorded")
177183
A374 = (20082, "A374", "Return to Surveillance After Symptomatic Referral")
178184
A375 = (
179185
160176,
@@ -188,6 +194,11 @@ class EventStatusType(Enum):
188194
A383 = (20421, "A383", "Handover into Symptomatic Care - Patient Letter Printed")
189195
A384 = (20420, "A384", "Discharged from Screening - GP letter not required")
190196
A385 = (20419, "A385", "Handover into Symptomatic Care")
197+
A389 = (
198+
305783,
199+
"A389",
200+
"Refer Another Diagnostic Test after return from Symptomatic Referral",
201+
)
191202
A391 = (20083, "A391", "Patient Discharge Letter Printed - No Patient Contact")
192203
A392 = (20084, "A392", "Patient Discharge Letter Printed - Patient Choice")
193204
A394 = (

pages/screening_subject_search/advance_fobt_screening_episode_page.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,24 @@ def __init__(self, page: Page):
9696
self.redirect_to_reestablish_suitability_for_diagnostic_test_repatient_contact = self.page.get_by_role(
9797
"button", name="Redirect to re-establish"
9898
)
99+
self.mdt_referral_required_button = self.page.get_by_role(
100+
"button", name="MDT Referral Required"
101+
)
102+
self.mdt_referral_not_required_button = self.page.get_by_role(
103+
"button", name="MDT Referral Not Required"
104+
)
105+
self.non_neoplastic_and_other_non_bowel_cancer_result_button = (
106+
self.page.get_by_role(
107+
"button", name="Non-neoplastic and Other Non-bowel Cancer Result"
108+
)
109+
)
110+
self.return_to_fobt_after_symptomatic_referral_button = self.page.get_by_role(
111+
"button", name="Return to FOBT after Symptomatic Referral"
112+
)
113+
self.refer_another_diagnostic_test_after_return_from_symptomatic_referral_button = self.page.get_by_role(
114+
"button",
115+
name="Refer Another Diagnostic Test after return from Symptomatic Referral",
116+
)
99117
# Contact recording locators
100118
self.contact_direction_dropdown = self.page.get_by_label("Contact Direction")
101119
self.contact_made_between_dropdown = self.page.get_by_label(
@@ -117,9 +135,6 @@ def __init__(self, page: Page):
117135
self.ct_colonography_test_type_dropdown = self.page.locator(
118136
"#UI_EXT_TEST_TYPE_38"
119137
)
120-
self.invite_for_diagnostic_test_button = self.page.get_by_role(
121-
"button", name="Invite for Diagnostic Test >>"
122-
)
123138

124139
def click_suitable_for_endoscopic_test_button(self) -> None:
125140
"""Click the 'Suitable for Endoscopic Test' button."""
@@ -396,3 +411,29 @@ def select_any_practitioner(self) -> None:
396411
return
397412

398413
logging.warning("[CONTACT RECORD] No valid practitioner found to select")
414+
415+
def click_mdt_referral_required_button(self) -> None:
416+
"""Click the 'MDT Referral Required' button."""
417+
self.safe_accept_dialog(self.mdt_referral_required_button)
418+
419+
def click_mdt_referral_not_required_button(self) -> None:
420+
"""Click the 'MDT Referral Not Required' button."""
421+
self.safe_accept_dialog(self.mdt_referral_not_required_button)
422+
423+
def click_non_neoplastic_and_other_non_bowel_cancer_result_button(self) -> None:
424+
"""Click the 'Non-neoplastic and Other Non-bowel Cancer Result' button."""
425+
self.safe_accept_dialog(
426+
self.non_neoplastic_and_other_non_bowel_cancer_result_button
427+
)
428+
429+
def click_return_to_fobt_after_symptomatic_referral_button(self) -> None:
430+
"""Click the 'Return to FOBT after Symptomatic Referral' button."""
431+
self.safe_accept_dialog(self.return_to_fobt_after_symptomatic_referral_button)
432+
433+
def click_refer_another_diagnostic_test_after_return_from_symptomatic_referral_button(
434+
self,
435+
) -> None:
436+
"""Click the 'Refer Another Diagnostic Test after return from Symptomatic Referral' button."""
437+
self.click(
438+
self.refer_another_diagnostic_test_after_return_from_symptomatic_referral_button
439+
)

pages/screening_subject_search/diagnostic_test_outcome_page.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class ReasonForOnwardReferral(StrEnum):
1414
CURRENTLY_UNSUITABLE_FOR_ENDOSCOPIC_REFERRAL = "20358"
1515
FURTHER_CLINICAL_ASSESSMENT = "20359"
1616
INCOMPLETE_COLONIC_VISUALISATION = "20481"
17+
POLYP_EXCISION = "203011"
18+
CORRECTIVE_SURGERY = "203012"
19+
SUSPECTED_CANCER_SURGERY = "203013"
1720

1821

1922
class DiagnosticTestOutcomePage(BasePage):
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from datetime import datetime
2+
from playwright.sync_api import Page
3+
from pages.base_page import BasePage
4+
from utils.calendar_picker import CalendarPicker
5+
6+
7+
class NonNeoplasticResultFromSymptomaticProcedurePage(BasePage):
8+
"""Non Neoplastic Result From Symptomatic Procedure Page locators, and methods for interacting with the page."""
9+
10+
def __init__(self, page: Page):
11+
super().__init__(page)
12+
# Non Neoplastic Result From Symptomatic Procedure - page locators
13+
self.date_of_symptomatic_procedure_calendar_button = self.page.locator(
14+
"#UI_SURGERY_DATE__LinkOrButton"
15+
)
16+
self.alert_textbox = self.page.locator("#UI_SPAN_RECALL_TEXT")
17+
self.all_tests = self.page.locator("#UI_ID_RECALL_ANCHOR_DATE_EXT_TEST_ID")
18+
self.save_button = self.page.get_by_role("button", name="Save")
19+
20+
def click_date_of_symptomatic_procedure_calendar_button(self) -> None:
21+
"""Click the date of symptomatic procedure calendar button."""
22+
self.click(self.date_of_symptomatic_procedure_calendar_button)
23+
24+
def enter_date_of_symptomatic_procedure(self, date: datetime) -> None:
25+
"""
26+
Enter the date of the symptomatic procedure.
27+
Args:
28+
date (datetime): The date to be entered in the date of symptomatic procedure field. Example: datetime(2023, 10, 25)
29+
"""
30+
self.click_date_of_symptomatic_procedure_calendar_button()
31+
CalendarPicker(self.page).v1_calender_picker(date)
32+
33+
def assert_text_in_alert_textbox(self, expected_text: str) -> None:
34+
"""
35+
Assert that the expected text is present in the alert textbox.
36+
Args:
37+
expected_text (str): The text expected to be found in the alert textbox. Example: "This is a test alert"
38+
"""
39+
actual_text = self.alert_textbox.inner_text()
40+
assert (
41+
expected_text in actual_text
42+
), f"Expected text '{expected_text}' not found in alert textbox. Actual text: '{actual_text}'"
43+
44+
def select_test_number(self, test_number: int) -> None:
45+
"""
46+
Select a test from the all tests dropdown by its index.
47+
Args:
48+
test_number (int): The index of the test to select (1-based index). Example: if you want to select the 1st test pass in 1
49+
"""
50+
self.click(self.all_tests.nth(test_number - 1))
51+
52+
def click_save_button(self) -> None:
53+
"""Click the 'Save' button."""
54+
self.click(self.save_button)

pages/screening_subject_search/reopen_fobt_screening_episode_page.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ def __init__(self, page: Page):
2929
self.reopen_to_reschedule_diagnostic_test_button = self.page.get_by_role(
3030
"button", name="Reopen to Reschedule Diagnostic Test"
3131
)
32+
self.reopen_to_rerecord_outcome_from_symptomatic_referral_button = (
33+
self.page.get_by_role(
34+
"button", name="Reopen to Re-record Outcome from Symptomatic Referral"
35+
)
36+
)
3237

3338
def click_reopen_to_book_an_assessment_button(self) -> None:
3439
"""Click the 'Reopen to book an assessment' button."""
@@ -55,3 +60,9 @@ def click_reopen_to_confirm_diagnostic_test_result_and_outcome_button(self) -> N
5560
def click_reopen_to_reschedule_diagnostic_test_button(self) -> None:
5661
"""Click the 'Reopen to Reschedule Diagnostic Test' button."""
5762
self.safe_accept_dialog(self.reopen_to_reschedule_diagnostic_test_button)
63+
64+
def click_reopen_to_rerecord_outcome_from_symptomatic_referral_button(self) -> None:
65+
"""Click the 'Reopen to Re-record Outcome from Symptomatic Referral' button."""
66+
self.safe_accept_dialog(
67+
self.reopen_to_rerecord_outcome_from_symptomatic_referral_button
68+
)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from playwright.sync_api import Page
2+
from pages.base_page import BasePage
3+
4+
5+
class ReturnFromSymptomaticReferralPage(BasePage):
6+
"""Return From Symptomatic Referral Page locators, and methods for interacting with the page."""
7+
8+
def __init__(self, page: Page):
9+
super().__init__(page)
10+
# Return From Symptomatic Referral - page locators
11+
self.radiological_or_endoscopic_referral_dropdown = self.page.locator(
12+
"#referralTypeId"
13+
)
14+
self.reason_for_onward_referral_dropdown = self.page.locator(
15+
"#referralReasonId"
16+
)
17+
self.save_button = self.page.get_by_role("button", name="Save")
18+
19+
def select_radiological_or_endoscopic_referral_option(
20+
self, referral_type: str
21+
) -> None:
22+
"""
23+
Select a radiological or endoscopic referral from the dropdown.
24+
Args:
25+
referral_type (str): The referral type to be selected in the dropdown. Example: "Colonoscopy"
26+
"""
27+
self.radiological_or_endoscopic_referral_dropdown.select_option(
28+
label=referral_type
29+
)
30+
31+
def select_reason_for_onward_referral_option(
32+
self, reason_for_referral: str
33+
) -> None:
34+
"""
35+
Select a reason for onward referral from the dropdown.
36+
Args:
37+
reason_for_referral (str): The reason for onward referral to be selected in the dropdown. Example: "Further Clinical Assessment"
38+
"""
39+
self.reason_for_onward_referral_dropdown.select_option(
40+
label=reason_for_referral
41+
)
42+
43+
def click_save_button(self) -> None:
44+
"""Click the 'Save' button."""
45+
self.click(self.save_button)

pages/screening_subject_search/subject_demographic_page.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from playwright.sync_api import Page, expect
1+
from playwright.sync_api import Page, Dialog
22
from pages.base_page import BasePage
33
from datetime import datetime
44
from utils.calendar_picker import CalendarPicker
5+
import logging
56

67

78
class SubjectDemographicPage(BasePage):
@@ -13,11 +14,9 @@ def __init__(self, page: Page):
1314
# Subject Demographic - page filters
1415
self.forename_field = self.page.get_by_role("textbox", name="Forename")
1516
self.surname_field = self.page.get_by_role("textbox", name="Surname")
16-
self.postcode_field = self.page.get_by_role("textbox", name="Postcode")
17+
self.postcode_field = self.page.locator("#UI_SUBJECT_POSTCODE")
1718
self.dob_field = self.page.get_by_role("textbox", name="Date of Birth")
18-
self.update_subject_data_button = self.page.get_by_role(
19-
"button", name="Update Subject Data"
20-
)
19+
self.update_subject_data_button = self.page.locator("#BTN_DEMOG_UPDATE_SUBJECT")
2120
self.temporary_address_show_link = (
2221
self.page.locator("font")
2322
.filter(has_text="Temporary Address show")
@@ -126,6 +125,39 @@ def click_update_subject_data_button(self) -> None:
126125
"""Clicks on the 'Update Subject Data' button"""
127126
self.click(self.update_subject_data_button)
128127

128+
def click_update_subject_data_button_and_assert_dialog(
129+
self, expected_text: str
130+
) -> None:
131+
"""
132+
Clicks on the 'Update Subject Data' button and asserts that a dialog appears with the expected text.
133+
Args:
134+
expected_text (str): The text expected to be found in the dialog.
135+
"""
136+
self._dialog_assertion_error = None
137+
138+
def handle_dialog(dialog: Dialog):
139+
"""
140+
Handles the dialog and asserts that the dialog contains the expected text.
141+
Args:
142+
dialog (Dialog): the playwright dialog object
143+
"""
144+
logging.info(f"Dialog appeared with message: {dialog.message}")
145+
actual_text = dialog.message
146+
try:
147+
assert (
148+
expected_text in actual_text
149+
), f"Expected dialog to contain '{expected_text}', but got '{actual_text}'"
150+
except AssertionError as e:
151+
self._dialog_assertion_error = e
152+
try:
153+
dialog.accept()
154+
except Exception:
155+
logging.warning("Dialog already accepted or handled")
156+
157+
self.page.once("dialog", lambda dialog: handle_dialog(dialog))
158+
self.click(self.update_subject_data_button)
159+
self.page.wait_for_timeout(2000)
160+
129161
def get_dob_field_value(self) -> str:
130162
"""
131163
Returns the value in the date of birth input textbox

0 commit comments

Comments
 (0)