Skip to content

Commit 8f7aa63

Browse files
committed
Created new test scenario 8 file
Added mark_as_attended_yesterday method Renamed existing mark_as_attended to mark_as_attended_today Added get_subject_for_pre_invitation to class SubjectSelector
1 parent 493ae29 commit 8f7aa63

File tree

4 files changed

+344
-3
lines changed

4 files changed

+344
-3
lines changed

tests/regression/regression_tests/fobt_regression_tests/test_scenario_6.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ def test_scenario_6(page: Page) -> None:
317317
# And I view the event history for the subject's latest episode
318318
# And I view the latest practitioner appointment in the subject's episode
319319
# And I attend the subject's practitioner appointment "today"
320-
attendance.mark_as_attended()
320+
attendance.mark_as_attended_today()
321321

322322
# Then my subject has been updated as follows:
323323
criteria = {
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
import pytest
2+
import logging
3+
from datetime import datetime
4+
from playwright.sync_api import Page
5+
from pages.datasets.subject_datasets_page import SubjectDatasetsPage
6+
from utils.oracle.subject_creation_util import CreateSubjectSteps
7+
from utils.user_tools import UserTools
8+
from utils.subject_assertion import subject_assertion
9+
from utils.call_and_recall_utils import CallAndRecallUtils
10+
from utils import screening_subject_page_searcher
11+
from utils.batch_processing import batch_processing
12+
from utils.fit_kit import FitKitLogged, FitKitGeneration
13+
from pages.screening_subject_search.subject_screening_summary_page import (
14+
SubjectScreeningSummaryPage,
15+
)
16+
from utils.appointments import book_appointments
17+
from pages.logout.log_out_page import LogoutPage
18+
from pages.base_page import BasePage
19+
from pages.screening_subject_search.advance_fobt_screening_episode_page import (
20+
AdvanceFOBTScreeningEpisodePage,
21+
)
22+
from pages.screening_subject_search.record_diagnosis_date_page import (
23+
RecordDiagnosisDatePage,
24+
)
25+
from utils.appointments import AppointmentAttendance
26+
from pages.datasets.colonoscopy_dataset_page import (
27+
ColonoscopyDatasetsPage,
28+
FitForColonoscopySspOptions,
29+
)
30+
from utils.sspi_change_steps import SSPIChangeSteps
31+
from pages.screening_subject_search.reopen_fobt_screening_episode_page import (
32+
ReopenFOBTScreeningEpisodePage,
33+
)
34+
from utils.oracle.oracle import OracleDB
35+
from utils.oracle.subject_selector import SubjectSelector
36+
from classes.subject_selection_query_builder.subject_selection_criteria_key import (
37+
SubjectSelectionCriteriaKey as Key,
38+
)
39+
40+
41+
@pytest.mark.wip
42+
@pytest.mark.usefixtures("setup_org_and_appointments")
43+
@pytest.mark.vpn_required
44+
@pytest.mark.regression
45+
@pytest.mark.fobt_regression_tests
46+
def test_scenario_8(page: Page) -> None:
47+
"""
48+
Scenario: 8: Discharge for no contact, diagnostic test result of "No result"
49+
50+
S9-S10-S43-A8-A183-A25-J10-A100-A59-A172-(A167)-(A52)-A397-A391-A351-C203 [SSCL13a(A351)] A172-A100-A59-A259-A315-A360-A410-A415-A416-A316-A430-A395-A100-J10-A99-A59-A250-A315-A361-A323-A317-A318-A380-A397-A391-A351-C203 [SSCL14a(A351)]
51+
52+
This scenario tests two routes to closure on A351 discharge no contact. The first follows DNA of the diagnostic test, and the second follows attendance of a "no result" test, then contact is lost before a follow-up test can be arranged. It tests both in-age and over-age closures, and includes two mid-episode redirects.
53+
54+
Scenario summary:
55+
56+
> Find an in-age subject at S9 whose episode started recently before today (1.1)
57+
> Run timed events > creates S9 letter (1.1)
58+
> Process S9 letter batch > S10 (1.1)
59+
> Log kit > S43 (1.2)
60+
> Read kit with ABNORMAL result > A8 (1.3)
61+
> Invite for colonoscopy assessment > A183 (1.11)
62+
> Process A183 appointment letter > A25 (1.11)
63+
> Attend assessment appointment > J10 (1.11)
64+
> Suitable for radiology > A100 (1.12)
65+
> Invite for diagnostic test > A59 (2.1)
66+
> Patient DNA diagnostic test > A172 (2.1)
67+
> Process A183 result letter (A167) (1.11)
68+
> Record diagnosis date reason (A52)
69+
> Record patient contact – not contacted, close on existing result > A397 (2.3)
70+
> Process A397 letter batch > A391 (2.3)
71+
> Process A391 letter batch > A351 (2.3) > C203 (1.13)
72+
> Check recall [SSCL13a(A351)]
73+
> Reopen to reschedule diagnostic test > A172 (2.3)
74+
> Suitable for radiology > A100 (2.3)
75+
> Invite for diagnostic test > A59 (2.1)
76+
> Attend diagnostic test > A259 (2.1)
77+
> Complete investigation dataset, result = Abnormal (2.1)
78+
> Enter diagnostic test outcome – refer another test > A315 (2.1)
79+
> Post-investigation appointment required > A360 (2.1)
80+
> Book post-investigation appointment > A410 (2.4)
81+
> Process A410 letter batch > A415 (2.4)
82+
> Attend post-investigation appointment > A416 > A316 > A430 (2.4)
83+
> Process A430 letter batch > A395 (2.4)
84+
> Redirect to DELETE the Latest Diagnostic Test Result > A100 (2.1)
85+
> Redirect to establish suitability for diagnostic tests > J10 (1.11)
86+
> Suitable for colonoscopy > A99 (1.12)
87+
> Invite for diagnostic test > A59 (2.1)
88+
> Attend diagnostic test > A259 (2.1)
89+
> Complete investigation dataset – no result (2.1)
90+
> Enter diagnostic test outcome – failed test, refer another > A315 (2.1)
91+
> Post-investigation appointment not required > A361 (2.1)
92+
> Record patient contact – post-investigation appointment not required > A323 (2.1) > A317 > A318 (2.5)
93+
> Process A318 letter batch > A380 (2.5)
94+
> Record patient contact – not contacted, close on existing result > A397 (2.3)
95+
> Process A397 letter batch > A391 (2.3)
96+
> SSPI update changes subject to over-age at recall
97+
> Process A391 letter batch > A351 (2.3) > C203 (1.13)
98+
> Check recall [SSCL14a(A351)]
99+
"""
100+
101+
summary_page = SubjectScreeningSummaryPage(page)
102+
attendance = AppointmentAttendance(page)
103+
dataset = ColonoscopyDatasetsPage(page)
104+
ssp_options = FitForColonoscopySspOptions
105+
advance_fobt_episode = AdvanceFOBTScreeningEpisodePage(page)
106+
107+
logging.info(
108+
"[TEST START] Regression - Scenario: 8: Discharge for no contact, diagnostic test result of 'No result'"
109+
)
110+
# Given I log in to BCSS "England" as user role "Hub Manager"
111+
user_role = UserTools.user_login(
112+
page, "Hub Manager at BCS01", return_role_type=True
113+
)
114+
if user_role is None:
115+
raise ValueError("User cannot be assigned to a UserRoleType")
116+
117+
# And there is a subject who meets the following criteria:
118+
user_details = UserTools.retrieve_user("Hub Manager at BCS01")
119+
120+
criteria = {
121+
Key.LATEST_EVENT_STATUS.description: "S9 Pre-invitation Sent",
122+
Key.LATEST_EPISODE_KIT_CLASS.description: "FIT",
123+
Key.LATEST_EPISODE_STARTED.description: "Within the last 6 months",
124+
Key.LATEST_EPISODE_TYPE.description: "FOBT",
125+
Key.SUBJECT_AGE.description: "Between 60 and 72",
126+
# Key.SUBJECT_HAS_UNPROCESSED_SSPI_UPDATES.description: "No",
127+
# Key.SUBJECT_HAS_USER_DOB_UPDATES.description: "No",
128+
# Key.SUBJECT_HUB_CODE.description: user_details["hub_code"],
129+
}
130+
131+
nhs_no = SubjectSelector.get_subject_for_pre_invitation(criteria)
132+
subject_assertion(nhs_no, criteria)
133+
134+
# Then Comment: NHS number
135+
logging.info(f"[SUBJECT FOUND] NHS number: {nhs_no}")
136+
137+
# When I run Timed Events for my subject
138+
OracleDB().exec_bcss_timed_events(nhs_number=nhs_no)
139+
140+
# Then there is a "S9" letter batch for my subject with the exact title "Invitation & Test Kit (FIT)"
141+
# When I process the open "S9" letter batch for my subject
142+
# Then my subject has been updated as follows:
143+
batch_processing(
144+
page,
145+
"S9",
146+
"Invitation & Test Kit (FIT)",
147+
"S10 - Invitation & Test Kit Sent",
148+
True,
149+
)
150+
151+
# When I log my subject's latest unlogged FIT kit
152+
fit_kit = FitKitGeneration().get_fit_kit_for_subject_sql(nhs_no, False, False)
153+
sample_date = datetime.now()
154+
FitKitLogged().log_fit_kits(page, fit_kit, sample_date)
155+
156+
# Then my subject has been updated as follows:
157+
criteria = {
158+
"latest event status": "S43 Kit Returned and Logged (Initial Test)",
159+
}
160+
subject_assertion(nhs_no, criteria)
161+
162+
# When I read my subject's latest logged FIT kit as "ABNORMAL"
163+
FitKitLogged().read_latest_logged_kit(user_role, 2, fit_kit, "ABNORMAL")
164+
165+
# Then my subject has been updated as follows:
166+
criteria = {
167+
"latest event status": "A8 Abnormal",
168+
}
169+
subject_assertion(nhs_no, criteria)
170+
# When I view the subject
171+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
172+
173+
# And I choose to book a practitioner clinic for my subject
174+
SubjectScreeningSummaryPage(page).click_book_practitioner_clinic_button()
175+
176+
# And I select "BCS001" as the screening centre where the practitioner appointment will be held
177+
# And I set the practitioner appointment date to "today"
178+
# And I book the "earliest" available practitioner appointment on this date
179+
book_appointments(
180+
page,
181+
"BCS001 - Wolverhampton Bowel Cancer Screening Centre",
182+
"The Royal Hospital (Wolverhampton)",
183+
)
184+
185+
# Then my subject has been updated as follows:
186+
criteria = {
187+
"latest event status": "A183 1st Colonoscopy Assessment Appointment Requested",
188+
}
189+
subject_assertion(nhs_no, criteria)
190+
191+
# And there is a "A183" letter batch for my subject with the exact title "Practitioner Clinic 1st Appointment"
192+
# When I process the open "A183 - Practitioner Clinic 1st Appointment" letter batch for my subject
193+
# Then my subject has been updated as follows:
194+
batch_processing(
195+
page,
196+
"A183",
197+
"Practitioner Clinic 1st Appointment",
198+
"A25 - 1st Colonoscopy Assessment Appointment Booked, letter sent",
199+
)
200+
201+
# And there is a "A183" letter batch for my subject with the exact title "GP Result (Abnormal)"
202+
batch_processing(
203+
page,
204+
"A183",
205+
"GP Result (Abnormal)",
206+
"A25 - 1st Colonoscopy Assessment Appointment Booked, letter sent",
207+
)
208+
209+
# When I switch users to BCSS "England" as user role "Screening Centre Manager"
210+
LogoutPage(page).log_out(close_page=False)
211+
BasePage(page).go_to_log_in_page()
212+
UserTools.user_login(page, "Screening Centre Manager at BCS001")
213+
214+
# When I view the subject
215+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
216+
217+
# And I view the event history for the subject's latest episode
218+
# And I view the latest practitioner appointment in the subject's episode
219+
# And I attend the subject's practitioner appointment "yesterday"
220+
attendance.mark_as_attended_yesterday()
221+
222+
# Then my subject has been updated as follows:
223+
criteria = {
224+
"latest event status": "J10 Attended Colonoscopy Assessment Appointment",
225+
}
226+
subject_assertion(nhs_no, criteria)
227+
228+
# When I view the subject
229+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
230+
231+
# And I edit the Colonoscopy Assessment Dataset for this subject
232+
# And I update the Colonoscopy Assessment Dataset with the following values:
233+
# | Fit for Colonoscopy (SSP) | No |
234+
# | Dataset complete? | Yes |
235+
# And I save the Colonoscopy Assessment Dataset
236+
SubjectScreeningSummaryPage(page).click_datasets_link()
237+
SubjectDatasetsPage(page).click_colonoscopy_show_datasets()
238+
dataset.select_fit_for_colonoscopy_option(ssp_options.NO)
239+
dataset.click_dataset_complete_radio_button_yes()
240+
dataset.save_dataset()
241+
242+
# And I view the subject
243+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
244+
245+
# And I advance the subject's episode for "Suitable for Radiological Test"
246+
SubjectScreeningSummaryPage(page).click_advance_fobt_screening_episode_button()
247+
advance_fobt_episode.click_suitable_for_radiological_test_button()
248+
249+
# Then my subject has been updated as follows: TODO: selenium line 1799
250+
criteria = {
251+
"latest event status": "A100 Suitable for Radiological Test",
252+
}
253+
subject_assertion(nhs_no, criteria)

utils/appointments.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
)
1717
from utils.calendar_picker import CalendarPicker
1818
from utils.user_tools import UserTools
19-
from datetime import datetime
19+
from datetime import datetime, timedelta
2020
from pages.screening_practitioner_appointments.appointment_detail_page import (
2121
AppointmentDetailPage,
2222
)
@@ -171,7 +171,7 @@ def mark_as_dna(self, non_attendance_reason: str) -> None:
171171

172172
logging.info("[APPOINTMENT DNA] DNA flow completed successfully")
173173

174-
def mark_as_attended(self) -> None:
174+
def mark_as_attended_today(self) -> None:
175175
"""
176176
Marks an appointment as attended and logs the auto-filled attendance details.
177177
This process starts from the subject screening summary page.
@@ -210,3 +210,48 @@ def mark_as_attended(self) -> None:
210210
self.appointment_detail_page.click_save_button(accept_dialog=True)
211211

212212
logging.info("[APPOINTMENT ATTENDED] Attended flow completed successfully")
213+
214+
def mark_as_attended_yesterday(self) -> None:
215+
"""
216+
Marks an appointment as attended with the attendance date set to yesterday.
217+
This process starts from the subject screening summary page.
218+
219+
Navigates through the subject's episode and appointment pages,
220+
selects the 'Attendance' radio option, checks the 'Attended' checkbox,
221+
manually sets the attendance date to yesterday, and logs the resulting details.
222+
223+
Raises:
224+
AssertionError: If expected elements are not found or interaction fails.
225+
"""
226+
logging.info("[APPOINTMENT ATTENDED] Starting attended-yesterday flow")
227+
228+
self.subject_screening_summary_page.click_list_episodes()
229+
self.subject_screening_summary_page.click_view_events_link()
230+
self.episode_events_and_notes_page.click_most_recent_view_appointment_link()
231+
self.appointment_detail_page.check_attendance_radio()
232+
233+
# Check the 'Attended' checkbox
234+
attended_checkbox = self.page.locator("#UI_ATTENDED")
235+
attended_checkbox.check()
236+
237+
# Manually set the attendance date to yesterday
238+
yesterday = (datetime.today() - timedelta(days=1)).strftime(
239+
"%d/%m/%Y"
240+
)
241+
self.page.locator("#UI_ATTENDED_DATE").fill(yesterday)
242+
243+
# Log the attendance details
244+
attended_date = self.page.locator("#UI_ATTENDED_DATE").input_value()
245+
time_from = self.page.locator("#UI_ATTENDED_TIME_FROM").input_value()
246+
time_to = self.page.locator("#UI_ATTENDED_TIME_TO").input_value()
247+
meeting_mode = self.page.locator("#UI_NEW_MEETING_MODE").input_value()
248+
249+
logging.info(
250+
f"[APPOINTMENT ATTENDED] How Attended: {meeting_mode}, Date: {attended_date}, Time From: {time_from}, Time To: {time_to}"
251+
)
252+
253+
self.appointment_detail_page.click_save_button(accept_dialog=True)
254+
255+
logging.info(
256+
"[APPOINTMENT ATTENDED] Attended-yesterday flow completed successfully"
257+
)

utils/oracle/subject_selector.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,46 @@ def get_subject_for_manual_cease(criteria: dict) -> str:
5353
nhs_number = result_df["subject_nhs_number"].iloc[0]
5454
logging.info(f"[SUBJECT SELECTOR] Found subject NHS number: {nhs_number}")
5555
return nhs_number
56+
57+
@staticmethod
58+
def get_subject_for_pre_invitation(criteria: dict) -> str:
59+
"""
60+
Retrieves a subject NHS number suitable for pre-invitation scenarios,
61+
based on dynamically provided selection criteria.
62+
63+
Args:
64+
criteria (dict): Dictionary of filtering conditions to select a subject.
65+
66+
Returns:
67+
str: The NHS number of the selected subject.
68+
69+
Raises:
70+
ValueError: If no subject is found matching the criteria.
71+
"""
72+
logging.info(
73+
f"[SUBJECT SELECTOR] Searching for pre-invitation subject using criteria: {criteria}"
74+
)
75+
76+
hub_code = criteria.get("subject hub code", "BCS02")
77+
user_details = UserTools.retrieve_user(f"Hub Manager at {hub_code}")
78+
user = UserTools.get_user_object(user_details)
79+
subject = Subject()
80+
81+
query_builder = SubjectSelectionQueryBuilder()
82+
query, bind_vars = query_builder.build_subject_selection_query(
83+
criteria=criteria,
84+
user=user,
85+
subject=subject,
86+
)
87+
88+
logging.debug(
89+
f"[SUBJECT SELECTOR] Executing query:\n{query}\nWith bind variables: {bind_vars}"
90+
)
91+
result_df = OracleDB().execute_query(query, bind_vars)
92+
93+
if result_df.empty:
94+
raise ValueError("No subject found for pre-invitation scenario.")
95+
96+
nhs_number = result_df["subject_nhs_number"].iloc[0]
97+
logging.info(f"[SUBJECT SELECTOR] Found subject NHS number: {nhs_number}")
98+
return nhs_number

0 commit comments

Comments
 (0)