Skip to content

Instantly share code, notes, and snippets.

@serbanghita
Last active April 11, 2022 17:55
Show Gist options
  • Save serbanghita/c11d02b46bed4fdb01c6ed90b069cd64 to your computer and use it in GitHub Desktop.
Save serbanghita/c11d02b46bed4fdb01c6ed90b069cd64 to your computer and use it in GitHub Desktop.
Selenium - wait for an element's animation to finish

Java

Interesting optimisation: https://github.com/cloudties/Automation/blob/4c15130230dd1e77ab7ba369071396d3efc6eab2/src/com/automation/ui/base/common/core/imageutilities/SimpleViewportRelativeCoordsProvider.java

	public static Boolean waitForReady() {
		return new WebDriverWait(getWebDriver(),5).until(waitForElementAnimationToFinish(".my-css-selector"));
	}
	public static ExpectedCondition<Boolean> waitForElementAnimationToFinish(final String cssSelector) {
		return new ExpectedCondition<Boolean>() {
			private double x  = 0;
			private double y = 0;
			private double width = 0;
			private double height = 0;

			private double convertToDouble(Object longValue) {
				if (longValue instanceof Long) {
					return ((Long) longValue).doubleValue();
				}

				return (double) longValue;
			}

			@Override
			public Boolean apply(WebDriver driver) {
				WebElement elem = driver.findElement(By.cssSelector(cssSelector));
				Map<String, Object> rect = driver().executeJavaScript("var rect = arguments[0].getBoundingClientRect(); return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };", elem);

				double newX = convertToDouble(rect.get("x"));
				double newY = convertToDouble(rect.get("y"));
				double newWidth = convertToDouble(rect.get("width"));
				double newHeight = convertToDouble(rect.get("height"));

				if (newX != x || newY != y || newWidth != width || newHeight != height) {
					x = newX;
					y = newY;
					width = newWidth;
					height = newHeight;
					return false;
				}

				return true;
			}

			@Override
			public String toString() {
				return String.format("CSS Selector: \"%s\"", cssSelector);
			}
		};
	}

Kotlin

    private fun waitForElementAnimationToFinish(cssSelector: String): ExpectedCondition<WebElement?>? {
        return object : ExpectedCondition<WebElement?> {

            var x: Int = 0
            var y: Int = 0
            var width: Int = 0
            var height: Int = 0

            override fun apply(driver: WebDriver?): WebElement? {
                val elem: WebElement? = waitForElementByCSS(cssSelector)
                val rect = elem?.rect

                if (
                        rect?.getX()!!.toInt() != x ||
                        rect.getY() != y ||
                        rect.getWidth() != width ||
                        rect.getHeight() != height
                ) {
                    x = rect.getX()
                    y = rect.getY()
                    width = rect.getWidth()
                    height = rect.getHeight()

                    return null
                }
                return elem
            }

        }
    }

Usage:

    fun waitForAnimationToFinish(cssSelector: String): WebElement? {
        return wait.until(waitForElementAnimationToFinish(cssSelector))
    }
    
    waitForAnimationToFinish(".modal")

JavaScript

browser is Webdriver.io instance

    /**
     * Waits until animation for the element is finished
     * @param {String} selector The element sector
     */
    function waitForElementAnimationToFinish(selector) {
        browser.waitForVisible(selector);

        // Wait until animation is finished
        let previousLocation = {};
        browser.waitUntil(() => {
            let currentLocation = browser.getLocation(selector);
            let hasStopped = previousLocation.x === currentLocation.x && previousLocation.y === currentLocation.y;

            previousLocation = currentLocation;

            return hasStopped;
        }, 3000);
    }

Usage:

waitForElementAnimationToFinish(".modal");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment