From 3feb19b32ce3fb7786e0d89b99feac6d1d065cc9 Mon Sep 17 00:00:00 2001 From: alanv Date: Mon, 22 Dec 2025 10:06:19 -0600 Subject: [PATCH 1/5] EditableGrid: Fix getCheckbox locator --- src/org/labkey/test/components/ui/grids/EditableGrid.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/labkey/test/components/ui/grids/EditableGrid.java b/src/org/labkey/test/components/ui/grids/EditableGrid.java index 15a33ee79e..de7f3c7936 100644 --- a/src/org/labkey/test/components/ui/grids/EditableGrid.java +++ b/src/org/labkey/test/components/ui/grids/EditableGrid.java @@ -1252,7 +1252,7 @@ protected class ElementCache extends Component.ElementCache Checkbox getCheckbox(int rowIndex) { - return new Checkbox(Locator.css("td > input[type=checkbox]").findElement(getRow(rowIndex))); + return new Checkbox(Locator.css("td > .table-cell-content > input[type=checkbox]").findElement(getRow(rowIndex))); } protected WebElement getColumnHeaderCell(CharSequence columnIdentifier) From 1ea55e5940aa3bc826d78de861e6650ac75f112f Mon Sep 17 00:00:00 2001 From: alanv Date: Mon, 22 Dec 2025 14:45:30 -0600 Subject: [PATCH 2/5] EntityTypeDesigner: Fix xpath for checkbox --- .../test/components/ui/domainproperties/EntityTypeDesigner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java b/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java index 62d61fbb25..497b004857 100644 --- a/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java +++ b/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java @@ -42,7 +42,7 @@ protected ElementCache newElementCache() public T setSystemFieldVisibility(String fieldName, boolean isVisible) { - var xpath = "//div[contains(@class, 'domain-system-fields__grid')]//td[text()='" + fieldName + "']/preceding-sibling::td//input"; + var xpath = "//div[contains(@class, 'domain-system-fields__grid')]//td[.//div[text()='" + fieldName + "']]/preceding-sibling::td//input"; var checkBox = Checkbox.Checkbox(Locator.xpath(xpath)); var enabledCheckBox = checkBox.find(getFieldsPanel()); enabledCheckBox.set(isVisible); From 4c4cbeceb19f1cd73db29df002e921d368bbee3a Mon Sep 17 00:00:00 2001 From: alanv Date: Tue, 23 Dec 2025 01:04:08 -0600 Subject: [PATCH 3/5] GridRow: Fix getCellStyle locator --- src/org/labkey/test/components/ui/grids/GridRow.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/labkey/test/components/ui/grids/GridRow.java b/src/org/labkey/test/components/ui/grids/GridRow.java index ee920a2767..e6c2a645f5 100644 --- a/src/org/labkey/test/components/ui/grids/GridRow.java +++ b/src/org/labkey/test/components/ui/grids/GridRow.java @@ -107,7 +107,7 @@ public WebElement getCell(CharSequence columnIdentifier) public String getCellStyle(CharSequence columnIdentifier) { var cell = getCell(columnIdentifier); - return Locator.tagWithClass("span", "ws-pre-wrap").findElement(cell).getAttribute("style"); + return Locator.byClass("table-cell-content").child(Locator.tag("span")).findElement(cell).getAttribute("style"); } /** From 2c61d2dc708e7f01a0b9f44727971e6721c53de1 Mon Sep 17 00:00:00 2001 From: alanv Date: Tue, 23 Dec 2025 13:48:52 -0600 Subject: [PATCH 4/5] ResponsiveGrid.clickColumnMenuItem: click the th instead of the chevron --- .../labkey/test/components/ui/grids/ResponsiveGrid.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/org/labkey/test/components/ui/grids/ResponsiveGrid.java b/src/org/labkey/test/components/ui/grids/ResponsiveGrid.java index 5242306ec2..e8ee4d0fb9 100644 --- a/src/org/labkey/test/components/ui/grids/ResponsiveGrid.java +++ b/src/org/labkey/test/components/ui/grids/ResponsiveGrid.java @@ -320,11 +320,8 @@ public void clickColumnMenuItem(CharSequence columnIdentifier, String menuText, WebElement headerCell = elementCache().getColumnHeaderCell(columnIdentifier); // Scroll to middle in order to make room for the dropdown menu getWrapper().scrollToMiddle(headerCell); - - WebElement toggle = Locator.tagWithClass("span", "fa-chevron-circle-down") - .findElement(headerCell); - getWrapper().shortWait().until(ExpectedConditions.elementToBeClickable(toggle)); - toggle.click(); + getWrapper().shortWait().until(ExpectedConditions.elementToBeClickable(headerCell)); + headerCell.click(); // Use getDriver() because the grid menus are rendered in a "react portal" at the end of the HTML body, so they // are totally detached from the rest of the grid. From c28e865d924549eb0f719f48c1ee73b73bf92c9d Mon Sep 17 00:00:00 2001 From: labkey-tchad Date: Tue, 23 Dec 2025 15:56:37 -0800 Subject: [PATCH 5/5] Handle floating grid headers --- src/org/labkey/test/Locators.java | 1 + .../test/util/selenium/ScrollUtils.java | 24 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/org/labkey/test/Locators.java b/src/org/labkey/test/Locators.java index 9140833f14..c14d8804d9 100644 --- a/src/org/labkey/test/Locators.java +++ b/src/org/labkey/test/Locators.java @@ -31,6 +31,7 @@ private Locators() { } public static final Locator.XPathLocator panelWebpartTitle = Locator.byClass("labkey-wp-title-text"); public static final Locator.XPathLocator folderTitle = Locator.tagWithClass("a", "lk-body-title-folder"); public static final Locator.XPathLocator loadingSpinner = Locator.byClass("fa-spinner"); + public static final Locator.CssLocator floatingGridHeader = Locator.css(".grid-panel__grid .table-responsive thead, .editable-grid__container .table-responsive thead"); public static Locator.XPathLocator headerContainer() { diff --git a/src/org/labkey/test/util/selenium/ScrollUtils.java b/src/org/labkey/test/util/selenium/ScrollUtils.java index 2f298d0e8d..3050347ec5 100644 --- a/src/org/labkey/test/util/selenium/ScrollUtils.java +++ b/src/org/labkey/test/util/selenium/ScrollUtils.java @@ -7,6 +7,8 @@ import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.TestLogger; import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.Point; +import org.openqa.selenium.Rectangle; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Locatable; @@ -53,17 +55,15 @@ public static boolean scrollUnderFloatingHeader(WebElement webElement) Locators.floatingHeaderContainer(), Locators.appFloatingHeader(), Locators.domainDesignerFloatingHeader(), - DataRegionTable.Locators.floatingHeader().notHidden()); + DataRegionTable.Locators.floatingHeader().notHidden(), + Locators.floatingGridHeader); - int headerHeight = 0; - for (WebElement floatingHeader : floatingHeaders) + if (!floatingHeaders.isEmpty()) { - headerHeight += floatingHeader.getSize().getHeight(); - } - if (headerHeight > 0) - { - int elYInViewPort = webElement.getLocation().getY() - getWindowScrollY(webDriver).intValue(); - if (headerHeight > elYInViewPort) + Rectangle rect = webElement.getRect(); + Point elementCenter = new Point(rect.getX() + rect.getWidth()/2, rect.getY() + rect.getHeight()/2); + + if (floatingHeaders.stream().anyMatch(el -> pointInRect(elementCenter, el.getRect()))) { TestLogger.debug("Scrolled under floating headers:\n" + floatingHeaders.stream().map(WebElement::toString).collect(Collectors.joining("\n"))); ((Locatable) webElement).getCoordinates().inViewPort(); // 'inViewPort()' will scroll element into view @@ -73,6 +73,12 @@ public static boolean scrollUnderFloatingHeader(WebElement webElement) return false; } + private static boolean pointInRect(Point point, Rectangle rect) + { + return rect.getX() <= point.getX() && point.getX() <= rect.getX() + rect.getWidth() && + rect.getY() <= point.getY() && point.getY() <= rect.getY() + rect.getHeight(); + } + public static Long getWindowScrollY(WebDriver webDriver) { Number N = (Number) executeScript(webDriver, "return window.scrollY;");