From 5a3f8b4113de8ecaa9a5eb4844dff74f9e03a0be Mon Sep 17 00:00:00 2001 From: Daria Bodiakova <70635654+DariaBod@users.noreply.github.com> Date: Mon, 6 Jul 2026 15:52:40 -0700 Subject: [PATCH 1/2] fix drag fill test --- .../components/ui/grids/EditableGrid.java | 55 ++++++++----------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/src/org/labkey/test/components/ui/grids/EditableGrid.java b/src/org/labkey/test/components/ui/grids/EditableGrid.java index f4a98faf73..5947f89600 100644 --- a/src/org/labkey/test/components/ui/grids/EditableGrid.java +++ b/src/org/labkey/test/components/ui/grids/EditableGrid.java @@ -1034,39 +1034,9 @@ public String copyCurrentSelection() throws IOException, UnsupportedFlavorExcept return getWrapper().getClipboardContent(); } - /** - * Select a cell range and drag-fill from the end of that selection to {@code dragEnd}. - * Because this overload owns the {@link #selectCellRange} step, it can fully restore state - * and retry if the first drag extended the selection without applying the fill. - * - * @param selectStart first cell of the selection (passed to {@link #selectCellRange}) - * @param selectEnd last cell of the selection; also the source of the fill value - * @param dragEnd destination cell for the fill drag - */ - public void dragFill(WebElement selectStart, WebElement selectEnd, WebElement dragEnd) - { - Locator.XPathLocator selectionHandleLoc = Locator.byClass("cell-selection-handle"); - selectCellRange(selectStart, selectEnd); - selectEnd.click(); - String fillValue = getCellValue(selectEnd); - WebElement selectionHandle = selectionHandleLoc.waitForElement(getComponentElement(), 2_000); - dragToCell(selectionHandle, dragEnd); - if (!WebDriverWrapper.waitFor(() -> fillValue.equals(getCellValue(dragEnd)), 3_000)) - { - // Fill didn't complete — the drag likely extended the selection without triggering the fill. - selectCellRange(selectStart, selectEnd); - selectEnd.click(); - selectionHandle = selectionHandleLoc.waitForElement(getComponentElement(), 2_000); - dragToCell(selectionHandle, dragEnd); - WebDriverWrapper.waitFor(() -> fillValue.equals(getCellValue(dragEnd)), - "Drag fill did not populate end cell with value: " + fillValue, 5_000); - } - } - /** * Drag-fill from {@code startCell} (which must already be selected / part of the current - * selection) to {@code endCell}. Prefer {@link #dragFill(WebElement, WebElement, WebElement)} - * when the selection range is known — that overload can retry reliably. + * selection) to {@code endCell}. */ public void dragFill(WebElement startCell, WebElement endCell) { @@ -1077,6 +1047,21 @@ public void dragFill(WebElement startCell, WebElement endCell) selectionHandleLoc.waitForElement(endCell, 5_000); } + /** + * Select {@code selectStart} through {@code dragEnd} and fill down from {@code selectEnd}'s row using Ctrl/Cmd+D. + * @param selectStart top-left cell of the range to select + * @param selectEnd cell whose value will be filled down (must be in {@code selectStart}'s row) + * @param dragEnd bottom-right cell of the range to select and fill down to + */ + public void fillDown(WebElement selectStart, WebElement selectEnd, WebElement dragEnd) + { + selectCellRange(selectStart, dragEnd); + String fillValue = getCellValue(selectEnd); + new Actions(getDriver()).keyDown(MODIFIER_KEY).sendKeys("d").keyUp(MODIFIER_KEY).build().perform(); + WebDriverWrapper.waitFor(() -> fillValue.equals(getCellValue(dragEnd)), + "Fill-down did not populate end cell with value: " + fillValue, 3_000); + } + public void selectCellRange(WebElement startCell, WebElement endCell) { dragToCell(startCell, endCell); @@ -1194,9 +1179,13 @@ public boolean isCellSelected(WebElement cell) private boolean isInSelection(WebElement cell) // 'in selection' shows as blue color, means it is part of one or many selected cells for copy/paste, etc { // Should not need to add code for a reactSelect here. A selection involves clicking/dragging, which closes the reactSelect. + // findOptionalElement rather than findElement: the cellular-display div can be briefly absent + // mid-transition (e.g. a lookup field's async dropdown still open right after a paste). Treat + // "not present yet" as "not selected yet" so callers' waitFor polling can retry instead of aborting. return Locator.tagWithClass("div", "cellular-display") - .findElement(cell) - .getDomAttribute("class").contains("cell-selection"); + .findOptionalElement(cell) + .map(el -> el.getDomAttribute("class").contains("cell-selection")) + .orElse(false); } /** From 3e3374079537437604e8d1b149ee290145cb4bee Mon Sep 17 00:00:00 2001 From: Daria Bodiakova <70635654+DariaBod@users.noreply.github.com> Date: Mon, 6 Jul 2026 16:11:28 -0700 Subject: [PATCH 2/2] fix comment --- src/org/labkey/test/components/ui/grids/EditableGrid.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/org/labkey/test/components/ui/grids/EditableGrid.java b/src/org/labkey/test/components/ui/grids/EditableGrid.java index 5947f89600..fb0e315767 100644 --- a/src/org/labkey/test/components/ui/grids/EditableGrid.java +++ b/src/org/labkey/test/components/ui/grids/EditableGrid.java @@ -1179,9 +1179,6 @@ public boolean isCellSelected(WebElement cell) private boolean isInSelection(WebElement cell) // 'in selection' shows as blue color, means it is part of one or many selected cells for copy/paste, etc { // Should not need to add code for a reactSelect here. A selection involves clicking/dragging, which closes the reactSelect. - // findOptionalElement rather than findElement: the cellular-display div can be briefly absent - // mid-transition (e.g. a lookup field's async dropdown still open right after a paste). Treat - // "not present yet" as "not selected yet" so callers' waitFor polling can retry instead of aborting. return Locator.tagWithClass("div", "cellular-display") .findOptionalElement(cell) .map(el -> el.getDomAttribute("class").contains("cell-selection"))