Skip to content

Commit e9c18b9

Browse files
Refactoring utils used in compartment 4
1 parent 38bf420 commit e9c18b9

File tree

8 files changed

+142
-78
lines changed

8 files changed

+142
-78
lines changed

pages/base_page.py

Lines changed: 22 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,24 @@ 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.info("Dialog already accepted")
180+
181+
def safe_accept_dialog(self, locator: Locator) -> None:
182+
"""
183+
This is used to accept dialogs multiple times without getting the error:
184+
playwright._impl._errors.Error: Dialog.accept: Cannot accept dialog which is already handled!
185+
"""
186+
self.page.once("dialog", self._accept_dialog)
187+
try:
188+
self.click(locator)
189+
except Exception as e:
190+
logging.error(f"Click failed: {e}")

pages/screening_practitioner_appointments/book_appointment_page.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,24 @@ def __init__(self, page: Page):
1010
# Book Appointment - page locators
1111
self.screening_center_dropdown = page.locator("#UI_NEW_SCREENING_CENTRE")
1212
self.site_dropdown = page.locator("#UI_NEW_SITE")
13-
self.day_with_available_slots = page.locator(
14-
'input.twoColumnCalendar[style*="background-color: rgb(102, 255, 153);"]'
15-
)
16-
self.day_with_some_available_slots = page.locator(
17-
'input.twoColumnCalendar[style*="background-color: rgb(255, 220, 144);"]'
18-
)
1913
self.appointment_time_radio_button = page.locator(
2014
page.get_by_role("radio", name="UI_NEW_SLOT_SELECTION_ID")
2115
)
2216
self.save_button = page.get_by_role("button", name="Save")
2317
self.appointments_table = TableUtils(self.page, "#displayRS")
2418
self.current_month_displayed = self.page.locator("#MONTH_AND_YEAR")
2519

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)"
23+
2624
def select_screening_centre_dropdown_option(self, screening_centre: str) -> None:
2725
self.screening_center_dropdown.select_option(label=screening_centre)
2826

2927
def select_site_dropdown_option(self, screening_site: str) -> None:
3028
self.site_dropdown.select_option(label=screening_site)
3129
self.site_dropdown.press("Enter")
3230

33-
def choose_day_with_available_slots(self) -> None:
34-
self.click(self.day_with_available_slots)
35-
3631
def choose_appointment_time(self) -> None:
3732
self.appointment_time_radio_button.check()
3833

@@ -42,8 +37,5 @@ def click_save_button(self) -> None:
4237
def appointment_booked_confirmation_is_displayed(self, message: str) -> None:
4338
expect(self.page.get_by_text(message)).to_be_visible()
4439

45-
def accept_dialog(self) -> None:
46-
self.page.once("dialog", lambda dialog: dialog.accept())
47-
4840
def get_current_month_displayed(self) -> str:
4941
return self.current_month_displayed.text_content()

pages/screening_practitioner_appointments/colonoscopy_assessment_appointments_page.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@ 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:
1926
self.click(self.nhs_number_filter_text_field)
2027
self.nhs_number_filter_text_field.fill(nhs_number)

tests/smokescreen/bcss_smokescreen_tests.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
# ----------------------------------
2727
# compartment 4
2828
# ----------------------------------
29-
# c4_eng_org_id=23159
29+
c4_eng_weeks_to_make_available = 6
3030
# c4_eng_centre_name=Wolverhampton
3131
# c4_eng_site_name=Royal Hospital
3232
# c4_eng_practitioner_id=243

tests/smokescreen/test_compartment_4.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ def test_compartment_4(page: Page, smokescreen_properties: dict) -> None:
5555
smokescreen_properties["c4_eng_number_of_appointments_to_book"]
5656
)
5757

58-
logging.info("Setting up appointments")
58+
logging.info("Compartment 4 - Setting up appointments")
59+
logging.info("Logging in as Screening Centre Manager at BCS001")
5960
UserTools.user_login(page, "Screening Centre Manager at BCS001")
6061
BasePage(page).go_to_screening_practitioner_appointments_page()
6162
ScreeningPractitionerAppointmentsPage(page).go_to_set_availability_page()
@@ -72,14 +73,18 @@ def test_compartment_4(page: Page, smokescreen_properties: dict) -> None:
7273
PractitionerAvailabilityPage(page).enter_start_time("09:00")
7374
PractitionerAvailabilityPage(page).enter_end_time("17:15")
7475
PractitionerAvailabilityPage(page).click_calculate_slots_button()
75-
PractitionerAvailabilityPage(page).enter_number_of_weeks("6")
76+
PractitionerAvailabilityPage(page).enter_number_of_weeks(
77+
smokescreen_properties["c4_eng_weeks_to_make_available"]
78+
)
7679
PractitionerAvailabilityPage(page).click_save_button()
7780
PractitionerAvailabilityPage(page).slots_updated_message_is_displayed(
78-
"Slots Updated for 6 Weeks"
81+
f"Slots Updated for {smokescreen_properties["c4_eng_weeks_to_make_available"]} Weeks"
7982
)
8083
Logout(page).log_out(close_page=False)
8184

85+
logging.info("Compartment 4 - Booking subjects to appointments")
8286
ScreeningPractitionerAppointmentsPage(page).go_to_log_in_page()
87+
logging.info("Logging in as Hub Manager State Registered at BCS01")
8388
UserTools.user_login(page, "Hub Manager State Registered at BCS01")
8489

8590
BasePage(page).go_to_screening_practitioner_appointments_page()
@@ -103,22 +108,29 @@ def test_compartment_4(page: Page, smokescreen_properties: dict) -> None:
103108
current_month_displayed = BookAppointmentPage(
104109
page
105110
).get_current_month_displayed()
106-
CalendarPicker(page).select_first_eligble_appointment(
111+
CalendarPicker(page).book_first_eligble_appointment(
107112
current_month_displayed,
108-
BookAppointmentPage(page).day_with_available_slots,
109-
BookAppointmentPage(page).day_with_some_available_slots,
113+
BookAppointmentPage(page).appointment_cell_locators,
114+
[
115+
BookAppointmentPage(page).available_background_colour,
116+
BookAppointmentPage(page).some_available_background_colour,
117+
],
110118
)
111119
BookAppointmentPage(page).appointments_table.click_first_input_in_column(
112120
"Appt/Slot Time"
113121
)
114-
BookAppointmentPage(page).accept_dialog()
115-
BookAppointmentPage(page).click_save_button()
116-
BookAppointmentPage(page).appointment_booked_confirmation_is_displayed(
117-
"Appointment booked"
118-
)
122+
BasePage(page).safe_accept_dialog(BookAppointmentPage(page).save_button)
123+
try:
124+
BookAppointmentPage(page).appointment_booked_confirmation_is_displayed(
125+
"Appointment booked"
126+
)
127+
logging.info(f"Appointment successfully booked for: {nhs_number}")
128+
except Exception as e:
129+
pytest.fail(f"Appointment not booked successfully: {e}")
119130
BasePage(page).click_back_button()
120-
BasePage(page).click_main_menu_link()
131+
ColonoscopyAssessmentAppointments(page).wait_for_page_header()
121132

133+
logging.info("Compartment 4 - Sending out appointment invitations")
122134
batch_processing(
123135
page,
124136
"A183",

utils/batch_processing.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
from pages.base_page import BasePage
2-
from pages.communication_production.communications_production_page import CommunicationsProduction
2+
from pages.communication_production.communications_production_page import (
3+
CommunicationsProduction,
4+
)
35
from pages.communication_production.manage_active_batch_page import ManageActiveBatch
4-
from pages.communication_production.batch_list_page import ActiveBatchList, ArchivedBatchList
6+
from pages.communication_production.batch_list_page import (
7+
ActiveBatchList,
8+
ArchivedBatchList,
9+
)
510
from utils.screening_subject_page_searcher import verify_subject_event_status_by_nhs_no
611
from utils.oracle.oracle_specific_functions import get_nhs_no_from_batch_id
712
from utils.oracle.oracle import OracleDB
@@ -119,8 +124,9 @@ def prepare_and_print_batch(page: Page, link_text) -> None:
119124
logging.info(
120125
f"Clicking confirm printed button {confirm_printed_button + 1}"
121126
)
122-
page.once("dialog", lambda dialog: dialog.accept())
123-
ManageActiveBatch(page).confirm_button.nth(0).click()
127+
BasePage(page).safe_accept_dialog(
128+
ManageActiveBatch(page).confirm_button.nth(0)
129+
)
124130
except Exception as e:
125131
pytest.fail(f"No confirm printed button available to click: {str(e)}")
126132

utils/calendar_picker.py

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -286,82 +286,81 @@ def v2_calendar_picker(self, date: datetime) -> None:
286286

287287
self.select_day(date)
288288

289-
def month_string_to_number(self, string: str) -> None:
290-
"""
291-
This is used to convert a month from a string to an integer.
292-
It accepts the full month or the short version and is not case sensitive
293-
"""
294-
months = {
295-
"jan": 1,
296-
"feb": 2,
297-
"mar": 3,
298-
"apr": 4,
299-
"may": 5,
300-
"jun": 6,
301-
"jul": 7,
302-
"aug": 8,
303-
"sep": 9,
304-
"oct": 10,
305-
"nov": 11,
306-
"dec": 12,
307-
}
308-
month_short = string.strip()[:3].lower()
309-
310-
try:
311-
out = months[month_short]
312-
return out
313-
except Exception:
314-
raise ValueError("Not a month")
315-
316-
def select_first_eligble_appointment(
289+
def book_first_eligble_appointment(
317290
self,
318291
current_month_displayed: str,
319-
avialble_locator: Locator,
320-
some_available_locator: Locator,
292+
locator: Locator,
293+
bg_colours: list,
321294
) -> None:
322295
"""
323296
This is used to select the first eligible appointment date
324-
It first gets all available dates, and then clicks on the first one starting from today's date
297+
It first sets the calendar to the current month
298+
Then gets all available dates, and then clicks on the first one starting from today's date
299+
If no available dates are found it moves onto the next month and repeats this 2 more times
300+
If in the end no available dates are found the test will fail.
325301
"""
326-
current_month_displayed_int = self.month_string_to_number(
302+
current_month_displayed_int = DateTimeUtils().month_string_to_number(
327303
current_month_displayed
328304
)
329305
if platform == "win32": # Windows
330-
current_month_int = int(datetime.now().strftime("%#d"))
306+
current_month_int = int(datetime.now().strftime("%#m"))
331307
else: # Linux or Mac
332-
current_month_int = int(datetime.now().strftime("%-d"))
308+
current_month_int = int(datetime.now().strftime("%-m"))
333309

334-
if current_month_displayed_int != current_month_int:
335-
self.click(self.appointments_prev_month)
310+
self.book_appointments_go_to_month(
311+
current_month_displayed_int, current_month_int
312+
)
336313

337314
months_looped = 0
338315
appointment_clicked = False
339316
while (
340317
months_looped < 3 and not appointment_clicked
341318
): # This loops through this month + next two months to find available appointments. If none found it has failed
342319
appointment_clicked = self.check_for_eligible_appointment_dates(
343-
avialble_locator
320+
locator, bg_colours
344321
)
345322

346-
if not appointment_clicked:
347-
appointment_clicked = self.check_for_eligible_appointment_dates(
348-
some_available_locator
349-
)
350-
351323
if not appointment_clicked:
352324
self.click(self.appointments_next_month)
353325
months_looped += 1
354326

355327
if not appointment_clicked:
356328
pytest.fail("No available appointments found for the current month")
357329

358-
def check_for_eligible_appointment_dates(self, locator: Locator) -> bool:
330+
def book_appointments_go_to_month(
331+
self, current_displayed_month: int, wanted_month: int
332+
):
333+
"""
334+
This is used to move the calendar on the appointments page to the wanted month
335+
"""
336+
month_difference = current_displayed_month - wanted_month
337+
if month_difference > 0:
338+
for _ in range(month_difference):
339+
self.click(self.appointments_prev_month)
340+
elif month_difference < 0:
341+
for _ in range(month_difference * -1):
342+
self.click(self.appointments_next_month)
343+
344+
def check_for_eligible_appointment_dates(
345+
self, locator: Locator, bg_colours: list
346+
) -> bool:
347+
"""
348+
This function loops through all of the appointment date cells and if the bacground colour matches
349+
It then checks that the length of the name is less than 5.
350+
This is done the name length is the only differentiating factor between the two calendar tables on the page
351+
- 1st table has a length of 4 (e.g. wed2, fri5) and the 2nd table has a length of 5 (e.g. wed11, fri14)
352+
"""
359353

360354
locator_count = locator.count()
361355

362356
for i in range(locator_count):
363-
locator_number = locator_count - i - 1
364-
value = locator.nth(locator_number).get_attribute("name")
365-
if len(value) < 5:
366-
self.click(locator.nth(locator_number))
367-
return True
357+
locator_element = locator.nth(i)
358+
background_colour = locator_element.evaluate(
359+
"el => window.getComputedStyle(el).backgroundColor"
360+
)
361+
362+
if background_colour in bg_colours:
363+
value = locator_element.get_attribute("name")
364+
if len(value) < 5:
365+
self.click(locator.nth(i))
366+
return True

utils/date_time_utils.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,30 @@ def screening_practitioner_appointments_report_timestamp_date_format() -> str:
9797
"""
9898

9999
return DateTimeUtils.format_date(datetime.now(), "%d.%m.%Y at %H:%M:%S")
100+
101+
def month_string_to_number(self, string: str) -> int:
102+
"""
103+
This is used to convert a month from a string to an integer.
104+
It accepts the full month or the short version and is not case sensitive
105+
"""
106+
months = {
107+
"jan": 1,
108+
"feb": 2,
109+
"mar": 3,
110+
"apr": 4,
111+
"may": 5,
112+
"jun": 6,
113+
"jul": 7,
114+
"aug": 8,
115+
"sep": 9,
116+
"oct": 10,
117+
"nov": 11,
118+
"dec": 12,
119+
}
120+
month_short = string.strip()[:3].lower()
121+
122+
try:
123+
out = months[month_short]
124+
return out
125+
except Exception:
126+
raise ValueError("Not a month")

0 commit comments

Comments
 (0)