Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test coverage for shift-select in product grids #1823

Merged
merged 2 commits into from
Feb 16, 2024
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
47 changes: 47 additions & 0 deletions src/org/labkey/test/components/ui/grids/EditableGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.components.Component;
import org.labkey.test.components.WebDriverComponent;
import org.labkey.test.components.html.Checkbox;
import org.labkey.test.components.html.Input;
import org.labkey.test.components.react.ReactDatePicker;
import org.labkey.test.components.react.ReactSelect;
Expand Down Expand Up @@ -145,6 +146,19 @@ public EditableGrid selectRow(int index, boolean 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);
}
}

public EditableGrid selectAll(boolean checked)
{
if (hasSelectColumn())
Expand All @@ -158,6 +172,39 @@ public EditableGrid selectAll(boolean 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.");
}

/**
* Selects a range of rows in the current view.
* If the range is within a range of already-selected rows, will deselect the specified range
* @param start the starting index (0-based), of non-header rows with checkboxes
* @param end the ending index
* @return the current instance
*/
public EditableGrid shiftSelectRange(int start, int end)
{
if (!hasSelectColumn())
throw new NoSuchElementException("there is no select checkbox for all rows");

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
new Actions(getDriver())
.click(checkBoxes.get(start))
.keyDown(Keys.SHIFT)
.click(checkBoxes.get(end))
.keyUp(Keys.SHIFT)
.perform();
return this;
}

private List<WebElement> getRows()
{
waitForLoaded();
Expand Down
21 changes: 21 additions & 0 deletions src/org/labkey/test/components/ui/grids/QueryGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
import org.labkey.test.components.react.ReactCheckBox;
import org.labkey.test.components.ui.FilterStatusValue;
import org.labkey.test.util.selenium.WebDriverUtils;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.util.HashMap;
Expand Down Expand Up @@ -340,6 +342,25 @@ public QueryGrid clearAllSelections()
return this;
}

/**
* Selects a range of rows in the current view.
* If the range is within a range of already-selected rows, will deselect the specified range
* @param start the starting index (0-based), of non-header rows with checkboxes
* @param end the ending index
* @return the current instance
*/
public QueryGrid shiftSelectRange(int start, int end)
{
var checkBoxes = Locator.tagWithClass("input", "grid-panel__row-checkbox").findElements(this);
getWrapper().scrollIntoView(checkBoxes.get(0), true); // scroll the top row to the top
new Actions(getDriver())
.click(checkBoxes.get(start))
.keyDown(Keys.SHIFT)
.click(checkBoxes.get(end))
.keyUp(Keys.SHIFT)
.perform();
return this;
}

/**
* Select a view from the 'Views' menu.
Expand Down
112 changes: 112 additions & 0 deletions src/org/labkey/test/tests/component/EditableGridTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
import org.junit.experimental.categories.Category;
import org.labkey.remoteapi.Connection;
import org.labkey.test.BaseWebDriverTest;
import org.labkey.test.Locator;
import org.labkey.test.categories.Daily;
import org.labkey.test.components.ui.grids.EditableGrid;
import org.labkey.test.pages.test.CoreComponentsTestPage;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.params.experiment.SampleTypeDefinition;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;

import java.time.LocalDate;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -241,6 +244,115 @@ public void testDragFillMultipleRows()
testGrid.getColumnData(FILL_DATE));
}

@Test
public void testShiftClick()
{
EditableGrid testGrid = goToEditableGrid(PASTING_SAMPLE_TYPE);
testGrid.addRows(15);
testGrid.shiftSelectRange(2, 7);

// select a range
checker().verifyFalse(String.format("row %d should not be checked", 1), testGrid.isRowSelected(1));
for (int i=2; i<7; i++)
{
checker().verifyTrue(String.format("row %d should be checked", i), testGrid.isRowSelected(i));
}
checker().verifyFalse(String.format("row %d should not be checked", 8), testGrid.isRowSelected(8));
checker().screenShotIfNewError("unexpected selection range");

// select a non-adjacent range
testGrid.shiftSelectRange(10, 13);
checker().verifyFalse(String.format("row %d should not be checked", 9), testGrid.isRowSelected(9));
for (int i=10; i<13; i++)
{
checker().verifyTrue(String.format("row %d should be checked", i), testGrid.isRowSelected(i));
}
checker().verifyFalse(String.format("row %d should not be checked", 14), testGrid.isRowSelected(14));
// ensure the first range is still selected
for (int i=2; i<7; i++)
{
checker().verifyTrue(String.format("row %d should be checked", i), testGrid.isRowSelected(i));
}
checker().screenShotIfNewError("unexpected selections1");

// now de-select cells 6 to 3
testGrid.shiftSelectRange(6, 3);
// ensure they are deselected
for (int i=3; i<6; i++)
{
checker().verifyFalse(String.format("row %d should not be checked", i), testGrid.isRowSelected(i));
}
// make sure 2 and 7 are still selected
checker().verifyTrue(String.format("row %d should be checked", 2), testGrid.isRowSelected(2));
checker().verifyTrue(String.format("row %d should be checked", 7), testGrid.isRowSelected(7));
// make sure 10-13 are still selected
for (int i=10; i<13; i++)
{
checker().verifyTrue(String.format("row %d should be checked", i), testGrid.isRowSelected(i));
}
checker().screenShotIfNewError("unexpected selections2");

// now select 0-14
testGrid.shiftSelectRange(0, 14);
checker().withScreenshot("all_rows_not_selected")
.verifyTrue("not all rows are selected",
testGrid.areAllRowsSelected());
}

/*
Tests the scenario where a row is selected, then another, and another are shift-selected
expects the range-bump to redefine the selected range
*/
@Test public void testShiftSelect_bumpSelect()
{
EditableGrid testGrid = goToEditableGrid(PASTING_SAMPLE_TYPE);
testGrid.addRows(15);

Locator boxes = Locator.tag("tr").child("td")
.child(Locator.tagWithAttribute("input", "type", "checkbox"));
var checkBoxes = boxes.findElements(testGrid);
scrollIntoView(checkBoxes.get(0), true); // bring as much of the grid into view as possible

new Actions(getDriver())
.click(checkBoxes.get(2))
.keyDown(Keys.SHIFT)
.click(checkBoxes.get(5))
.click(checkBoxes.get(7))
.keyUp(Keys.SHIFT)
.perform();

// make sure 2-7 are still selected
for (int i=2; i<7; i++)
{
checker().verifyTrue(String.format("row %d should be checked", i), testGrid.isRowSelected(i));
}
checker().screenShotIfNewError("unexpected_selection_range");

// clear all selections
testGrid.selectAll(false);

// now select a row and remove it
new Actions(getDriver())
.click(checkBoxes.get(2))
.perform();
testGrid.clickRemove();
checkBoxes = boxes.findElements(testGrid);

// verify shift-select to another row does not select the range from the now-removed row
new Actions(getDriver())
.keyDown(Keys.SHIFT)
.click(checkBoxes.get(7))
.keyUp(Keys.SHIFT)
.perform();

for (int i=2; i<6; i++)
{
checker().verifyFalse(String.format("row %d should not be checked", i), testGrid.isRowSelected(i));
}
checker().verifyTrue(String.format("row %d should be checked", 7), testGrid.isRowSelected(7));
checker().screenShotIfNewError("unexpected_selection_range");
}

@Test
public void testExpandedPaste() throws Exception
{
Expand Down
45 changes: 45 additions & 0 deletions src/org/labkey/test/tests/component/GridPanelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,51 @@ else if(sampleId % 7 == 0 && stringWithNumCount < NUMBER_STRING_COUNT)

}

@Test
public void testShiftClick()
{
QueryGrid grid = beginAtQueryGrid(FILTER_SAMPLE_TYPE);

// select a range of rows
grid.shiftSelectRange(2, 11);

// verify rows 2-11 are selected, 1 and 12 are not
checker().verifyFalse("row1 should remain unchecked", grid.isRowSelected(1));
for (int i=2; i<12; i++)
{
checker().verifyTrue(String.format("row %d should be selected", i), grid.isRowSelected(i));
}
checker().verifyFalse("row12 should remain unchecked", grid.isRowSelected(12));
checker().verifyEquals("expect selection status to equal",
"10 of 300 selected" ,grid.getSelectionStatusCount());
checker().screenShotIfNewError("unexpected range select");


// negatively select from within a selected range - uncheck 7, shift down, uncheck 4
grid.shiftSelectRange(7, 4);

// verify 4567 are unchecked, 3 and 8 remain checked
checker().verifyTrue("row3 should remain checked", grid.isRowSelected(3));
for (int i=4; i<8; i++)
{
checker().verifyFalse(String.format("row %d should be unchecked", i), grid.isRowSelected(i));
}
checker().verifyTrue("row8 should remain checked", grid.isRowSelected(8));
checker().verifyEquals("expect selection status to equal",
"6 of 300 selected" ,grid.getSelectionStatusCount());
checker().screenShotIfNewError("unexpected range select");

// select a non-adjacent range, verify
grid.shiftSelectRange(13, 17);
for (int i=13; i<17; i++)
{
checker().verifyTrue(String.format("row %d should be checked", i), grid.isRowSelected(i));
}
checker().verifyEquals("expect selection status to equal",
"11 of 300 selected" ,grid.getSelectionStatusCount());
checker().screenShotIfNewError("unexpected range select");
}

/**
* Validate that using the 'First Page' and 'Last Page' navigation works as expected.
*/
Expand Down