code: // 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.lift;
  
  import static org.openqa.selenium.lift.match.NumericalMatchers.atLeast;
  
  import java.time.Clock;
  import java.time.Duration;
  import java.util.Collection;
  import org.hamcrest.Description;
  import org.hamcrest.Matcher;
  import org.hamcrest.StringDescription;
  import org.openqa.selenium.WebDriver;
  import org.openqa.selenium.WebElement;
  import org.openqa.selenium.lift.find.Finder;
  import org.openqa.selenium.support.ui.ExpectedCondition;
  import org.openqa.selenium.support.ui.Sleeper;
  import org.openqa.selenium.support.ui.Wait;
  import org.openqa.selenium.support.ui.WebDriverWait;
  
  /** Gives the context for a test, holds page state, and interacts with the {@link WebDriver}. */
  @Deprecated
  public class WebDriverTestContext implements TestContext {
  
    private WebDriver driver;
    private final Clock clock;
    private final Sleeper sleeper;
  
    public WebDriverTestContext(WebDriver driver) {
      this(driver, Clock.systemDefaultZone(), Sleeper.SYSTEM_SLEEPER);
    }
  
    WebDriverTestContext(WebDriver driver, Clock clock, Sleeper sleeper) {
      this.driver = driver;
      this.clock = clock;
      this.sleeper = sleeper;
    }
  
    @Override
    public void quit() {
      driver.quit();
    }
  
    @Override
    public void goTo(String url) {
      driver.get(url);
    }
  
    @Override
    public void assertPresenceOf(Finder<WebElement, WebDriver> finder) {
      assertPresenceOf(atLeast(1), finder);
    }
  
    @Override
    public void assertPresenceOf(
        Matcher<Integer> cardinalityConstraint, Finder<WebElement, WebDriver> finder) {
      Collection<WebElement> foundElements = finder.findFrom(driver);
      if (!cardinalityConstraint.matches(foundElements.size())) {
        Description description = new StringDescription();
        description
            .appendText("\nExpected: ")
            .appendDescriptionOf(cardinalityConstraint)
            .appendText(" ")
            .appendDescriptionOf(finder)
            .appendText("\n     got: ")
            .appendValue(foundElements.size())
            .appendText(" ")
            .appendDescriptionOf(finder)
            .appendText("\n");
  
        failWith(description.toString());
      }
    }
  
    @Override
    public void type(String input, Finder<WebElement, WebDriver> finder) {
      WebElement element = findOneElementTo("type into", finder);
      element.sendKeys(input);
    }
  
    @Override
    public void clickOn(Finder<WebElement, WebDriver> finder) {
      WebElement element = findOneElementTo("click on", finder);
      element.click();
    }
  
    public void clickOnFirst(Finder<WebElement, WebDriver> finder) {
      WebElement element = findFirstElementTo("click on", finder);
      element.click();
    }
  
    private WebElement findFirstElementTo(String action, Finder<WebElement, WebDriver> finder) {
      Collection<WebElement> foundElements = finder.findFrom(driver);
      if (foundElements.isEmpty()) {
        failWith("could not find element to " + action);
      }
  
      return foundElements.iterator().next();
    }
  
    private WebElement findOneElementTo(String action, Finder<WebElement, WebDriver> finder) {
      Collection<WebElement> foundElements = finder.findFrom(driver);
      if (foundElements.isEmpty()) {
        failWith("could not find element to " + action);
      } else if (foundElements.size() > 1) {
        failWith("did not know what to " + action + " - ambiguous");
      }
  
      return foundElements.iterator().next();
    }
  
    private void failWith(String message) throws AssertionError {
      throw new java.lang.AssertionError(message);
    }
  
    @Override
    public void waitFor(final Finder<WebElement, WebDriver> finder, final long timeoutMillis) {
      final ExpectedCondition<Boolean> elementsDisplayedPredicate =
          driver -> finder.findFrom(driver).stream().anyMatch(WebElement::isDisplayed);
  
      final long defaultSleepTimeoutMillis = 500;
      final long sleepTimeout =
          (timeoutMillis > defaultSleepTimeoutMillis) ? defaultSleepTimeoutMillis : timeoutMillis / 2;
  
      Wait<WebDriver> wait =
          new WebDriverWait(
              driver,
              Duration.ofMillis(timeoutMillis),
              Duration.ofMillis(sleepTimeout),
              clock,
              sleeper) {
            @Override
            protected RuntimeException timeoutException(String message, Throwable lastException) {
              throw new AssertionError("Element was not rendered within " + timeoutMillis + "ms");
            }
          };
      wait.until(elementsDisplayedPredicate);
    }
  }
  