Skip to content

Commit c8e4c61

Browse files
Feature/bcss 21304 selenium0to playwright fobtregressiontests scenario 2 (#127)
<!-- markdownlint-disable-next-line first-line-heading --> ## Description <!-- Describe your changes in detail. --> ## Context This covers the migration of the fobt regression tests scenario 2 <!-- Why is this change required? What problem does it solve? --> ## Type of changes This is part of the selenium to playwright migration work <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply. --> - [x] Refactoring (non-breaking change) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would change existing functionality) - [ ] Bug fix (non-breaking change which fixes an issue) ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply. --> - [x] I am familiar with the [contributing guidelines](https://github.com/nhs-england-tools/playwright-python-blueprint/blob/main/CONTRIBUTING.md) - [x] I have followed the code style of the project - [x] I have added tests to cover my changes (where appropriate) - [x] I have updated the documentation accordingly - [x] This PR is a result of pair or mob programming --- ## Sensitive Information Declaration To ensure the utmost confidentiality and protect your and others privacy, we kindly ask you to NOT including [PII (Personal Identifiable Information) / PID (Personal Identifiable Data)](https://digital.nhs.uk/data-and-information/keeping-data-safe-and-benefitting-the-public) or any other sensitive data in this PR (Pull Request) and the codebase changes. We will remove any PR that do contain any sensitive information. We really appreciate your cooperation in this matter. - [x] I confirm that neither PII/PID nor sensitive data are included in this PR and the codebase changes. --------- Co-authored-by: Adriano Aru <[email protected]> Co-authored-by: adrianoaru-nhs <[email protected]>
1 parent 1da5d8f commit c8e4c61

File tree

7 files changed

+290
-6
lines changed

7 files changed

+290
-6
lines changed

pages/communication_production/batch_list_page.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from playwright.sync_api import Page, expect, Locator
22
from pages.base_page import BasePage
33
from datetime import datetime
4+
from pages.communication_production.communications_production_page import (
5+
CommunicationsProductionPage,
6+
)
47
from utils.calendar_picker import CalendarPicker
58
from utils.table_util import TableUtils
69
import logging
@@ -204,6 +207,14 @@ def select_first_batch_row(self, table_selector: str, timeout_ms: int = 0) -> No
204207
), f"No batch links found in table '{table_selector}'"
205208
first_link.click()
206209

210+
def navigate_to_active_batch_list_page(self) -> None:
211+
"""
212+
Navigates to the active batch list page from anywhere in bcss (providing the main menu link is displayed).
213+
"""
214+
self.click_main_menu_link()
215+
self.go_to_communications_production_page()
216+
CommunicationsProductionPage(self.page).go_to_active_batch_list_page()
217+
207218

208219
class ActiveBatchListPage(BatchListPage):
209220
"""Active Batch List Page-specific methods."""
@@ -216,7 +227,10 @@ def select_first_active_batch(self) -> None:
216227
self.select_first_batch_row(self.table_selector, timeout_ms=10000)
217228

218229
def is_batch_present(self, batch_type: str) -> bool:
219-
"""Checks if a batch of the given type exists in the active batch list."""
230+
"""Checks if a batch of the given type exists in the active batch list.
231+
Args:
232+
batch_type (str): The type of the batch to check for e.g. "S1 - Pre-invitation (FIT)"
233+
"""
220234
locator = self.page.locator(
221235
f"{self.table_selector} tbody tr td", has_text=batch_type
222236
)

pages/screening_subject_search/subject_screening_summary_page.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ def __init__(self, page: Page):
8181
"td.epihdr_label:text('Screening Status') + td.epihdr_data"
8282
)
8383
self.latest_event_status_cell = self.page.locator(
84-
"table#subjectSummaryTable tr:has(td:text('Latest Event Status')) td.epihdr_data"
85-
).nth(0)
84+
"td.epihdr_label:text('Latest Event Status') + td.epihdr_data"
85+
)
8686

8787
def wait_for_page_title(self) -> None:
8888
"""Waits for the page to be the Subject Screening Summary"""
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
import pytest
2+
import logging
3+
from datetime import datetime
4+
from playwright.sync_api import Page
5+
from pages.communication_production.batch_list_page import ActiveBatchListPage
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 pages.communication_production.batch_list_page import BatchListPage
17+
from pages.logout.log_out_page import LogoutPage
18+
19+
20+
@pytest.mark.vpn_required
21+
@pytest.mark.regression
22+
@pytest.mark.fobt_regression_tests
23+
def test_scenario_2(page: Page) -> None:
24+
"""
25+
Scenario: 2: Normal kit reading
26+
27+
S1-S9-S10-S43-S2-S158-S159-C203 [SSCL4a]
28+
29+
This scenario tests the basic scenario where a subject returns their initial test kit which gives a normal result.
30+
31+
Scenario summary:
32+
> Create a new subject in the FOBT age range > Inactive
33+
> Run the FOBT failsafe trawl > Call
34+
> Run the database transition to invite them for FOBT screening > S1(1.1)
35+
> Process S1 letter batch > S9 (1.1)
36+
> Run timed events > creates S9 letter (1.1)
37+
> Process S9 letter batch > S10 (1.1)
38+
> Log kit > S43 (1.2)
39+
> Read kit with NORMAL result > S2 (1.3)
40+
> Process S2 letter batch > S158 (1.3)
41+
> Process S158 letter batch > S159 (1.3) > C203 (1.13)
42+
> Check recall [SSCL4a]
43+
"""
44+
summary_page = SubjectScreeningSummaryPage(page)
45+
logging.info("[TEST START] Regression - fobt normal kit reading")
46+
47+
# Given I log in to BCSS "England" as user role "Hub Manager"
48+
user_role = UserTools.user_login(
49+
page, "Hub Manager State Registered at BCS01", return_role_type=True
50+
)
51+
if user_role is None:
52+
raise ValueError("User cannot be assigned to a UserRoleType")
53+
54+
# And I create a subject that meets the following criteria:
55+
requirements = {
56+
"age (y/d)": "66/130",
57+
"active gp practice in hub/sc": "BCS01/BCS001",
58+
}
59+
nhs_no = CreateSubjectSteps().create_custom_subject(requirements, user_role)
60+
if nhs_no is None:
61+
pytest.fail("Failed to create subject: NHS number not returned.")
62+
63+
# Then Comment: NHS number
64+
logging.info(f"[SUBJECT CREATED] Created subject's NHS number: {nhs_no}")
65+
66+
# And my subject has been updated as follows:
67+
subject_assertion(
68+
nhs_no,
69+
{
70+
"subject age": "66",
71+
"subject has episodes": "No",
72+
"screening status": "Inactive",
73+
},
74+
)
75+
76+
# Navigate to subject summary page in UI
77+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
78+
79+
# Assert subject details in the UI
80+
summary_page.assert_subject_age(66)
81+
summary_page.assert_screening_status("Inactive")
82+
logging.info("[UI ASSERTIONS COMPLETE] Updated subject details checked in the UI")
83+
84+
# When I run the FOBT failsafe trawl for my subject
85+
CallAndRecallUtils().run_failsafe(nhs_no)
86+
87+
# Then my subject has been updated as follows:
88+
subject_assertion(
89+
nhs_no,
90+
{
91+
"subject has episodes": "No",
92+
"Screening Due Date": "Last Birthday",
93+
"Screening due date date of change": "Today",
94+
"Screening Due Date Reason": "Failsafe Trawl",
95+
"screening status": "Call",
96+
"Screening Status Date of Change": "Today",
97+
"Screening Status Reason": "Failsafe Trawl",
98+
},
99+
)
100+
101+
# Navigate to subject summary page in UI
102+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
103+
104+
# Assert subject details in the UI
105+
summary_page.assert_screening_status("Call")
106+
logging.info("[UI ASSERTIONS COMPLETE] Updated subject details checked in the UI")
107+
108+
# When I invite my subject for FOBT screening
109+
CallAndRecallUtils().invite_subject_for_fobt_screening(nhs_no, user_role)
110+
111+
# Then my subject has been updated as follows:
112+
subject_assertion(
113+
nhs_no,
114+
{
115+
"latest event status": "S1 Selected for Screening",
116+
"latest episode kit class": "FIT",
117+
"latest episode type": "FOBT",
118+
},
119+
)
120+
121+
# Then there is a "S1" letter batch for my subject with the exact title "Pre-invitation (FIT)"
122+
# When I process the open "S1" letter batch for my subject
123+
# Then there is a "S9" letter batch for my subject with the exact title "Invitation & Test Kit (FIT)"
124+
batch_processing(
125+
page, "S1", "Pre-invitation (FIT)", "S9 - Pre-invitation Sent", True
126+
)
127+
128+
# Then my subject has been updated as follows:
129+
subject_assertion(
130+
nhs_no,
131+
{
132+
"latest event status": "S9 - Pre-invitation Sent",
133+
},
134+
)
135+
136+
# When I process the open "S9" letter batch for my subject
137+
batch_processing(
138+
page,
139+
"S9",
140+
"Invitation & Test Kit (FIT)",
141+
"S10 - Invitation & Test Kit Sent",
142+
True,
143+
)
144+
145+
# Then my subject has been updated as follows:
146+
subject_assertion(
147+
nhs_no,
148+
{
149+
"latest event status": "S10 - Invitation & Test Kit Sent",
150+
},
151+
)
152+
153+
# When I log my subject's latest unlogged FIT kit
154+
fit_kit = FitKitGeneration().get_fit_kit_for_subject_sql(nhs_no, False, False)
155+
sample_date = datetime.now()
156+
FitKitLogged().log_fit_kits(page, fit_kit, sample_date)
157+
158+
# Then my subject has been updated as follows:
159+
subject_assertion(
160+
nhs_no,
161+
{
162+
"latest event status": "S43 Kit Returned and Logged (Initial Test)",
163+
},
164+
)
165+
166+
# Navigate to subject summary page in UI
167+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
168+
169+
# Assert subject details in the UI
170+
summary_page.assert_latest_event_status(
171+
"S43 - Kit Returned and Logged (Initial Test)"
172+
)
173+
logging.info("[UI ASSERTIONS COMPLETE] Updated subject details checked in the UI")
174+
175+
# When I read my subject's latest logged FIT kit as "NORMAL"
176+
FitKitLogged().read_latest_logged_kit(user_role, 2, fit_kit, "NORMAL")
177+
178+
# Then my subject has been updated as follows:
179+
subject_assertion(
180+
nhs_no,
181+
{
182+
"latest event status": "S2 Normal",
183+
},
184+
)
185+
186+
# Navigate to subject summary page in UI
187+
screening_subject_page_searcher.navigate_to_subject_summary_page(page, nhs_no)
188+
189+
# Assert subject details in the UI
190+
summary_page.assert_latest_event_status("S2 - Normal")
191+
logging.info("[UI ASSERTIONS COMPLETE] Updated subject details checked in the UI")
192+
193+
# And there is a "S2" letter batch for my subject with the exact title "Subject Result (Normal)"
194+
# When I process the open "S2" letter batch for my subject
195+
batch_processing(
196+
page,
197+
"S2",
198+
"Subject Result (Normal)",
199+
"S158 - Subject Discharge Sent (Normal)",
200+
True,
201+
)
202+
203+
# Then my subject has been updated as follows:
204+
subject_assertion(
205+
nhs_no,
206+
{
207+
"latest event status": "S158 Subject Discharge Sent (Normal)",
208+
},
209+
)
210+
211+
# And there is a "S158" letter batch for my subject with the exact title "GP Result (Normal)"
212+
# When I process the open "S158" letter batch for my subject
213+
batch_processing(
214+
page,
215+
"S158",
216+
"GP Result (Normal)",
217+
"S159 - GP Discharge Sent (Normal)",
218+
True,
219+
)
220+
221+
# Then my subject has been updated as follows:
222+
subject_assertion(
223+
nhs_no,
224+
{
225+
"calculated screening due date": "2 years from latest S158 event",
226+
"calculated lynch due date": "Null",
227+
"calculated surveillance due date": "Null",
228+
"ceased confirmation date": "Null",
229+
"ceased confirmation details": "Null",
230+
"ceased confirmation user ID": "Null",
231+
"clinical reason for cease": "Null",
232+
"latest episode accumulated result": "Definitive normal FOBt outcome",
233+
"latest episode recall calculation method": "Date of last patient letter",
234+
"latest episode recall episode type": "FOBT screening",
235+
"latest episode recall surveillance type": "Null",
236+
"latest episode status": "Closed",
237+
"latest episode status reason": "Episode Complete",
238+
"lynch due date": "Null",
239+
"lynch due date date of change": "Null",
240+
"lynch due date reason": "Null",
241+
"screening status": "Recall",
242+
# 'Screening status date of change' intentionally omitted as status may or may not have changed
243+
"screening status reason": "Recall",
244+
"screening due date": "Calculated screening due date",
245+
"screening due date date of change": "Today",
246+
"screening due date reason": "Recall",
247+
"surveillance due date": "Null",
248+
"surveillance due date date of change": "Unchanged",
249+
"surveillance due date reason": "Unchanged",
250+
},
251+
)
252+
253+
logging.info("[TEST COMPLETE] Scenario 2 passed all assertions")
254+
LogoutPage(page).log_out()

utils/batch_processing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ def batch_processing(
3131
save_csv_as_df: bool = False,
3232
) -> Optional[pd.DataFrame]:
3333
"""
34-
This is used to process batches.
34+
Processes a batch in the BCSS UI by navigating to the batch, extracting subject NHS numbers (from the database or PDF),
35+
verifying each subject's event status in the UI, and optionally running timed events or returning batch data as a DataFrame.
3536
3637
Args:
3738
page (Page): This is the playwright page object

utils/call_and_recall_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def run_failsafe(self, nhs_no: str) -> None:
5555
result_cursor.close()
5656
cur.close()
5757
conn.close()
58-
logging.info(f"END: failsafe stored proc executed for {nhs_no}")
58+
logging.info(f"[FAILSAFE TRAWL RUN] FOBT failsafe trawl run for subject {nhs_no}")
5959

6060
def invite_subject_for_fobt_screening(
6161
self, nhs_no: str, user_role: UserRoleType

utils/screening_subject_page_searcher.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,18 @@ def search_subject_episode_by_nhs_number(page: Page, nhs_number: str) -> None:
240240
SearchAreaSearchOptions.SEARCH_AREA_WHOLE_DATABASE.value
241241
)
242242
SubjectScreeningPage(page).click_search_button()
243+
244+
245+
def navigate_to_subject_summary_page(page, nhs_no: str) -> None:
246+
"""
247+
Navigates to the subject summary page in the UI using the given NHS number.
248+
This method can be used from anywhere in bcss providing the main menu link is displayed.
249+
250+
Args:
251+
page (Page): The Playwright page object.
252+
nhs_no (str): The NHS number of the subject to view.
253+
"""
254+
BasePage(page).click_main_menu_link()
255+
BasePage(page).go_to_screening_subject_search_page()
256+
search_subject_by_nhs_number(page, nhs_no)
257+
logging.info(f"[SUBJECT VIEW] Subject {nhs_no} loaded in UI")

utils/subject_assertion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
def subject_assertion(nhs_number: str, criteria: dict) -> None:
99
"""
10-
Asserts that a subject with the given NHS number exists and matches the provided criteria.
10+
Asserts that a subject with the given NHS number exists in the database and matches the provided criteria.
1111
Args:
1212
nhs_number (str): The NHS number of the subject to find.
1313
criteria (dict): A dictionary of criteria to match against the subject's attributes.

0 commit comments

Comments
 (0)