diff --git a/src/org/labkey/test/components/react/BaseReactSelect.java b/src/org/labkey/test/components/react/BaseReactSelect.java index 3af1d1c115..0761b6fbaf 100644 --- a/src/org/labkey/test/components/react/BaseReactSelect.java +++ b/src/org/labkey/test/components/react/BaseReactSelect.java @@ -156,6 +156,22 @@ public boolean isPlaceholderVisible() return placeholder != null && placeholder.isDisplayed(); } + public @Nullable String getHelpBlockText() + { + waitForReady(); + + if (!isHelpBlockVisible()) + return null; + + return Locators.helpBlock.findElement(getComponentElement()).getText().trim(); + } + + public boolean isHelpBlockVisible() + { + var helpBlock = Locators.helpBlock.findElementOrNull(getComponentElement()); + return helpBlock != null && helpBlock.isDisplayed(); + } + public String getValue() { waitForReady(); @@ -499,6 +515,7 @@ private Locators() public static final Locator.XPathLocator singleValueLabel = Locator.tagWithClass("div", "select-input__single-value"); public static final Locator loadingSpinner = Locator.tagWithClass("span", "select-input__loading-indicator"); public static final Locator listItems = Locator.tagWithClass("div", "select-input__option"); + public static final Locator.XPathLocator helpBlock = Locator.tagWithClass("span", "help-block"); public static Locator.XPathLocator selectContainer() { diff --git a/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java b/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java index c961e1065b..a789bb8ba1 100644 --- a/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java +++ b/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java @@ -276,10 +276,8 @@ public ReactSelect getEntityType(String entityName) String inputName = input.findElement(this).getAttribute("name"); return new ReactSelect.ReactSelectFinder(getDriver()).withNamedInput(inputName).find(this); } - else - { - return null; - } + + return null; } /** @@ -352,12 +350,10 @@ public ParentEntityEditPanel addParent(String typeName, String parentId) */ public ParentEntityEditPanel addParents(String typeName, List parentIds) { - if(getEntityType(typeName) == null) + if (getEntityType(typeName) == null) getAddNewEntityTypeSelect().select(typeName); - var selectParent = FilteringReactSelect.finder(getDriver()) - .withNamedInput(String.format("parentEntityValue_%s", typeName)) - .waitFor(elementCache()); + var selectParent = getParent(typeName); // Adding for debugging (trying to understand why save button is not enabled after setting). getWrapper().log(String.format("Selections before adding: %s", selectParent.getSelections())); diff --git a/src/org/labkey/test/components/ui/grids/DetailTableEdit.java b/src/org/labkey/test/components/ui/grids/DetailTableEdit.java index a7336805dc..432284e7ca 100644 --- a/src/org/labkey/test/components/ui/grids/DetailTableEdit.java +++ b/src/org/labkey/test/components/ui/grids/DetailTableEdit.java @@ -131,7 +131,7 @@ public String getTextField(String fieldLabel) { WebElement fieldValueElement = elementCache().valueCellWithLabel(fieldLabel); WebElement textElement = fieldValueElement.findElement(By.xpath("./div/div/*")); - if(textElement.getTagName().equalsIgnoreCase("textarea")) + if (textElement.getTagName().equalsIgnoreCase("textarea")) return textElement.getText(); else return textElement.getAttribute("value"); @@ -146,14 +146,14 @@ public String getTextField(String fieldLabel) **/ public DetailTableEdit setTextField(String fieldLabel, String value) { - if(isFieldEditable(fieldLabel)) + if (isFieldEditable(fieldLabel)) { WebElement fieldValueElement = elementCache().valueCellWithLabel(fieldLabel); WebElement editableElement = fieldValueElement.findElement(By.xpath("./div/div/*")); String elementType = editableElement.getTagName().toLowerCase().trim(); - switch(elementType) + switch (elementType) { case "textarea": case "input": @@ -291,6 +291,11 @@ public boolean isFileFieldBlank(String fieldLabel) .hasAttachedFile(); } + public FilteringReactSelect getSelectField(String fieldLabel) + { + return elementCache().findSelect(fieldLabel); + } + /** * Get the value of a select field. * @@ -299,17 +304,18 @@ public boolean isFileFieldBlank(String fieldLabel) **/ public String getSelectedValue(String fieldLabel) { - FilteringReactSelect reactSelect = elementCache().findSelect(fieldLabel); - return reactSelect.getValue(); + return getSelectField(fieldLabel).getValue(); } - /* - This allows you to query a given select in the edit panel to see what options it offers - */ + /** + * This allows you to query a given select in the edit panel to see what options it offers. + * + * @param fieldLabel The label of the field to get. + * @return List of strings for the values in the list. + **/ public List getSelectOptions(String fieldLabel) { - FilteringReactSelect reactSelect = elementCache().findSelect(fieldLabel); - return reactSelect.getOptions(); + return getSelectField(fieldLabel).getOptions(); } /** @@ -333,7 +339,6 @@ public DetailTableEdit createSelectValue(String fieldLabel, String value) return this; } - /** * Select multiple values from a select list. * @@ -343,7 +348,7 @@ public DetailTableEdit createSelectValue(String fieldLabel, String value) **/ public DetailTableEdit setSelectValue(String fieldLabel, List selectValues) { - FilteringReactSelect reactSelect = elementCache().findSelect(fieldLabel); + FilteringReactSelect reactSelect = getSelectField(fieldLabel); selectValues.forEach(reactSelect::typeAheadSelect); _changeCounter++; return this; @@ -361,24 +366,25 @@ public DetailTableEdit clearSelectValue(String fieldLabel) } /** - * Clear a given select field + * Clear a given select field. + * * @param fieldLabel The label of the field to clear. * @param waitForSelection If true, wait for the select to have a selection before clearing it * @param assertSelection If true, assert if no selection appears (note: does nothing if waitForSelection is not true) - * @return + * @return A reference to this editable detail table. */ public DetailTableEdit clearSelectValue(String fieldLabel, boolean waitForSelection, boolean assertSelection) { - var select = elementCache().findSelect(fieldLabel); + var select = getSelectField(fieldLabel); if (waitForSelection) { - if (assertSelection) { - WebDriverWrapper.waitFor(() -> select.hasSelection(), + if (assertSelection) + { + WebDriverWrapper.waitFor(select::hasSelection, String.format("The %s select did not have any selection in time", fieldLabel), _readyTimeout); } - else { - WebDriverWrapper.waitFor(() -> select.hasSelection(), 1000); - } + else + WebDriverWrapper.waitFor(select::hasSelection, 1_000); } select.clearSelection(); _changeCounter++; @@ -398,19 +404,19 @@ public DetailTableEdit clearSelectValue(String fieldLabel, boolean waitForSelect public DetailTableEdit setDateTimeField(String fieldName, Object dateTime) { ReactDateTimePicker dateTimePicker = getDateTimePicker(fieldName); - if(dateTime instanceof LocalDateTime localDateTime) + if (dateTime instanceof LocalDateTime localDateTime) { dateTimePicker.select(localDateTime); } - else if(dateTime instanceof LocalDate localDate) + else if (dateTime instanceof LocalDate localDate) { dateTimePicker.selectDate(localDate); } - else if(dateTime instanceof LocalTime localTime) + else if (dateTime instanceof LocalTime localTime) { dateTimePicker.selectTime(localTime); } - else if(dateTime instanceof String setValue) + else if (dateTime instanceof String setValue) { dateTimePicker.set(setValue, true); } @@ -481,7 +487,7 @@ private String getSourceTitle() */ public String getValidationMessage() { - if(elementCache().validationMsg.existsIn(this)) + if (elementCache().validationMsg.existsIn(this)) return elementCache().validationMsg.findElement(getDriver()).getText(); else return ""; @@ -534,8 +540,7 @@ public String clickSaveExpectingError() { elementCache().saveButton.click(); WebElement errorBanner = BootstrapLocators.errorBanner.findWhenNeeded(this); - WebDriverWrapper.waitFor(()->errorBanner.isDisplayed(), - "No error message was shown.", 1_000); + WebDriverWrapper.waitFor(errorBanner::isDisplayed, "No error message was shown.", 1_000); return errorBanner.getText(); } @@ -550,8 +555,7 @@ public String clickCancelExpectingError() { elementCache().cancelButton.click(); WebElement errorBanner = BootstrapLocators.errorBanner.findWhenNeeded(this); - WebDriverWrapper.waitFor(()->errorBanner.isDisplayed(), - "No error message was shown.", 1_000); + WebDriverWrapper.waitFor(errorBanner::isDisplayed, "No error message was shown.", 1_000); return errorBanner.getText(); } @@ -647,5 +651,4 @@ protected Locator locator() return _locator; } } - }