All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openqa.selenium.support.ui.ExpectedConditions Maven / Gradle / Ivy

// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

package org.openqa.selenium.support.ui;

import com.google.common.base.Joiner;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.NoSuchFrameException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

/**
 * Canned {@link ExpectedCondition}s which are generally useful within webdriver tests.
 */
public class ExpectedConditions {

  private ExpectedConditions() {
    // Utility class
  }

  /**
   * An expectation for checking the title of a page.
   *
   * @param title the expected title, which must be an exact match
   * @return true when the title matches, false otherwise
   */
  public static ExpectedCondition titleIs(final String title) {
    return new ExpectedCondition() {
      private String currentTitle = "";

      @Override
      public Boolean apply(WebDriver driver) {
        currentTitle = driver.getTitle();
        return title.equals(currentTitle);
      }

      @Override
      public String toString() {
        return String.format("title to be \"%s\". Current title: \"%s\"", title, currentTitle);
      }
    };
  }

  /**
   * An expectation for checking that the title contains a case-sensitive substring
   *
   * @param title the fragment of title expected
   * @return true when the title matches, false otherwise
   */
  public static ExpectedCondition titleContains(final String title) {
    return new ExpectedCondition() {
      private String currentTitle = "";

      @Override
      public Boolean apply(WebDriver driver) {
        currentTitle = driver.getTitle();
        return currentTitle != null && currentTitle.contains(title);
      }

      @Override
      public String toString() {
        return String.format("title to contain \"%s\". Current title: \"%s\"", title, currentTitle);
      }
    };
  }

  /**
   * An expectation for the URL of the current page to be a specific url.
   *
   * @param url the url that the page should be on
   * @return true when the URL is what it should be
   */
  public static ExpectedCondition urlToBe(final String url) {
    return new ExpectedCondition() {
      private String currentUrl = "";

      @Override
      public Boolean apply(WebDriver driver) {
        currentUrl = driver.getCurrentUrl();
        return currentUrl != null && currentUrl.equals(url);
      }

      @Override
      public String toString() {
        return String.format("url to be \"%s\". Current url: \"%s\"", url, currentUrl);
      }
    };
  }

  /**
   * An expectation for the URL of the current page to contain specific text.
   *
   * @param fraction the fraction of the url that the page should be on
   * @return true when the URL contains the text
   */
  public static ExpectedCondition urlContains(final String fraction) {
    return new ExpectedCondition() {
      private String currentUrl = "";

      @Override
      public Boolean apply(WebDriver driver) {
        currentUrl = driver.getCurrentUrl();
        return currentUrl != null && currentUrl.contains(fraction);
      }

      @Override
      public String toString() {
        return String.format("url to contain \"%s\". Current url: \"%s\"", fraction, currentUrl);
      }
    };
  }

  /**
   * Expectation for the URL to match a specific regular expression
   *
   * @param regex the regular expression that the URL should match
   * @return true if the URL matches the specified regular expression
   */
  public static ExpectedCondition urlMatches(final String regex) {
    return new ExpectedCondition() {
      private final Pattern pattern = Pattern.compile(regex);
      private String currentUrl;

      @Override
      public Boolean apply(WebDriver driver) {
        currentUrl = driver.getCurrentUrl();
        return pattern.matcher(currentUrl).find();
      }

      @Override
      public String toString() {
        return String
          .format("url to match the regex \"%s\". Current url: \"%s\"", regex, currentUrl);
      }
    };
  }

  /**
   * An expectation for checking that an element is present on the DOM of a page. This does not
   * necessarily mean that the element is visible.
   *
   * @param locator used to find the element
   * @return the WebElement once it is located
   */
  public static ExpectedCondition presenceOfElementLocated(final By locator) {
    return new ExpectedCondition() {
      @Override
      public WebElement apply(WebDriver driver) {
        return driver.findElement(locator);
      }

      @Override
      public String toString() {
        return "presence of element located by: " + locator;
      }
    };
  }

  /**
   * An expectation for checking that an element is present on the DOM of a page and visible.
   * Visibility means that the element is not only displayed but also has a height and width that is
   * greater than 0.
   *
   * @param locator used to find the element
   * @return the WebElement once it is located and visible
   */
  public static ExpectedCondition visibilityOfElementLocated(final By locator) {
    return new ExpectedCondition() {
      @Override
      public WebElement apply(WebDriver driver) {
        try {
          return elementIfVisible(driver.findElement(locator));
        } catch (StaleElementReferenceException | NoSuchElementException e) {
          // Returns null because the element is no longer or not present in DOM.
          return null;
        }
      }

      @Override
      public String toString() {
        return "visibility of element located by " + locator;
      }
    };
  }

  /**
   * An expectation for checking that all elements present on the web page that match the locator
   * are visible. Visibility means that the elements are not only displayed but also have a height
   * and width that is greater than 0.
   *
   * @param locator used to find the element
   * @return the list of WebElements once they are located
   */
  public static ExpectedCondition> visibilityOfAllElementsLocatedBy(
    final By locator) {
    return new ExpectedCondition>() {
      @Override
      public List apply(WebDriver driver) {
        List elements = driver.findElements(locator);
        for (WebElement element : elements) {
          if (!element.isDisplayed()) {
            return null;
          }
        }
        return elements.size() > 0 ? elements : null;
      }

      @Override
      public String toString() {
        return "visibility of all elements located by " + locator;
      }
    };
  }

  /**
   * An expectation for checking that all elements present on the web page that match the locator
   * are visible. Visibility means that the elements are not only displayed but also have a height
   * and width that is greater than 0.
   *
   * @param elements list of WebElements
   * @return the list of WebElements once they are located
   */
  public static ExpectedCondition> visibilityOfAllElements(
    final WebElement... elements) {
    return visibilityOfAllElements(Arrays.asList(elements));
  }

  /**
   * An expectation for checking that all elements present on the web page that match the locator
   * are visible. Visibility means that the elements are not only displayed but also have a height
   * and width that is greater than 0.
   *
   * @param elements list of WebElements
   * @return the list of WebElements once they are located
   */
  public static ExpectedCondition> visibilityOfAllElements(
    final List elements) {
    return new ExpectedCondition>() {
      @Override
      public List apply(WebDriver driver) {
        for (WebElement element : elements) {
          if (!element.isDisplayed()) {
            return null;
          }
        }
        return elements.size() > 0 ? elements : null;
      }

      @Override
      public String toString() {
        return "visibility of all " + elements;
      }
    };
  }

  /**
   * An expectation for checking that an element, known to be present on the DOM of a page, is
   * visible. Visibility means that the element is not only displayed but also has a height and
   * width that is greater than 0.
   *
   * @param element the WebElement
   * @return the (same) WebElement once it is visible
   */
  public static ExpectedCondition visibilityOf(final WebElement element) {
    return new ExpectedCondition() {
      @Override
      public WebElement apply(WebDriver driver) {
        return elementIfVisible(element);
      }

      @Override
      public String toString() {
        return "visibility of " + element;
      }
    };
  }

  /**
   * @return the given element if it is visible and has non-zero size, otherwise null.
   */
  private static WebElement elementIfVisible(WebElement element) {
    return element.isDisplayed() ? element : null;
  }

  /**
   * An expectation for checking that there is at least one element present on a web page.
   *
   * @param locator used to find the element
   * @return the list of WebElements once they are located
   */
  public static ExpectedCondition> presenceOfAllElementsLocatedBy(
    final By locator) {
    return new ExpectedCondition>() {
      @Override
      public List apply(WebDriver driver) {
        List elements = driver.findElements(locator);
        return elements.size() > 0 ? elements : null;
      }

      @Override
      public String toString() {
        return "presence of any elements located by " + locator;
      }
    };
  }

  /**
   * An expectation for checking if the given text is present in the specified element.
   *
   * @param element the WebElement
   * @param text    to be present in the element
   * @return true once the element contains the given text
   */
  public static ExpectedCondition textToBePresentInElement(final WebElement element,
                                                                    final String text) {

    return new ExpectedCondition() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          String elementText = element.getText();
          return elementText.contains(text);
        } catch (StaleElementReferenceException e) {
          return false;
        }
      }

      @Override
      public String toString() {
        return String.format("text ('%s') to be present in element %s", text, element);
      }
    };
  }

  /**
   * An expectation for checking if the given text is present in the element that matches the given
   * locator.
   *
   * @param locator used to find the element
   * @param text    to be present in the element found by the locator
   * @return true once the first element located by locator contains the given text
   */
  public static ExpectedCondition textToBePresentInElementLocated(final By locator,
                                                                           final String text) {

    return new ExpectedCondition() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          String elementText = driver.findElement(locator).getText();
          return elementText.contains(text);
        } catch (StaleElementReferenceException e) {
          return false;
        }
      }

      @Override
      public String toString() {
        return String.format("text ('%s') to be present in element found by %s",
                             text, locator);
      }
    };
  }

  /**
   * An expectation for checking if the given text is present in the specified elements value
   * attribute.
   *
   * @param element the WebElement
   * @param text    to be present in the element's value attribute
   * @return true once the element's value attribute contains the given text
   */
  public static ExpectedCondition textToBePresentInElementValue(final WebElement element,
                                                                         final String text) {

    return new ExpectedCondition() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          String elementText = element.getAttribute("value");
          if (elementText != null) {
            return elementText.contains(text);
          }
          return false;
        } catch (StaleElementReferenceException e) {
          return false;
        }
      }

      @Override
      public String toString() {
        return String.format("text ('%s') to be the value of element %s", text, element);
      }
    };
  }

  /**
   * An expectation for checking if the given text is present in the specified elements value
   * attribute.
   *
   * @param locator used to find the element
   * @param text    to be present in the value attribute of the element found by the locator
   * @return true once the value attribute of the first element located by locator contains the
   * given text
   */
  public static ExpectedCondition textToBePresentInElementValue(final By locator,
                                                                         final String text) {

    return new ExpectedCondition() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          String elementText = driver.findElement(locator).getAttribute("value");
          if (elementText != null) {
            return elementText.contains(text);
          }
          return false;
        } catch (StaleElementReferenceException e) {
          return false;
        }
      }

      @Override
      public String toString() {
        return String.format("text ('%s') to be the value of element located by %s",
                             text, locator);
      }
    };
  }

  /**
   * An expectation for checking whether the given frame is available to switch to. 

If the frame * is available it switches the given driver to the specified frame. * * @param frameLocator used to find the frame (id or name) * @return WebDriver instance after frame has been switched */ public static ExpectedCondition frameToBeAvailableAndSwitchToIt( final String frameLocator) { return new ExpectedCondition() { @Override public WebDriver apply(WebDriver driver) { try { return driver.switchTo().frame(frameLocator); } catch (NoSuchFrameException e) { return null; } } @Override public String toString() { return "frame to be available: " + frameLocator; } }; } /** * An expectation for checking whether the given frame is available to switch to.

If the frame * is available it switches the given driver to the specified frame. * * @param locator used to find the frame * @return WebDriver instance after frame has been switched */ public static ExpectedCondition frameToBeAvailableAndSwitchToIt(final By locator) { return new ExpectedCondition() { @Override public WebDriver apply(WebDriver driver) { try { return driver.switchTo().frame(driver.findElement(locator)); } catch (NoSuchFrameException e) { return null; } } @Override public String toString() { return "frame to be available: " + locator; } }; } /** * An expectation for checking whether the given frame is available to switch to.

If the frame * is available it switches the given driver to the specified frameIndex. * * @param frameLocator used to find the frame (index) * @return WebDriver instance after frame has been switched */ public static ExpectedCondition frameToBeAvailableAndSwitchToIt( final int frameLocator) { return new ExpectedCondition() { @Override public WebDriver apply(WebDriver driver) { try { return driver.switchTo().frame(frameLocator); } catch (NoSuchFrameException e) { return null; } } @Override public String toString() { return "frame to be available: " + frameLocator; } }; } /** * An expectation for checking whether the given frame is available to switch to.

If the frame * is available it switches the given driver to the specified web element. * * @param frameLocator used to find the frame (webelement) * @return WebDriver instance after frame has been switched */ public static ExpectedCondition frameToBeAvailableAndSwitchToIt( final WebElement frameLocator) { return new ExpectedCondition() { @Override public WebDriver apply(WebDriver driver) { try { return driver.switchTo().frame(frameLocator); } catch (NoSuchFrameException e) { return null; } } @Override public String toString() { return "frame to be available: " + frameLocator; } }; } /** * An expectation for checking that an element is either invisible or not present on the DOM. * * @param locator used to find the element * @return true if the element is not displayed or the element doesn't exist or stale element */ public static ExpectedCondition invisibilityOfElementLocated(final By locator) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { try { return !(driver.findElement(locator).isDisplayed()); } catch (NoSuchElementException | StaleElementReferenceException e) { // Returns true because the element is not present in DOM. The // try block checks if the element is present but is invisible. return true; } } @Override public String toString() { return "element to no longer be visible: " + locator; } }; } /** * An expectation for checking that an element with text is either invisible or not present on the * DOM. * * @param locator used to find the element * @param text of the element * @return true if no such element, stale element or displayed text not equal that provided */ public static ExpectedCondition invisibilityOfElementWithText(final By locator, final String text) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { try { return !driver.findElement(locator).getText().equals(text); } catch (NoSuchElementException e) { // Returns true because the element with text is not present in DOM. The // try block checks if the element is present but is invisible. return true; } catch (StaleElementReferenceException e) { // Returns true because stale element reference implies that element // is no longer visible. return true; } } @Override public String toString() { return String.format("element containing '%s' to no longer be visible: %s", text, locator); } }; } /** * An expectation for checking an element is visible and enabled such that you can click it. * * @param locator used to find the element * @return the WebElement once it is located and clickable (visible and enabled) */ public static ExpectedCondition elementToBeClickable(final By locator) { return new ExpectedCondition() { @Override public WebElement apply(WebDriver driver) { WebElement element = visibilityOfElementLocated(locator).apply(driver); try { if (element != null && element.isEnabled()) { return element; } return null; } catch (StaleElementReferenceException e) { return null; } } @Override public String toString() { return "element to be clickable: " + locator; } }; } /** * An expectation for checking an element is visible and enabled such that you can click it. * * @param element the WebElement * @return the (same) WebElement once it is clickable (visible and enabled) */ public static ExpectedCondition elementToBeClickable(final WebElement element) { return new ExpectedCondition() { @Override public WebElement apply(WebDriver driver) { WebElement visibleElement = visibilityOf(element).apply(driver); try { if (visibleElement != null && visibleElement.isEnabled()) { return visibleElement; } return null; } catch (StaleElementReferenceException e) { return null; } } @Override public String toString() { return "element to be clickable: " + element; } }; } /** * Wait until an element is no longer attached to the DOM. * * @param element The element to wait for. * @return false if the element is still attached to the DOM, true otherwise. */ public static ExpectedCondition stalenessOf(final WebElement element) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver ignored) { try { // Calling any method forces a staleness check element.isEnabled(); return false; } catch (StaleElementReferenceException expected) { return true; } } @Override public String toString() { return String.format("element (%s) to become stale", element); } }; } /** * Wrapper for a condition, which allows for elements to update by redrawing. * * This works around the problem of conditions which have two parts: find an element and then * check for some condition on it. For these conditions it is possible that an element is located * and then subsequently it is redrawn on the client. When this happens a {@link * StaleElementReferenceException} is thrown when the second part of the condition is checked. * * @param condition ExpectedCondition to wrap * @param return type of the condition provided * @return the result of the provided condition */ public static ExpectedCondition refreshed(final ExpectedCondition condition) { return new ExpectedCondition() { @Override public T apply(WebDriver driver) { try { return condition.apply(driver); } catch (StaleElementReferenceException e) { return null; } } @Override public String toString() { return String.format("condition (%s) to be refreshed", condition); } }; } /** * An expectation for checking if the given element is selected. * * @param element WebElement to be selected * @return true once the element is selected */ public static ExpectedCondition elementToBeSelected(final WebElement element) { return elementSelectionStateToBe(element, true); } /** * An expectation for checking if the given element is selected. * * @param element WebElement to be selected * @param selected boolean state of the selection state of the element * @return true once the element's selection stated is that of selected */ public static ExpectedCondition elementSelectionStateToBe(final WebElement element, final boolean selected) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { return element.isSelected() == selected; } @Override public String toString() { return String.format("element (%s) to %sbe selected", element, (selected ? "" : "not ")); } }; } public static ExpectedCondition elementToBeSelected(final By locator) { return elementSelectionStateToBe(locator, true); } public static ExpectedCondition elementSelectionStateToBe(final By locator, final boolean selected) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { try { WebElement element = driver.findElement(locator); return element.isSelected() == selected; } catch (StaleElementReferenceException e) { return false; } } @Override public String toString() { return String.format("element found by %s to %sbe selected", locator, (selected ? "" : "not ")); } }; } public static ExpectedCondition alertIsPresent() { return new ExpectedCondition() { @Override public Alert apply(WebDriver driver) { try { return driver.switchTo().alert(); } catch (NoAlertPresentException e) { return null; } } @Override public String toString() { return "alert to be present"; } }; } public static ExpectedCondition numberOfWindowsToBe(final int expectedNumberOfWindows) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { try { return driver.getWindowHandles().size() == expectedNumberOfWindows; } catch (WebDriverException e) { return false; } } @Override public String toString() { return "number of open windows to be " + expectedNumberOfWindows; } }; } /** * An expectation with the logical opposite condition of the given condition. * * Note that if the Condition you are inverting throws an exception that is caught by the Ignored * Exceptions, the inversion will not take place and lead to confusing results. * * @param condition ExpectedCondition to be inverted * @return true once the condition is satisfied */ public static ExpectedCondition not(final ExpectedCondition condition) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { Object result = condition.apply(driver); return result == null || result.equals(Boolean.FALSE); } @Override public String toString() { return "condition to not be valid: " + condition; } }; } /** * An expectation for checking WebElement with given locator has attribute with a specific value * * @param locator used to find the element * @param attribute used to define css or html attribute * @param value used as expected attribute value * @return Boolean true when element has css or html attribute with the value */ public static ExpectedCondition attributeToBe( final By locator, final String attribute, final String value) { return new ExpectedCondition() { private String currentValue = null; @Override public Boolean apply(WebDriver driver) { WebElement element = driver.findElement(locator); currentValue = element.getAttribute(attribute); if (currentValue == null || currentValue.isEmpty()) { currentValue = element.getCssValue(attribute); } return value.equals(currentValue); } @Override public String toString() { return String.format("element found by %s to have value \"%s\". Current value: \"%s\"", locator, value, currentValue); } }; } /** * An expectation for checking WebElement with given locator has specific text * * @param locator used to find the element * @param value used as expected text * @return Boolean true when element has text value equal to @value */ public static ExpectedCondition textToBe(final By locator, final String value) { return new ExpectedCondition() { private String currentValue = null; @Override public Boolean apply(WebDriver driver) { try { currentValue = driver.findElement(locator).getText(); return currentValue.equals(value); } catch (Exception e) { return false; } } @Override public String toString() { return String.format("element found by %s to have text \"%s\". Current text: \"%s\"", locator, value, currentValue); } }; } /** * An expectation for checking WebElement with given locator has text with a value as a part of * it * * @param locator used to find the element * @param pattern used as expected text matcher pattern * @return Boolean true when element has text value containing @value */ public static ExpectedCondition textMatches(final By locator, final Pattern pattern) { return new ExpectedCondition() { private String currentValue = null; @Override public Boolean apply(WebDriver driver) { try { currentValue = driver.findElement(locator).getText(); return pattern.matcher(currentValue).find(); } catch (Exception e) { return false; } } @Override public String toString() { return String .format("text found by %s to match pattern \"%s\". Current text: \"%s\"", locator, pattern.pattern(), currentValue); } }; } /** * An expectation for checking number of WebElements with given locator being more than defined number * * @param locator used to find the element * @param number used to define minimum number of elements * @return Boolean true when size of elements list is more than defined */ public static ExpectedCondition> numberOfElementsToBeMoreThan(final By locator, final Integer number) { return new ExpectedCondition>() { private Integer currentNumber = 0; @Override public List apply(WebDriver webDriver) { List elements = webDriver.findElements(locator); currentNumber = elements.size(); return currentNumber > number ? elements : null; } @Override public String toString() { return String.format("number of elements found by %s to be more than \"%s\". Current number: \"%s\"", locator, number, currentNumber); } }; } /** * An expectation for checking number of WebElements with given locator being less than defined * number * * @param locator used to find the element * @param number used to define maximum number of elements * @return Boolean true when size of elements list is less than defined */ public static ExpectedCondition> numberOfElementsToBeLessThan(final By locator, final Integer number) { return new ExpectedCondition>() { private Integer currentNumber = 0; @Override public List apply(WebDriver webDriver) { List elements = webDriver.findElements(locator); currentNumber = elements.size(); return currentNumber < number ? elements : null; } @Override public String toString() { return String.format("number of elements found by %s to be less than \"%s\". Current number: \"%s\"", locator, number, currentNumber); } }; } /** * An expectation for checking number of WebElements with given locator * * @param locator used to find the element * @param number used to define number of elements * @return Boolean true when size of elements list is equal to defined */ public static ExpectedCondition> numberOfElementsToBe(final By locator, final Integer number) { return new ExpectedCondition>() { private Integer currentNumber = 0; @Override public List apply(WebDriver webDriver) { List elements = webDriver.findElements(locator); currentNumber = elements.size(); return currentNumber.equals(number) ? elements : null; } @Override public String toString() { return String .format("number of elements found by %s to be \"%s\". Current number: \"%s\"", locator, number, currentNumber); } }; } /** * An expectation for checking given WebElement has DOM property with a specific value * * @param element used to check its parameters * @param property property name * @param value used as expected property value * @return Boolean true when element has DOM property with the value */ public static ExpectedCondition domPropertyToBe(final WebElement element, final String property, final String value) { return new ExpectedCondition() { private String currentValue = null; @Override public Boolean apply(WebDriver driver) { currentValue = element.getDomProperty(property); return value.equals(currentValue); } @Override public String toString() { return String.format("DOM property '%s' to be '%s'. Current value: '%s'", property, value, currentValue); } }; } /** * An expectation for checking given WebElement has DOM attribute with a specific value * * @param element used to check its parameters * @param attribute attribute name * @param value used as expected attribute value * @return Boolean true when element has DOM attribute with the value */ public static ExpectedCondition domAttributeToBe(final WebElement element, final String attribute, final String value) { return new ExpectedCondition() { private String currentValue = null; @Override public Boolean apply(WebDriver driver) { currentValue = element.getDomAttribute(attribute); return value.equals(currentValue); } @Override public String toString() { return String.format("DOM attribute '%s' to be '%s'. Current value: '%s'", attribute, value, currentValue); } }; } /** * An expectation for checking given WebElement has attribute with a specific value * * @param element used to check its parameters * @param attribute used to define css or html attribute * @param value used as expected attribute value * @return Boolean true when element has css or html attribute with the value */ public static ExpectedCondition attributeToBe(final WebElement element, final String attribute, final String value) { return new ExpectedCondition() { private String currentValue = null; @Override public Boolean apply(WebDriver driver) { currentValue = element.getAttribute(attribute); if (currentValue == null || currentValue.isEmpty()) { currentValue = element.getCssValue(attribute); } return value.equals(currentValue); } @Override public String toString() { return String.format("Attribute or property '%s' to be '%s'. Current value: '%s'", attribute, value, currentValue); } }; } /** * An expectation for checking WebElement with given locator has attribute which contains specific * value * * @param element used to check its parameters * @param attribute used to define css or html attribute * @param value used as expected attribute value * @return Boolean true when element has css or html attribute which contains the value */ public static ExpectedCondition attributeContains(final WebElement element, final String attribute, final String value) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { return getAttributeOrCssValue(element, attribute) .map(seen -> seen.contains(value)) .orElse(false); } @Override public String toString() { return String.format("value to contain \"%s\".", value); } }; } /** * An expectation for checking WebElement with given locator has attribute which contains specific * value * * @param locator used to define WebElement to check its parameters * @param attribute used to define css or html attribute * @param value used as expected attribute value * @return Boolean true when element has css or html attribute which contains the value */ public static ExpectedCondition attributeContains(final By locator, final String attribute, final String value) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { return getAttributeOrCssValue(driver.findElement(locator), attribute) .map(seen -> seen.contains(value)) .orElse(false); } @Override public String toString() { return String.format("value found by %s to contain \"%s\".", locator, value); } }; } /** * An expectation for checking WebElement any non empty value for given attribute * * @param element used to check its parameters * @param attribute used to define css or html attribute * @return Boolean true when element has css or html attribute with non empty value */ public static ExpectedCondition attributeToBeNotEmpty(final WebElement element, final String attribute) { return driver -> getAttributeOrCssValue(element, attribute).isPresent(); } private static Optional getAttributeOrCssValue(WebElement element, String name) { String value = element.getAttribute(name); if (value == null || value.isEmpty()) { value = element.getCssValue(name); } if (value == null || value.isEmpty()) { return Optional.empty(); } return Optional.of(value); } /** * An expectation for checking child WebElement as a part of parent element to be visible * * @param parent used to check parent element. For example table with locator * By.id("fish") * @param childLocator used to find the ultimate child element. * @return visible nested element */ public static ExpectedCondition> visibilityOfNestedElementsLocatedBy( final By parent, final By childLocator) { return new ExpectedCondition>() { @Override public List apply(WebDriver driver) { WebElement current = driver.findElement(parent); List allChildren = current.findElements(childLocator); // The original code only checked the first element. Fair enough. if (!allChildren.isEmpty() && allChildren.get(0).isDisplayed()) { return allChildren; } return null; } @Override public String toString() { return String.format("visibility of elements located by %s -> %s", parent, childLocator); } }; } /** * An expectation for checking child WebElement as a part of parent element to be visible * * @param element used as parent element. For example table with locator By.xpath("//table") * @param childLocator used to find child element. For example td By.xpath("./tr/td") * @return visible sub-element */ public static ExpectedCondition> visibilityOfNestedElementsLocatedBy( final WebElement element, final By childLocator) { return new ExpectedCondition>() { @Override public List apply(WebDriver webDriver) { List allChildren = element.findElements(childLocator); // The original code only checked the visibility of the first element. if (!allChildren.isEmpty() && allChildren.get(0).isDisplayed()) { return allChildren; } return null; } @Override public String toString() { return String.format("visibility of element located by %s -> %s", element, childLocator); } }; } /** * An expectation for checking child WebElement as a part of parent element to present * * @param locator used to check parent element. For example table with locator * By.xpath("//table") * @param childLocator used to find child element. For example td By.xpath("./tr/td") * @return sub-element */ public static ExpectedCondition presenceOfNestedElementLocatedBy( final By locator, final By childLocator) { return new ExpectedCondition() { @Override public WebElement apply(WebDriver webDriver) { return webDriver.findElement(locator).findElement(childLocator); } @Override public String toString() { return String.format("visibility of element located by %s -> %s", locator, childLocator); } }; } /** * An expectation for checking child WebElement as a part of parent element to be present * * @param element used as parent element * @param childLocator used to find child element. For example td By.xpath("./tr/td") * @return sub-element */ public static ExpectedCondition presenceOfNestedElementLocatedBy( final WebElement element, final By childLocator) { return new ExpectedCondition() { @Override public WebElement apply(WebDriver webDriver) { return element.findElement(childLocator); } @Override public String toString() { return String.format("visibility of element located by %s", childLocator); } }; } /** * An expectation for checking child WebElement as a part of parent element to present * * @param parent used to check parent element. For example table with locator * By.xpath("//table") * @param childLocator used to find child element. For example td By.xpath("./tr/td") * @return sub-element */ public static ExpectedCondition> presenceOfNestedElementsLocatedBy( final By parent, final By childLocator) { return new ExpectedCondition>() { @Override public List apply(WebDriver driver) { List allChildren = driver.findElement(parent).findElements(childLocator); return allChildren.isEmpty() ? null : allChildren; } @Override public String toString() { return String.format("visibility of element located by %s -> %s", parent, childLocator); } }; } /** * An expectation for checking all elements from given list to be invisible * * @param elements used to check their invisibility * @return Boolean true when all elements are not visible anymore */ public static ExpectedCondition invisibilityOfAllElements(final WebElement... elements) { return invisibilityOfAllElements(Arrays.asList(elements)); } /** * An expectation for checking all elements from given list to be invisible * * @param elements used to check their invisibility * @return Boolean true when all elements are not visible anymore */ public static ExpectedCondition invisibilityOfAllElements(final List elements) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver webDriver) { return elements.stream().allMatch(ExpectedConditions::isInvisible); } @Override public String toString() { return "invisibility of all elements " + elements; } }; } /** * An expectation for checking the element to be invisible * * @param element used to check its invisibility * @return Boolean true when elements is not visible anymore */ public static ExpectedCondition invisibilityOf(final WebElement element) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver webDriver) { return isInvisible(element); } @Override public String toString() { return "invisibility of " + element; } }; } private static boolean isInvisible(final WebElement element) { try { return !element.isDisplayed(); } catch (StaleElementReferenceException | NoSuchElementException ignored) { // We can assume a stale element isn't displayed. return true; } } /** * An expectation with the logical or condition of the given list of conditions. * * Each condition is checked until at least one of them returns true or not null. * * @param conditions ExpectedCondition is a list of alternative conditions * @return true once one of conditions is satisfied */ public static ExpectedCondition or(final ExpectedCondition... conditions) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { RuntimeException lastException = null; for (ExpectedCondition condition : conditions) { try { Object result = condition.apply(driver); if (result != null) { if (result instanceof Boolean) { if (Boolean.TRUE.equals(result)) { return true; } } else { return true; } } } catch (RuntimeException e) { lastException = e; } } if (lastException != null) { throw lastException; } return false; } @Override public String toString() { StringBuilder message = new StringBuilder("at least one condition to be valid: "); Joiner.on(" || ").appendTo(message, conditions); return message.toString(); } }; } /** * An expectation with the logical and condition of the given list of conditions. * * Each condition is checked until all of them return true or not null * * @param conditions ExpectedCondition is a list of alternative conditions * @return true once all conditions are satisfied */ public static ExpectedCondition and(final ExpectedCondition... conditions) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { for (ExpectedCondition condition : conditions) { Object result = condition.apply(driver); if (result instanceof Boolean) { if (Boolean.FALSE.equals(result)) { return false; } } if (result == null) { return false; } } return true; } @Override public String toString() { StringBuilder message = new StringBuilder("all conditions to be valid: "); Joiner.on(" && ").appendTo(message, conditions); return message.toString(); } }; } /** * An expectation to check if js executable. * * Useful when you know that there should be a Javascript value or something at the stage. * * @param javaScript used as executable script * @return true once javaScript executed without errors */ public static ExpectedCondition javaScriptThrowsNoExceptions(final String javaScript) { return new ExpectedCondition() { @Override public Boolean apply(WebDriver driver) { try { ((JavascriptExecutor) driver).executeScript(javaScript); return true; } catch (WebDriverException e) { return false; } } @Override public String toString() { return String.format("js %s to be executable", javaScript); } }; } /** * An expectation for String value from javascript * * @param javaScript as executable js line * @return object once javaScript executes without errors */ public static ExpectedCondition jsReturnsValue(final String javaScript) { return new ExpectedCondition() { @Override public Object apply(WebDriver driver) { try { Object value = ((JavascriptExecutor) driver).executeScript(javaScript); if (value instanceof List) { return ((List) value).isEmpty() ? null : value; } if (value instanceof String) { return ((String) value).isEmpty() ? null : value; } return value; } catch (WebDriverException e) { return null; } } @Override public String toString() { return String.format("js %s to be executable", javaScript); } }; } }