Skip to content

Commit 36ba642

Browse files
Feature/bcss 20589 new regression release standard tests (#123)
<!-- markdownlint-disable-next-line first-line-heading --> ## Description Selenium to Playwright - Regression Tests - Release <!-- Describe your changes in detail. --> ## Context <!-- Why is this change required? What problem does it solve? --> As per JIRA Ticket, BCSS - 20589 New Code is implemented & also existing code is Refactored in below files. 1) subject_diagnosis_date/test_subject_hub_user_national.py 2) utils/screening_subject_page_searcher.py 3) pytest.ini ## 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) - [X] 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. --------- Co-authored-by: AndyG <[email protected]>
1 parent 6fea184 commit 36ba642

File tree

8 files changed

+249
-3
lines changed

8 files changed

+249
-3
lines changed

pages/alerts/alerts_page.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from playwright.sync_api import Page
2+
from pages.base_page import BasePage
3+
4+
5+
class AlertsPage(BasePage):
6+
def __init__(self, page: Page):
7+
super().__init__(page)
8+
self.refresh_alerts_link = self.page.get_by_role("link", name="Refresh alerts")
9+
10+
def click_refresh_alerts(self) -> None:
11+
"""Clicks the 'Refresh Alerts' link to trigger an update of alert messages."""
12+
self.refresh_alerts_link.click()
13+
14+
def is_refresh_alerts_visible(self, timeout=5000) -> bool:
15+
"""Returns True if the 'Refresh Alerts' link is visible within the given timeout."""
16+
return self.refresh_alerts_link.is_visible(timeout=timeout)

pages/gfobt_test_kits/gfobt_test_kits_page.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class GFOBTTestKitsPage(BasePage):
88
def __init__(self, page: Page):
99
super().__init__(page)
1010
self.page = page
11-
11+
self.test_kits_header = self.page.get_by_text("gFOBT Test Kits")
1212
self.test_kit_logging_page = self.page.get_by_role(
1313
"link", name="Test Kit Logging"
1414
)
@@ -35,3 +35,9 @@ def go_to_test_kit_result_page(self) -> None:
3535
def go_to_create_qc_kit_page(self) -> None:
3636
"""Navigate to the Create QC Kit page."""
3737
self.click(self.create_qc_kit_page)
38+
39+
def open_test_kits_report(self) -> None:
40+
"""Clicks the 'Test Kits' header to open the corresponding report section."""
41+
self.click(self.test_kits_header)
42+
43+

pages/organisations/organisations_page.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,29 @@
22
from pages.base_page import BasePage
33
from typing import List
44

5+
56
class OrganisationsPage(BasePage):
67
"""Organisations Page locators, and methods for interacting with the page."""
78

89
def __init__(self, page: Page):
910
super().__init__(page)
11+
self.page = page
12+
self.org_and_site_details_link = self.page.get_by_role(
13+
"link", name="Organisation and Site Details"
14+
)
15+
self.list_all_orgs_link = self.page.get_by_role(
16+
"link", name="List All Organisations"
17+
)
18+
self.list_all_sites_link = self.page.get_by_role("link", name="List All Sites")
19+
self.surveillance_link = self.page.get_by_role(
20+
"link", name="Surveillance", exact=True
21+
)
22+
self.manage_surveillance_review_link = self.page.get_by_role(
23+
"link", name="Manage Surveillance Review"
24+
)
25+
self.surveillance_review_summary_header = self.page.get_by_text(
26+
"Surveillance Review Summary"
27+
)
1028

1129
# Organisations page links
1230
self.screening_centre_parameters_page = self.page.get_by_role(
@@ -50,6 +68,21 @@ def go_to_bureau_page(self) -> None:
5068
"""Clicks the 'Bureau' link."""
5169
self.click(self.bureau_page)
5270

71+
def navigate_to_surveillance_review_summary(self) -> None:
72+
"""Navigates through the organisation pages to the Surveillance Review Summary."""
73+
self.click(self.org_and_site_details_link)
74+
self.click(self.list_all_orgs_link)
75+
self.click_back_button()
76+
self.click(self.list_all_sites_link)
77+
for _ in range(3):
78+
self.click_back_button()
79+
self.click(self.surveillance_link)
80+
self.click(self.manage_surveillance_review_link)
81+
self.page.goto(
82+
"https://bcss-bcss-18680-ddc-bcss.k8s-nonprod.texasplatform.uk/surveillance/review/summary"
83+
)
84+
85+
5386
class OrganisationSwitchPage:
5487
"""Page Object Model for interacting with the Organisation Switch page."""
5588

@@ -120,5 +153,3 @@ def get_logged_in_text(self) -> str:
120153
str: The text indicating the logged-in user's role or name.
121154
"""
122155
return self.login_info.inner_text()
123-
124-

pages/screening_practitioner_appointments/screening_practitioner_appointments_page.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ def __init__(self, page: Page):
1010
self.page = page
1111
# ScreeningPractitionerAppointments Page
1212
self.log_in_page = self.page.get_by_role("button", name="Log in")
13+
self.appointments_header = self.page.get_by_text("Screening Practitioner Appointments")
14+
1315
self.view_appointments_page = self.page.get_by_role(
1416
"link", name="View appointments"
1517
)
@@ -43,3 +45,9 @@ def go_to_patients_that_require_page(self) -> None:
4345
def go_to_set_availability_page(self) -> None:
4446
"""Click on the Set Availability link to navigate to the set availability page."""
4547
self.click(self.set_availability_link)
48+
49+
def open_appointments_report(self) -> None:
50+
"""Clicks the 'Appointments' header to open the related report section."""
51+
self.click(self.appointments_header)
52+
53+

pages/screening_subject_search/subject_screening_search_page.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pages.base_page import BasePage
44
from enum import Enum
55
from utils.calendar_picker import CalendarPicker
6+
from typing import Optional
67

78

89
class SubjectScreeningPage(BasePage):
@@ -65,6 +66,13 @@ def __init__(self, page: Page):
6566
"textarea[data-testid='reasonNote']"
6667
)
6768

69+
self.surname_field = self.page.locator("#A_C_Surname")
70+
self.forename_field = self.page.locator("#A_C_Forename")
71+
self.screening_status_dropdown = self.page.locator("#A_C_ScreeningStatus")
72+
self.episode_status_dropdown = self.page.locator("#A_C_EpisodeStatus")
73+
self.search_button = self.page.get_by_role("button", name="Search")
74+
self.back_link = self.page.get_by_role("link", name="Back", exact=True)
75+
6876
def click_clear_filters_button(self) -> None:
6977
"""Click the 'Clear Filters' button."""
7078
self.click(self.clear_filters_button)
@@ -206,6 +214,38 @@ def complete_send_kit_form(
206214

207215
logging.info("[KIT REQUEST] 'Send a kit' form submitted successfully")
208216

217+
def search_subject_with_args(
218+
self,
219+
surname: Optional[str] = None,
220+
forename: Optional[str] = None,
221+
screening_status: Optional[str] = None,
222+
episode_status: Optional[str] = None,
223+
) -> None:
224+
"""
225+
Searches for a subject using any combination of the provided criteria.
226+
227+
Args:
228+
surname (Optional[str]): Subject's surname.
229+
forename (Optional[str]): Subject's forename.
230+
screening_status (Optional[str]): Screening status code.
231+
episode_status (Optional[str]): Episode status code.
232+
"""
233+
# Fill in all provided fields before triggering any search
234+
if surname:
235+
self.surname_field.fill(surname)
236+
if forename:
237+
self.forename_field.fill(forename)
238+
if screening_status:
239+
self.screening_status_dropdown.select_option(screening_status)
240+
self.click(self.screening_status_dropdown)
241+
if episode_status:
242+
self.episode_status_dropdown.select_option(episode_status)
243+
244+
# Only click search if at least one field was filled
245+
if any([surname, forename, screening_status, episode_status]):
246+
self.click(self.search_button)
247+
self.click(self.back_link)
248+
209249

210250
class ScreeningStatusSearchOptions(Enum):
211251
"""Enum for Screening Status Search Options"""
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from playwright.sync_api import Page
2+
from pages.base_page import BasePage
3+
4+
5+
class SurveillanceSummaryPage(BasePage):
6+
"""Page object for navigating to and interacting with the Surveillance Review Summary section."""
7+
8+
def __init__(self, page: Page):
9+
super().__init__(page)
10+
11+
# Locators
12+
self.org_and_site_details_link = self.page.get_by_role(
13+
"link", name="Organisation and Site Details"
14+
)
15+
self.list_all_orgs_link = self.page.get_by_role(
16+
"link", name="List All Organisations"
17+
)
18+
self.list_all_sites_link = self.page.get_by_role("link", name="List All Sites")
19+
self.surveillance_link = self.page.get_by_role(
20+
"link", name="Surveillance", exact=True
21+
)
22+
self.manage_surveillance_review_link = self.page.get_by_role(
23+
"link", name="Manage Surveillance Review"
24+
)
25+
self.surveillance_review_summary_header = self.page.get_by_text(
26+
"Surveillance Review Summary"
27+
)
28+
self.back_link = self.page.get_by_role("link", name="Back", exact=True)
29+
30+
def navigate_to_surveillance_review_summary(self):
31+
"""Navigates through multiple UI steps to reach the Surveillance Review Summary section."""
32+
self.click(self.org_and_site_details_link)
33+
self.click(self.list_all_orgs_link)
34+
self.click(self.back_link)
35+
self.click(self.list_all_sites_link)
36+
for _ in range(3):
37+
self.click(self.back_link)
38+
self.click(self.surveillance_link)
39+
self.click(self.manage_surveillance_review_link)

pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,5 @@ markers =
5353
colonoscopy_dataset_tests: tests that are part of the colonoscopy datasets test suite
5454
fobt_diagnosis_date_entry_tests: tests that are part of fobt subject episodes record diagnosis date
5555
spine_retrieval_search_tests: tests that are part of subject spine retrieval demographics
56+
hub_user_tests: tests that are part of the hub user test suite
5657
fobt_regression_tests: tests that are part of the fobt regression test suite
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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.alerts.alerts_page import AlertsPage
6+
from pages.gfobt_test_kits.gfobt_test_kits_page import GFOBTTestKitsPage
7+
from pages.screening_practitioner_appointments.screening_practitioner_appointments_page import (
8+
ScreeningPractitionerAppointmentsPage,
9+
)
10+
from pages.screening_subject_search.subject_screening_search_page import (
11+
SubjectScreeningPage,
12+
)
13+
from pages.surveillance.surveillance_summary_review_page import SurveillanceSummaryPage
14+
15+
16+
# Scenario 1
17+
@pytest.mark.regression
18+
@pytest.mark.hub_user_tests
19+
def test_hub_user_alerts_populated(page: Page) -> None:
20+
"""
21+
Scenario: Hub User - Alerts populated
22+
This test ensures that the alerts have at least been populated for the user within a reasonable amount of time.
23+
"""
24+
# Step 1: Log in as Hub Manager - State Registered (England)
25+
UserTools.user_login(page, "Hub Manager State Registered at BCS01")
26+
BasePage(page).click_refresh_alerts_link()
27+
28+
# Step 2: Assert the refresh alerts button is visible
29+
alerts_page = AlertsPage(page)
30+
alerts_page.click_refresh_alerts()
31+
expect(alerts_page.refresh_alerts_link).to_be_visible(timeout=5000)
32+
33+
34+
# Scenario 2
35+
@pytest.mark.regression
36+
@pytest.mark.hub_user_tests
37+
def test_hub_user_kits_logged_not_read_report(page: Page) -> None:
38+
"""
39+
Scenario: Hub User - Kits Logged Not Read report
40+
This test ensures that if available, the Kits Logged Not Read report loads within a reasonable amount of time.
41+
"""
42+
# Step 1: Log in as Hub Manager - State Registered (England)
43+
UserTools.user_login(page, "Hub Manager State Registered at BCS01")
44+
BasePage(page).go_to_gfobt_test_kits_page()
45+
46+
# Step 2: Assert the Kits Logged Not Read report loads as expected
47+
test_kits_page = GFOBTTestKitsPage(page)
48+
test_kits_page.open_test_kits_report()
49+
expect(test_kits_page.test_kits_header).to_be_visible(timeout=5000)
50+
51+
52+
# Scenario 3
53+
@pytest.mark.regression
54+
@pytest.mark.hub_user_tests
55+
def test_hub_user_people_requiring_colonoscopy_assessment_report(page: Page) -> None:
56+
"""
57+
Scenario: Hub User - People Requiring Colonoscopy Assessment report
58+
This test ensures that if available, the People Requiring Colonoscopy Assessment report loads within a reasonable amount of time.
59+
"""
60+
# Step 1: Log in as Hub Manager - State Registered (England)
61+
UserTools.user_login(page, "Hub Manager State Registered at BCS01")
62+
BasePage(page).go_to_screening_practitioner_appointments_page()
63+
64+
# Step 2: Assert the People Requiring Colonoscopy Assessment report loads as expected
65+
appointments_page = ScreeningPractitionerAppointmentsPage(page)
66+
appointments_page.open_appointments_report()
67+
expect(appointments_page.appointments_header).to_be_visible(timeout=5000)
68+
69+
70+
# Scenario 4
71+
@pytest.mark.regression
72+
@pytest.mark.hub_user_tests
73+
def test_screening_centre_user_subject_search_and_summary(page: Page) -> None:
74+
"""
75+
Scenario: Screening Centre User - Subject Search & Subject Summary
76+
This test ensures that the subject search works as expected and the subject summary loads and displays data correctly
77+
"""
78+
# Step 1: Log in as Screening Centre Manager (England)
79+
UserTools.user_login(page, "Screening Centre Manager at BCS001")
80+
BasePage(page).go_to_screening_subject_search_page()
81+
82+
# Step 2: Use POM for subject search
83+
search_page = SubjectScreeningPage(page)
84+
"""screening_status=4004 value represents 'Recall' & episode_status=2 value represents 'Closed'"""
85+
search_page.search_subject_with_args(
86+
surname="A*", forename="A*", screening_status="4004", episode_status="2"
87+
)
88+
89+
90+
# Scenario 5
91+
@pytest.mark.regression
92+
@pytest.mark.hub_user_tests
93+
def test_screening_centre_user_subject_search_and_surveillance(page: Page) -> None:
94+
"""
95+
Scenario: Screening Centre User - Organisation Search & Surveillance Review Summary
96+
This test ensures that the organisation search works as expected and the surveillance review summary loads and displays data correctly
97+
"""
98+
# Step 1: Log in as Screening Centre Manager (England)
99+
UserTools.user_login(page, "Screening Centre Manager at BCS001")
100+
BasePage(page).go_to_organisations_page()
101+
102+
# Step 2: Use POM for navigation and assertion
103+
sur_page = SurveillanceSummaryPage(page)
104+
sur_page.navigate_to_surveillance_review_summary()
105+
expect(sur_page.surveillance_review_summary_header).to_be_visible(timeout=5000)

0 commit comments

Comments
 (0)