Background and Code
I am using the following JavaScript code to inject CSS classes into a webpage after the page has loaded. These classes act as selectors that I can use to pinpoint a table cell to perform other actions (the actions that I wish to perform are out of the scope of this question).
These selectors are used in automated UI testing on a legacy system where tables are used as layout, some tables are often times nested in other tables as layout elements, and unique IDs/names are not available. By injecting CSS classes with JavaScript in this way, I can accurately perform Selenium actions that are resilient (testing is out of the scope of this question the JavaScript that is here and it's performance are the scope of this question).
async function addTableCellClassInjector(row, tableIndex, rowIndex) {
for (let columnIndex = 0; column = row.cells[columnIndex]; columnIndex++) {
column.classList.add('agtelc-' + tableIndex + '-' + rowIndex + '-' + columnIndex);
}
}
async function addTableRowClassInjector(table, tableIndex) {
for (let rowIndex = 0; row = table.rows[rowIndex]; rowIndex++) {
row.classList.add('agtelr-' + tableIndex + '-' + rowIndex);
addTableCellClassInjector(row, tableIndex, rowIndex);
}
}
async function addTableClassInjector(tables) {
for (let tableIndex = 0; tableIndex < tables.length; tableIndex++) {
tables[tableIndex].classList.add('agtelt-' + tableIndex);
addTableRowClassInjector(tables[tableIndex], tableIndex);
}
}
addTableRowClassInjector(document.querySelectorAll('table'));
This code performs just fine when there are a couple of tables with a few rows to iterate over. However, the performance slows greatly when there are multiple tables with hundreds of rows.
I believe there might be a better way to handle this whether through reworking the algorithm or using a combination of element selection and the arrays that are return through element selection operations.
Example Usage
Given the following HTML code (inaccuracies and all)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Convoluted Layout Example</title>
</head>
<body>
<div>
<table>
<tbody>
<div>
<tr>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
</tr>
</div>
<div>
<tr>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
</tr>
</div>
<div>
<tr>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
</tr>
</div>
<div>
<tr>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
<td><button>Hello</button></td>
</tr>
</div>
</tbody>
</table>
</div>
</body>
</html>
I am using Selenium to target a button that is listed on a table. Have made an example with similarities to the actual web page I am testing against. Please note that I cannot change the source of page I am testing against.
In order to click on the 5 button in the fourth row in Selenium, I need to use the following selector (please note that an additional div or span may be added to the row, or cell elements during run time depending on the JavaScript that is running in the background thusly breaking this selection method).
body > div:nth-child(1) > table:nth-child(5) > tbody:nth-child(1) > tr:nth-child(3) > td:nth-child(5) > button:nth-child(1)
By injecting these classes I can target that same element using the following query.
.agtelc-0-3-4 > button
This allows me to accurately target the button in a more stable way.
Question
Are there any code improvements that can be made to this solution that will scale well as tables and rows/columns increase?
I have setup a sample page as a test for the purposes of this question Example page with tables for iteration performance improvements
:nth-child
instead. \$\endgroup\$