testbench
testbench copied to clipboard
Add missing row methods to VirtualListElement
The row API for VirtualListElement and GridElement are very similar in that they both have the following methods:
-
void scrollToRow(int index) -
boolean isRowInView(int index) -
int getRowCount() -
int getFirstVisibleRowIndex() -
int getLastVisibleRowIndex()
However, GridElement has the following three methods for which there are no complementary VirtualListElement methods.
-
GridTRElement getRow(int index) -
List<GridTRElement> getRows(int firstRowIndex, int lastRowIndex) -
List<GridTRElement> getVisibleRows()
I propose adding something like the following three methods to VirtualListElement:
-
DivElement getRow(int index) -
List<DivElement> getRows(int firstRowIndex, int lastRowIndex) -
List<DivElement> getVisibleRows()
This is a start, however it only gets the virtual rows, not all of them. This is presumably because the rows are coming from the browser, and being that the rows are virtualized, there are only a limited number in the client to be found. Perhaps a loop of (performance risky) scrollToRow calls could be used to fetch them all?
/**
* Gets the rows (present in the DOM) specified by the lower and upper row
* indexes.
*
* @param firstRowIndex
* the lower row index to be retrieved (inclusive)
* @param lastRowIndex
* the upper row index to be retrieved (inclusive)
* @return a {@link DivElement} list with the rows contained between the
* given coordinates.
* @throws IndexOutOfBoundsException
* if either of the provided row indexes do not exist
*/
public List<DivElement> getRows(int firstRowIndex, int lastRowIndex)
throws IndexOutOfBoundsException {
var rowCount = getRowCount();
if ((firstRowIndex < 0) || (firstRowIndex > lastRowIndex) || (lastRowIndex >= rowCount)) {
throw new IndexOutOfBoundsException(
"firstRowIndex and lastRowIndex: expected to be [0.."
+ (rowCount - 1) + "] but were [" + firstRowIndex
+ ".." + lastRowIndex + "]");
}
var script = """
var virtualList = arguments[0];
var firstRowIndex = arguments[1];
var lastRowIndex = arguments[2];
return Array.from(virtualList.children)
.filter((item) => !item.hidden)
.sort((a, b) => a.__virtualIndex - b.__virtualIndex)
.filter((row) =>
(row.__virtualIndex >= firstRowIndex) &&
(row.__virtualIndex <= lastRowIndex));
""";
var result = executeScript(script, this,
(Integer) firstRowIndex, (Integer) lastRowIndex);
if (!(result instanceof List<?> rows)) {
return List.of();
}
return rows.stream()
.filter(TestBenchElement.class::isInstance)
.map(TestBenchElement.class::cast)
.map(testBenchElement -> testBenchElement.wrap(DivElement.class))
.toList();
}
/**
* Gets the <code>div</code> element for the given row index.
*
* @param rowIndex
* the row index
* @return the div element for the row
* @throws IndexOutOfBoundsException
* if no row with given index exists
*/
public DivElement getRow(int rowIndex) throws IndexOutOfBoundsException {
var rows = getRows(rowIndex, rowIndex);
return (rows.size() == 1) ? rows.getFirst() : null;
}
/**
* Gets all the currently visible rows.
*
* @return a {@link DivElement} list representing the currently visible
* rows.
*/
public List<DivElement> getVisibleRows() {
return getRows(getFirstVisibleRowIndex(), getLastVisibleRowIndex());
}