View Javadoc

1   package com.atlassian.webdriver.utils.element;
2   
3   import com.atlassian.pageobjects.PageBinder;
4   import com.google.common.base.Function;
5   import org.openqa.selenium.TimeoutException;
6   import org.openqa.selenium.WebDriver;
7   import org.openqa.selenium.support.ui.WebDriverWait;
8   
9   import javax.annotation.Nonnull;
10  import javax.inject.Inject;
11  import java.util.concurrent.TimeUnit;
12  
13  import static com.google.common.base.Preconditions.checkArgument;
14  import static com.google.common.base.Preconditions.checkNotNull;
15  
16  /**
17   * <p/>
18   * A component that can be used to wait for certain conditions to happen on the tested page.
19   *
20   * <p/>
21   * The conditions are expressed as a generic {@link Function} from {@link WebDriver} to {@code boolean}.
22   * {@link ElementConditions} contains factory methods to easily create some commonly used conditions.
23   *
24   * <p/>
25   * The {@link #DEFAULT_TIMEOUT} and {@link #DEFAULT_TIMEOUT_UNIT} specify the default timeout used when
26   * no explicit timeout is provided by the client, which is currently 30 seconds. Clients are encouraged to use
27   * their own timeout specific to the situation.
28   *
29   * <p/>
30   * NOTE: the default poll interval used by this class is as in the underlying {@link WebDriverWait} and is currently
31   * 500ms (subject to change as the underlying {@link WebDriverWait} implementation changes. This may be generally
32   * acceptable, but may not be granular enough for some scenarios (e.g. performance testing).
33   *
34   * <p/>
35   * Example usage:
36   * <pre>
37   *     {@code
38   *     @literal @Inject private WebDriverPoller poller;
39   *
40   *     // ...
41   *     // wait for 5s for a 'my-element' to be present on the page
42   *     poller.waitUntil(ElementConditions.isPresent(By.id("my-element")), 5);
43   *     }
44   * </pre>
45   *
46   * <p/>
47   * This component can be injected into page objects running within a {@link PageBinder} context.
48   *
49   * <p/>
50   * For more sophisticated polling/waiting toolkit, check the {@code PageElement} API in the
51   * atlassian-pageobjects-elements module.
52   *
53   * @since 2.2
54   * @see ElementConditions
55   * @see WebDriverWait
56   */
57  public final class WebDriverPoller
58  {
59      public static final long DEFAULT_TIMEOUT = 30;
60      public static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.SECONDS;
61  
62      private final WebDriver webDriver;
63      private final TimeUnit timeUnit;
64      private final long timeout;
65  
66      @Inject
67      public WebDriverPoller(@Nonnull WebDriver webDriver)
68      {
69          this(webDriver, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNIT);
70      }
71  
72      public WebDriverPoller(@Nonnull WebDriver webDriver, long timeout, @Nonnull TimeUnit timeUnit)
73      {
74          checkArgument(timeout > 0, "Timeout must be >0");
75          this.webDriver = checkNotNull(webDriver, "webDriver");
76          this.timeout = timeout;
77          this.timeUnit = checkNotNull(timeUnit, "timeUnit");
78      }
79  
80      public WebDriverPoller withDefaultTimeout(long timeout, TimeUnit timeUnit)
81      {
82          return new WebDriverPoller(webDriver, timeout, timeUnit);
83      }
84  
85  
86      /**
87       * Wait until {@literal condition} is {@literal true} up to the default timeout. The default timeout depends
88       * on the arguments supplied while creating an instance of this {@code WebDriverPoller}.
89       *
90       * @param condition condition that must evaluate to {@literal true}
91       * @throws TimeoutException if the condition does not come true before the timeout expires
92       * @see #DEFAULT_TIMEOUT
93       * @see #DEFAULT_TIMEOUT_UNIT
94       */
95      public void waitUntil(Function<WebDriver,Boolean> condition)
96      {
97          waitUntil(condition, timeout, timeUnit);
98      }
99  
100     /**
101      * Wait until {@literal condition} up to the {@literal timeoutInSeconds}.
102      *
103      * @param condition condition that must evaluate to {@literal true}
104      * @param timeoutInSeconds timeout in seconds to wait for {@literal condition} to come true
105      * @throws TimeoutException if the condition does not come true before the timeout expires
106      */
107     public void waitUntil(Function<WebDriver,Boolean> condition, long timeoutInSeconds)
108     {
109         new WebDriverWait(webDriver, timeoutInSeconds).until(condition);
110     }
111 
112 
113     /**
114      * Wait until {@literal condition} up to the {@literal timeout} specified by {@literal unit}.
115      *
116      * @param condition condition that must evaluate to {@literal true}
117      * @param timeout timeout to wait for {@literal condition} to come true
118      * @param unit unit of the {@literal timeout}
119      * @throws TimeoutException if the condition does not come true before the timeout expires
120      */
121     public void waitUntil(Function<WebDriver,Boolean> condition, long timeout, TimeUnit unit)
122     {
123         waitUntil(condition, unit.toSeconds(timeout));
124     }
125 }