|
1 | | -from playwright.sync_api import Page, Locator, expect |
2 | | -from pages.base_page import BasePage |
| 1 | +from playwright.sync_api import Page, Locator |
3 | 2 | import logging |
4 | 3 | import secrets |
5 | 4 |
|
@@ -51,17 +50,21 @@ def get_column_index(self, column_name: str) -> int: |
51 | 50 | header_texts = headers.evaluate_all("ths => ths.map(th => th.innerText.trim())") |
52 | 51 | logging.info(f"First Row Headers Found: {header_texts}") |
53 | 52 |
|
54 | | - # Extract detailed second-row headers if first-row headers seem generic |
| 53 | + # Attempt to extract a second row of headers (commonly used for filters or alternate titles) |
55 | 54 | second_row_headers = self.table.locator( |
56 | 55 | "thead tr:nth-child(2) th" |
57 | 56 | ).evaluate_all("ths => ths.map(th => th.innerText.trim())") |
58 | | - # Merge both lists: Prioritize second-row headers if available |
59 | | - if second_row_headers: |
| 57 | + |
| 58 | + # Use the second row only if it contains meaningful text (not filters, dropdowns, or placeholder values) |
| 59 | + if second_row_headers and all( |
| 60 | + h and not any(c in h.lower() for c in ("input", "all", "select")) |
| 61 | + for h in second_row_headers |
| 62 | + ): |
60 | 63 | header_texts = second_row_headers |
| 64 | + logging.info(f"Second Row Headers Found: {second_row_headers}") |
61 | 65 |
|
62 | | - logging.info(f"Second Row Headers Found: {header_texts}") |
63 | 66 | for index, header in enumerate(header_texts): |
64 | | - if column_name.lower() in header.lower(): |
| 67 | + if column_name.strip().lower() == header.strip().lower(): |
65 | 68 | return index + 1 # Convert to 1-based index |
66 | 69 | return -1 # Column not found |
67 | 70 |
|
@@ -130,36 +133,52 @@ def get_table_headers(self) -> dict: |
130 | 133 | dict: A mapping of column index (1-based) to header text. |
131 | 134 | """ |
132 | 135 | # Strategy 1: Try <thead> with <tr><th><span class="dt-column-title">Header</span></th> |
133 | | - header_spans = self.page.locator(f"{self.table_id} > thead tr:first-child th span.dt-column-title") |
| 136 | + header_spans = self.page.locator( |
| 137 | + f"{self.table_id} > thead tr:first-child th span.dt-column-title" |
| 138 | + ) |
134 | 139 | if header_spans.count(): |
135 | 140 | try: |
136 | | - header_texts = header_spans.evaluate_all("els => els.map(el => el.textContent.trim())") |
| 141 | + header_texts = header_spans.evaluate_all( |
| 142 | + "els => els.map(el => el.textContent.trim())" |
| 143 | + ) |
| 144 | + print("[DEBUG] Parsed header texts:", repr(header_texts)) |
137 | 145 | return {idx + 1: text for idx, text in enumerate(header_texts)} |
138 | 146 | except Exception as e: |
139 | | - logging.warning(f"[get_table_headers] span.dt-column-title fallback failed: {e}") |
| 147 | + logging.warning( |
| 148 | + f"[get_table_headers] span.dt-column-title fallback failed: {e}" |
| 149 | + ) |
140 | 150 |
|
141 | 151 | # Strategy 2: Fallback to standard <thead> > tr > th inner text |
142 | | - header_cells = self.page.locator(f"{self.table_id} > thead tr").first.locator("th") |
| 152 | + header_cells = self.page.locator(f"{self.table_id} > thead tr").first.locator( |
| 153 | + "th" |
| 154 | + ) |
143 | 155 | if header_cells.count(): |
144 | 156 | try: |
145 | | - header_texts = header_cells.evaluate_all("els => els.map(th => th.innerText.trim())") |
| 157 | + header_texts = header_cells.evaluate_all( |
| 158 | + "els => els.map(th => th.innerText.trim())" |
| 159 | + ) |
146 | 160 | return {idx + 1: text for idx, text in enumerate(header_texts)} |
147 | 161 | except Exception as e: |
148 | 162 | logging.warning(f"[get_table_headers] basic <th> fallback failed: {e}") |
149 | 163 |
|
150 | 164 | # Strategy 3: Last resort — try to find header from tbody row (some old tables use <tbody> only) |
151 | | - fallback_row = self.table.locator("tbody tr").filter(has=self.page.locator("th")).first |
| 165 | + fallback_row = ( |
| 166 | + self.table.locator("tbody tr").filter(has=self.page.locator("th")).first |
| 167 | + ) |
152 | 168 | if fallback_row.locator("th").count(): |
153 | 169 | try: |
154 | | - header_texts = fallback_row.locator("th").evaluate_all("els => els.map(th => th.innerText.trim())") |
| 170 | + header_texts = fallback_row.locator("th").evaluate_all( |
| 171 | + "els => els.map(th => th.innerText.trim())" |
| 172 | + ) |
155 | 173 | return {idx + 1: text for idx, text in enumerate(header_texts)} |
156 | 174 | except Exception as e: |
157 | 175 | logging.warning(f"[get_table_headers] tbody fallback failed: {e}") |
158 | 176 |
|
159 | | - logging.warning(f"[get_table_headers] No headers found for table: {self.table_id}") |
| 177 | + logging.warning( |
| 178 | + f"[get_table_headers] No headers found for table: {self.table_id}" |
| 179 | + ) |
160 | 180 | return {} |
161 | 181 |
|
162 | | - |
163 | 182 | def get_row_count(self) -> int: |
164 | 183 | """ |
165 | 184 | This returns the total rows visible on the table (on the screen currently) |
|
0 commit comments