Skip to content

Commit

Permalink
Allows explicit waits on web elements in a page
Browse files Browse the repository at this point in the history
For example:
 withTimeoutOf(5, TimeUnit.SECONDS).waitFor(facebookIcon).click()
  • Loading branch information
wakaleo committed Mar 19, 2015
1 parent b497a1d commit 33ff1a1
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.serenitybdd.core.pages;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import net.thucydides.core.scheduling.NormalFluentWait;
import net.thucydides.core.scheduling.ThucydidesFluentWait;
Expand Down Expand Up @@ -63,7 +64,7 @@ public FluentWait<WebDriver> doWait() {
private ExpectedCondition<Boolean> elementDisplayed(final By byElementCriteria) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return (elementIsDisplayed(byElementCriteria));
return (elementIsCurrentlyVisible(byElementCriteria));
}
};
}
Expand All @@ -86,6 +87,63 @@ public void waitFor(final ExpectedCondition expectedCondition) {
doWait().until(expectedCondition);
}

public WebElementFacade waitFor(final WebElement webElement) {
return (webElement instanceof WebElementFacade) ?
waitForElement((WebElementFacade)webElement) :
waitForElement(pageObject.element(webElement));
}

public List<WebElementFacade> waitFor(final List<WebElementFacade> webElements) {
return waitForElements(webElements);
}

private WebElementFacade waitForElement(final WebElementFacade webElement) {
waitForCondition().until(elementIsDisplayed(webElement));
return webElement;
}

private List<WebElementFacade> waitForElements(final List<WebElementFacade> elements) {
waitForCondition().until(elementsAreDisplayed(elements));
return elements;
}

private Function<? super WebDriver, Boolean> elementIsDisplayed(final WebElementFacade webElement) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
try {
if (webElement.isCurrentlyVisible()) {
return true;
}
} catch (NoSuchElementException noSuchElement) {
LOGGER.trace("No such element " + noSuchElement);
}
return false;
}
};
}

private Function<? super WebDriver, Boolean> elementsAreDisplayed(final List<WebElementFacade> webElements) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
try {
return (webElements.size() > 0) && allElementsVisibleIn(webElements);
} catch (NoSuchElementException noSuchElement) {
LOGGER.trace("No such element " + noSuchElement);
}
return false;
}
};
}

private boolean allElementsVisibleIn(List<WebElementFacade> webElements) {
for(WebElementFacade element: webElements) {
if (!element.isCurrentlyVisible()) {
return false;
}
}
return true;
}

/**
* This method will wait until an element is present on the screen, though not necessarily visible.
*/
Expand Down Expand Up @@ -123,6 +181,21 @@ public boolean elementIsDisplayed(final By byElementCriteria) {
}
}

public boolean elementIsCurrentlyVisible(final By byElementCriteria) {
try {
List<WebElement> matchingElements = driver.findElements(byElementCriteria);
return (!matchingElements.isEmpty() && matchingElements.get(0).isDisplayed());
} catch (NoSuchElementException noSuchElement) {
LOGGER.trace("No such element " + noSuchElement);
return false;
} catch (StaleElementReferenceException se) {
LOGGER.trace("Element no longer attached to the DOM " + se);
return false;
} catch (TimeoutException iGuessItsNotThere) {
return false;
}
}

private ExpectedCondition<Boolean> textPresent(final String expectedText) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,8 @@ private void notifyScreenChange() {

@Override
public String toString() {
return (resolvedElement() != null) ? resolvedElement().toString() : "<Undefined web element>";
String locatorString = (locator != null) ? locator.toString() : "<Undefined web element>";
return (resolvedElement() != null) ? resolvedElement().toString() : locatorString;
}

public void submit() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class WhenManagingWebdriverTimeouts extends Specification {
}

def "If the implicit wait times out when fetching a list of values only the currently loaded values will be returned"() {
given: "We configure the WebDriver implicit wait to be 100 milliseconds"
given: "We configure the WebDriver implicit wait to be 0 milliseconds"
environmentVariables.setProperty("webdriver.timeouts.implicitlywait","0")
when: "We access the a list of elements"
page = openTestPageUsing(defaultBrowser)
Expand All @@ -100,6 +100,16 @@ class WhenManagingWebdriverTimeouts extends Specification {
itemCount == 0
}

def "You can force an extra delay to give elements time to load"() {
given: "We configure the WebDriver implicit wait to be 0 milliseconds"
environmentVariables.setProperty("webdriver.timeouts.implicitlywait","0")
environmentVariables.setProperty("webdriver.wait.for.timeout", "0")
when: "We access the a list of elements"
page = openTestPageUsing(defaultBrowser)
def count = page.withTimeoutOf(5,SECONDS).waitFor(page.elementItems).size()
then: "Only the elements loaded after the timeout should be loaded"
count == 4
}

def "You can override the implicit wait during test execution"() {
given: "The #slow-loader field takes 3 seconds to load"
Expand Down

0 comments on commit 33ff1a1

Please sign in to comment.