Skip to content

Commit

Permalink
Test Automation Fixes (#1585)
Browse files Browse the repository at this point in the history
  • Loading branch information
labkey-danield authored Aug 30, 2023
1 parent c11519a commit 0d7fe57
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 45 deletions.
4 changes: 3 additions & 1 deletion src/org/labkey/test/components/bootstrap/ModalDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.labkey.test.components.bootstrap;

import org.labkey.test.BootstrapLocators;
import org.labkey.test.Locator;
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.components.Component;
Expand Down Expand Up @@ -67,7 +68,8 @@ protected void waitForReady()
protected void waitForReady(ElementCache ec)
{
elementCache().body.isDisplayed(); // Make sure timeout doesn't get used up by waiting for the dialog to appear
WebDriverWrapper.waitFor(() -> elementCache().body.getText().length() > 0, "Modal dialog not ready", 2000);
WebDriverWrapper.waitFor(() -> !BootstrapLocators.loadingSpinner.areAnyVisible(getDriver()) &&
elementCache().body.getText().length() > 0, "Modal dialog not ready.", 2_500);
}

@Override
Expand Down
3 changes: 2 additions & 1 deletion src/org/labkey/test/components/react/BaseReactSelect.java
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ public T removeSelection(String value)

private void attemptRemove(String value)
{
WebElement removeBtn = Locators.removeMultiSelectValueButton(value).findElement(getComponentElement());
WebElement removeBtn = Locators.removeMultiSelectValueButton(value)
.waitForElement(getComponentElement(), 1_000);
removeBtn.click();

getWrapper().shortWait().until(ExpectedConditions.stalenessOf(removeBtn));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,11 @@ public FilteringReactSelect typeAheadSelect(String value, String optionText, Str
throw sere;
}

if (!WebDriverWrapper.waitFor(()-> !isExpanded(), 1500)) // give it a moment to close, blur if it hasn't
if (Boolean.FALSE.equals(WebDriverWrapper.waitFor(()-> !isExpanded(), 1500))) // give it a moment to close, blur if it hasn't
{
// Adding for debugging. Trying to see if there is any correlation between this and failures where a "Save"
// button is not enabled because it did not see the change event in the select control.
log("Firing the blur event on the input control for the react select.");
getWrapper().fireEvent(elementCache().input, WebDriverWrapper.SeleniumEvent.blur);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected void waitForReady()
{
WebDriverWrapper.waitFor(()-> elementCache().body.isDisplayed() &&
!BootstrapLocators.loadingSpinner.existsIn(this),
"The 'Choose Samples to Add' dialog did not display.", 1_000);
"The delete confirmation dialog did not become ready.", 1_000);
}

public SourcePage cancelDelete()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ public T removeParentAlias(int index)
public String getParentAlias(int index)
{
expandPropertiesPanel();
WebDriverWrapper.waitFor(()->elementCache().parentAliases().size() > 0,
"There are no parent aliases visible.", 2_500);
return elementCache().parentAlias(index).get();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ public void clickSave()
*/
public void clickSave(int waitTime)
{
// Making changes, like to lineage, may cause a slight delay before the save button is enabled.
WebDriverWrapper.waitFor(()->elementCache().button("Save").isEnabled(),
"Save button is not enabled.", 2_500);

// The wait time is used here to validate the panel exits edit mode.
clickButtonWaitForPanel(elementCache()
.button("Save"),
Expand Down Expand Up @@ -359,13 +363,19 @@ public ParentEntityEditPanel addParents(String typeName, List<String> parentIds)
.withNamedInput(String.format("parentEntityValue_%s", typeName))
.waitFor(this);

// Adding for debugging (trying to understand why save button is not enabled after setting).
getWrapper().log(String.format("Selections before adding: %s", selectParent.getSelections()));

for (String id : parentIds)
{
int selCount = selectParent.getSelections().size();
selectParent.typeAheadSelect(id);
WebDriverWrapper.waitFor(()-> selectParent.getSelections().size() > selCount, 500);
WebDriverWrapper.waitFor(()-> selectParent.getSelections().contains(id) ,
String.format("Parent '%s' was not added to the list.", parentIds), 2_500);
}

// Adding for debugging (trying to understand why save button is not enabled after setting).
getWrapper().log(String.format("Selections after adding: %s", selectParent.getSelections()));

return this;
}

Expand Down
7 changes: 7 additions & 0 deletions src/org/labkey/test/components/ui/grids/DetailTable.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.labkey.test.components.ui.grids;

import org.labkey.test.Locator;
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.components.Component;
import org.labkey.test.components.WebDriverComponent;
import org.openqa.selenium.By;
Expand Down Expand Up @@ -120,9 +121,15 @@ public String getFieldValueByKey(String fieldKey)
**/
public void clickField(String fieldCaption)
{
String urlBefore = getWrapper().getCurrentRelativeURL().toLowerCase();

// Should not click the container, it could be a td which would miss the clickable element.
// Maybe this shouldn't assume an anchor but should be a generic(*)?
Locator.tag("a").waitForElement(getField(fieldCaption), 1500).click();

WebDriverWrapper.waitFor(()->!urlBefore.equals(getWrapper().getCurrentRelativeURL().toLowerCase()),
String.format("Clicking field (link) '%s' did not navigate.", fieldCaption), 500);

}

/**
Expand Down
38 changes: 25 additions & 13 deletions src/org/labkey/test/components/ui/grids/ResponsiveGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.labkey.test.components.ui.search.FilterExpressionPanel;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.NotFoundException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
Expand Down Expand Up @@ -60,9 +61,10 @@ public WebElement getComponentElement()
public Boolean isLoaded()
{
return getComponentElement().isDisplayed() &&
!Locators.loadingGrid.existsIn(this) &&
(!Locators.loadingGrid.existsIn(this) &&
!Locators.spinner.existsIn(this) &&
Locator.tag("td").existsIn(this);
Locator.tag("td").existsIn(this)) ||
getGridEmptyMessage().isPresent();
}

protected void waitForLoaded()
Expand Down Expand Up @@ -157,20 +159,22 @@ public T filterColumn(String columnLabel, Filter.Operator operator)
public T filterColumn(String columnLabel, Filter.Operator operator, Object value)
{
T _this = getThis();
GridFilterModal filterModal = initFilterColumn(columnLabel, operator, value);
filterModal.confirm();
doAndWaitForUpdate(()->initFilterColumn(columnLabel, operator, value).confirm());
return _this;
}

public T filterColumn(String columnLabel, Filter.Operator operator1, Object value1, Filter.Operator operator2, Object value2)
{
T _this = getThis();
GridFilterModal filterModal = initFilterColumn(columnLabel, null, null);
filterModal.selectExpressionTab().setFilters(
new FilterExpressionPanel.Expression(operator1, value1),
new FilterExpressionPanel.Expression(operator2, value2)
);
filterModal.confirm();
doAndWaitForUpdate(()-> {
GridFilterModal filterModal = initFilterColumn(columnLabel, null, null);
filterModal.selectExpressionTab().setFilters(
new FilterExpressionPanel.Expression(operator1, value1),
new FilterExpressionPanel.Expression(operator2, value2)
);
filterModal.confirm();
});

return _this;
}

Expand Down Expand Up @@ -676,10 +680,18 @@ public Optional<String> getGridEmptyMessage()
{
Optional<String> msg = Optional.empty();

WebElement tr = Locator.tagWithClass("tr", "grid-empty").refindWhenNeeded(this);
if(tr.isDisplayed())
try
{
WebElement tr = Locator.tagWithClass("tr", "grid-empty").refindWhenNeeded(this);
if (tr.isDisplayed())
{
msg = Optional.of(Locator.tag("td").findElement(tr).getText());
}
}
catch (StaleElementReferenceException stale)
{
msg = Optional.of(Locator.tag("td").findElement(tr).getText());
getWrapper().log("Grid empty message was present but has now gone stale (went away).");
msg = Optional.empty();
}

return msg;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class ManageSampleFinderViewsModal extends ModalDialog
{
Expand All @@ -23,22 +23,32 @@ protected ManageSampleFinderViewsModal(String title, WebDriver driver)
super(new ModalDialog.ModalDialogFinder(driver).withTitle(title));
}

@Override
protected void waitForReady()
{
// This will wait for something to show up in the dialog body and if it is a spinner it will wait for it to go away.
super.waitForReady();

// Now, specifically check for:
// An input box (to save a new image).
// Or some grey text (get this when you delete all views and the dialog is still up).
// Or a list of existing views.
WebDriverWrapper.waitFor(()->
Locator.tag("input").refindWhenNeeded(this).isDisplayed() ||
Locator.tagWithClass("div", "grey-text").refindWhenNeeded(this). isDisplayed() ||
Locator.tagWithClass("div", "row").refindWhenNeeded(this). isDisplayed(),
"Save view dialog did not display in time.",
2_500);
}

public void editViewName(String viewName)
{
WebElement editIcon = getViewEditIcon(viewName);
if (editIcon != null)
{
editIcon.click();
}
getViewEditIcon(viewName).click();
}

public void deleteView(String viewName)
{
WebElement deleteIcon = getViewDeleteIcon(viewName);
if (deleteIcon != null)
{
deleteIcon.click();
}
getViewDeleteIcon(viewName).click();
}

public void deleteAllViews()
Expand All @@ -51,27 +61,40 @@ public void deleteAllViews()
}
}

private static final String viewNameLocatorXpath = "//div[@class='modal-body']//div[contains(@class,'row')]//div[1]";

public List<String> getViews()
{
return Locator.tagWithClass("div", "small-margin-bottom")
.findElements(getComponentElement())
.stream()
.map(WebElement::getText)
.collect(Collectors.toList());
}
Locator viewNameLocator = Locator.xpath(viewNameLocatorXpath);
// Wait until some view shows up.
WebDriverWrapper.waitFor(()->getWrapper().isElementPresent(viewNameLocator),
"No views are present.", 2_500);

public WebElement getView(String viewName)
{
List<WebElement> webElements = Locator.tagWithClass("div", "small-margin-bottom")
.findElements(getComponentElement());
List<String> views = new ArrayList<>();

// Get all the view names.
List<WebElement> elements = viewNameLocator.findElements(this);

for (WebElement element : webElements)
getWrapper().log(String.format("Found %d views in the dialog.", elements.size()));

for(WebElement element : elements)
{
if (element.getText().equals(viewName))
return element;
views.add(element.getText());
}

return null;
return views;
}

public WebElement getView(String viewName)
{
// Wait until some view shows up.
Locator viewNameLocator = Locator.xpath(viewNameLocatorXpath);
WebDriverWrapper.waitFor(()->getWrapper().isElementPresent(viewNameLocator),
"No views are present.", 2_500);

// Get the row for the given view.
return Locator.xpath(String.format("//div[text()='%s']/parent::div[contains(@class,'row')]", viewName))
.findElement(this);
}

public WebElement getViewIcon(String reportName, String iconCls)
Expand Down Expand Up @@ -113,6 +136,8 @@ public String getInputValue()
public ManageSampleFinderViewsModal setName(String name)
{
WebElement input = elementCache().nameInput;
WebDriverWrapper.waitFor(input::isDisplayed, "Name input field not visible.", 2_500);

getWrapper().actionClear(input);
input.sendKeys(name);
input.sendKeys(Keys.TAB);
Expand All @@ -126,7 +151,7 @@ public void clickDone()

public String getErrorMsg()
{
if(WebDriverWrapper.waitFor(()->elementCache().errorMsg.isDisplayed(), 1_000))
if(Boolean.TRUE.equals(WebDriverWrapper.waitFor(()->elementCache().errorMsg.isDisplayed(), 1_000)))
return elementCache().errorMsg.getText();
else
return "";
Expand Down

0 comments on commit 0d7fe57

Please sign in to comment.