Skip to content

Commit bfa4ed7

Browse files
Updating markdown doc to address feedback comments (#84)
<!-- markdownlint-disable-next-line first-line-heading --> ## Description <!-- Describe your changes in detail. --> Updating the markdown document as according to feedback comments. ## Context <!-- Why is this change required? What problem does it solve? --> Makes it easier to understand what the util does and how to use it. ## 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 9b60997 commit bfa4ed7

File tree

1 file changed

+106
-139
lines changed

1 file changed

+106
-139
lines changed

docs/utility-guides/TableUtil.md

Lines changed: 106 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Utility Guide: Table Utility
22

3-
The Table Utilities module provides helper functions to interact with and validate HTML tables in Playwright-based UI tests.
3+
The Table Utilities module (`utils/table_util.py`) provides helper functions to interact with and validate HTML tables in Playwright-based UI tests.
4+
**This utility is designed to be used inside Page Object Model (POM) classes** to simplify table interactions and assertions.
45

56
## Table of Contents
67

@@ -9,227 +10,193 @@ The Table Utilities module provides helper functions to interact with and valida
910
- [Using the Table Utility](#using-the-table-utility)
1011
- [Example usage](#example-usage)
1112
- [Get Column Index](#get-column-index)
12-
- [Required Arguments](#required-arguments)
13-
- [How This Function Works](#how-this-function-works)
13+
- [Example](#example)
1414
- [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)
15+
- [Example](#example-1)
1716
- [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)
17+
- [Example](#example-2)
2018
- [Format Inner Text](#format-inner-text)
21-
- [Required Arguments](#required-arguments-3)
22-
- [How This Function Works](#how-this-function-works-3)
19+
- [Example](#example-3)
2320
- [Get Table Headers](#get-table-headers)
24-
- [Required Arguments](#required-arguments-4)
25-
- [How This Function Works](#how-this-function-works-4)
21+
- [Example](#example-4)
2622
- [Get Row Count](#get-row-count)
27-
- [Required Arguments](#required-arguments-5)
28-
- [How This Function Works](#how-this-function-works-5)
23+
- [Example](#example-5)
2924
- [Pick Row](#pick-row)
30-
- [Required Arguments](#required-arguments-6)
31-
- [How This Function Works](#how-this-function-works-6)
25+
- [Example](#example-6)
3226
- [Pick Random Row](#pick-random-row)
33-
- [Required Arguments](#required-arguments-7)
34-
- [How This Function Works](#how-this-function-works-7)
27+
- [Example](#example-7)
3528
- [Pick Random Row Number](#pick-random-row-number)
36-
- [Required Arguments](#required-arguments-8)
37-
- [How This Function Works](#how-this-function-works-8)
29+
- [Example](#example-8)
3830
- [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)
31+
- [Example](#example-9)
4132
- [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)
33+
- [Example](#example-10)
4434

4535
## Using the Table Utility
4636

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.
37+
To use the Table Utility, import the `TableUtils` class into your Page Object Model (POM) file and instantiate it for each table you want to interact with.
4838

49-
## Example usage
50-
51-
Below is an example of how the TableUtils used in reports_page.py
39+
```python
40+
from utils.table_util import TableUtils
5241

53-
from utils.table_util import TableUtils
54-
class ReportsPage(BasePage):
42+
class ReportsPage(BasePage):
5543
"""Reports Page locators, and methods for interacting with the page."""
5644

57-
def __init__(self, page):
45+
def __init__(self, page):
5846
super().__init__(page)
5947
self.page = page
6048

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")
49+
# Initialize TableUtils for different tables by passing the page and table selector
50+
self.reports_table = TableUtils(page, "#listReportDataTable")
51+
self.subjects_table = TableUtils(page, "#subjInactiveOpenEpisodes")
52+
```
6953

70-
### Get Column Index
54+
## Example usage
7155

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.
56+
Below are examples of how to use `TableUtils` methods inside your POM methods or tests:
7457

75-
#### Required Arguments
58+
```python
59+
# Click the first NHS number link in the reports table
60+
self.reports_table.click_first_link_in_column("NHS Number")
7661

77-
- `column_name`:
78-
- Type: `str`
79-
- The visible header text of the column to locate.
62+
# Get the index of the "Status" column
63+
status_col_index = self.reports_table.get_column_index("Status")
8064

81-
#### How This Function Works
65+
# Click the first checkbox in the "Select" column
66+
self.subjects_table.click_first_input_in_column("Select")
8267

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.
68+
# Get all table headers as a dictionary
69+
headers = self.reports_table.get_table_headers()
8670

87-
### Click First Link In Column
71+
# Get the number of visible rows in the table
72+
row_count = self.reports_table.get_row_count()
8873

89-
Clicks on the first hyperlink present in a specified column.
74+
# Pick a specific row (e.g., row 2)
75+
row_locator = self.reports_table.pick_row(2)
9076

91-
#### Required Arguments
77+
# Pick a random row and click a link in the "Details" column
78+
random_row = self.reports_table.pick_random_row()
79+
random_row.locator("td").nth(self.reports_table.get_column_index("Details") - 1).locator("a").click()
9280

93-
- `column_name`:
94-
- Type: `str`
95-
- The column in which the link needs to be found.
81+
# Get data for a specific row as a header-value dictionary
82+
row_data = self.reports_table.get_row_data_with_headers(1)
9683

97-
#### How This Function Works
84+
# Get the entire table as a dictionary of rows
85+
full_table = self.reports_table.get_full_table_with_headers()
86+
```
9887

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.
88+
---
10289

103-
### Click First Input In Column
90+
### Get Column Index
10491

105-
Clicks on the first input element (e.g., checkbox/radio) in a specific column.
92+
Returns the index (1-based) of a specified column name. Returns -1 if not found.
10693

107-
#### Required Arguments
94+
#### Example
10895

109-
- `column_name`:
110-
- Type: `str`
111-
- The name of the column containing the input element.
96+
```python
97+
col_index = self.reports_table.get_column_index("Date")
98+
```
11299

113-
#### How This Function Works
100+
### Click First Link In Column
114101

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.
102+
Clicks on the first hyperlink present in a specified column.
118103

119-
### Format Inner Text
104+
#### Example
120105

121-
Formats inner text of a row string into a dictionary.
106+
```python
107+
self.reports_table.click_first_link_in_column("NHS Number")
108+
```
122109

123-
#### Required Arguments
110+
### Click First Input In Column
124111

125-
- data:
126-
- Type: `str`
127-
- Raw inner text of a table row (tab-delimited).
112+
Clicks on the first input element (e.g., checkbox/radio) in a specific column.
128113

129-
#### How This Function Works
114+
#### Example
130115

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.
116+
```python
117+
self.reports_table.click_first_input_in_column("Select")
118+
```
134119

135-
### Get Table Headers
120+
### Format Inner Text
136121

137-
Extracts and returns table headers.
122+
Formats inner text of a row string into a dictionary.
138123

139-
#### Required Arguments
124+
#### Example
140125

141-
- None
126+
```python
127+
row_dict = self.reports_table.format_inner_text("123\tJohn Doe\tActive")
128+
```
142129

143-
#### How This Function Works
130+
### Get Table Headers
144131

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.
132+
Extracts and returns table headers as a dictionary.
148133

149-
### Get Row Count
134+
#### Example
150135

151-
Returns the count of visible rows in the table.
136+
```python
137+
headers = self.reports_table.get_table_headers()
138+
```
152139

153-
#### Required Arguments
140+
### Get Row Count
154141

155-
- None
142+
Returns the count of visible rows in the table.
156143

157-
#### How This Function Works
144+
#### Example
158145

159-
1. Locates all <tr> elements inside <tbody>.
160-
2. Filters to include only visible rows.
161-
3. Returns the total count.
146+
```python
147+
count = self.reports_table.get_row_count()
148+
```
162149

163150
### Pick Row
164151

165-
Returns a locator for a specific row.
166-
167-
#### Required Arguments
152+
Returns a locator for a specific row (1-based).
168153

169-
- `row_number`:
170-
- Type: `int`
171-
- The row index to locate (1-based).
154+
#### Example
172155

173-
#### How This Function Works
174-
175-
1. Builds a locator for the nth <tr> inside <tbody>.
176-
2. Returns the locator object.
156+
```python
157+
row_locator = self.reports_table.pick_row(3)
158+
```
177159

178160
### Pick Random Row
179161

180-
Picks and returns a random row locator.
181-
182-
#### Required Arguments
162+
Picks and returns a locator for a random visible row.
183163

184-
- None
164+
#### Example
185165

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.
166+
```python
167+
random_row = self.reports_table.pick_random_row()
168+
```
191169

192170
### Pick Random Row Number
193171

194172
Returns the number of a randomly selected row.
195173

196-
#### Required Arguments
197-
198-
- None
174+
#### Example
199175

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.
176+
```python
177+
random_row_number = self.reports_table.pick_random_row_number()
178+
```
205179

206180
### Get Row Data With Headers
207181

208182
Returns a dictionary of header-value pairs for a given row.
209183

210-
#### Required Arguments
211-
212-
- `row_number`:
213-
- Type:int
214-
- Index of the target row (1-based).
215-
216-
#### How This Function Works
184+
#### Example
217185

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.
186+
```python
187+
row_data = self.reports_table.get_row_data_with_headers(2)
188+
```
221189

222190
### Get Full Table With Headers
223191

224192
Constructs a dictionary of the entire table content.
225193

226-
#### Required Arguments
194+
#### Example
227195

228-
- None
196+
```python
197+
full_table = self.reports_table.get_full_table_with_headers()
198+
```
229199

230-
#### How This Function Works
200+
---
231201

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.
202+
For more details on each function's implementation, refer to the source code in `utils/table_util.py`.

0 commit comments

Comments
 (0)