From a2651b78e0342328e3c43bc41a7bdcb795896614 Mon Sep 17 00:00:00 2001 From: Daria Bodiakova <70635654+DariaBod@users.noreply.github.com> Date: Thu, 3 Sep 2026 14:33:51 -0700 Subject: [PATCH 1/2] Fix for AuthenticationProviderReorderTest.testReorderConfigurations (#3183) ## Rationale A single-jump Selenium drag can lift and drop having registered no movement, so the reorder silently does nothing. Some of the changes in this PR are already in develop due to previous test fixes. ## Related Pull Requests - https://github.com/LabKey/platform/pull/8015 ## Changes - `WebDriverWrapper.keyboardDragAndDrop(WebElement, int)` drives the library's keyboard sensor instead of the mouse: Space to lift, one Arrow per step, Space to drop. - Overload taking a target element derives the step count from the two handles' sibling indexes, so call sites read like the existing `dragAndDrop(from, to)`. - `FieldSelectionDialog.repositionField` delegates to the shared helper instead of its own copy. - `LoginConfigRow.getDragHandle()` exposes a row's drag handle. On the authentication configuration page `dragHandleProps` sit on the row wrapper rather than the visible `.domain-row-handle` icon, so the handle is an ancestor of the row's component element. --- src/org/labkey/test/WebDriverWrapper.java | 29 +++++++ .../ui/grids/FieldSelectionDialog.java | 80 ++++++++++--------- .../test/pages/core/login/LoginConfigRow.java | 8 ++ 3 files changed, 79 insertions(+), 38 deletions(-) diff --git a/src/org/labkey/test/WebDriverWrapper.java b/src/org/labkey/test/WebDriverWrapper.java index b742bde15c..4ea14429f2 100644 --- a/src/org/labkey/test/WebDriverWrapper.java +++ b/src/org/labkey/test/WebDriverWrapper.java @@ -3086,6 +3086,35 @@ public void dragAndDrop(WebElement fromEl, int xOffset, int yOffset) builder.clickAndHold(fromEl).moveByOffset(xOffset + 1, yOffset + 1).release().build().perform(); } + /** + * Reorder a drag-and-drop list with the keyboard instead of the mouse: focus the drag handle, Space to lift, + * one Arrow per step, Space to drop. Required for lists built on '@hello-pangea/dnd' (auth configurations, + * domain designer, field selection). + * + * @param dragHandle Element carrying the library's drag handle props; must be focusable. + * @param steps Positions to move; negative moves up, positive moves down. + */ + public void keyboardDragAndDrop(WebElement dragHandle, int steps) + { + dragHandle.sendKeys(Keys.SPACE); + + Actions drag = new Actions(getDriver()).pause(Duration.ofMillis(400)); + Keys arrow = steps < 0 ? Keys.ARROW_UP : Keys.ARROW_DOWN; + for (int i = 0; i < Math.abs(steps); i++) + drag.sendKeys(arrow).pause(Duration.ofMillis(300)); + drag.sendKeys(Keys.SPACE).perform(); + } + + /** + * @see #keyboardDragAndDrop(WebElement, int) + * @param dragHandle Drag handle of the element to move. + * @param target Drag handle of a sibling element to move it to. + */ + public void keyboardDragAndDrop(WebElement dragHandle, WebElement target) + { + keyboardDragAndDrop(dragHandle, getElementIndex(target) - getElementIndex(dragHandle)); + } + // This is useful when making a draggin selection in a plot, and there may be many elements ontop of the one you want. public void dragAndDrop(int xOffset, int yOffset) { diff --git a/src/org/labkey/test/components/ui/grids/FieldSelectionDialog.java b/src/org/labkey/test/components/ui/grids/FieldSelectionDialog.java index 73b5c143e6..a7b4cf5eca 100644 --- a/src/org/labkey/test/components/ui/grids/FieldSelectionDialog.java +++ b/src/org/labkey/test/components/ui/grids/FieldSelectionDialog.java @@ -522,49 +522,48 @@ private List getSelectedListItems(String fieldLabel) */ public FieldSelectionDialog repositionField(FieldKey fieldToMove, FieldKey targetField, boolean beforeTarget) { - WebElement elementToMove = elementCache().findSelectedField(fieldToMove); - WebElement elementTarget = elementCache().findSelectedField(targetField); + List order = selectedFieldKeys(); + int from = indexOfFieldKey(order, fieldToMove); + int target = indexOfFieldKey(order, targetField); + int to = beforeTarget ? (from < target ? target - 1 : target) : (from < target ? target : target + 1); - int yBefore = elementToMove.getRect().getY(); + getWrapper().keyboardDragAndDrop(elementCache().findDragHandle(fieldToMove), to - from); - int offset; + WebDriverWrapper.waitFor(() -> { + List now = selectedFieldKeys(); + return indexOfFieldKey(now, fieldToMove) - indexOfFieldKey(now, targetField) == (beforeTarget ? -1 : 1); + }, "Field '" + fieldToMove + "' was not repositioned as expected", 5_000); - if(beforeTarget) - { - if(elementTarget.getRect().getY() < elementToMove.getRect().getY()) - { - // If the target is above the field being moved. - offset = -1 * elementTarget.getSize().getHeight(); - } - else - { - // If the target is below the field being moved. - offset = -1 * elementTarget.getSize().getHeight() / 2; - } - } - else - { - offset = elementTarget.getSize().getHeight() / 2 + 10; - } - - WebElement dragHandle = Locator.tagWithAttribute("div", "role", "button").findWhenNeeded(elementToMove); - getWrapper().mouseOver(dragHandle); - new Actions(getDriver()) - .clickAndHold(dragHandle) - .moveToElement(elementTarget) - .moveByOffset(2, offset) - .release() - .perform(); - - // Maybe I don't need to wait? - WebDriverWrapper.sleep(1_000); - - int yAfter = elementToMove.getRect().getY(); + return this; + } - WebDriverWrapper.waitFor(()-> yAfter != yBefore, "I don't think I repositioned the field in the list.", - 1_000); + /** + * Get the 'data-fieldkey' values of the selected fields, in display order. + * + * @return The encoded field keys. + */ + private List selectedFieldKeys() + { + return elementCache().getListItemElements(elementCache().selectedFieldsPanel).stream() + .map(el -> el.getDomAttribute("data-fieldkey")) + .collect(Collectors.toList()); + } - return this; + /** + * Get the index of a field in the given list, matched case-insensitively (as findFieldRow locates rows). + * + * @param fieldKeys Encoded field keys, in display order. + * @param fieldKey Field to locate. + * @return The index, or -1 if not present. + */ + private static int indexOfFieldKey(List fieldKeys, FieldKey fieldKey) + { + for (int i = 0; i < fieldKeys.size(); i++) + { + if (fieldKey.toString().equalsIgnoreCase(fieldKeys.get(i))) + return i; + } + return -1; } /** @@ -662,6 +661,11 @@ protected WebElement findSelectedField(FieldKey fieldKey) return findFieldRow(fieldKey, selectedFieldsPanel); } + protected WebElement findDragHandle(FieldKey fieldKey) + { + return Locator.tagWithAttribute("div", "role", "button").findElement(findSelectedField(fieldKey)); + } + protected WebElement findAvailableField(FieldKey fieldKey) { return findFieldRow(fieldKey, availableFieldsPanel); diff --git a/src/org/labkey/test/pages/core/login/LoginConfigRow.java b/src/org/labkey/test/pages/core/login/LoginConfigRow.java index 2f840381e8..42059113e0 100644 --- a/src/org/labkey/test/pages/core/login/LoginConfigRow.java +++ b/src/org/labkey/test/pages/core/login/LoginConfigRow.java @@ -72,6 +72,11 @@ public boolean canEdit() return elementCache().editButtonLoc.existsIn(this); } + public WebElement getDragHandle() + { + return elementCache().dragHandle; + } + @Override public WebElement getComponentElement() { @@ -93,6 +98,9 @@ protected ElementCache newElementCache() protected class ElementCache extends Component.ElementCache { + final WebElement dragHandle = Locator.xpath("ancestor::div") + .withAttribute("data-rfd-drag-handle-draggable-id").findWhenNeeded(this); + final WebElement baseFieldsElement = Locator.tagWithClass("div", "domain-row-base-fields").findWhenNeeded(this); final WebElement description = Locator.tagWithClass("div", "description").findWhenNeeded(baseFieldsElement); final WebElement details = Locator.tagWithClass("div", "details").findWhenNeeded(baseFieldsElement); From aebacefec82a2fbd8171f1033acbcc93e30373be Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Thu, 3 Sep 2026 14:49:16 -0700 Subject: [PATCH 2/2] Update productKeys used in tests (#3184) (#3185) ## Rationale Update product keys backport Co-authored-by: Susan Hert --- src/org/labkey/test/LabKeySiteWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/labkey/test/LabKeySiteWrapper.java b/src/org/labkey/test/LabKeySiteWrapper.java index e0a9c51281..62b26da729 100644 --- a/src/org/labkey/test/LabKeySiteWrapper.java +++ b/src/org/labkey/test/LabKeySiteWrapper.java @@ -117,9 +117,9 @@ public enum ProductKey { sampleManagerStarter, sampleManagerProfessional, - labkeyLims, limsStarter, limsEnterprise, + biologics, } public boolean isGuestModeTest()