Skip to content

Commit d722cbf

Browse files
Adding scneario 12 and relevant POMs / Classes / Utils
Fixing scenario 11
1 parent 6fea184 commit d722cbf

13 files changed

+1290
-27
lines changed

classes/data/data_creation.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from classes.organisation.organisation_complex import Organisation
66
from classes.subject.gender_type import GenderType
77
from classes.address.address import Address
8-
from classes.person.person import Person
8+
from classes.person.person_data import Person
99
from classes.screening.region_type import RegionType
1010
from classes.subject.pi_subject import PISubject
1111
from utils.nhs_number_tools import NHSNumberTools
@@ -113,17 +113,17 @@ def generate_random_subject(
113113
pi_subject = PISubject()
114114
pi_subject.nhs_number = NHSNumberTools.generate_random_nhs_number()
115115
person = self.generate_random_person(random_words_list, GenderType.NOT_KNOWN)
116-
pi_subject.family_name = person.get_surname()
117-
pi_subject.first_given_names = person.get_forename()
118-
pi_subject.other_given_names = person.get_other_forenames()
119-
pi_subject.previous_family_name = person.get_previous_surname()
120-
pi_subject.name_prefix = person.get_title()
116+
pi_subject.family_name = person.surname
117+
pi_subject.first_given_names = person.forename
118+
pi_subject.other_given_names = person.other_forenames
119+
pi_subject.previous_family_name = person.previous_surname
120+
pi_subject.name_prefix = person.title
121121
pi_subject.birth_date = datetime.date.today() - datetime.timedelta(
122122
days=60 * 365
123123
)
124124

125125
pi_subject.death_date = None
126-
gender = person.get_gender()
126+
gender = person.gender
127127
if gender is not None:
128128
pi_subject.gender_code = gender.redefined_value
129129
else:
@@ -225,15 +225,15 @@ def generate_random_person(
225225
)
226226

227227
person = Person()
228-
person.set_title(self.generate_random_title(gender))
229-
person.set_forename(random_words_list.get("forename", ""))
230-
person.set_surname(random_words_list.get("surname", ""))
231-
person.set_gender(gender)
228+
person.title = self.generate_random_title(gender)
229+
person.forename = random_words_list.get("forename", "")
230+
person.surname = random_words_list.get("surname", "")
231+
person.gender = gender
232232

233233
if self.rand.randint(0, 100) < 5:
234-
person.set_other_forenames(random_words_list.get("forename2", ""))
234+
person.other_forenames = random_words_list.get("forename2", "")
235235
if self.rand.randint(0, 100) < 5:
236-
person.set_previous_surname(random_words_list.get("surname2", ""))
236+
person.previous_surname = random_words_list.get("surname2", "")
237237

238238
logging.debug("generateRandomPerson: end")
239239
return person

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 = (

classes/person/person_data.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from dataclasses import dataclass
2+
from typing import Optional
3+
from classes.subject.gender_type import GenderType
4+
5+
6+
@dataclass
7+
class Person:
8+
"""
9+
Represents a person with name, title, previous surname, other forenames, and gender.
10+
Provides methods to get full name and string representation.
11+
"""
12+
13+
surname: Optional[str] = None
14+
forename: Optional[str] = None
15+
title: Optional[str] = None
16+
other_forenames: Optional[str] = None
17+
previous_surname: Optional[str] = None
18+
gender: Optional[GenderType] = None
19+
20+
def get_full_name(self) -> str:
21+
"""
22+
Returns the full name of the person.
23+
"""
24+
return f"{self.title or ''} {self.forename or ''} {self.surname or ''}".strip()
25+
26+
def __str__(self) -> str:
27+
"""
28+
Returns a string representation of the person.
29+
"""
30+
return f"{self.title or ''} {self.forename or ''} {self.surname or ''} (gender={self.gender})".strip()

pages/screening_subject_search/advance_fobt_screening_episode_page.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,27 @@ 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.invite_for_diagnostic_test_button = self.page.get_by_role(
100+
"button", name="Invite for Diagnostic Test >>"
101+
)
102+
self.mdt_referral_required_button = self.page.get_by_role(
103+
"button", name="MDT Referral Required"
104+
)
105+
self.mdt_referral_not_required_button = self.page.get_by_role(
106+
"button", name="MDT Referral Not Required"
107+
)
108+
self.non_neoplastic_and_other_non_bowel_cancer_result_button = (
109+
self.page.get_by_role(
110+
"button", name="Non-neoplastic and Other Non-bowel Cancer Result"
111+
)
112+
)
113+
self.return_to_fobt_after_symptomatic_referral_button = self.page.get_by_role(
114+
"button", name="Return to FOBT after Symptomatic Referral"
115+
)
116+
self.refer_another_diagnostic_test_after_return_from_symptomatic_referral_button = self.page.get_by_role(
117+
"button",
118+
name="Refer Another Diagnostic Test after return from Symptomatic Referral",
119+
)
99120
# Contact recording locators
100121
self.contact_direction_dropdown = self.page.get_by_label("Contact Direction")
101122
self.contact_made_between_dropdown = self.page.get_by_label(
@@ -117,9 +138,6 @@ def __init__(self, page: Page):
117138
self.ct_colonography_test_type_dropdown = self.page.locator(
118139
"#UI_EXT_TEST_TYPE_38"
119140
)
120-
self.invite_for_diagnostic_test_button = self.page.get_by_role(
121-
"button", name="Invite for Diagnostic Test >>"
122-
)
123141

124142
def click_suitable_for_endoscopic_test_button(self) -> None:
125143
"""Click the 'Suitable for Endoscopic Test' button."""
@@ -396,3 +414,29 @@ def select_any_practitioner(self) -> None:
396414
return
397415

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

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: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
self.page = page
13+
# Non Neoplastic Result From Symptomatic Procedure - page locators
14+
self.date_of_symptomatic_procedure_calendar_button = self.page.locator(
15+
"#UI_SURGERY_DATE__LinkOrButton"
16+
)
17+
self.alert_textbox = self.page.locator("#UI_SPAN_RECALL_TEXT")
18+
self.all_tests = self.page.locator("#UI_ID_RECALL_ANCHOR_DATE_EXT_TEST_ID")
19+
self.save_button = self.page.get_by_role("button", name="Save")
20+
21+
def click_date_of_symptomatic_procedure_calendar_button(self) -> None:
22+
"""Click the date of symptomatic procedure calendar button."""
23+
self.click(self.date_of_symptomatic_procedure_calendar_button)
24+
25+
def enter_date_of_symptomatic_procedure(self, date: datetime) -> None:
26+
"""
27+
Enter the date of the symptomatic procedure.
28+
Args:
29+
date (datetime): The date to be entered in the date of symptomatic procedure field. Example: datetime(2023, 10, 25)
30+
"""
31+
self.click_date_of_symptomatic_procedure_calendar_button()
32+
CalendarPicker(self.page).v1_calender_picker(date)
33+
34+
def assert_text_in_alert_textbox(self, expected_text: str) -> None:
35+
"""
36+
Assert that the expected text is present in the alert textbox.
37+
Args:
38+
expected_text (str): The text expected to be found in the alert textbox. Example: "This is a test alert"
39+
"""
40+
actual_text = self.alert_textbox.inner_text()
41+
assert (
42+
expected_text in actual_text
43+
), f"Expected text '{expected_text}' not found in alert textbox. Actual text: '{actual_text}'"
44+
45+
def select_test_number(self, test_number: int) -> None:
46+
"""
47+
Select a test from the all tests dropdown by its index.
48+
Args:
49+
test_number (int): The index of the test to select (1-based index). Example: 1
50+
"""
51+
self.click(self.all_tests.nth(test_number - 1))
52+
53+
def click_save_button(self) -> None:
54+
"""Click the 'Save' button."""
55+
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: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
self.page = page
11+
# Return From Symptomatic Referral - page locators
12+
self.radiological_or_endoscopic_referral_dropdown = self.page.locator(
13+
"#referralTypeId"
14+
)
15+
self.reason_for_onward_referral_dropdown = self.page.locator(
16+
"#referralReasonId"
17+
)
18+
self.save_button = self.page.get_by_role("button", name="Save")
19+
20+
def select_radiological_or_endoscopic_referral_option(
21+
self, referral_type: str
22+
) -> None:
23+
"""
24+
Select a radiological or endoscopic referral from the dropdown.
25+
Args:
26+
referral_type (str): The referral type to be selected in the dropdown. Example: "Colonoscopy"
27+
"""
28+
self.radiological_or_endoscopic_referral_dropdown.select_option(
29+
label=referral_type
30+
)
31+
32+
def select_reason_for_onward_referral_option(
33+
self, reason_for_referral: str
34+
) -> None:
35+
"""
36+
Select a reason for onward referral from the dropdown.
37+
Args:
38+
reason_for_referral (str): The reason for onward referral to be selected in the dropdown. Example: "Further Clinical Assessment"
39+
"""
40+
self.reason_for_onward_referral_dropdown.select_option(
41+
label=reason_for_referral
42+
)
43+
44+
def click_save_button(self) -> None:
45+
"""Click the 'Save' button."""
46+
self.click(self.save_button)

pages/screening_subject_search/subject_demographic_page.py

Lines changed: 38 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,40 @@ 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+
accept (bool): Set to True if you want to accept the dialog, by default is is set to False.
144+
"""
145+
logging.info(f"Dialog appeared with message: {dialog.message}")
146+
actual_text = dialog.message
147+
try:
148+
assert (
149+
expected_text in actual_text
150+
), f"Expected dialog to contain '{expected_text}', but got '{actual_text}'"
151+
except AssertionError as e:
152+
self._dialog_assertion_error = e
153+
try:
154+
dialog.accept()
155+
except Exception:
156+
logging.warning("Dialog already accepted or handled")
157+
158+
self.page.once("dialog", lambda dialog: handle_dialog(dialog))
159+
self.click(self.update_subject_data_button)
160+
self.page.wait_for_timeout(2000)
161+
129162
def get_dob_field_value(self) -> str:
130163
"""
131164
Returns the value in the date of birth input textbox

0 commit comments

Comments
 (0)