Skip to content

Commit 0a2f6d5

Browse files
Feature/bcss 20230 compartment 4 utils (#29)
<!-- markdownlint-disable-next-line first-line-heading --> ## Description <!-- Describe your changes in detail. --> Adding utils to compartment 4 so that the test runs end to end successfully ## Context <!-- Why is this change required? What problem does it solve? --> Adds the ability to reuse utils for later playwright tests and increases the readability of compartment 4 ## 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) - [x] 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 16c3438 commit 0a2f6d5

16 files changed

+302
-68
lines changed

pages/base_page.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from playwright.sync_api import Page, expect, Locator
1+
from playwright.sync_api import Page, expect, Locator, Dialog
22
import logging
33

44

@@ -167,3 +167,25 @@ def click(self, locator: Locator) -> None:
167167
f"Failed to click element with error: {locatorClickError}, trying again..."
168168
)
169169
locator.click()
170+
171+
def _accept_dialog(self, dialog: Dialog) -> None:
172+
"""
173+
This method is used to accept dialogs
174+
If it has already been accepted then it is ignored
175+
"""
176+
try:
177+
dialog.accept()
178+
except Exception:
179+
logging.warning("Dialog already handled")
180+
181+
def safe_accept_dialog(self, locator: Locator) -> None:
182+
"""
183+
Safely accepts a dialog triggered by a click, avoiding the error:
184+
playwright._impl._errors.Error: Dialog.accept: Cannot accept dialog which is already handled!
185+
If no dialog appears, continues without error.
186+
"""
187+
self.page.once("dialog", self._accept_dialog)
188+
try:
189+
self.click(locator)
190+
except Exception as e:
191+
logging.error(f"Click failed: {e}")

pages/gfobt_test_kits/gfobt_test_kit_logging_page.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pages.base_page import BasePage
33

44

5-
class TestKitLogging(BasePage):
5+
class GFOBTTestKitLogging(BasePage):
66
def __init__(self, page: Page):
77
super().__init__(page)
88
self.page = page

pages/gfobt_test_kits/gfobt_test_kit_quality_control_reading_page.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from pages.base_page import BasePage
33

44

5-
class TestKitQualityControlReading(BasePage):
5+
class GFOBTTestKitQualityControlReading(BasePage):
66
def __init__(self, page: Page):
77
super().__init__(page)
88
self.page = page
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from playwright.sync_api import Page, expect
22
from pages.base_page import BasePage
3+
from utils.table_util import TableUtils
34

45

56
class BookAppointmentPage(BasePage):
@@ -9,24 +10,24 @@ def __init__(self, page: Page):
910
# Book Appointment - page locators
1011
self.screening_center_dropdown = page.locator("#UI_NEW_SCREENING_CENTRE")
1112
self.site_dropdown = page.locator("#UI_NEW_SITE")
12-
self.day_with_available_slots = page.locator(
13-
'input.twoColumnCalendar[style*="background-color: rgb(102, 255, 153);"]'
14-
).last
1513
self.appointment_time_radio_button = page.locator(
1614
page.get_by_role("radio", name="UI_NEW_SLOT_SELECTION_ID")
1715
)
1816
self.save_button = page.get_by_role("button", name="Save")
17+
self.appointments_table = TableUtils(self.page, "#displayRS")
18+
self.current_month_displayed = self.page.locator("#MONTH_AND_YEAR")
19+
20+
self.appointment_cell_locators = self.page.locator("input.twoColumnCalendar")
21+
self.available_background_colour = "rgb(102, 255, 153)"
22+
self.some_available_background_colour = "rgb(255, 220, 144)"
1923

2024
def select_screening_centre_dropdown_option(self, screening_centre: str) -> None:
2125
self.screening_center_dropdown.select_option(label=screening_centre)
2226

23-
def select_site_dropdown_option(self, screening_site: str) -> None:
27+
def select_site_dropdown_option(self, screening_site: str | list) -> None:
2428
self.site_dropdown.select_option(label=screening_site)
2529
self.site_dropdown.press("Enter")
2630

27-
def choose_day_with_available_slots(self) -> None:
28-
self.click(self.day_with_available_slots)
29-
3031
def choose_appointment_time(self) -> None:
3132
self.appointment_time_radio_button.check()
3233

@@ -35,3 +36,6 @@ def click_save_button(self) -> None:
3536

3637
def appointment_booked_confirmation_is_displayed(self, message: str) -> None:
3738
expect(self.page.get_by_text(message)).to_be_visible()
39+
40+
def get_current_month_displayed(self) -> str:
41+
return self.current_month_displayed.text_content()

pages/screening_practitioner_appointments/colonoscopy_assessment_appointments_page.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,22 @@ def __init__(self, page: Page):
88
self.page = page
99
# Colonoscopy Assessment Appointments - page locators
1010
self.page_header = self.page.locator("#page-title")
11+
self.page_header_with_title = self.page.locator(
12+
"#page-title",
13+
has_text="Patients that Require Colonoscopy Assessment Appointments",
14+
)
1115
self.nhs_number_filter_text_field = self.page.locator("#nhsNumberFilter")
1216

1317
def verify_page_header(self) -> None:
1418
expect(self.page_header).to_contain_text(
1519
"Patients that Require Colonoscopy Assessment Appointments"
1620
)
1721

22+
def wait_for_page_header(self) -> None:
23+
self.page_header_with_title.wait_for()
24+
1825
def filter_by_nhs_number(self, nhs_number: str) -> None:
26+
self.click(self.nhs_number_filter_text_field)
1927
self.nhs_number_filter_text_field.fill(nhs_number)
2028
self.nhs_number_filter_text_field.press("Enter")
2129

pages/screening_practitioner_appointments/screening_practitioner_appointments.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ def go_to_view_appointments_page(self) -> None:
3434

3535
def go_to_patients_that_require_page(self) -> None:
3636
self.click(self.patients_that_require_page)
37+
38+
def go_to_set_availability_page(self) -> None:
39+
self.click(self.set_availability_link)

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,6 @@ markers =
3232
compartment1: only for compartment 1
3333
compartment2: only for compartment 2
3434
compartment3: only for compartment 3
35+
compartment4: only for compartment 4
36+
compartment1_plan_creation: to run the plan creation for compartment 1
3537
vpn_required: for tests that require a VPN connection

tests/smokescreen/bcss_smokescreen_tests.properties

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,11 @@
2626
# ----------------------------------
2727
# compartment 4
2828
# ----------------------------------
29-
# c4_eng_org_id=23159
30-
# c4_eng_centre_name=Wolverhampton
31-
# c4_eng_site_name=Royal Hospital
32-
# c4_eng_practitioner_id=243
33-
# c4_eng_practitioner_name=Arvind, Vanaja
34-
# c4_eng_practitioner_name=Macarena, Gave #use this for anonymised
35-
# c4_eng_practitioner_id_for_rebooking=870
36-
# c4_eng_practitioner_name_for_rebookings=Burns, Harriet
29+
c4_eng_weeks_to_make_available = 6
30+
c4_eng_centre_name=BCS001 - Wolverhampton Bowel Cancer Screening Centre
31+
c4_eng_site_name1=THE ROYAL HOSPITAL (WOLVERHAMPTON)
32+
c4_eng_site_name2=The Royal Hospital (Wolverhampton)
33+
c4_eng_practitioner_name=Astonish, Ethanol
3734

3835
# ----------------------------------
3936
# compartment 6
@@ -76,7 +73,7 @@
7673
# compartment 4
7774
# ----------------------------------
7875
# # note there is a max of 16 slots available each day
79-
# c4_eng_number_of_appointments_to_book=6
76+
c4_eng_number_of_appointments_to_book=6
8077

8178
# ----------------------------------
8279
# compartment 5

tests/smokescreen/test_compartment_4.py

Lines changed: 65 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
from utils.calendar_picker import CalendarPicker
2929
from utils.batch_processing import batch_processing
3030
from datetime import datetime
31+
from utils.oracle.oracle_specific_functions import get_subjects_for_appointments
32+
from utils.nhs_number_tools import NHSNumberTools
33+
import logging
3134

3235

3336
@pytest.fixture
@@ -48,67 +51,92 @@ def test_compartment_4(page: Page, smokescreen_properties: dict) -> None:
4851
Finally it processes the necessary batches to send out the letters and checks the subjects satus has been updated to what is expected
4952
"""
5053

51-
# Add method of getting test data using the query below. To remove once subject retrieval logic is created
52-
"""select tk.kitid, ss.subject_nhs_number, se.screening_subject_id
53-
from tk_items_t tk
54-
inner join ep_subject_episode_t se on se.screening_subject_id = tk.screening_subject_id
55-
inner join screening_subject_t ss on ss.screening_subject_id = se.screening_subject_id
56-
inner join sd_contact_t c on c.nhs_number = ss.subject_nhs_number
57-
where se.latest_event_status_id = 11132
58-
and tk.logged_in_flag = 'Y'
59-
and se.episode_status_id = 11352
60-
and ss.screening_status_id != 4008
61-
and tk.logged_in_at = 23159
62-
and c.hub_id = 23159
63-
and tk.tk_type_id = 2
64-
and tk.datestamp > add_months(sysdate,-24)
65-
order by ss.subject_nhs_number desc"""
54+
subjects_df = get_subjects_for_appointments(
55+
smokescreen_properties["c4_eng_number_of_appointments_to_book"]
56+
)
6657

58+
logging.info(
59+
f"Compartment 4 - Setting up appointments for {smokescreen_properties["c4_eng_weeks_to_make_available"]} Weeks"
60+
)
6761
UserTools.user_login(page, "Screening Centre Manager at BCS001")
6862
BasePage(page).go_to_screening_practitioner_appointments_page()
6963
ScreeningPractitionerAppointmentsPage(page).go_to_set_availability_page()
7064
SetAvailabilityPage(page).go_to_practitioner_availability_page()
7165
PractitionerAvailabilityPage(page).select_site_dropdown_option(
72-
"THE ROYAL HOSPITAL (WOLVERHAMPTON)"
66+
smokescreen_properties["c4_eng_site_name1"]
7367
)
7468
PractitionerAvailabilityPage(page).select_practitioner_dropdown_option(
75-
"Astonish, Ethanol"
69+
smokescreen_properties["c4_eng_practitioner_name"]
7670
)
7771
PractitionerAvailabilityPage(page).click_calendar_button()
78-
CalendarPicker(page).select_day(
79-
datetime.today()
80-
) # This will make it so that we can only run this test once a day, or we need to restore the DB back to the snapshot
72+
CalendarPicker(page).select_day(datetime.today())
8173
PractitionerAvailabilityPage(page).click_show_button()
8274
PractitionerAvailabilityPage(page).enter_start_time("09:00")
8375
PractitionerAvailabilityPage(page).enter_end_time("17:15")
8476
PractitionerAvailabilityPage(page).click_calculate_slots_button()
85-
PractitionerAvailabilityPage(page).enter_number_of_weeks("6")
77+
PractitionerAvailabilityPage(page).enter_number_of_weeks(
78+
smokescreen_properties["c4_eng_weeks_to_make_available"]
79+
)
8680
PractitionerAvailabilityPage(page).click_save_button()
8781
PractitionerAvailabilityPage(page).slots_updated_message_is_displayed(
88-
"Slots Updated for 6 Weeks"
82+
f"Slots Updated for {smokescreen_properties["c4_eng_weeks_to_make_available"]} Weeks"
8983
)
9084
Logout(page).log_out(close_page=False)
9185

86+
logging.info(
87+
f"Compartment 4 - Booking {smokescreen_properties["c4_eng_number_of_appointments_to_book"]} subjects to appointments"
88+
)
9289
ScreeningPractitionerAppointmentsPage(page).go_to_log_in_page()
9390
UserTools.user_login(page, "Hub Manager State Registered at BCS01")
91+
9492
BasePage(page).go_to_screening_practitioner_appointments_page()
9593
ScreeningPractitionerAppointmentsPage(page).go_to_patients_that_require_page()
96-
# Add for loop to loop x times (depends on how many we want to run it for) 70 - 79
97-
ColonoscopyAssessmentAppointments(page).filter_by_nhs_number("999 205 6339")
98-
ColonoscopyAssessmentAppointments(page).click_nhs_number_link("999 205 6339")
99-
BookAppointmentPage(page).select_screening_centre_dropdown_option(
100-
"BCS001 - Wolverhampton Bowel Cancer Screening Centre"
101-
)
102-
BookAppointmentPage(page).select_site_dropdown_option("Holly Hall Clinic (? km)")
103-
BookAppointmentPage(page).choose_day_with_available_slots()
104-
# page.locator("#UI_NEW_SLOT_SELECTION_ID_359119").check()
105-
# Will be revisited as part of Utilities update
106-
BookAppointmentPage(page).choose_appointment_time()
107-
BookAppointmentPage(page).click_save_button()
108-
BookAppointmentPage(page).appointment_booked_confirmation_is_displayed(
109-
"Appointment booked"
110-
)
11194

95+
for subject_num in range(
96+
int(smokescreen_properties["c4_eng_number_of_appointments_to_book"])
97+
):
98+
nhs_number = subjects_df["subject_nhs_number"].iloc[subject_num]
99+
logging.info(f"Booking appointment for: {nhs_number}")
100+
101+
nhs_number_spaced = NHSNumberTools().spaced_nhs_number(nhs_number)
102+
ColonoscopyAssessmentAppointments(page).filter_by_nhs_number(nhs_number)
103+
ColonoscopyAssessmentAppointments(page).click_nhs_number_link(nhs_number_spaced)
104+
BookAppointmentPage(page).select_screening_centre_dropdown_option(
105+
smokescreen_properties["c4_eng_centre_name"]
106+
)
107+
BookAppointmentPage(page).select_site_dropdown_option(
108+
[
109+
f"{smokescreen_properties["c4_eng_site_name2"]} (? km)",
110+
f"{smokescreen_properties["c4_eng_site_name2"]} (? km) (attended)",
111+
]
112+
)
113+
114+
current_month_displayed = BookAppointmentPage(
115+
page
116+
).get_current_month_displayed()
117+
CalendarPicker(page).book_first_eligble_appointment(
118+
current_month_displayed,
119+
BookAppointmentPage(page).appointment_cell_locators,
120+
[
121+
BookAppointmentPage(page).available_background_colour,
122+
BookAppointmentPage(page).some_available_background_colour,
123+
],
124+
)
125+
BookAppointmentPage(page).appointments_table.click_first_input_in_column(
126+
"Appt/Slot Time"
127+
)
128+
BasePage(page).safe_accept_dialog(BookAppointmentPage(page).save_button)
129+
try:
130+
BookAppointmentPage(page).appointment_booked_confirmation_is_displayed(
131+
"Appointment booked"
132+
)
133+
logging.info(f"Appointment successfully booked for: {nhs_number}")
134+
except Exception as e:
135+
pytest.fail(f"Appointment not booked successfully: {e}")
136+
BasePage(page).click_back_button()
137+
ColonoscopyAssessmentAppointments(page).wait_for_page_header()
138+
139+
logging.info("Compartment 4 - Sending out appointment invitations")
112140
batch_processing(
113141
page,
114142
"A183",

tests/test_gfobt_test_kits_page.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
from pages.base_page import BasePage
55
from pages.gfobt_test_kits.gfobt_test_kits_page import GFOBTTestKits
6-
from pages.gfobt_test_kits.gfobt_test_kit_logging_page import TestKitLogging
6+
from pages.gfobt_test_kits.gfobt_test_kit_logging_page import GFOBTTestKitLogging
77
from pages.gfobt_test_kits.gfobt_test_kit_quality_control_reading_page import (
8-
TestKitQualityControlReading,
8+
GFOBTTestKitQualityControlReading,
99
)
1010
from pages.gfobt_test_kits.gfobt_view_test_kit_result import ViewTestKitResult
1111
from pages.gfobt_test_kits.gfobt_create_qc_kit_page import (
@@ -27,6 +27,7 @@ def before_each(page: Page):
2727
# Go to gFOBT test kits page
2828
BasePage(page).go_to_gfobt_test_kits_page()
2929

30+
3031
@pytest.mark.smoke
3132
def test_gfobt_test_kit_page_navigation(page: Page) -> None:
3233
"""
@@ -35,12 +36,12 @@ def test_gfobt_test_kit_page_navigation(page: Page) -> None:
3536
"""
3637
# Test kit logging page opens as expected
3738
GFOBTTestKits(page).go_to_test_kit_logging_page()
38-
TestKitLogging(page).verify_test_kit_logging_title()
39+
GFOBTTestKitLogging(page).verify_test_kit_logging_title()
3940
BasePage(page).click_back_button()
4041

4142
# Test kit reading page opens as expected
4243
GFOBTTestKits(page).go_to_test_kit_reading_page()
43-
TestKitQualityControlReading(page).verify_test_kit_logging_tile()
44+
GFOBTTestKitQualityControlReading(page).verify_test_kit_logging_tile()
4445
BasePage(page).click_back_button()
4546

4647
# View test kit result page opens as expected

0 commit comments

Comments
 (0)