Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/org/labkey/test/WebDriverWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
import static org.labkey.test.TestProperties.isWebDriverLoggingEnabled;
import static org.labkey.test.WebTestHelper.makeRelativeUrl;
import static org.labkey.test.components.html.RadioButton.RadioButton;
import static org.labkey.test.util.LabKeyExpectedConditions.windowIsPresent;
import static org.openqa.selenium.chrome.ChromeDriverService.CHROME_DRIVER_LOG_PROPERTY;
import static org.openqa.selenium.chrome.ChromeDriverService.CHROME_DRIVER_VERBOSE_LOG_PROPERTY;
import static org.openqa.selenium.firefox.GeckoDriverService.GECKO_DRIVER_LOG_PROPERTY;
Expand Down Expand Up @@ -2151,7 +2152,8 @@ public long doAndWaitForWindow(Runnable action, String windowName)

action.run();

getDriver().switchTo().window(windowName);
new WebDriverWait(getDriver(), Duration.ofSeconds(5)).until(windowIsPresent(windowName));

return targetWindowExists;
});
}
Expand Down
100 changes: 32 additions & 68 deletions src/org/labkey/test/util/LabKeyExpectedConditions.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.Point;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
Expand All @@ -33,6 +33,7 @@

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

public class LabKeyExpectedConditions
Expand All @@ -42,32 +43,6 @@ private LabKeyExpectedConditions()
// Utility class
}

/**
* An expectation for checking child WebElement as a part of parent element to be present
*
* @param context SearchContext to find element within
* @param childLocator used to find child element. For example Locator.xpath("./tr/td")
* @return subelement
*/
public static ExpectedCondition<WebElement> presenceOfNestedElementLocatedBy(final SearchContext context, final By childLocator)
{
return new ExpectedCondition<>()
{

@Override
public WebElement apply(WebDriver webDriver)
{
return context.findElement(childLocator);
}

@Override
public String toString()
{
return String.format("visibility of element located by %s", childLocator);
}
};
}

/**
* An expectation for checking that an element has stopped moving
*
Expand Down Expand Up @@ -101,7 +76,7 @@ public String toString()
/**
* Another expectation for checking that an element has stopped moving
*
* @param el the element who's position changes
* @param el the element whose position changes
* @return the element when animation is complete
*/
public static ExpectedCondition<WebElement> animationIsDone(final WebElement el) {
Expand Down Expand Up @@ -165,7 +140,7 @@ public WebElement apply(WebDriver driver)
return null;
}

if (el.isEnabled() && !el.getAttribute("class").contains("disabled"))
if (el.isEnabled() && !Objects.requireNonNullElse(el.getAttribute("class"), "").contains("disabled"))
return el;
else
return null;
Expand Down Expand Up @@ -202,54 +177,18 @@ public Boolean apply(WebDriver ignored)
@Override
public String toString()
{
return staleCheck.toString() + " after clicking";
}
};
}

/**
* Wraps {@link ExpectedConditions#visibilityOfAllElements(WebElement...)}
* This expectations accounts for the behavior of LabKey WebElement wrappers, which will throw if you attempt to
* inspect them before the element has appeared.
*
* @param elements list of WebElements
* @return the list of WebElements once they are located
* @see org.labkey.test.selenium.LazyWebElement
*/
public static ExpectedCondition<List<WebElement>> visibilityOfAllElements(WebElement... elements)
{
return new ExpectedCondition<>()
{
final ExpectedCondition<List<WebElement>> wrapped = ExpectedConditions.visibilityOfAllElements(elements);

@Override
public List<WebElement> apply(WebDriver driver)
{
try
{
return wrapped.apply(driver);
}
catch (StaleElementReferenceException | NoSuchElementException ignore)
{
return null;
}
}

@Override
public String toString()
{
return wrapped.toString();
return staleCheck + " after clicking";
}
};
}

/**
* Wraps {@link ExpectedConditions#stalenessOf(WebElement)}
* Firefox occasionally throws "NoSuchElementException: Web element reference not seen before"
* for short lived elements.
* for short-lived elements.
*
* @param element WebElement that should go stale.
* @return false if the element is still attached to the DOM, true otherwise.
* @return ExpectedCondition that returns false if the element is still attached to the DOM, true otherwise.
*/
public static ExpectedCondition<Boolean> stalenessOf(WebElement element)
{
Expand Down Expand Up @@ -292,6 +231,31 @@ public static ExpectedCondition<?> visibilityOf(WebElement element, boolean visi
: ExpectedConditions.invisibilityOf(element);
}

/**
* An expectation for checking whether a window or tab with the give name is present.
* If the window/tab is available it switches the given driver to the specified window/tab.
* @param windowName The name of the window
* @return An expected condition that returns the driver with focus switched to the specified window or tab.
* @see WebDriver.TargetLocator#window(String)
*/
public static ExpectedCondition<WebDriver> windowIsPresent(final String windowName) {
return new ExpectedCondition<>() {
@Override
public WebDriver apply(WebDriver driver) {
try {
return driver.switchTo().window(windowName);
} catch (NoSuchWindowException e) {
return null;
}
}

@Override
public String toString() {
return "window named " + windowName;
}
};
}

/**
* Wraps a 'Wait' to terminate after function return a non-null value.
* Normally, 'Wait' expects a non-null, non-false return value
Expand Down