Skip to content

Commit 2d2508d

Browse files
committed
Added scenarios for fit self refer letter processing
1 parent ab85423 commit 2d2508d

File tree

8 files changed

+202
-144
lines changed

8 files changed

+202
-144
lines changed

pages/call_and_recall/generate_invitations_page.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from utils.oracle.subject_selection_query_builder import SubjectSelectionQueryBuilder
77
from classes.user import User
88
from classes.subject import Subject
9+
from utils.table_util import TableUtils
910

1011

1112
class GenerateInvitationsPage(BasePage):
@@ -108,6 +109,68 @@ def wait_for_invitation_generation_complete(
108109
logging.warning("No S1 Digital Leaflet batch will be generated")
109110
return False
110111

112+
def wait_for_self_referral_invitation_generation_complete(
113+
self, expected_minimum: int = 1
114+
) -> bool:
115+
"""
116+
Waits until the invitations have been generated and checks that 'Self Referrals Generated' meets the expected threshold.
117+
118+
Args:
119+
expected_minimum (int): Minimum number of self-referrals expected to be generated (default is 1)
120+
121+
Returns:
122+
bool: True if threshold is met, False otherwise.
123+
"""
124+
# Reuse the existing table completion logic — consider extracting this into a shared method later
125+
timeout = 120000
126+
wait_interval = 5000
127+
elapsed = 0
128+
logging.info(
129+
"[WAIT] Waiting for self-referral invitation generation to complete"
130+
)
131+
132+
while elapsed < timeout:
133+
table_text = self.display_rs.text_content()
134+
if table_text is None:
135+
pytest.fail("Failed to retrieve table text content")
136+
137+
if "Failed" in table_text:
138+
pytest.fail("Invitation has failed to generate")
139+
elif "Queued" in table_text or "In Progress" in table_text:
140+
self.click_refresh_button()
141+
self.page.wait_for_timeout(wait_interval)
142+
elapsed += wait_interval
143+
else:
144+
break
145+
146+
try:
147+
expect(self.display_rs).to_contain_text("Completed")
148+
logging.info(
149+
f"[STATUS] Generation finished after {elapsed / 1000:.1f} seconds"
150+
)
151+
except Exception as e:
152+
pytest.fail(f"[ERROR] Invitations not generated successfully: {str(e)}")
153+
154+
# Dynamically check 'Self Referrals Generated'
155+
table_utils = TableUtils(self.page, "#displayRS")
156+
157+
try:
158+
value_text = table_utils.get_footer_value_by_header(
159+
"Self Referrals Generated"
160+
)
161+
value = int(value_text.strip())
162+
logging.info(f"[RESULT] 'Self Referrals Generated' = {value}")
163+
except Exception as e:
164+
pytest.fail(f"[ERROR] Unable to read 'Self Referrals Generated': {str(e)}")
165+
166+
if value >= expected_minimum:
167+
return True
168+
else:
169+
logging.warning(
170+
f"[ASSERTION] Expected at least {expected_minimum}, but got {value}"
171+
)
172+
return False
173+
111174
def check_self_referral_subjects_ready(
112175
self, search_scope: str, volume: str
113176
) -> None:

pages/communication_production/batch_list_page.py

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,16 @@ def enter_id_filter(self, search_text: str) -> None:
9191
self.id_filter.fill(search_text)
9292
self.id_filter.press("Enter")
9393

94-
def enter_type_filter(self, search_text: str) -> None:
95-
self.type_filter.fill(search_text)
96-
self.type_filter.press("Enter")
94+
def enter_type_filter(self, option_text: str) -> None:
95+
"""
96+
Selects the given option from the 'Type' filter dropdown.
97+
98+
Args:
99+
option_text (str): The visible label of the option to select (e.g. "Original", "All")
100+
"""
101+
self.type_filter.select_option(label=option_text)
102+
logging.info(f"[FILTER] Type filter set to '{option_text}'")
103+
97104

98105
def enter_original_filter(self, search_text: str) -> None:
99106
self.original_filter.fill(search_text)
@@ -184,19 +191,6 @@ def is_batch_present(self, batch_type: str) -> bool:
184191
)
185192
return locator.count() > 0
186193

187-
def prepare_batch(self, batch_type: str) -> None:
188-
"""Finds and clicks the Prepare button for the specified batch type."""
189-
row = (
190-
self.page.locator(f"{self.table_selector} tbody tr")
191-
.filter(has=self.page.locator("td", has_text=batch_type))
192-
.first
193-
)
194-
195-
prepare_button = row.locator("a", has_text="Prepare").first
196-
expect(prepare_button).to_be_visible()
197-
prepare_button.click()
198-
expect(row).not_to_be_visible(timeout=5000)
199-
200194
def get_open_original_batch_row(self) -> Locator | None:
201195
"""
202196
Returns the first table row where:
@@ -298,29 +292,26 @@ def __init__(self, page: Page):
298292
def assert_letter_component_present(self, letter_type: str, format: str) -> None:
299293
"""
300294
Asserts that a letter component with the given type and format is listed.
295+
This version works with div-based structures, not tables.
301296
302297
Args:
303-
letter_type (str): The letter type (e.g. "Invitation & Test Kit (Self-referral) (FIT)")
304-
format (str): The file format (e.g. "PDF-A4-V03")
298+
letter_type (str): Visible component description
299+
format (str): File format label (e.g., "PDF-A4-V03", "FIT-KIT-CSV")
305300
"""
306-
row_locator = self.letter_table.locator("tbody tr")
301+
descriptions = self.page.locator("div.letterDescription")
302+
formats = self.page.locator("div.letterFormat")
307303
match_found = False
308304

309-
for i in range(row_locator.count()):
310-
row = row_locator.nth(i)
311-
type_cell = row.locator("td").nth(1)
312-
format_cell = row.locator("td").nth(2)
313-
305+
for i in range(min(descriptions.count(), formats.count())):
314306
if (
315-
letter_type.lower() in type_cell.inner_text().lower()
316-
and format.lower() in format_cell.inner_text().lower()
307+
letter_type.lower() in descriptions.nth(i).inner_text().lower()
308+
and format.lower() in formats.nth(i).inner_text().lower()
317309
):
318310
match_found = True
319311
break
320312

321-
assert (
322-
match_found
323-
), f"Letter type '{letter_type}' with format '{format}' not found"
313+
assert match_found, f"Letter type '{letter_type}' with format '{format}' not found"
314+
324315

325316
def get_first_subject_nhs_number(self) -> str:
326317
"""

pages/communication_production/manage_active_batch_page.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ def assert_active_batch_details_visible(self) -> None:
3737
page_title = self.page.locator("#page-title")
3838
expect(page_title).to_have_text("Manage Active Batch")
3939

40-
def prepare_and_print(self) -> None:
41-
"""Clicks the Prepare and Print button."""
42-
button = self.page.get_by_role("button", name="Prepare and Print")
43-
expect(button).to_be_enabled()
44-
button.click()
45-
4640
def retrieve_and_confirm_letters(self) -> None:
4741
"""Clicks the Retrieve and Confirm Letters button."""
4842
button = self.page.get_by_role("button", name="Retrieve and Confirm Letters")

pages/screening_subject_search/subject_screening_search_page.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,13 @@ def click_send_kit_button(self) -> None:
192192
f"[PAGE TRANSITION FAILED] Did not reach Send a kit page: {e}"
193193
)
194194
raise
195-
196-
def complete_send_kit_form(self, request_from: str = "Subject", previous_kit_status: str = "Lost", note_text: str = "Test") -> None:
195+
196+
def complete_send_kit_form(
197+
self,
198+
request_from: str = "Subject",
199+
previous_kit_status: str = "Lost",
200+
note_text: str = "Test",
201+
) -> None:
197202
"""
198203
Completes the 'Send a kit' form by:
199204
- Selecting who requested the kit
@@ -218,6 +223,17 @@ def complete_send_kit_form(self, request_from: str = "Subject", previous_kit_sta
218223
expect(send_button).to_be_enabled()
219224
send_button.click()
220225

226+
# Handle confirmation modal if it appears
227+
success_button = self.page.locator("button[data-testid='successButton']")
228+
if success_button.is_visible():
229+
expect(success_button).to_be_enabled()
230+
success_button.click()
231+
logging.info("[MODAL CLOSED] Success modal dismissed")
232+
else:
233+
logging.warning(
234+
"[MODAL NOT FOUND] Success button not visible after kit request"
235+
)
236+
221237
logging.info("[KIT REQUEST] 'Send a kit' form submitted successfully")
222238

223239

pages/screening_subject_search/subject_screening_summary_page.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ def __init__(self, page: Page):
6060
self.temporary_address_popup = self.page.locator("#idTempAddress")
6161
self.close_button = self.page.get_by_role("img", name="close")
6262

63+
# List of Subject Episodes - page filters
64+
self.view_events_link = self.page.get_by_role("link", name="events")
65+
6366
def wait_for_page_title(self) -> None:
6467
"""Waits for the page to be the Subject Screening Summary"""
6568
self.subject_screening_summary.wait_for()
@@ -227,36 +230,35 @@ def click_close_button(self) -> None:
227230
"""Click on the close button in the temporary address popup."""
228231
self.click(self.close_button)
229232

233+
def click_view_events_link(self) -> None:
234+
"""Click on the 'View Events' link."""
235+
self.click(self.view_events_link)
236+
230237
def assert_view_letter_links_for_event(
231238
self, event_name: str, expected_count: int
232239
) -> None:
233-
"""
234-
Asserts that the specified event row contains the expected number of 'View Letter' links.
235-
236-
Args:
237-
event_name (str): The name of the event to locate (e.g. "S84 - Invitation and Test Kit Sent (Self-referral)")
238-
expected_count (int): The expected number of 'View Letter' links in that row
239-
"""
240-
# Locate the event row by its name
240+
# Locate the row where the 3rd <td> contains the target event status
241241
event_row = (
242-
self.page.locator("table#subjectEvents tbody tr")
243-
.filter(has=self.page.locator("td", has_text=event_name))
242+
self.page.locator("table#displayRS tbody tr")
243+
.filter(has=self.page.locator("td:nth-child(3)", has_text=event_name))
244244
.first
245245
)
246246

247+
event_row.wait_for(timeout=10000)
248+
247249
if event_row.count() == 0:
248-
raise RuntimeError(f"Event row for '{event_name}' not found")
250+
raise RuntimeError(f"[ERROR] Event row for '{event_name}' not found")
249251

250-
# Count the 'View Letter' links in that row
251-
view_links = event_row.locator("a", has_text="View Letter")
252-
actual_count = view_links.count()
252+
# Count the number of 'View Letter' links inside the 5th column (Item)
253+
letter_links = event_row.locator("td:nth-child(5) a", has_text="View Letter")
254+
actual_count = letter_links.count()
253255

254256
logging.info(
255-
f"Found {actual_count} 'View Letter' links for event '{event_name}'"
257+
f"[DEBUG] Found {actual_count} 'View Letter' links for event: {event_name}"
256258
)
257259
assert (
258260
actual_count == expected_count
259-
), f"Expected {expected_count} 'View Letter' links for event '{event_name}', but found {actual_count}"
261+
), f"[ASSERTION FAILED] Expected {expected_count} 'View Letter' links for '{event_name}', but found {actual_count}"
260262

261263

262264
class ChangeScreeningStatusOptions(Enum):

0 commit comments

Comments
 (0)