From 90cd54c0e0534d63bfb922ca583b7b6d641d05aa Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Fri, 28 Sep 2018 16:28:00 +0200 Subject: [PATCH 01/10] #288 BobcatWait reworked --- .../qa/bb/provider/selenium/BobcatWait.java | 19 +-- .../selenium/BobcatWebDriverWait.java | 6 +- .../qa/bb/utils/BrowserTabsHelper.java | 13 +- .../qa/bb/utils/WebElementUtils.java | 10 +- .../com/cognifide/qa/bb/wait/BobcatWait.java | 120 ++++++++++++++++++ .../com/cognifide/qa/bb/wait/Timings.java | 56 ++++++++ .../cognifide/qa/bb/wait/TimingsBuilder.java | 81 ++++++++++++ .../bb/webelement/WebElementConditions.java | 103 +++++++++++++++ 8 files changed, 383 insertions(+), 25 deletions(-) create mode 100644 bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java create mode 100644 bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java create mode 100644 bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java create mode 100644 bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWait.java b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWait.java index bbab730f..308e8161 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWait.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWait.java @@ -33,11 +33,13 @@ /** * This is an utility class that extends Selenium's wait functionality. If you need wait/until replacement, - * inject instance of this class into your PageObject. If you only need "sleep" function, call it directly - * from BobcatWait statically, because "sleep" is static. + * inject instance of this class into your PageObject. *

* This class serves as a factory for BobcatWebDriverWait instances. + * + * @deprecated moved under {@link com.cognifide.qa.bb.wait.BobcatWait} */ +@Deprecated public class BobcatWait { private static final Logger LOG = LoggerFactory.getLogger(BobcatWait.class); @@ -52,18 +54,9 @@ public class BobcatWait { private WebDriverProvider webDriverProvider; /** - * This is a wrapper method for Thread's sleep method. - *

- * It catches and logs InterruptedException thrown from original sleep method, - * so the user doesn't need to bother with writing a try-catch block. - *

- * Use this method only if you can't use "withTimeout" (which is more flexible). - *

- * If you don't use "withTimeout", call "sleep" directly from BobcatWait, - * without creating an instance. - * - * @param durationInSec Thread will sleep for durationInSec seconds. + * @deprecated it's 2018, don't use sleeps in your tests :) */ + @Deprecated public static void sleep(double durationInSec) { try { TimeUnit.MILLISECONDS.sleep((long) (durationInSec * 1000)); diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWebDriverWait.java b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWebDriverWait.java index dfb7baf9..4e87db92 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWebDriverWait.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/BobcatWebDriverWait.java @@ -28,7 +28,10 @@ /** * This class performs actual wait. It should always be used with BobcatWait class which acts as a factory for * BobcatWebDriverWait. + * + * @deprecated will be removed in 2.0 */ +@Deprecated public class BobcatWebDriverWait { private static final int IMPLICITLY_WAIT_TIME = 1; @@ -88,7 +91,8 @@ public T until(ExpectedCondition condition) { */ public T until(ExpectedCondition condition, long delay) { webDriver.manage().timeouts().implicitlyWait(IMPLICITLY_WAIT_TIME, TimeUnit.SECONDS); - final T result = new WebDriverWait(webDriver, timeOutInSeconds, delay * 1000L).until(condition::apply); + final T result = + new WebDriverWait(webDriver, timeOutInSeconds, delay * 1000L).until(condition::apply); webDriver.manage().timeouts().implicitlyWait(defaultTimeout, TimeUnit.SECONDS); return result; } diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/utils/BrowserTabsHelper.java b/bb-core/src/main/java/com/cognifide/qa/bb/utils/BrowserTabsHelper.java index 59d8589a..ff4e4c3b 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/utils/BrowserTabsHelper.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/utils/BrowserTabsHelper.java @@ -7,9 +7,9 @@ * Licensed 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. @@ -25,6 +25,7 @@ import org.openqa.selenium.WebDriver; import com.cognifide.qa.bb.guice.ThreadScoped; +import com.cognifide.qa.bb.wait.BobcatWait; import com.google.inject.Inject; /** @@ -38,7 +39,7 @@ public final class BrowserTabsHelper { private WebDriver webDriver; @Inject - private WebElementUtils webElementUtils; + private BobcatWait bobcatWait; /** * Checks if expected tabs count is opened with timeout defined in @@ -48,7 +49,7 @@ public final class BrowserTabsHelper { * @return value indicating if expected tabs count is opened. */ public boolean isExpectedTabsCountOpened(int tabsCount) { - return webElementUtils.isConditionMet(driver -> getOpenedTabsCount() == tabsCount); + return bobcatWait.isConditionMet(driver -> getOpenedTabsCount() == tabsCount); } /** @@ -77,8 +78,8 @@ public void switchToPreviousTab() { } /** - * Switches to the browser tab with specified index offset from active tab. If resulting index - * exceeds the index of first or last tab counting continues from another end. + * Switches to the browser tab with specified index offset from active tab. If resulting index + * exceeds the index of first or last tab counting continues from another end. * * @param tabOffset tab index offset from active tab. */ diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/utils/WebElementUtils.java b/bb-core/src/main/java/com/cognifide/qa/bb/utils/WebElementUtils.java index e221a42e..36913941 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/utils/WebElementUtils.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/utils/WebElementUtils.java @@ -19,11 +19,7 @@ */ package com.cognifide.qa.bb.utils; -import static org.openqa.selenium.support.ui.ExpectedConditions.not; -import static org.openqa.selenium.support.ui.ExpectedConditions.textToBePresentInElement; -import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOf; -import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfAllElements; -import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated; +import static org.openqa.selenium.support.ui.ExpectedConditions.*; import java.util.ArrayDeque; import java.util.Deque; @@ -41,13 +37,17 @@ import com.cognifide.qa.bb.constants.Timeouts; import com.cognifide.qa.bb.guice.ThreadScoped; import com.cognifide.qa.bb.provider.selenium.BobcatWait; +import com.cognifide.qa.bb.webelement.WebElementConditions; import com.google.inject.Inject; /** * This class contains utility methods for checking with waits if WebElements are meeting different * conditions. + * + * @deprecated use {@link WebElementConditions} together with {@link com.cognifide.qa.bb.wait.BobcatWait} */ @ThreadScoped +@Deprecated public final class WebElementUtils { private static final Logger LOG = LoggerFactory.getLogger(WebElementUtils.class); diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java new file mode 100644 index 00000000..28e99483 --- /dev/null +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java @@ -0,0 +1,120 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2016 Cognifide Ltd. + * %% + * Licensed 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. + * #L% + */ +package com.cognifide.qa.bb.wait; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +import org.openqa.selenium.StaleElementReferenceException; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.cognifide.qa.bb.guice.ThreadScoped; +import com.google.inject.Inject; + +/** + * This is the go-to solution for handling dynamic elements with Bobcat. + * It is based on the {@link org.openqa.selenium.support.ui.WebDriverWait} mechanism. + */ +@ThreadScoped +public class BobcatWait { + + private static final Logger LOG = LoggerFactory.getLogger(BobcatWait.class); + + @Inject + private WebDriver webDriver; + + private Timings timings = new TimingsBuilder().build(); + + private List> ignoredExceptions = new ArrayList<>(); + + /** + * Allows to customize the timings (explicit & implicit timeout + polling time). + * + * @param timings a {@link Timings} instance - use the {@link TimingsBuilder} to create one + * @return a self reference + * @see Timings + */ + public BobcatWait tweak(Timings timings) { + this.timings = timings; + return this; + } + + /** + * Adds a list of exception to be ignored during condition evaluation + * + * @param exceptions list of exceptions to be ignored + * @return a self reference + * @see org.openqa.selenium.support.ui.FluentWait#ignoreAll(Collection) + */ + public BobcatWait ignoring(List> exceptions) { + ignoredExceptions.addAll(exceptions); + return this; + } + + /** + * This method enhances Selenium's "until" method. + * First it reduces implicit timeout to a near-zero value. + * Then a timer is started and the condition is checked cyclically until it is fulfilled + * or the timer times out. Finally, implicit timeout is set back to the value + * defined in the property file (under "wait.implicitTimeout"). + * + * @param condition Selenium's condition object that is queried cyclically inside the wait loop. + * @param The function's expected return type. + * @return The ExpectedCondition's return value if the function returned something different. + * from null or false before the timeout expired. + * @see WebDriverWait#until(Function) + */ + public T until(ExpectedCondition condition) { + webDriver.manage().timeouts().implicitlyWait(Timings.NEAR_ZERO, TimeUnit.SECONDS); + final T result = getWebDriverWait() + .ignoreAll(ignoredExceptions) + .until(condition); + webDriver.manage().timeouts().implicitlyWait(timings.getImplicitTimeout(), TimeUnit.SECONDS); + return result; + } + + /** + * Checks if the provided condition is met. + * + * @param condition condition to be checked + * @return boolean indicating if condition is met + */ + public boolean isConditionMet(final ExpectedCondition condition) { + try { + until(condition); + } catch (TimeoutException | StaleElementReferenceException e) { + LOG.debug("{} condition has not been met before timeout ", condition, e); + return false; + } + return true; + } + + private WebDriverWait getWebDriverWait() { + return new WebDriverWait(webDriver, timings.getExplicitTimeout(), timings.getPollingTime()); + } +} diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java new file mode 100644 index 00000000..0d23c394 --- /dev/null +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java @@ -0,0 +1,56 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2018 Cognifide Ltd. + * %% + * Licensed 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. + * #L% + */ +package com.cognifide.qa.bb.wait; + +/** + * A value object defining the set of timings used in {@link BobcatWait}. + * Use {@link TimingsBuilder} to create instances of this class. + *

+ * Contains info about: + *

+ */ +public class Timings { + public static final int NEAR_ZERO = 1; + private long explicitTimeout; + private long pollingTime; + private long implicitTimeout; + + public Timings(long explicitTimeout, long pollingTime, long implicitTimeout) { + this.explicitTimeout = explicitTimeout; + this.pollingTime = pollingTime; + this.implicitTimeout = implicitTimeout; + } + + public long getExplicitTimeout() { + return explicitTimeout; + } + + public long getPollingTime() { + return pollingTime; + } + + public long getImplicitTimeout() { + return implicitTimeout; + } +} diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java new file mode 100644 index 00000000..1448811d --- /dev/null +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java @@ -0,0 +1,81 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2018 Cognifide Ltd. + * %% + * Licensed 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. + * #L% + */ +package com.cognifide.qa.bb.wait; + +/** + * Builder for {@link Timings} instances. + *

+ * Default values are taken from System properties: + *

+ */ +public class TimingsBuilder { + + private long pollingTime = Long.valueOf(System.getProperty("wait.pollingTime", "500")); + + private long explicitTimeout = Long.valueOf(System.getProperty("wait.explicitTimeout", "10")); + + private long implicitTimeout = Long.valueOf(System.getProperty("wait.implicitTimeout", "10")); + + /** + * Set the explicit timeout + * + * @param timeout timeout in seconds + * @return a self reference + */ + public TimingsBuilder explicitTimeout(long timeout) { + explicitTimeout = timeout; + return this; + } + + /** + * Set the polling time. + * + * @param time in milliseconds + * @return a self reference + */ + public TimingsBuilder pollingTime(long time) { + pollingTime = time; + return this; + } + + /** + * Set the implicit timeout. + * + * @param timeout in miliseconds + * @return a self reference + */ + public TimingsBuilder implicitTimeout(long timeout) { + implicitTimeout = timeout; + return this; + } + + /** + * Creates an instance of {@link Timings} + * + * @return new {@link Timings} instance + */ + public Timings build() { + return new Timings(explicitTimeout, pollingTime, implicitTimeout); + } +} diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java b/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java new file mode 100644 index 00000000..513b9a2f --- /dev/null +++ b/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java @@ -0,0 +1,103 @@ +/*- + * #%L + * Bobcat + * %% + * Copyright (C) 2016 Cognifide Ltd. + * %% + * Licensed 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. + * #L% + */ +package com.cognifide.qa.bb.webelement; + +import java.util.ArrayDeque; +import java.util.Deque; + +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.Point; +import org.openqa.selenium.StaleElementReferenceException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class contains utility methods for checking with waits if WebElements are meeting different + * conditions. + */ +public final class WebElementConditions { + + private static final Logger LOG = LoggerFactory.getLogger(WebElementConditions.class); + + /** + * Condition that checks if specified WebElement has the provided attribute. + * + * @param element WebElement to be checked. + * @param attribute name of the attribute which presence is to be checked. + * @return ExpectedCondtion representing the above check + */ + public static ExpectedCondition elementHasAttribute(WebElement element, + String attribute) { + return webDriver -> (element.getAttribute(attribute) != null) ? element : null; + } + + /** + * Condition that checks if given attribute has the provided value in the specified WebElement. + * + * @param element WebElement to be checked. + * @param attribute name of the attribute which presence is to be checked. + * @param value value which presence in attribute is to be checked. + * @return ExpectedCondition representing the above check + */ + public static ExpectedCondition elementHasAttributeWithValue(final WebElement element, + final String attribute, + final String value) { + return webDriver -> element.getAttribute(attribute).contains(value) ? element : null; + } + + /** + * Condition that checks if animation of provided WebElement finished. + * + * @param element WebElement to be checked + * @return ExpectedCondition representing the above check + */ + public ExpectedCondition hasAnimationFinished(final WebElement element) { + final Deque locations = new ArrayDeque<>(); + return webDriver -> { + Point currentLocation = element.getLocation(); + boolean animationStopped = false; + if (!locations.isEmpty()) { + animationStopped = locations.peekFirst().equals(currentLocation); + } + + locations.addFirst(currentLocation); + return animationStopped ? element : null; + }; + } + + /** + * Condition that checks if provided WebElement is ready to be operated on, ie. is visible and not stale. + * + * @param element list of WebElements within which the specified WebElement is searched + * @return ExpectedCondition representing the above check + */ + public static ExpectedCondition isReady(final WebElement element) { + return webDriver -> { + try { + return element.isDisplayed() ? element : null; + } catch (NoSuchElementException | StaleElementReferenceException e) { + LOG.debug("Element {} not present: {}", element, e); + return null; + } + }; + } +} From d31028c7463d3552604fa5d7bea5700ada8f7285 Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Fri, 28 Sep 2018 16:50:34 +0200 Subject: [PATCH 02/10] #288 Cleanup of the available expected conditions; favoring the ones from Selenium OOTB --- .../CommonExpectedConditions.java | 13 ++++--- .../UrlExpectedConditions.java | 4 ++ .../bb/webelement/WebElementConditions.java | 38 ++++++------------- 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/CommonExpectedConditions.java b/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/CommonExpectedConditions.java index 370a962a..bff4522d 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/CommonExpectedConditions.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/CommonExpectedConditions.java @@ -34,7 +34,10 @@ /** * Class contains custom ExpectedConditions for explicit waiting (provided by BobcatWait) + * + * @deprecated to be removed in 2.0; use methods from {@link org.openqa.selenium.support.ui.ExpectedConditions} or {@link com.cognifide.qa.bb.webelement.WebElementConditions} */ +@Deprecated public final class CommonExpectedConditions { private static final Logger LOG = LoggerFactory.getLogger(CommonExpectedConditions.class); @@ -56,9 +59,9 @@ public static ExpectedCondition elementNotPresent(final By bySelector) /** * Check if element has attribute with provided value * - * @param attributeName name of the attribute + * @param attributeName name of the attribute * @param attributeValue value of the attribute - * @param element WebElement to check + * @param element WebElement to check * @return true if element has attribute with provided value */ public static ExpectedCondition elementHasAttributeWithValue(final WebElement element, @@ -71,7 +74,7 @@ public static ExpectedCondition elementHasAttributeWithValue(final WebE * Check if element located by specified By locator exists in DOM in an * element's context * - * @param scope scope in which element will be searched for + * @param scope scope in which element will be searched for * @param locator {@link By} locator of the searched element * @return false if element does not exist or WebDriver is null */ @@ -102,7 +105,7 @@ public static ExpectedCondition elementNotPresentOrVisible(final By byS /** * Check if provided element height is greater than expected height * - * @param element - WebElement to check + * @param element - WebElement to check * @param expectedHeight - expected height of an element * @return true if element height is greater than expected */ @@ -115,7 +118,7 @@ public static ExpectedCondition heightOfElementGreaterThan(final WebEle * List of WebElements found in provided scope using provided locator is * constant * - * @param element WebElement to set scope for elements finder + * @param element WebElement to set scope for elements finder * @param byElement By selector * @return true if list of WebElements is the same after one second */ diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditions.java b/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditions.java index 36523e46..ba7d138c 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditions.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditions.java @@ -21,10 +21,14 @@ import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; /** * Class contains custom ExpectedConditions for testing current URL + * + * @deprecated use methods from {@link ExpectedConditions} */ +@Deprecated public final class UrlExpectedConditions { private UrlExpectedConditions() { diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java b/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java index 513b9a2f..b62c9273 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java @@ -38,32 +38,6 @@ public final class WebElementConditions { private static final Logger LOG = LoggerFactory.getLogger(WebElementConditions.class); - /** - * Condition that checks if specified WebElement has the provided attribute. - * - * @param element WebElement to be checked. - * @param attribute name of the attribute which presence is to be checked. - * @return ExpectedCondtion representing the above check - */ - public static ExpectedCondition elementHasAttribute(WebElement element, - String attribute) { - return webDriver -> (element.getAttribute(attribute) != null) ? element : null; - } - - /** - * Condition that checks if given attribute has the provided value in the specified WebElement. - * - * @param element WebElement to be checked. - * @param attribute name of the attribute which presence is to be checked. - * @param value value which presence in attribute is to be checked. - * @return ExpectedCondition representing the above check - */ - public static ExpectedCondition elementHasAttributeWithValue(final WebElement element, - final String attribute, - final String value) { - return webDriver -> element.getAttribute(attribute).contains(value) ? element : null; - } - /** * Condition that checks if animation of provided WebElement finished. * @@ -100,4 +74,16 @@ public static ExpectedCondition isReady(final WebElement element) { } }; } + + /** + * Check if provided element height is greater than expected height + * + * @param element - WebElement to check + * @param expectedHeight - expected height of an element + * @return true if element height is greater than expected + */ + public static ExpectedCondition heightOfElementGreaterThan(final WebElement element, + final int expectedHeight) { + return driver -> element.getSize().getHeight() > expectedHeight; + } } From 41831a39df520a692eec54ecaca06dc67bba7ea2 Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Mon, 1 Oct 2018 17:19:23 +0200 Subject: [PATCH 03/10] #288 Added default properties, refactoring + docs --- .../cognifide/qa/bb/constants/ConfigKeys.java | 11 +++++++++++ .../com/cognifide/qa/bb/wait/BobcatWait.java | 2 +- .../java/com/cognifide/qa/bb/wait/Timings.java | 6 +++--- .../cognifide/qa/bb/wait/TimingsBuilder.java | 17 +++++++++++------ .../qa/bb/webelement/WebElementConditions.java | 10 +++++----- bb-core/src/main/resources/default.properties | 12 +++++++----- bb-core/src/main/resources/default.yaml | 11 +++++------ 7 files changed, 43 insertions(+), 26 deletions(-) diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java b/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java index ec1ad585..a507b93f 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java @@ -36,6 +36,10 @@ public final class ConfigKeys { public static final String WEBDRIVER_CAP_PLATFORM_NAME = "webdriver.cap.platformName"; + /** + * @deprecated since 1.6.0; use {@code timings.*} properties + */ + @Deprecated public static final String WEBDRIVER_DEFAULT_TIMEOUT = "webdriver.defaultTimeout"; public static final String WEBDRIVER_FIREFOX_BIN = "webdriver.firefox.bin"; @@ -52,10 +56,13 @@ public final class ConfigKeys { public static final String WEBDRIVER_URL = "webdriver.url"; + @Deprecated public static final String CONFIGURATION_PATHS = "configuration.paths"; + @Deprecated public static final String DEFAULT_PROPERTIES_NAME = "default.properties"; + @Deprecated public static final String JUNIT_RERUNS = "junit.reruns"; public static final String CONFIG_STRATEGY = "bobcat.config"; @@ -63,6 +70,10 @@ public final class ConfigKeys { public static final String COOKIE_LOAD_AUTOMATICALLY = "cookies.loadAutomatically"; + public static final String TIMINGS_EXPLICIT_TIMEOUT = "timings.explicitTimeout"; + public static final String TIMINGS_IMPLICIT_TIMEOUT = "timings.implicitTimeout"; + public static final String TIMINGS_POLLING_TIME = "timings.pollingTime"; + private ConfigKeys() { } } diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java index 28e99483..ebe6fc78 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java @@ -81,7 +81,7 @@ public BobcatWait ignoring(List> exceptions) { * First it reduces implicit timeout to a near-zero value. * Then a timer is started and the condition is checked cyclically until it is fulfilled * or the timer times out. Finally, implicit timeout is set back to the value - * defined in the property file (under "wait.implicitTimeout"). + * defined in the property file (under {@value com.cognifide.qa.bb.constants.ConfigKeys#TIMINGS_IMPLICIT_TIMEOUT} * * @param condition Selenium's condition object that is queried cyclically inside the wait loop. * @param The function's expected return type. diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java index 0d23c394..5e9c797a 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java @@ -25,9 +25,9 @@ *

* Contains info about: *

    - *
  • explicit timeout
  • - *
  • implicit timeout
  • - *
  • polling time
  • + *
  • explicit timeout (in seconds)
  • + *
  • implicit timeout (in milliseconds)
  • + *
  • polling time (in milliseconds)
  • *
*/ public class Timings { diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java index 1448811d..a77f102c 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java @@ -19,23 +19,28 @@ */ package com.cognifide.qa.bb.wait; +import com.cognifide.qa.bb.constants.ConfigKeys; + /** * Builder for {@link Timings} instances. *

* Default values are taken from System properties: *

    - *
  • for explicit timeout - {@code wait.explicitTimeout}
  • - *
  • for implicit timeout - {@code wait.implicitTimeout}
  • - *
  • for polling time - {@code wait.pollingTime}
  • + *
  • for explicit timeout - {@value ConfigKeys#TIMINGS_EXPLICIT_TIMEOUT}
  • + *
  • for implicit timeout - {@value ConfigKeys#TIMINGS_IMPLICIT_TIMEOUT}
  • + *
  • for polling time - {@value ConfigKeys#TIMINGS_POLLING_TIME}
  • *
*/ public class TimingsBuilder { - private long pollingTime = Long.valueOf(System.getProperty("wait.pollingTime", "500")); + private long pollingTime = + Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_POLLING_TIME, "500")); - private long explicitTimeout = Long.valueOf(System.getProperty("wait.explicitTimeout", "10")); + private long explicitTimeout = + Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_EXPLICIT_TIMEOUT, "10")); - private long implicitTimeout = Long.valueOf(System.getProperty("wait.implicitTimeout", "10")); + private long implicitTimeout = + Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_IMPLICIT_TIMEOUT, "10")); /** * Set the explicit timeout diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java b/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java index b62c9273..3c697656 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/webelement/WebElementConditions.java @@ -59,12 +59,12 @@ public ExpectedCondition hasAnimationFinished(final WebElement eleme } /** - * Condition that checks if provided WebElement is ready to be operated on, ie. is visible and not stale. + * Condition that checks if provided WebElement is 'ready' to be operated on, ie. is visible and not stale. * * @param element list of WebElements within which the specified WebElement is searched * @return ExpectedCondition representing the above check */ - public static ExpectedCondition isReady(final WebElement element) { + public static ExpectedCondition elementIsReady(final WebElement element) { return webDriver -> { try { return element.isDisplayed() ? element : null; @@ -80,10 +80,10 @@ public static ExpectedCondition isReady(final WebElement element) { * * @param element - WebElement to check * @param expectedHeight - expected height of an element - * @return true if element height is greater than expected + * @return ExpectedCondition representing the above check */ - public static ExpectedCondition heightOfElementGreaterThan(final WebElement element, + public static ExpectedCondition heightOfElementGreaterThan(final WebElement element, final int expectedHeight) { - return driver -> element.getSize().getHeight() > expectedHeight; + return driver -> element.getSize().getHeight() > expectedHeight ? element : null; } } diff --git a/bb-core/src/main/resources/default.properties b/bb-core/src/main/resources/default.properties index 61a1e683..89a335f7 100644 --- a/bb-core/src/main/resources/default.properties +++ b/bb-core/src/main/resources/default.properties @@ -1,17 +1,19 @@ webdriver.type=firefox +#deprecated, see ConfigKeys webdriver.defaultTimeout=10 webdriver.mobile=false webdriver.maximize=true webdriver.reusable=false -timeouts.big=30 -timeouts.medium=15 -timeouts.small=5 -timeouts.minimal=1 - proxy.enabled=false proxy.ip=127.0.0.1 proxy.port=9000 analytics.uri.prefix = /b/ss analytics.call.timeout.ms = 30000 + +cookies.loadAutomatically = true + +timings.explicitTimeout=10 +timings.implicitTimeout=10 +timings.pollingTime=500 diff --git a/bb-core/src/main/resources/default.yaml b/bb-core/src/main/resources/default.yaml index eaac8cc7..6dca16ed 100644 --- a/bb-core/src/main/resources/default.yaml +++ b/bb-core/src/main/resources/default.yaml @@ -11,11 +11,6 @@ default: bobcat.report.path: ./target/report bobcat.report.reporters: html,json,simple,stdout - timeouts.big: 30 - timeouts.medium: 15 - timeouts.small: 5 - timeouts.minimal: 1 - analytics.uri.prefix: /b/ss analytics.call.timeout.ms: 30000 @@ -24,6 +19,10 @@ default: webdriver.mobile: false webdriver.maximize: true webdriver.reusable: false - webdriver.defaultTimeout: 10 + webdriver.defaultTimeout: 10 #deprecated, see ConfigKeys cookies.loadAutomatically: true + + timings.explicitTimeout: 10 + timings.implicitTimeout: 10 + timings.pollingTime: 500 From dc43b423e142c698a78bfc6214bc4834d53ed03a Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Mon, 1 Oct 2018 18:00:29 +0200 Subject: [PATCH 04/10] #288 Made BobcatWait#until more robust --- .../java/com/cognifide/qa/bb/wait/BobcatWait.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java index ebe6fc78..f608b6bd 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java @@ -90,12 +90,14 @@ public BobcatWait ignoring(List> exceptions) { * @see WebDriverWait#until(Function) */ public T until(ExpectedCondition condition) { - webDriver.manage().timeouts().implicitlyWait(Timings.NEAR_ZERO, TimeUnit.SECONDS); - final T result = getWebDriverWait() - .ignoreAll(ignoredExceptions) - .until(condition); - webDriver.manage().timeouts().implicitlyWait(timings.getImplicitTimeout(), TimeUnit.SECONDS); - return result; + try { + webDriver.manage().timeouts().implicitlyWait(Timings.NEAR_ZERO, TimeUnit.SECONDS); + return getWebDriverWait() + .ignoreAll(ignoredExceptions) + .until(condition); + } finally { + webDriver.manage().timeouts().implicitlyWait(timings.getImplicitTimeout(), TimeUnit.SECONDS); + } } /** From f48f8b2dc99aef22e45ac813a44db0dc7b989e5c Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Mon, 1 Oct 2018 18:06:50 +0200 Subject: [PATCH 05/10] #288 Implicit timeout modifier can now be disabled + is using new properties --- .../java/com/cognifide/qa/bb/constants/ConfigKeys.java | 2 ++ .../modifiers/webdriver/ImplicitTimeoutModifier.java | 8 ++++++-- bb-core/src/main/resources/default.properties | 1 + bb-core/src/main/resources/default.yaml | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java b/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java index a507b93f..08626480 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java @@ -70,6 +70,8 @@ public final class ConfigKeys { public static final String COOKIE_LOAD_AUTOMATICALLY = "cookies.loadAutomatically"; + public static final String MODIFIERS_IMPLICIT_TIMEOUT = "modifiers.implicitTimeout"; + public static final String TIMINGS_EXPLICIT_TIMEOUT = "timings.explicitTimeout"; public static final String TIMINGS_IMPLICIT_TIMEOUT = "timings.implicitTimeout"; public static final String TIMINGS_POLLING_TIME = "timings.pollingTime"; diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/webdriver/ImplicitTimeoutModifier.java b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/webdriver/ImplicitTimeoutModifier.java index 2cddf857..f25bfa3e 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/webdriver/ImplicitTimeoutModifier.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/provider/selenium/webdriver/modifiers/webdriver/ImplicitTimeoutModifier.java @@ -30,12 +30,16 @@ public class ImplicitTimeoutModifier implements WebDriverModifier { @Inject - @Named(ConfigKeys.WEBDRIVER_DEFAULT_TIMEOUT) + @Named(ConfigKeys.TIMINGS_IMPLICIT_TIMEOUT) private int defaultTimeout; + @Inject + @Named(ConfigKeys.MODIFIERS_IMPLICIT_TIMEOUT) + private boolean enabled; + @Override public boolean shouldModify() { - return true; + return enabled; } @Override diff --git a/bb-core/src/main/resources/default.properties b/bb-core/src/main/resources/default.properties index 89a335f7..4538dec1 100644 --- a/bb-core/src/main/resources/default.properties +++ b/bb-core/src/main/resources/default.properties @@ -14,6 +14,7 @@ analytics.call.timeout.ms = 30000 cookies.loadAutomatically = true +modifiers.implicitTimeout=true timings.explicitTimeout=10 timings.implicitTimeout=10 timings.pollingTime=500 diff --git a/bb-core/src/main/resources/default.yaml b/bb-core/src/main/resources/default.yaml index 6dca16ed..55794466 100644 --- a/bb-core/src/main/resources/default.yaml +++ b/bb-core/src/main/resources/default.yaml @@ -23,6 +23,7 @@ default: cookies.loadAutomatically: true + modifiers.implicitTimeout: true timings.explicitTimeout: 10 timings.implicitTimeout: 10 timings.pollingTime: 500 From 43799ac576371e3864188a9576cc75f7967e26c0 Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Tue, 2 Oct 2018 12:24:53 +0200 Subject: [PATCH 06/10] #288 Wording of a property improved, added tests --- .../cognifide/qa/bb/constants/ConfigKeys.java | 2 +- .../com/cognifide/qa/bb/wait/BobcatWait.java | 36 ++++++++-- .../com/cognifide/qa/bb/wait/Timings.java | 14 ++-- .../cognifide/qa/bb/wait/TimingsBuilder.java | 12 ++-- bb-core/src/main/resources/default.properties | 2 +- bb-core/src/main/resources/default.yaml | 2 +- ...ExpectedConditionsPageUrlContainsTest.java | 1 + .../UrlExpectedConditionsPageUrlIsTest.java | 1 + .../cognifide/qa/bb/wait/BobcatWaitTest.java | 68 +++++++++++++++++++ 9 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 bb-core/src/test/java/com/cognifide/qa/bb/wait/BobcatWaitTest.java diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java b/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java index 08626480..b15154fc 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/constants/ConfigKeys.java @@ -74,7 +74,7 @@ public final class ConfigKeys { public static final String TIMINGS_EXPLICIT_TIMEOUT = "timings.explicitTimeout"; public static final String TIMINGS_IMPLICIT_TIMEOUT = "timings.implicitTimeout"; - public static final String TIMINGS_POLLING_TIME = "timings.pollingTime"; + public static final String TIMINGS_POLLING_INTERVAL = "timings.pollingInterval"; private ConfigKeys() { } diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java index f608b6bd..7ae71aab 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java @@ -45,13 +45,17 @@ public class BobcatWait { private static final Logger LOG = LoggerFactory.getLogger(BobcatWait.class); - @Inject - private WebDriver webDriver; - private Timings timings = new TimingsBuilder().build(); private List> ignoredExceptions = new ArrayList<>(); + private WebDriver webDriver; + + @Inject + public BobcatWait(WebDriver webDriver) { + this.webDriver = webDriver; + } + /** * Allows to customize the timings (explicit & implicit timeout + polling time). * @@ -91,12 +95,13 @@ public BobcatWait ignoring(List> exceptions) { */ public T until(ExpectedCondition condition) { try { - webDriver.manage().timeouts().implicitlyWait(Timings.NEAR_ZERO, TimeUnit.SECONDS); + setImplicitTimeoutToNearZero(); return getWebDriverWait() .ignoreAll(ignoredExceptions) .until(condition); } finally { - webDriver.manage().timeouts().implicitlyWait(timings.getImplicitTimeout(), TimeUnit.SECONDS); + ignoredExceptions = new ArrayList<>(); + restoreImplicitTimeout(); } } @@ -116,7 +121,24 @@ public boolean isConditionMet(final ExpectedCondition condition) { return true; } - private WebDriverWait getWebDriverWait() { - return new WebDriverWait(webDriver, timings.getExplicitTimeout(), timings.getPollingTime()); + /** + * Sets implicit timeout to {@value Timings#NEAR_ZERO} milliseconds. + */ + protected void setImplicitTimeoutToNearZero() { + webDriver.manage().timeouts().implicitlyWait(Timings.NEAR_ZERO, TimeUnit.SECONDS); + } + + /** + * Restores implicit timeout to the value defined in the {@link Timings} instance. + */ + protected void restoreImplicitTimeout() { + webDriver.manage().timeouts().implicitlyWait(timings.getImplicitTimeout(), TimeUnit.SECONDS); + } + + /** + * @return an instance of {@link WebDriverWait} based on the provided {@link Timings} + */ + protected WebDriverWait getWebDriverWait() { + return new WebDriverWait(webDriver, timings.getExplicitTimeout(), timings.getPollingInterval()); } } diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java index 5e9c797a..a22a5884 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/Timings.java @@ -26,19 +26,19 @@ * Contains info about: *
    *
  • explicit timeout (in seconds)
  • - *
  • implicit timeout (in milliseconds)
  • - *
  • polling time (in milliseconds)
  • + *
  • implicit timeout (in seconds)
  • + *
  • polling interval (in milliseconds)
  • *
*/ public class Timings { public static final int NEAR_ZERO = 1; private long explicitTimeout; - private long pollingTime; + private long pollingInterval; private long implicitTimeout; - public Timings(long explicitTimeout, long pollingTime, long implicitTimeout) { + public Timings(long explicitTimeout, long pollingInterval, long implicitTimeout) { this.explicitTimeout = explicitTimeout; - this.pollingTime = pollingTime; + this.pollingInterval = pollingInterval; this.implicitTimeout = implicitTimeout; } @@ -46,8 +46,8 @@ public long getExplicitTimeout() { return explicitTimeout; } - public long getPollingTime() { - return pollingTime; + public long getPollingInterval() { + return pollingInterval; } public long getImplicitTimeout() { diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java index a77f102c..221ea344 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java @@ -28,13 +28,13 @@ *
    *
  • for explicit timeout - {@value ConfigKeys#TIMINGS_EXPLICIT_TIMEOUT}
  • *
  • for implicit timeout - {@value ConfigKeys#TIMINGS_IMPLICIT_TIMEOUT}
  • - *
  • for polling time - {@value ConfigKeys#TIMINGS_POLLING_TIME}
  • + *
  • for polling interval - {@value ConfigKeys#TIMINGS_POLLING_INTERVAL}
  • *
*/ public class TimingsBuilder { - private long pollingTime = - Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_POLLING_TIME, "500")); + private long pollingInterval = + Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_POLLING_INTERVAL, "500")); private long explicitTimeout = Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_EXPLICIT_TIMEOUT, "10")); @@ -59,8 +59,8 @@ public TimingsBuilder explicitTimeout(long timeout) { * @param time in milliseconds * @return a self reference */ - public TimingsBuilder pollingTime(long time) { - pollingTime = time; + public TimingsBuilder pollingInterval(long time) { + pollingInterval = time; return this; } @@ -81,6 +81,6 @@ public TimingsBuilder implicitTimeout(long timeout) { * @return new {@link Timings} instance */ public Timings build() { - return new Timings(explicitTimeout, pollingTime, implicitTimeout); + return new Timings(explicitTimeout, pollingInterval, implicitTimeout); } } diff --git a/bb-core/src/main/resources/default.properties b/bb-core/src/main/resources/default.properties index 4538dec1..460541d2 100644 --- a/bb-core/src/main/resources/default.properties +++ b/bb-core/src/main/resources/default.properties @@ -17,4 +17,4 @@ cookies.loadAutomatically = true modifiers.implicitTimeout=true timings.explicitTimeout=10 timings.implicitTimeout=10 -timings.pollingTime=500 +timings.pollingInterval=500 diff --git a/bb-core/src/main/resources/default.yaml b/bb-core/src/main/resources/default.yaml index 55794466..afd4120c 100644 --- a/bb-core/src/main/resources/default.yaml +++ b/bb-core/src/main/resources/default.yaml @@ -26,4 +26,4 @@ default: modifiers.implicitTimeout: true timings.explicitTimeout: 10 timings.implicitTimeout: 10 - timings.pollingTime: 500 + timings.pollingInterval: 500 diff --git a/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlContainsTest.java b/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlContainsTest.java index c8d45c25..9be3b985 100644 --- a/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlContainsTest.java +++ b/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlContainsTest.java @@ -35,6 +35,7 @@ import org.mockito.junit.MockitoRule; import org.openqa.selenium.WebDriver; +@Deprecated @RunWith(Parameterized.class) public class UrlExpectedConditionsPageUrlContainsTest { diff --git a/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlIsTest.java b/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlIsTest.java index a37ec732..e0ad9fad 100644 --- a/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlIsTest.java +++ b/bb-core/src/test/java/com/cognifide/qa/bb/expectedconditions/UrlExpectedConditionsPageUrlIsTest.java @@ -35,6 +35,7 @@ import org.mockito.junit.MockitoRule; import org.openqa.selenium.WebDriver; +@Deprecated @RunWith(Parameterized.class) public class UrlExpectedConditionsPageUrlIsTest { diff --git a/bb-core/src/test/java/com/cognifide/qa/bb/wait/BobcatWaitTest.java b/bb-core/src/test/java/com/cognifide/qa/bb/wait/BobcatWaitTest.java new file mode 100644 index 00000000..55f49f87 --- /dev/null +++ b/bb-core/src/test/java/com/cognifide/qa/bb/wait/BobcatWaitTest.java @@ -0,0 +1,68 @@ +package com.cognifide.qa.bb.wait; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; + +@RunWith(MockitoJUnitRunner.class) +public class BobcatWaitTest { + + @Mock + private WebDriver webDriver; + + @Mock + private WebDriver.Options options; + + @Mock + private WebDriver.Timeouts timeouts; + + private BobcatWait tested; + + @Before + public void setup() { + when(webDriver.manage()).thenReturn(options); + when(options.timeouts()).thenReturn(timeouts); + when(timeouts.implicitlyWait(anyLong(), any())).thenReturn(timeouts); + tested = new BobcatWait(webDriver); + } + + @Test + public void whenUntilIsInvokedImplicitTimeoutsShouldBeReducedThenRestored() { + BobcatWait spied = spy(tested); + InOrder inOrder = inOrder(spied); + when(condition.apply(any())).thenReturn(true); + + spied.until(condition); + + inOrder.verify(spied).setImplicitTimeoutToNearZero(); + inOrder.verify(spied).getWebDriverWait(); + inOrder.verify(spied).restoreImplicitTimeout(); + } + + @Mock + private ExpectedCondition condition; + + @Test + public void isConditionMetShouldCatchTimeoutExceptionAndReturnBoolean() { + when(condition.apply(any())).thenThrow(new TimeoutException()); + + boolean result = true; + try { + result = tested.isConditionMet(condition); + } catch (TimeoutException e) { + fail("Exception should not be thrown"); + } + assertThat(result).isFalse(); + } +} From 0c5945bad903df1206b167685a211aec56dc78df Mon Sep 17 00:00:00 2001 From: Michal Krzyzanowski Date: Tue, 2 Oct 2018 17:24:26 +0200 Subject: [PATCH 07/10] #288 Documentation and changes in default values --- .../com/cognifide/qa/bb/wait/BobcatWait.java | 4 +- .../cognifide/qa/bb/wait/TimingsBuilder.java | 6 +- bb-core/src/main/resources/default.properties | 2 +- bb-core/src/main/resources/default.yaml | 2 +- docs/_data/navigation.yml | 6 +- docs/_docs/modules/core/waiting.md | 96 +++++++++++++++++++ 6 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 docs/_docs/modules/core/waiting.md diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java index 7ae71aab..82f6194f 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/BobcatWait.java @@ -89,8 +89,7 @@ public BobcatWait ignoring(List> exceptions) { * * @param condition Selenium's condition object that is queried cyclically inside the wait loop. * @param The function's expected return type. - * @return The ExpectedCondition's return value if the function returned something different. - * from null or false before the timeout expired. + * @return The ExpectedCondition's return value if the function returned something different from null or false before the timeout expired. * @see WebDriverWait#until(Function) */ public T until(ExpectedCondition condition) { @@ -101,6 +100,7 @@ public T until(ExpectedCondition condition) { .until(condition); } finally { ignoredExceptions = new ArrayList<>(); + timings = new TimingsBuilder().build(); restoreImplicitTimeout(); } } diff --git a/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java index 221ea344..94659251 100644 --- a/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java +++ b/bb-core/src/main/java/com/cognifide/qa/bb/wait/TimingsBuilder.java @@ -34,13 +34,13 @@ public class TimingsBuilder { private long pollingInterval = - Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_POLLING_INTERVAL, "500")); + Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_POLLING_INTERVAL)); private long explicitTimeout = - Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_EXPLICIT_TIMEOUT, "10")); + Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_EXPLICIT_TIMEOUT)); private long implicitTimeout = - Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_IMPLICIT_TIMEOUT, "10")); + Long.valueOf(System.getProperty(ConfigKeys.TIMINGS_IMPLICIT_TIMEOUT)); /** * Set the explicit timeout diff --git a/bb-core/src/main/resources/default.properties b/bb-core/src/main/resources/default.properties index 460541d2..188e6c8b 100644 --- a/bb-core/src/main/resources/default.properties +++ b/bb-core/src/main/resources/default.properties @@ -16,5 +16,5 @@ cookies.loadAutomatically = true modifiers.implicitTimeout=true timings.explicitTimeout=10 -timings.implicitTimeout=10 +timings.implicitTimeout=1 timings.pollingInterval=500 diff --git a/bb-core/src/main/resources/default.yaml b/bb-core/src/main/resources/default.yaml index afd4120c..80469eca 100644 --- a/bb-core/src/main/resources/default.yaml +++ b/bb-core/src/main/resources/default.yaml @@ -25,5 +25,5 @@ default: modifiers.implicitTimeout: true timings.explicitTimeout: 10 - timings.implicitTimeout: 10 + timings.implicitTimeout: 1 timings.pollingInterval: 500 diff --git a/docs/_data/navigation.yml b/docs/_data/navigation.yml index 9bb641f5..b0410580 100644 --- a/docs/_data/navigation.yml +++ b/docs/_data/navigation.yml @@ -24,6 +24,8 @@ docs: children: - title: "Overview" url: /docs/modules/core/ + - title: "Explicit and implicit waiting" + url: /docs/modules/core/waiting - title: "Setting cookies" url: /docs/modules/core/cookies - title: "Other modules" @@ -36,7 +38,9 @@ docs: url: /docs/modules/traffic/ - title: "Email" url: /docs/modules/email/ - - title: "AEM modules (new API incoming!)" + - title: "AEM modules" + children: + - title: "New API incoming in 2.0!" - title: "EOL Modules" children: - title: "AEM Common" diff --git a/docs/_docs/modules/core/waiting.md b/docs/_docs/modules/core/waiting.md new file mode 100644 index 00000000..3e7e9154 --- /dev/null +++ b/docs/_docs/modules/core/waiting.md @@ -0,0 +1,96 @@ +--- +title: "Waiting" +--- + +Available in `bb-core` since version `1.6.0`. Mechanism from previous versions: [link](https://github.com/Cognifide/bobcat/wiki/Explicit-Waits) +{: .notice--info} + +## Overview +One of the fundamental problems when automating GUI is handling dynamic elements on a website: pop-ups, carousels, menus, lazy-loaded data in various places, etc. + +Bobcat utilizes Selenium's out-of-the-box mechanisms: implicit and explicit waiting. More information about them can be found in [official docs](https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp). + +## Implicit waiting + +Implicit waiting happens before any lookup of a `WebElement` is being executed during your tests. When searching for an element it waits for a specific period of time to actually report the issue in case of the element not being present on the page. +This implicit timeout can be set manually using: `webDriver.manage().timeouts().implicitlyWait(,