0

I've come across an interesting problem while automating our web application using selenium webdriver. I'm waiting for page load and all the ajax call to finish but the application use JavaScript scrolling to scroll the page after page load. The problem is sometimes chrome driver miss the click since the page is scrolling. I am using static wait to solve this problem. Is there any way we can wait for the scroll event to finish before executing click?

  • Is the page auto scrolling without any user action? – Vishal Aggarwal Sep 23 '18 at 1:20
  • @V.A. yes. For example when we click on a link to open a collapsed section. The section is opened and then it is scrolled in to the view. In my cases its scrolled to top that is a pure javascript scrolling. – Senan Sep 24 '18 at 11:46
0

I did this many years ago in Java and JavaScript so it may be out-dated but I use to scroll to an element and then call a JavaScript function which I injected into the webpage to check if scrolling has stopped. AutomationJS below is the class used to inject the scrolling method first and the method scrollUntilElementIsVisible() will start scrolling and then using a explicit wait to wait for the scroll to stop.

/**
 * Scroll until element provided has stopped moving
 * @param element WebElement
 */
public void scrollUntilElementIsVisible(final WebElement element) {
    automationJS.injectAutomationObject();

    evaluateJavascript("$(arguments[0]).automation(arguments[1]);", element, "scroll");  // Start Scrolling

    waitFor(new ExpectedCondition<Boolean>() {
        public Boolean apply(WebDriver driver) {
            boolean isVisible = (Boolean) evaluateJavascript("return automation.scrollComplete;");

            return isVisible;
        }
    });
}

public class AutomationJS {

private JavascriptExecutor javascriptExecutor;

private final String js = "(function (window, $) {"
        + "    var automation = {"
        + "        container: $('html, body'),"
        + "        scroll: function () {"
        + "            var e = this,"
        + "                t = this.offset().top,"
        + "                n = this.height(),"
        + "                r = $(window).height(),"
        + "                i;"
        + "            automation.scrollComplete = false;"
        + "            if (n < r) {"
        + "                i = t - (r / 2 - n / 2)"
        + "            } else {"
        + "                i = t"
        + "            }"
        + "            automation.container.animate({"
        + "                scrollTop: i"
        + "            }, 'fast', function () {"
        + "                automation.scrollComplete = true;"
        + "            });"
        + "        },"
        + "        scrollTop: function () {"
        + "            automation.container.animate({"
        + "                scrollTop: i"
        + "            }, 'fast', function () {"
        + "                automation.scrollComplete = true;"
        + "            });"
        + "        }"
        + "    };"
        + "    $.fn.automation = function (method) {"
        + "        if (typeof automation[method] === 'function') {"
        + "            return automation[method].apply(this, Array.prototype.slice.call(arguments, 1));"
        + "        }"
        + "    };"
        + "    window.automation = automation;"
        + "})(window, jQuery);";

        public AutomationJS(WebDriver driver) {
            javascriptExecutor = (JavascriptExecutor) driver;
        }

        public void injectAutomationObject() {
            if (!automationJSExist()) {
                javascriptExecutor.executeScript(js);
            }
        }

        private boolean automationJSExist() {
            return (Boolean) javascriptExecutor.executeScript("return typeof($.fn.automation) === 'function'");
        }
    }
0

Closely analyze the DOM for detecting any state/properties change on scrolling completion. And use expected Condition to wait dynamically for that instead of static wait.

Protractor Code Example:

var EC = protractor.ExpectedConditions;
var button = $('#xyz');
var isClickable = EC.elementToBeClickable(button);

browser.get(URL);
browser.wait(isClickable, 5000); //wait for an element to become clickable
button.click();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.