Skip to content

Commit 4fbc663

Browse files
Feature/bcss 20615 new regression tests subject episodes diagnosis date (#110)
<!-- markdownlint-disable-next-line first-line-heading --> BCSS - 20615 - Selenium to Playwright - Regression Tests - Subject Episodes - Diagnosis Date New PR is created. ## Context Code change is implemeted. Locator is created & Hard coded values are removed & moved to POM. Below are the lists of files checked in. 1. Test File --> tests/regression/subject_diagnosis_date/test_subject_episodes_diagnosis_date.py 2. Pages --> Screening_Subject_Search --> subject_episode_events_and_notes_page.py 3. Pages --> Screening_Subject_Search --> advance_fobt_screening_episode_page.py 4. Pages --> Screening_Subject_Search --> record_diagnosis_date_page.py 5. pytest.ini 6. users.json 7. Classes --> diagnosis_date_reason_type ## 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 6c51163 commit 4fbc663

File tree

7 files changed

+1202
-2
lines changed

7 files changed

+1202
-2
lines changed

classes/diagnosis_date_reason_type.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,6 @@ def get_valid_value_id(self) -> Optional[int]:
9898

9999
def get_description(self) -> str:
100100
"""
101-
Returns the description for the diagnosis date reason.
101+
Returns the description for the diagnosis date reason
102102
"""
103103
return self._description

pages/screening_subject_search/advance_fobt_screening_episode_page.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def __init__(self, page: Page):
1717
self.calendar_button = self.page.get_by_role("button", name="Calendar")
1818
self.test_type_dropdown = self.page.locator("#UI_EXT_TEST_TYPE_2233")
1919
self.test_type_dropdown_2 = self.page.locator("#UI_EXT_TEST_TYPE_4325")
20+
self.advance_checkbox = self.page.get_by_label("There are some events available which should only be used in exceptional circumstances. If you wish to see them, check this box")
2021
self.invite_for_diagnostic_test_button = self.page.get_by_role(
2122
"button", name="Invite for Diagnostic Test >>"
2223
)
@@ -111,3 +112,7 @@ def click_record_diagnosis_date_button(self) -> None:
111112
def click_record_contact_with_patient_button(self) -> None:
112113
"""Click the 'Record Contact with Patient' button."""
113114
self.click(self.record_contact_with_patient_button)
115+
116+
def check_advance_checkbox(self) -> None:
117+
"""Selects the 'Advance FOBT' checkbox"""
118+
self.advance_checkbox.check()

pages/screening_subject_search/record_diagnosis_date_page.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,22 @@ def enter_date_in_diagnosis_date_field(self, date: datetime) -> None:
2222
"""
2323
self.click(self.diagnosis_date_field)
2424
CalendarPicker(self.page).v2_calendar_picker(date)
25-
self.diagnosis_date_field.press("Enter")
25+
self.diagnosis_date_field.press("Tab")
2626

2727
def click_save_button(self) -> None:
2828
"""Clicks the save button."""
2929
self.click(self.save_button)
30+
31+
def get_alert_message(self) -> str:
32+
"""
33+
Retrieve the visible alert message from the page, if any.
34+
35+
Returns:
36+
str: The inner text of the alert element if it's visible;
37+
otherwise, an empty string.
38+
"""
39+
self.alert_message = self.page.get_by_role("alert")
40+
if self.alert_message.is_visible():
41+
return self.alert_message.inner_text()
42+
else:
43+
return ""
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import logging
2+
import pytest
3+
from playwright.sync_api import Page, expect
4+
from pages.base_page import BasePage
5+
from typing import Dict
6+
7+
class SubjectEpisodeEventsAndNotesPage(BasePage):
8+
"""Episode Events and Notes Page locators, and methods for interacting with the page."""
9+
10+
def __init__(self, page: Page):
11+
super().__init__(page)
12+
self.page = page
13+
# List of episode events and notes - page locators
14+
self.latest_event_status_cell = self.page.locator(
15+
"table >> td.epihdr_data"
16+
).nth(
17+
0
18+
) # if it's the first one
19+
self.latest_event_cell = self.page.get_by_role(
20+
"cell", name="Record Diagnosis Date", exact=True
21+
)
22+
self.latest_diagnosis_cell = self.page.locator(
23+
"td[align='center']:has-text('Diag Date :')"
24+
)
25+
26+
# Episode details (Replace with actual selectors only for scenario 17)
27+
self.latest_episode_status = self.page.locator("#latestEpisodeStatus")
28+
self.latest_episode_has_diagnosis_date = self.page.locator(
29+
"#latestEpisodeHasDiagnosisDate"
30+
)
31+
self.latest_episode_diagnosis_reason = self.page.locator(
32+
"#latestEpisodeDiagnosisDateReason"
33+
)
34+
self.process_sspi_update_button = self.page.get_by_text("Process SSPI Update")
35+
self.deduction_reason_dropdown = self.page.locator("#deductionReason")
36+
self.confirm_sspi_update_button = self.page.get_by_text("Confirm")
37+
38+
def expected_episode_event_is_displayed(self, event_description: str) -> None:
39+
"""Check if the expected episode event is displayed on the page."""
40+
expect(
41+
self.page.get_by_role("cell", name=event_description, exact=True)
42+
).to_be_visible()
43+
44+
def get_latest_event_details(self) -> dict:
45+
"""
46+
Retrieves key details for the latest episode entry from the UI.
47+
48+
Returns:
49+
dict: A dictionary containing the following keys:
50+
- "latest_event_status" (str): The current status text of the latest event.
51+
- "event" (str): A description or name of the latest event.
52+
- "item" (str): Details related to the latest diagnosis item.
53+
54+
Raises:
55+
pytest.fail: If any of the UI elements cannot be read, the test fails immediately.
56+
"""
57+
try:
58+
status_text = self.latest_event_status_cell.inner_text()
59+
event_text = self.latest_event_cell.inner_text()
60+
diagnosis_text = self.latest_diagnosis_cell.first.inner_text()
61+
logging.debug(f"DEBUG: {event_text}, {status_text}, {diagnosis_text}")
62+
except Exception as e:
63+
pytest.fail(f"Failed to read latest episode event details from UI: {e}")
64+
return {
65+
"latest_event_status": status_text,
66+
"event": event_text,
67+
"item": diagnosis_text,
68+
}
69+
70+
def validate_event_status_is_not_A50(self, event_details: dict) -> None:
71+
"""Validates that latest_event_status does not contain 'A50'."""
72+
latest_status = event_details.get("latest_event_status")
73+
logging.info(f"Validating Latest Event Status: {latest_status}")
74+
75+
if latest_status is None:
76+
pytest.fail("Missing 'latest_event_status' in event_details.")
77+
elif "A50" in str(latest_status):
78+
pytest.fail(
79+
f"Invalid status detected: 'A50' is not allowed. Received: '{latest_status}'"
80+
)
81+
logging.info(f"Status '{latest_status}' is allowed.")
82+
83+
def is_record_diagnosis_date_option_available(self) -> bool:
84+
"""
85+
Check if the 'Record Diagnosis Date' option is available on the page
86+
87+
Returns:
88+
bool: True if the option is available, False otherwise.
89+
"""
90+
try:
91+
return self.page.get_by_role(
92+
"button", name="Record Diagnosis Date"
93+
).is_visible()
94+
except Exception as e:
95+
logging.error(f"Record Diagnosis Date option not found: {e}")
96+
return False
97+
98+
def is_amend_diagnosis_date_option_available(self) -> bool:
99+
"""
100+
Check if the 'Amend Diagnosis Date' option is available on the page.
101+
102+
Returns:
103+
bool: True if the option is available, False otherwise.
104+
"""
105+
try:
106+
return self.page.get_by_role(
107+
"button", name="Amend Diagnosis Date"
108+
).is_visible()
109+
except Exception as e:
110+
logging.error(f"Error checking for 'Amend Diagnosis Date' option: {e}")
111+
return False
112+
113+
def process_sspi_update_for_death(self, deduction_reason: str) -> None:
114+
"""
115+
Submits an SSPI update for a death-related deduction reason through the UI workflow.
116+
117+
Args:
118+
deduction_reason (str): The label of the deduction reason to select from the dropdown.
119+
120+
Steps:
121+
- Clicks the SSPI update button.
122+
- Selects the specified deduction reason from the dropdown.
123+
- Confirms the SSPI update by clicking the confirmation button.
124+
"""
125+
self.process_sspi_update_button.click()
126+
self.deduction_reason_dropdown.select_option(label=deduction_reason)
127+
self.confirm_sspi_update_button.click()
128+
129+
def get_latest_episode_details(self) -> Dict[str, str]:
130+
"""
131+
Retrieve details of the latest episode from the UI elements.
132+
133+
Returns:
134+
Dict[str, str]: A dictionary containing:
135+
- 'latest_episode_status': The status text of the latest episode.
136+
- 'latest_episode_has_diagnosis_date': Indicator of whether a diagnosis date is present.
137+
- 'latest_episode_diagnosis_date_reason': Reason explaining the diagnosis date status.
138+
"""
139+
return {
140+
"latest_episode_status": self.latest_episode_status.inner_text(),
141+
"latest_episode_has_diagnosis_date": self.latest_episode_has_diagnosis_date.inner_text(),
142+
"latest_episode_diagnosis_date_reason": self.latest_episode_diagnosis_reason.inner_text(),
143+
}

pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ markers =
4545
subject_search: tests that are part of the subject search test suite
4646
investigation_dataset_tests: tests that are part of the investigation dataset test suite
4747
skip_before_test: tests that will not use the before_test fixture
48+
fobt_diagnosis_date_entry_tests: tests that are part of fobt subject episodes record diagnosis date

0 commit comments

Comments
 (0)