Skip to content

Commit f448ae3

Browse files
vidhya-chandra1Andyg79
authored andcommitted
Feature/bcss 20608 new regression tests subject spine retrieval (#112)
<!-- markdownlint-disable-next-line first-line-heading --> ## Description Selenium to Playwright - Regression Tests - Subject - Spine Retrieval <!-- Describe your changes in detail. --> ## Context New Code is implemented in below files 1) Tests File --> subject_diagnosis_date --> test_subject_episodes_diagnosis_spine_retrieval.py 2) POM --> subject_diagnosis_date --> subject_diagnosis_date.py 3) pytest.ini <!-- Why is this change required? What problem does it solve? --> ## Type of changes <!-- 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) - [ ] I have updated the documentation accordingly - [ ] 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.
1 parent 931f2fc commit f448ae3

File tree

5 files changed

+134
-1
lines changed

5 files changed

+134
-1
lines changed

pages/screening_subject_search/subject_screening_summary_page.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class SubjectScreeningSummaryPage(BasePage):
1111
def __init__(self, page: Page):
1212
super().__init__(page)
1313
self.page = page
14+
self.spine_url = "https://bcss-bcss-18680-ddc-bcss.k8s-nonprod.texasplatform.uk/servlet/SpineSearchScreen"
15+
1416
# Subject Screening Summary - page filters
1517
self.subject_screening_summary = self.page.get_by_role(
1618
"cell", name="Subject Screening Summary", exact=True
@@ -30,6 +32,7 @@ def __init__(self, page: Page):
3032
self.individual_letters = self.page.get_by_role(
3133
"link", name="Individual Letters"
3234
)
35+
self.retrieve_data_link = self.page.get_by_role("link", name="Retrieve Data from Spine")
3336
self.patient_contacts = self.page.get_by_role("link", name="Patient Contacts")
3437
self.more = self.page.get_by_role("link", name="more")
3538
self.change_screening_status = self.page.get_by_label("Change Screening Status")
@@ -310,6 +313,14 @@ def click_book_practitioner_clinic_button(self) -> None:
310313
"""Click on the 'Book Practitioner Clinic' button"""
311314
self.click(self.book_practitioner_clinic_button)
312315

316+
def navigate_to_spine_search(self) -> None:
317+
"""
318+
Navigates to the Spine Search screen by clicking the appropriate link
319+
and loading the target URL.
320+
"""
321+
#self.retrieve_data_link.click()
322+
self.click(self.retrieve_data_link)
323+
self.page.goto(self.spine_url)
313324

314325
class ChangeScreeningStatusOptions(Enum):
315326
"""Enum for Change Screening Status options."""
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from datetime import datetime
2+
from playwright.sync_api import Page, Locator
3+
from pages.base_page import BasePage
4+
from typing import Dict
5+
from utils.calendar_picker import CalendarPicker
6+
7+
class SpineSearchPage(BasePage):
8+
"""
9+
Page object for the Spine Search screen, enabling demographic searches
10+
and data retrieval from the Spine system.
11+
"""
12+
def __init__(self, page: Page):
13+
super().__init__(page)
14+
self.page = page
15+
16+
# Define locators
17+
self.demographics_radio = self.page.get_by_role("radio", name="Demographics")
18+
self.date_of_birth_field = self.page.locator("#dateOfBirth")
19+
self.surname_field = self.page.locator("#surname")
20+
self.forename_field = self.page.locator("#forename")
21+
self.gender_dropdown = self.page.locator("#gender")
22+
self.postcode_field = self.page.locator("#postcode")
23+
self.search_button = self.page.get_by_role("button", name="Search")
24+
self.alert_locator= self.page.locator(".spine-alert")
25+
26+
# CalendarPicker utility instance
27+
self.calendar_picker = CalendarPicker(self.page)
28+
29+
def select_demographic_search(self) -> None:
30+
"""
31+
Selects the 'Demographics' radio button to enable demographic search mode.
32+
"""
33+
self.demographics_radio.check()
34+
35+
def enter_search_criteria(
36+
self, dob: str, surname: str, forename: str, gender: str, postcode: str
37+
) -> None:
38+
"""
39+
Fills in the demographic search fields with the provided values.
40+
41+
Args:
42+
dob (str): Date of birth in string format (e.g., "06 May 1940").
43+
surname (str): Subject's surname.
44+
forename (str): Subject's forename.
45+
gender (str): Gender value ("Male" or "Female").
46+
postcode (str): Subject's postcode.
47+
"""
48+
49+
# Convert dob string to datetime object
50+
dob_dt = datetime.strptime(dob, "%d %b %Y") # Adjust format if needed
51+
self.click(self.date_of_birth_field)
52+
self.calendar_picker.v2_calendar_picker(dob_dt) # dob should be in a supported format, e.g. "YYYY-MM-DD"
53+
self.surname_field.fill(surname)
54+
self.forename_field.fill(forename)
55+
gender_option = {"Male": "1", "Female": "2"}.get(gender, "1")
56+
self.gender_dropdown.select_option(gender_option)
57+
self.postcode_field.fill(postcode)
58+
59+
def perform_search(self) -> None:
60+
"""
61+
Clicks the 'Search' button to initiate the Spine demographic search.
62+
"""
63+
self.click(self.search_button)
64+
65+
def get_spine_alert_message(self) -> str:
66+
"""
67+
Retrieves the text content of a visible spine alert message from the page.
68+
69+
This method waits for the alert element with the CSS class `.spine-alert` to become visible
70+
within a 5-second timeout. If the alert appears, its inner text is returned after stripping
71+
leading and trailing whitespace. If the alert does not appear within the timeout or an unexpected
72+
error occurs, an empty string is returned and the error is logged to the console.
73+
74+
Returns:
75+
str: The stripped text of the alert message if visible, otherwise an empty string.
76+
"""
77+
alert_locator = self.page.locator(".spine-alert")
78+
try:
79+
alert_locator.wait_for(state="visible", timeout=5000)
80+
return alert_locator.inner_text().strip()
81+
except TimeoutError:
82+
print("Alert message not visible within timeout.")
83+
return ""
84+
except Exception as e:
85+
print(f"Unexpected error while fetching alert: {e}")
86+
return ""

pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ markers =
4949
bcss_additional_tests: tests that are part of the BCSS additional tests test suite
5050
colonoscopy_dataset_tests: tests that are part of the colonoscopy datasets test suite
5151
fobt_diagnosis_date_entry_tests: tests that are part of fobt subject episodes record diagnosis date
52+
spine_retrieval_search_tests: tests that are part of subject spine retrieval demographics
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import pytest
2+
from playwright.sync_api import Page, expect
3+
from utils.user_tools import UserTools
4+
from pages.base_page import BasePage
5+
from pages.screening_subject_search.subject_spine_retrieval_search_page import SpineSearchPage
6+
from pages.screening_subject_search.subject_screening_summary_page import SubjectScreeningSummaryPage
7+
8+
@pytest.mark.regression
9+
@pytest.mark.spine_retrieval_search_tests
10+
def test_user_can_search_for_subject_spine_retrieval(page: Page) -> None:
11+
"""
12+
Tests to ensure that Spine searching is enabled for English users.
13+
"""
14+
# Step 1: Log in as Hub Manager - State Registered (England)
15+
UserTools.user_login(page, "Hub Manager State Registered at BCS01")
16+
BasePage(page).go_to_screening_subject_search_page()
17+
18+
# Step 2: Perform spine demographic search
19+
spine_page = SpineSearchPage(page)
20+
spine_page_summary = SubjectScreeningSummaryPage(page)
21+
spine_page_summary.navigate_to_spine_search()
22+
spine_page.select_demographic_search()
23+
spine_page.enter_search_criteria(
24+
dob="06 May 1940",
25+
surname="vickers",
26+
forename="rob",
27+
gender="Male",
28+
postcode="ex25se"
29+
)
30+
spine_page.perform_search()
31+
32+
# Step 3: Assert in-page alert message
33+
alert_message = spine_page.get_spine_alert_message()
34+
assert not alert_message, f"Unexpected alert shown: '{alert_message}'"
35+
f"Expected alert message not found. Got: '{alert_message}'"

utils/calendar_picker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def v2_calendar_picker_traverse_forward(
302302
if click_decade:
303303
self.click(self.page.get_by_text(str(decade), exact=True).first)
304304
if click_year:
305-
self.click(self.page.get_by_text(str(year), exact=True))
305+
self.click(self.page.locator("span.year", has_text=str(year)).first)
306306
if click_month:
307307
self.click(self.page.get_by_text(str(month_short)))
308308

0 commit comments

Comments
 (0)