Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 26 additions & 44 deletions src/org/labkey/test/components/ui/grids/EditableGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.labkey.test.components.ui.grids.FieldReferenceManager.FieldReference;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.params.FieldKey;
import org.labkey.test.util.CachingSupplier;
import org.labkey.test.util.selenium.ScrollUtils;
import org.labkey.test.util.selenium.WebElementUtils;
import org.openqa.selenium.By;
Expand Down Expand Up @@ -151,55 +152,29 @@ public EditableGrid removeColumn(CharSequence columnIdentifier)

private boolean hasSelectColumn()
{
return elementCache().selectColumn.isDisplayed();
return elementCache().hasSelectColumn.get();
}

public EditableGrid selectRow(int index, boolean checked)
{
if (hasSelectColumn())
{
WebElement checkBox = Locator.css("td > input[type=checkbox]").findElement(getRow(index));
getWrapper().setCheckbox(checkBox, checked);
}
else
{
throw new NoSuchElementException("There is no select checkbox for row " + index);
}
elementCache().getCheckbox(index).set(checked);
return this;
}

public boolean isRowSelected(int index)
{
if (hasSelectColumn())
{
WebElement checkBox = Locator.css("td > input[type=checkbox]").findElement(getRow(index));
return checkBox.isSelected();
}
else
{
throw new NoSuchElementException("There is no select checkbox for row " + index);
}
return elementCache().getCheckbox(index).isSelected();
}

public EditableGrid selectAll(boolean checked)
{
if (hasSelectColumn())
{
getWrapper().setCheckbox(elementCache().selectColumn, checked);
}
else
{
throw new NoSuchElementException("There is no select checkbox for all rows.");
}
elementCache().selectAllCheckbox.set(checked);
return this;
}

public boolean areAllRowsSelected()
{
if (hasSelectColumn())
return new Checkbox(elementCache().selectColumn).isSelected();
else
throw new NoSuchElementException("There is no select checkbox for all rows.");
return elementCache().selectAllCheckbox.isSelected();
}

/**
Expand All @@ -212,26 +187,21 @@ public boolean areAllRowsSelected()
public EditableGrid shiftSelectRange(int start, int end)
{
if (!hasSelectColumn())
throw new NoSuchElementException("there is no select checkbox for all rows");
throw new NoSuchElementException("there is no selection column for grid");

var checkBoxes = Locator.tag("tr").child("td")
.child(Locator.tagWithAttribute("input", "type", "checkbox"))
.findElements(elementCache().table);
getWrapper().scrollIntoView(checkBoxes.get(0), true); // bring as much of the grid into view as possible
checkBoxes.get(start).click();
getWrapper().scrollIntoView(checkBoxes.get(end), true); // Actions.click() doesn't scroll
new Actions(getDriver())
.click(checkBoxes.get(start))
.keyDown(Keys.SHIFT)
.click(checkBoxes.get(end))
.keyUp(Keys.SHIFT)
.perform();
return this;
}

private List<WebElement> getRows()
{
return Locators.rows.findElements(elementCache().table);
}

/**
* @param columnIdentifiers fieldKeys, names, or labels of columns
* @return grid data for the specified columns, keyed by column label
Expand Down Expand Up @@ -291,7 +261,7 @@ private <T> List<Map<T, String>> getGridData(Function<FieldReferenceManager.Fiel
}
}

for (WebElement row : getRows())
for (WebElement row : elementCache().getRows())
{
List<WebElement> cells = row.findElements(By.tagName("td"));
Map<T, String> rowMap = new LinkedHashMap<>(includedColHeaders.size());
Expand Down Expand Up @@ -337,7 +307,7 @@ public List<String> getColumnData(CharSequence columnIdentifier)

private WebElement getRow(int index)
{
return getRows().get(index);
return elementCache().getRows().get(index);
}

/**
Expand Down Expand Up @@ -387,7 +357,7 @@ public boolean isCellReadOnly(int row, CharSequence columnIdentifier)

public int getRowCount()
{
return getRows().size();
return elementCache().getRows().size();
}

/**
Expand Down Expand Up @@ -657,6 +627,7 @@ public WebElement activateCellUsingDoubleClick(int row, CharSequence columnIdent
// Account for the cell already being active.
if(!textArea.isDisplayed())
{
getWrapper().scrollIntoView(gridCell);
getWrapper().doubleClick(gridCell);
waitFor(textArea::isDisplayed,
String.format("Table cell for row %d and column '%s' was not activated.", row, columnIdentifier), 1_000);
Expand Down Expand Up @@ -1086,7 +1057,7 @@ private boolean areAllInSelection()
List<String> columns = getColumnLabels();
int selectIndexOffset = hasSelectColumn() ? 1 : 0;
WebElement indexCell = getCell(0, columns.get(1 + selectIndexOffset));
WebElement endCell = getCell(getRows().size()-1, columns.get(columns.size()-1));
WebElement endCell = getCell(elementCache().getRows().size()-1, columns.get(columns.size()-1));
return (isInSelection(indexCell) && isInSelection(endCell));
}

Expand Down Expand Up @@ -1219,7 +1190,13 @@ protected class ElementCache extends Component<?>.ElementCache
final WebElement deleteRowsBtn = Locator.byClass("bulk-remove-button").findWhenNeeded(topControls);
final ExportMenu exportMenu = ExportMenu.finder(getDriver()).findWhenNeeded(topControls);
final WebElement table = Locator.byClass("table-cellular").findWhenNeeded(this);
private final WebElement selectColumn = Locator.xpath("//th/input[@type='checkbox']").findWhenNeeded(table);
private final Checkbox selectAllCheckbox = new Checkbox(Locator.xpath("//th/input[@type='checkbox']").findWhenNeeded(table));
private final CachingSupplier<Boolean> hasSelectColumn = new CachingSupplier<>(selectAllCheckbox::isDisplayed);

Checkbox getCheckbox(int rowIndex)
{
return new Checkbox(Locator.css("td > input[type=checkbox]").findElement(getRow(rowIndex)));
}

protected WebElement getColumnHeaderCell(CharSequence columnIdentifier)
{
Expand Down Expand Up @@ -1292,6 +1269,11 @@ public ReactDateTimePicker datePicker()
final WebElement addRowsPanel = Locator.byClass("editable-grid__controls").findWhenNeeded(this);
final Input addCountInput = Input.Input(Locator.name("addCount"), getDriver()).findWhenNeeded(addRowsPanel);
final WebElement addRowsButton = Locator.byClass("btn-primary").findWhenNeeded(addRowsPanel);

List<WebElement> getRows()
{
return Locators.rows.findElements(table);
}
}

protected abstract static class Locators
Expand Down
13 changes: 6 additions & 7 deletions src/org/labkey/test/tests/component/EditableGridTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.hamcrest.CoreMatchers.everyItem;
Expand Down Expand Up @@ -1102,7 +1103,7 @@ public void testShiftArrowSelectHorizontal()

checker().verifyTrue(String.format("The expected cell on row %d and column %s is not selected after hitting <tab>.",
gridRow, PASTE_2),
endCell.getAttribute("class").toLowerCase().contains("cell-selected"));
Objects.requireNonNullElse(endCell.getAttribute("class"), "").toLowerCase().contains("cell-selected"));

checker().screenShotIfNewError("TAB_ERROR");
}
Expand Down Expand Up @@ -1252,8 +1253,8 @@ private void checkSelectedStyle(EditableGrid editableGrid,
for(int rowIndex = startRow; rowIndex <= endRow; rowIndex++)
{
WebElement gridCell = Locator.tag("div").findElement(editableGrid.getCell(rowIndex, columnNames.get(colIndex)));
checker().verifyTrue(String.format("Cell (%s, %d) is not selected.",columnNames.get(colIndex), rowIndex),
gridCell.getAttribute("class").toLowerCase().contains("cell-selection"));
checker().verifyTrue(String.format("Cell (%s, %d) is not selected.", columnNames.get(colIndex), rowIndex),
Objects.requireNonNullElse(gridCell.getAttribute("class"), "").toLowerCase().contains("cell-selection"));
}
}

Expand Down Expand Up @@ -1398,9 +1399,8 @@ public void testPasteCellValidation()
testGrid.addRows(3);

log("Pasting invalid values");
testGrid.selectCell(0, STR_FIELD);
testGrid.pasteFromCell(0, STR_FIELD, rowsToString(clipRows), false);

actionPaste(null, rowsToString(clipRows));
List<List<String>> expectedCellWarnings = List.of(
Arrays.asList(null, null, null, null, null, null, null, null, null, null, null, null, null, null),
Arrays.asList(null, REQ_STR_FIELD.getLabel() + " is required.", null, REQ_INT_FIELD.getLabel() + " is required.", null, REQ_DATETIME_FIELD.getLabel() + " is required.", null, REQ_TIME_FIELD.getLabel() + " is required.", null, null, null, REQ_TEXTCHOICE_FIELD.getLabel() + " is required.", null, REQ_LOOKUP_FIELD.getLabel() + " is required."),
Expand Down Expand Up @@ -1511,8 +1511,7 @@ public void testFillCellValidation()
testGrid.addRows(3);

log("Start with pasting invalid values, so we can fill down invalid values for dropdowns and data/time inputs");
testGrid.selectCell(0, STR_FIELD);
actionPaste(null, rowsToString(clipRows));
testGrid.pasteFromCell(0, STR_FIELD, rowsToString(clipRows), false);

// Scroll one column to the right into view, this will help ensure the REQ_LOOKUP_FIELD is within the viewport.
var index = testGrid.getColumnLabels().indexOf(REQ_LOOKUP_FIELD.getLabel() + " *") + 1;
Expand Down