Skip to content

Commit be356ac

Browse files
Feature/bcss 20327 compartment 5 utils (#46)
<!-- markdownlint-disable-next-line first-line-heading --> ## Description <!-- Describe your changes in detail. --> Adding Utils for compartment 5 Altering the calendar picker util to use the date time utils and work for more dates Added markdown documents for two utils ## Context <!-- Why is this change required? What problem does it solve? --> Allows compartment 5 to retrieve subjects from the DB Increases reliability of the calendar utils ## 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 0af1a97 commit be356ac

16 files changed

+431
-193
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Utility Guide: Batch Processing
2+
3+
The Batch Processing utility allows for the processing of batches on the active batch list page to be completed in one method
4+
5+
## Table of Contents
6+
7+
- [Utility Guide: Batch Processing](#utility-guide-batch-processing)
8+
- [Table of Contents](#table-of-contents)
9+
- [Functions Overview](#functions-overview)
10+
- [Batch Processing](#batch-processing)
11+
- [Required Arguments](#required-arguments)
12+
- [Optional Arguments](#optional-arguments)
13+
- [How This Function Works](#how-this-function-works)
14+
- [Prepare And Print Batch](#prepare-and-print-batch)
15+
- [Arguments](#arguments)
16+
- [How This Function Works](#how-this-function-works-1)
17+
- [Check Batch In Archived Batch List](#check-batch-in-archived-batch-list)
18+
- [Arguments](#arguments-1)
19+
- [How This Function Works](#how-this-function-works-2)
20+
21+
## Functions Overview
22+
23+
For this utility we have the following functions:
24+
25+
- `batch_processing`
26+
- `prepare_and_print_batch`
27+
- `check_batch_in_archived_batch_list`
28+
29+
### Batch Processing
30+
31+
This is the main function that is called in order to process a batch.
32+
This will call the other two functions in order to successfully process a batch.
33+
34+
#### Required Arguments
35+
36+
- `page`:
37+
- Type: `Page`
38+
- This is the playwright page object which is used to tell playwright what page the test is currently on.
39+
- `batch_type`:
40+
- Type: `str`
41+
- This is the event code for the batch. For example: **S1** or **A323**
42+
- `batch_description`:
43+
- Type: `str`
44+
- This is the description of the batch. For example: **Pre-invitation (FIT)** or **Post-investigation Appointment NOT Required**
45+
- `latest_event_status`:
46+
- Type: `str`
47+
- This is the status the subject will get updated to after the batch has been processed. It is used to check that the subject has been updated to the correct status after a batch has been printed
48+
49+
#### Optional Arguments
50+
51+
- `run_timed_events`:
52+
- Type: `bool`
53+
- If this is set to **True**, then bcss_timed_events will be executed against all the subjects found in the batch
54+
- `get_subjects_from_pdf`:
55+
- Type: `bool`
56+
- If this is set to **True**, then the subjects will be retrieved from the downloaded PDF file instead of from the DB
57+
58+
#### How This Function Works
59+
60+
1. It starts off by navigating to the main menu if not already on this page. This is done to ensure that this can be called from any page
61+
2. Once on the main menu it navigates to the active batch list
62+
3. From here it fills in the search filters to narrow down the list of active batches to only those which match the arguments provided
63+
4. Once only the expected batches are shown it checks the status column of the records
64+
1. If *Prepared* is found then it ignores it, otherwise if *Open* is found then it carries on
65+
5. Now it extracts the ID of the batch and stores it in the local variable `link_text`, this is used later on to extracts the subjects in the batch from the DB
66+
6. After the ID is stored, it clicks on the ID to get to the Manage Active Batch page
67+
7. From Here it calls the `prepare_and_print_batch` function.
68+
1. If `get_subjects_from_pdf` was set to False it calls `get_nhs_no_from_batch_id`, which is imported from *utils.oracle.oracle_specific_functions*, to get the subjects from the batch and stores them as a pandas DataFrame - **nhs_no_df**
69+
2. For more Info on `get_nhs_no_from_batch_id` please look at: [`PDFReader`](PDFReader.md)
70+
8. Once this is complete it calls the `check_batch_in_archived_batch_list` function
71+
9. Finally, once that function is complete it calls `verify_subject_event_status_by_nhs_no` which is imported from *utils/screening_subject_page_searcher*
72+
73+
### Prepare And Print Batch
74+
75+
This is used when on the Manage Active Batch page.
76+
It is in charge of pressing on the following button: **Prepare Batch**, **Retrieve** and **Confirm Printed**
77+
78+
#### Arguments
79+
80+
- `page`:
81+
- Type: `Page`
82+
- This is the playwright page object which is used to tell playwright what page the test is currently on.
83+
- `link_text`:
84+
- Type: `str`
85+
- This is the batch ID of the batch currently being processed
86+
- `get_subjects_from_pdf`:
87+
- Type: `bool`
88+
- This is an optional argument and if this is set to **True**, then the subjects will be retrieved from the downloaded PDF file instead of from the DB
89+
90+
#### How This Function Works
91+
92+
1. It starts off by clicking on the **Prepare Batch** button.
93+
2. After this it waits for the button to turn into **Re-Prepare Batch**. Once this happens it means that the batch is ready to be printed.
94+
3. Now It clicks on each **Retrieve** button visible.
95+
1. If `get_subjects_from_pdf` was set to True and the file is a **.pdf**, then it calls `extract_nhs_no_from_pdf`, which is imported from *utils/pdf_reader*, to get the subjects from the batch and stores them as a pandas DataFrame - **nhs_no_df**
96+
2. After a file is downloaded, it gets deleted.
97+
4. Then it clicks on each **Confirm Printed** button ensuring to handle the dialog that appears.
98+
5. Finally it checks for the message: *Batch Successfully Archived and Printed*
99+
100+
### Check Batch In Archived Batch List
101+
102+
This function checks that the batch that was just prepared and printed is now visible in the archived batch list
103+
104+
#### Arguments
105+
106+
- `page`:
107+
- Type: `Page`
108+
- This is the playwright page object which is used to tell playwright what page the test is currently on.
109+
- `link_text`:
110+
- Type: `str`
111+
- This is the batch ID of the batch currently being processed
112+
113+
#### How This Function Works
114+
115+
1. This starts off by navigating to the main menu.
116+
2. From here it goes to the archived batch list page.
117+
3. Once on the archived batch list page, it enters `link_text` into the ID filter.
118+
4. Finally it checks that the batch is visible in the table.

docs/utility-guides/PDFReader.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Utility Guide: PDF Reader
2+
3+
The PDF Reader utility allows for reading of PDF files and performing specific tasks on them.
4+
5+
## Table of Contents
6+
7+
- [Utility Guide: PDF Reader](#utility-guide-pdf-reader)
8+
- [Table of Contents](#table-of-contents)
9+
- [Functions Overview](#functions-overview)
10+
- [Extract NHS No From PDF](#extract-nhs-no-from-pdf)
11+
- [Required Arguments](#required-arguments)
12+
- [How This Function Works](#how-this-function-works)
13+
14+
## Functions Overview
15+
16+
For this utility we have the following functions/methods:
17+
18+
- `extract_nhs_no_from_pdf`
19+
20+
### Extract NHS No From PDF
21+
22+
This is called to extract all NHS numbers from a PDF file.
23+
The way it finds an NHS number is by looking for the string **"NHS No:"**
24+
25+
#### Required Arguments
26+
27+
- `file`:
28+
- Type: `str`
29+
- This is the file path stored as a string.
30+
31+
#### How This Function Works
32+
33+
1. It starts off by storing the PDF file as a PdfReader object, this is from the `pypdf` package.
34+
2. Then it loops through each page.
35+
3. If it finds the string *"NHS No"* in the page, it extracts it and removes any whitespaces, then adds it to a pandas DataFrame - `nhs_no_df`

pages/communication_production/batch_list_page.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ def __init__(self, page: Page):
2828
self.deadline_date_filter = self.page.get_by_role("cell", name="").get_by_role(
2929
"textbox"
3030
)
31+
self.deadline_date_filter_with_input = self.page.locator(
32+
"input.form-control.filter.filtering"
33+
)
3134
self.deadline_date_clear_button = self.page.get_by_role("cell", name="Clear")
3235

3336
def verify_batch_list_page_title(self, text) -> None:
@@ -88,6 +91,9 @@ def clear_deadline_filter_date(self) -> None:
8891
self.click(self.deadline_calendar_picker)
8992
self.click(self.deadline_date_clear_button)
9093

94+
def verify_deadline_date_filter_input(self, expected_text: str) -> None:
95+
expect(self.deadline_date_filter_with_input).to_have_value(expected_text)
96+
9197

9298
class ActiveBatchListPage(BatchListPage):
9399
"""Active Batch List Page locators, and methods for interacting with the Active Batch List page"""

pages/screening_practitioner_appointments/screening_practitioner_day_view_page.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def __init__(self, page: Page):
1010
self.page = page
1111
# Screening Practitioner Day View - page locators
1212
self.calendar_button = page.get_by_role("button", name="Calendar")
13+
self.practitioner_dropdown = self.page.locator("#UI_PRACTITIONER_NDV")
1314

1415
def click_calendar_button(self) -> None:
1516
"""Click on the Calendar button to open the calendar picker."""
@@ -18,3 +19,7 @@ def click_calendar_button(self) -> None:
1819
def click_patient_link(self, patient_name: str) -> None:
1920
"""Click on the patient link to navigate to the patient's details page."""
2021
self.click(self.page.get_by_role("link", name=patient_name))
22+
23+
def select_practitioner_dropdown_option(self, practitioner: str | list) -> None:
24+
"""Select given practitioner from the practitioner dropdown list"""
25+
self.practitioner_dropdown.select_option(label=practitioner)

pages/screening_subject_search/advance_fobt_screening_episode_page.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from playwright.sync_api import Page, expect, Locator
22
from pages.base_page import BasePage
3+
import logging
4+
import pytest
35

46

57
class AdvanceFOBTScreeningEpisodePage(BasePage):
@@ -62,11 +64,16 @@ def get_latest_event_status_cell(self, latest_event_status: str) -> Locator:
6264
return self.page.get_by_role("cell", name=latest_event_status, exact=True)
6365

6466
def verify_latest_event_status_value(self, latest_event_status: str) -> None:
65-
"""Verify the latest event status value."""
67+
"""Verify that the latest event status value is visible."""
68+
logging.info(f"Verifying subject has the status: {latest_event_status}")
6669
latest_event_status_cell = self.get_latest_event_status_cell(
6770
latest_event_status
6871
)
69-
expect(latest_event_status_cell).to_be_visible()
72+
try:
73+
expect(latest_event_status_cell).to_be_visible()
74+
logging.info(f"Subject has the status: {latest_event_status}")
75+
except Exception:
76+
pytest.fail(f"Subject does not have the status: {latest_event_status}")
7077

7178
def click_record_other_post_investigation_contact_button(self) -> None:
7279
"""Click the 'Record other post-investigation contact' button."""

pages/screening_subject_search/subject_screening_search_page.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from playwright.sync_api import Page
1+
from playwright.sync_api import Page, expect
22
from pages.base_page import BasePage
33
from enum import Enum
44
from utils.calendar_picker import CalendarPicker
@@ -148,6 +148,9 @@ def select_dob_using_calendar_picker(self, date) -> None:
148148
self.click(self.dob_calendar_picker)
149149
CalendarPicker(self.page).v1_calender_picker(date)
150150

151+
def verify_date_of_birth_filter_input(self, expected_text: str) -> None:
152+
expect(self.date_of_birth_filter).to_have_value(expected_text)
153+
151154

152155
class ScreeningStatusSearchOptions(Enum):
153156
"""Enum for Screening Status Search Options"""

pages/screening_subject_search/subject_screening_summary_page.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from playwright.sync_api import Page, expect, Locator
22
from pages.base_page import BasePage
33
from enum import Enum
4+
import logging
5+
import pytest
46

57

68
class SubjectScreeningSummaryPage(BasePage):
@@ -84,10 +86,15 @@ def verify_latest_event_status_header(self) -> None:
8486

8587
def verify_latest_event_status_value(self, latest_event_status: str) -> None:
8688
"""Verify that the latest event status value is visible."""
89+
logging.info(f"Verifying subject has the status: {latest_event_status}")
8790
latest_event_status_cell = self.get_latest_event_status_cell(
8891
latest_event_status
8992
)
90-
expect(latest_event_status_cell).to_be_visible()
93+
try:
94+
expect(latest_event_status_cell).to_be_visible()
95+
logging.info(f"Subject has the status: {latest_event_status}")
96+
except Exception:
97+
pytest.fail(f"Subject does not have the status: {latest_event_status}")
9198

9299
def click_subjects_events_notes(self) -> None:
93100
"""Click on the 'Subject Events & Notes' link."""
@@ -155,7 +162,12 @@ def click_datasets_link(self) -> None:
155162

156163
def click_advance_fobt_screening_episode_button(self) -> None:
157164
"""Click on the 'Advance FOBT Screening Episode' button."""
158-
self.click(self.advance_fobt_screening_episode_button)
165+
logging.info("Advancing the episode")
166+
try:
167+
self.click(self.advance_fobt_screening_episode_button)
168+
logging.info("Episode successfully advanced")
169+
except Exception as e:
170+
pytest.fail(f"Unable to advance the episode: {e}")
159171

160172

161173
class ChangeScreeningStatusOptions(Enum):

tests/smokescreen/bcss_smokescreen_tests.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@
8585
# ----------------------------------
8686
# compartment 5
8787
# ----------------------------------
88-
# c5_eng_number_of_screening_appts_to_attend=5
88+
c5_eng_number_of_screening_appts_to_attend=5
8989

9090
# ----------------------------------
9191
# compartment 6
9292
# ----------------------------------
93-
# c6_eng_number_of_normal_results_to_record=2
93+
# c6_eng_number_of_normal_results_to_record=1
9494
# c6_eng_number_of_lnpcp_results_to_record=1
9595
# c6_eng_number_of_high_risk_findings_results_to_record=1
9696
# c6_eng_number_of_lnpcp_results_over_74_to_record=1

tests/smokescreen/test_compartment_2.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,9 @@ def test_compartment_2(page: Page, smokescreen_properties: dict) -> None:
5656
pytest.fail(f"{fit_device_id} unsuccessfully logged: {str(e)}")
5757

5858
nhs_no = subjectdf["subject_nhs_number"].iloc[0]
59-
try:
60-
verify_subject_event_status_by_nhs_no(
61-
page, nhs_no, "S43 - Kit Returned and Logged (Initial Test)"
62-
)
63-
logging.info(
64-
f"Successfully verified NHS number {nhs_no} with status S43 - Kit Returned and Logged (Initial Test)"
65-
)
66-
except Exception as e:
67-
pytest.fail(f"Verification failed for NHS number {nhs_no}: {str(e)}")
59+
verify_subject_event_status_by_nhs_no(
60+
page, nhs_no, "S43 - Kit Returned and Logged (Initial Test)"
61+
)
6862

6963
BasePage(page).click_main_menu_link()
7064
BasePage(page).go_to_fit_test_kits_page()

tests/smokescreen/test_compartment_3.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,7 @@ def test_compartment_3(page: Page, smokescreen_properties: dict) -> None:
6666
f"Verifying NHS number: {nhs_number} with expected status: {expected_status}"
6767
)
6868

69-
try:
70-
verify_subject_event_status_by_nhs_no(page, nhs_number, expected_status)
71-
logging.info(
72-
f"Successfully verified NHS number {nhs_number} with status {expected_status}"
73-
)
74-
except Exception as e:
75-
logging.error(
76-
f"Verification failed for NHS number {nhs_number} with status {expected_status}: {str(e)}"
77-
)
78-
raise
69+
verify_subject_event_status_by_nhs_no(page, nhs_number, expected_status)
7970

8071
# Process S2 batch
8172
batch_processing(

0 commit comments

Comments
 (0)