From 8f1b58139d26558ef2b5adf4af6487e512c19de0 Mon Sep 17 00:00:00 2001 From: labkey-tchad Date: Wed, 27 Aug 2025 15:28:55 -0700 Subject: [PATCH] Improve synchronization of ParentEntityEditPanel --- src/org/labkey/test/Locator.java | 9 +++ .../test/components/bootstrap/Panel.java | 36 +++++++---- .../ui/entities/ParentEntityEditPanel.java | 59 +++++++++---------- 3 files changed, 61 insertions(+), 43 deletions(-) diff --git a/src/org/labkey/test/Locator.java b/src/org/labkey/test/Locator.java index f838d7832f..17bd5dc435 100644 --- a/src/org/labkey/test/Locator.java +++ b/src/org/labkey/test/Locator.java @@ -19,6 +19,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.mutable.MutableObject; import org.intellij.lang.annotations.Language; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.labkey.test.selenium.LazyWebElement; @@ -373,11 +374,13 @@ protected static T extractInputFromFluentWait(FluentWait wait) return wrappedContext.getValue(); } + @Contract(pure = true) public LazyWebElement findWhenNeeded(SearchContext context) { return new LazyWebElement<>(this, context); } + @Contract(pure = true) public RefindingWebElement refindWhenNeeded(SearchContext context) { return new RefindingWebElement(this, context); @@ -391,11 +394,13 @@ public WebElement findElement(SearchContext context) new NoSuchElementException("Unable to find element: " + getFindDescription(context))); } + @Contract(pure = true) public WebElement findElementOrNull(SearchContext context) { return findOptionalElement(context).orElse(null); } + @Contract(pure = true) public Optional findOptionalElement(SearchContext context) { List elements = findElements(context); @@ -404,6 +409,7 @@ public Optional findOptionalElement(SearchContext context) return Optional.of(elements.get(0)); } + @Contract(pure = true) @Override public List findElements(SearchContext context) { @@ -454,11 +460,13 @@ public List findElements(SearchContext context) } } + @Contract(pure = true) public boolean existsIn(SearchContext context) { return findElementOrNull(context) != null; } + @Contract(pure = true) public boolean isDisplayed(SearchContext context) { WebElement element = findElementOrNull(context); @@ -471,6 +479,7 @@ public boolean isDisplayed(SearchContext context) * @param context Search context. * @return True if there are any elements visible, false otherwise. */ + @Contract(pure = true) public boolean areAnyVisible(SearchContext context) { List elements = findElements(context); diff --git a/src/org/labkey/test/components/bootstrap/Panel.java b/src/org/labkey/test/components/bootstrap/Panel.java index 6daee505ec..2b8a74edff 100644 --- a/src/org/labkey/test/components/bootstrap/Panel.java +++ b/src/org/labkey/test/components/bootstrap/Panel.java @@ -71,26 +71,20 @@ public class ElementCache extends Component.ElementCache protected final WebElement panelBody = Locator.byClass("panel-body").findWhenNeeded(this); } - public static class PanelFinder extends WebDriverComponentFinder, PanelFinder> + protected static abstract class AbstractPanelFinder, F extends AbstractPanelFinder> extends WebDriverComponentFinder { - private final Locator.XPathLocator _baseLocator = Locator.tagWithClass("div", "panel-default"); + private final Locator.XPathLocator _baseLocator = Locator.tagWithClass("div", "panel"); private String _title = null; - public PanelFinder(WebDriver driver) + public AbstractPanelFinder(WebDriver driver) { super(driver); } - public PanelFinder withTitle(String title) + public F withTitle(String title) { _title = title; - return this; - } - - @Override - protected Panel construct(WebElement el, WebDriver driver) - { - return new PanelImpl(el, driver); + return getThis(); } @Override @@ -103,6 +97,26 @@ protected Locator locator() return _baseLocator; } } + + public static class PanelFinder extends AbstractPanelFinder, PanelFinder> + { + public PanelFinder(WebDriver driver) + { + super(driver); + } + + @Override + protected PanelFinder getThis() + { + return this; + } + + @Override + protected Panel construct(WebElement el, WebDriver driver) + { + return new PanelImpl(el, driver); + } + } } class PanelImpl extends Panel diff --git a/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java b/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java index 34efbee7fa..b4407433e4 100644 --- a/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java +++ b/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java @@ -4,8 +4,7 @@ import org.labkey.test.BootstrapLocators; import org.labkey.test.Locator; import org.labkey.test.WebDriverWrapper; -import org.labkey.test.components.Component; -import org.labkey.test.components.WebDriverComponent; +import org.labkey.test.components.bootstrap.Panel; import org.labkey.test.components.react.BaseReactSelect; import org.labkey.test.components.react.FilteringReactSelect; import org.labkey.test.components.react.ReactSelect; @@ -13,9 +12,12 @@ import org.openqa.selenium.StaleElementReferenceException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** *

@@ -25,11 +27,8 @@ *

* @see ParentEntityEditPanel.tsx */ -public class ParentEntityEditPanel extends WebDriverComponent +public class ParentEntityEditPanel extends Panel { - private final WebDriver driver; - private final WebElement editingDiv; - /** * Constructor for the panel. * @@ -38,20 +37,7 @@ public class ParentEntityEditPanel extends WebDriverComponentelementCache().saveButton.isEnabled(), "Save button is not enabled.", 2_500); + String parentType = getTitle().split(" ", 2)[1].trim(); // Trim "Editing" from the title + Set selections = new HashSet<>(); + getAllParents().stream().map(BaseReactSelect::getSelections).forEach(selections::addAll); + // The wait time is used here to validate the panel exits edit mode. clickButtonWaitForPanel(elementCache().saveButton, waitTime); @@ -192,6 +182,20 @@ public void clickSave(int waitTime) WebDriverWrapper.waitFor(()->!progressbar.isDisplayed(), "It looks like an update took too long.", waitTime); + Panel detailsPanel = new Panel.PanelFinder(getDriver()).withTitle(parentType).waitFor(getDriver()); + if (!selections.isEmpty()) + { + for (String selection : selections) + { + getWrapper().quickWait().until(ExpectedConditions.visibilityOf( + Locator.linkWithText(selection).findWhenNeeded(detailsPanel))); + } + } + else + { + getWrapper().quickWait().until(ExpectedConditions.visibilityOf( + Locator.tag("td").containing("has been set for this sample.").findWhenNeeded(detailsPanel))); + } } /** @@ -467,11 +471,12 @@ public boolean hasParentInputError() /** * Simple finder for this panel. */ - public static class ParentEntityEditPanelFinder extends WebDriverComponentFinder + public static class ParentEntityEditPanelFinder extends AbstractPanelFinder { public ParentEntityEditPanelFinder(WebDriver driver) { super(driver); + withTitle("Editing"); } @Override @@ -479,16 +484,6 @@ protected ParentEntityEditPanel construct(WebElement element, WebDriver driver) { return new ParentEntityEditPanel(element, driver); } - - @Override - protected Locator locator() - { - return Locator - .tagContainingText("div", "Editing") - .withClass("panel-heading") - .parent() - .child(Locator.tagWithClass("div", "panel-body")); - } } public static class DataClassAddParentEntityPanelFinder extends WebDriverComponentFinder @@ -517,7 +512,7 @@ protected ElementCache newElementCache() return new ElementCache(); } - protected class ElementCache extends Component.ElementCache + protected class ElementCache extends Panel.ElementCache { final WebElement saveButton = Locator.byClass("btn-success").withText("Save").findWhenNeeded(this); final WebElement cancelButton = Locator.byClass("btn-default").withText("Cancel").refindWhenNeeded(this);