Skip to content

Commit f05e5a4

Browse files
authored
Feature/bcss 20441 tableutil markdown doc and doc strings (#51)
<!-- markdownlint-disable-next-line first-line-heading --> ## Description Adding a markdown document explaining the table utility Added docstrings for all of the table utility methods/functions ## Context Allows users to better understand the table util ## 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) - [ ] 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 - [ ] 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 afb0e23 commit f05e5a4

File tree

2 files changed

+246
-4
lines changed

2 files changed

+246
-4
lines changed

docs/utility-guides/TableUtil.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# Utility Guide: Table Utility
2+
3+
The Table Utilities module provides helper functions to interact with and validate HTML tables in Playwright-based UI tests.
4+
5+
## Table of Contents
6+
7+
- [Utility Guide: Table Utility](#utility-guide-table-utility)
8+
- [Table of Contents](#table-of-contents)
9+
- [Using the Table Utility](#using-the-table-utility)
10+
- [Example usage](#example-usage)
11+
- [Get Column Index](#get-column-index)
12+
- [Required Arguments](#required-arguments)
13+
- [How This Function Works](#how-this-function-works)
14+
- [Click First Link In Column](#click-first-link-in-column)
15+
- [Required Arguments](#required-arguments-1)
16+
- [How This Function Works](#how-this-function-works-1)
17+
- [Click First Input In Column](#click-first-input-in-column)
18+
- [Required Arguments](#required-arguments-2)
19+
- [How This Function Works](#how-this-function-works-2)
20+
- [Format Inner Text](#format-inner-text)
21+
- [Required Arguments](#required-arguments-3)
22+
- [How This Function Works](#how-this-function-works-3)
23+
- [Get Table Headers](#get-table-headers)
24+
- [Required Arguments](#required-arguments-4)
25+
- [How This Function Works](#how-this-function-works-4)
26+
- [Get Row Count](#get-row-count)
27+
- [Required Arguments](#required-arguments-5)
28+
- [How This Function Works](#how-this-function-works-5)
29+
- [Pick Row](#pick-row)
30+
- [Required Arguments](#required-arguments-6)
31+
- [How This Function Works](#how-this-function-works-6)
32+
- [Pick Random Row](#pick-random-row)
33+
- [Required Arguments](#required-arguments-7)
34+
- [How This Function Works](#how-this-function-works-7)
35+
- [Pick Random Row Number](#pick-random-row-number)
36+
- [Required Arguments](#required-arguments-8)
37+
- [How This Function Works](#how-this-function-works-8)
38+
- [Get Row Data With Headers](#get-row-data-with-headers)
39+
- [Required Arguments](#required-arguments-9)
40+
- [How This Function Works](#how-this-function-works-9)
41+
- [Get Full Table With Headers](#get-full-table-with-headers)
42+
- [Required Arguments](#required-arguments-10)
43+
- [How This Function Works](#how-this-function-works-10)
44+
45+
## Using the Table Utility
46+
47+
To use the Table Utility, import the `TableUtils` class into your POM file and then define the actions using the its methods as needed.
48+
49+
## Example usage
50+
51+
Below is an example of how the TableUtils used in reports_page.py
52+
53+
from utils.table_util import TableUtils
54+
class ReportsPage(BasePage):
55+
"""Reports Page locators, and methods for interacting with the page."""
56+
57+
def __init__(self, page):
58+
super().__init__(page)
59+
self.page = page
60+
61+
# Initialize TableUtils for different tables
62+
self.failsafe_reports_sub_links_table = TableUtils(page, "#listReportDataTable")
63+
self.fail_safe_reports_screening_subjects_with_inactive_open_episodes_table = (
64+
TableUtils(page, "#subjInactiveOpenEpisodes")
65+
)
66+
def click_failsafe_reports_sub_links(self):
67+
"""Clicks the first NHS number link from the primary report table."""
68+
self.failsafe_reports_sub_links_table.click_first_link_in_column("NHS Number")
69+
70+
### Get Column Index
71+
72+
This function returns the index (1-based) of a specified column name. 1-based indexing means the first column is considered index 1 (not 0 as in Python lists).
73+
If the column is not found, the function returns -1.
74+
75+
#### Required Arguments
76+
77+
- `column_name`:
78+
- Type: `str`
79+
- The visible header text of the column to locate.
80+
81+
#### How This Function Works
82+
83+
1. Attempts to identify table headers from <thead> or <tbody>.
84+
2. Iterates through header cells and matches text with `column_name`.
85+
3. Returns the index if found, otherwise raises an error.
86+
87+
### Click First Link In Column
88+
89+
Clicks on the first hyperlink present in a specified column.
90+
91+
#### Required Arguments
92+
93+
- `column_name`:
94+
- Type: `str`
95+
- The column in which the link needs to be found.
96+
97+
#### How This Function Works
98+
99+
1. Finds the index of the specified column.
100+
2. Searches the first visible row in the column for an `<a>` tag.
101+
3. Clicks the first available link found.
102+
103+
### Click First Input In Column
104+
105+
Clicks on the first input element (e.g., checkbox/radio) in a specific column.
106+
107+
#### Required Arguments
108+
109+
- `column_name`:
110+
- Type: `str`
111+
- The name of the column containing the input element.
112+
113+
#### How This Function Works
114+
115+
1. Locates the index of the specified column.
116+
2. Checks the first visible row for an `<input>` tag in that column.
117+
3. Clicks the first input found.
118+
119+
### Format Inner Text
120+
121+
Formats inner text of a row string into a dictionary.
122+
123+
#### Required Arguments
124+
125+
- data:
126+
- Type: `str`
127+
- Raw inner text of a table row (tab-delimited).
128+
129+
#### How This Function Works
130+
131+
1. Splits the string by tab characters (\t).
132+
2. Enumerates the result and maps index to cell value.
133+
3. Returns a dictionary representing the row.
134+
135+
### Get Table Headers
136+
137+
Extracts and returns table headers.
138+
139+
#### Required Arguments
140+
141+
- None
142+
143+
#### How This Function Works
144+
145+
1. Selects the first row inside <thead> (if available).
146+
2. Captures the visible text of each <th>.
147+
3. Returns a dictionary mapping index to header text.
148+
149+
### Get Row Count
150+
151+
Returns the count of visible rows in the table.
152+
153+
#### Required Arguments
154+
155+
- None
156+
157+
#### How This Function Works
158+
159+
1. Locates all <tr> elements inside <tbody>.
160+
2. Filters to include only visible rows.
161+
3. Returns the total count.
162+
163+
### Pick Row
164+
165+
Returns a locator for a specific row.
166+
167+
#### Required Arguments
168+
169+
- `row_number`:
170+
- Type: `int`
171+
- The row index to locate (1-based).
172+
173+
#### How This Function Works
174+
175+
1. Builds a locator for the nth <tr> inside <tbody>.
176+
2. Returns the locator object.
177+
178+
### Pick Random Row
179+
180+
Picks and returns a random row locator.
181+
182+
#### Required Arguments
183+
184+
- None
185+
186+
#### How This Function Works
187+
188+
1. Gets all visible rows inside <tbody>.
189+
2. Uses a secure random generator to pick one.
190+
3. Returns the locator for that row.
191+
192+
### Pick Random Row Number
193+
194+
Returns the number of a randomly selected row.
195+
196+
#### Required Arguments
197+
198+
- None
199+
200+
#### How This Function Works
201+
202+
1. Retrieves visible rows from <tbody>.
203+
2. Randomly selects an index using secrets.choice.
204+
3. Returns the numeric index.
205+
206+
### Get Row Data With Headers
207+
208+
Returns a dictionary of header-value pairs for a given row.
209+
210+
#### Required Arguments
211+
212+
- `row_number`:
213+
- Type:int
214+
- Index of the target row (1-based).
215+
216+
#### How This Function Works
217+
218+
1. Extracts text from the specified row.
219+
2. Retrieves headers using get_table_headers.
220+
3. Maps each cell to its respective header.
221+
222+
### Get Full Table With Headers
223+
224+
Constructs a dictionary of the entire table content.
225+
226+
#### Required Arguments
227+
228+
- None
229+
230+
#### How This Function Works
231+
232+
1. Gets all visible rows.
233+
2. Retrieves headers once.
234+
3. Loops over each row and builds a dictionary using get_row_data_with_headers.
235+
4. Returns a dictionary where each key is a row number.

utils/table_util.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ def get_column_index(self, column_name: str) -> int:
3131
Finds the column index dynamically based on column name.
3232
Works even if <thead> is missing and header is inside <tbody>.
3333
34-
:param column_name: Name of the column (e.g., 'NHS Number')
35-
:return: 1-based column index or -1 if not found
34+
Args:
35+
column_name (str): Name of the column (e.g., 'NHS Number')
36+
37+
Return:
38+
An int (1-based column index or -1 if not found)
3639
"""
3740
# Try to find headers in <thead> first
3841
header_row = self.table.locator("thead tr").first
@@ -53,7 +56,9 @@ def get_column_index(self, column_name: str) -> int:
5356
def click_first_link_in_column(self, column_name: str):
5457
"""
5558
Clicks the first link found in the given column.
56-
:param column_name: Name of the column containing links
59+
60+
Args:
61+
column_name (str): Name of the column containing links
5762
"""
5863
column_index = self.get_column_index(column_name)
5964
if column_index == -1:
@@ -71,7 +76,9 @@ def click_first_link_in_column(self, column_name: str):
7176
def click_first_input_in_column(self, column_name: str):
7277
"""
7378
Clicks the first input found in the given column. E.g. Radios
74-
:param column_name: Name of the column containing inputs
79+
80+
Args:
81+
column_name (str): Name of the column containing inputs
7582
"""
7683
column_index = self.get_column_index(column_name)
7784
if column_index == -1:

0 commit comments

Comments
 (0)