How to create custom ExpectedCondition to check whether an element within web viewport & not obstructed by other elements.

Dennis Sandjaya
Blibli.com Tech Blog
4 min readDec 7, 2020

Hello, if you come to here chances are that you are having a problem with your web automation, where you want to check whether your element is display on the browser viewport and that element is not obstructed by other elements, and that it is not checkable using the usual provided ExpectedCondition which is provided by Selenium. Let’s illustrate and talk a little bit about this problem..

Illustration of an element in a web page that might not be within the viewport or is obstructed by other elements.

So in the simple illustration above you could see that our element (Light Blue) is already present on the web page (Green), but it is not currently appear on the web viewport (Yellow), which display what is currently shown on the browser and even if it’s shown within the viewport, there are also chances that after we scroll the Banner/Other Element (Dark Blue) might be on top of the element and obstructing our element.

If we try to perform a click action on that element when it’s not on appear on the viewport or being obstruct by the banner. The Selenium might throw an ElementClickInterceptedException error

ElementClickInterceptedException error

And when we do a scroll to that element, there are 50/50 chance that ElementClickInterceptedException error will still be thrown, because when your run your code and the click is after the scroll action. The scroll might still be executing and the click action want to immediately executed, this too could produce the same error, because the element might have not yet shown completely.

The solution is to wait for the element to completely appear on the viewport without being obstructed, the fastest one is to use something like Thread.sleep() to wait for the scroll to finish. This could solve it, but it might not be good enough, since you might not know the exact time when the scroll is finish and couldn’t check whether the element have appear as expected. If you used Selenium or Serenity framework, even though there is an option of using wait.until() or waitFor() where you could an ExpectedCondition of what to be wait in there.

The only problem is that if you put the following ExpectedConditions visibilityOf, presenceOfElementLocated, or elementToBeClickable all of this will return true even though the element might not completely shown on the viewport, this is because the element already exist on the web page.

The solution is to check the condition of the element via JavaScript there are 2 condition that need to be check, first whether the element on the viewport and second it’s not obstructed by other elements.

If you are already familiar with Javascript, you might have heard a function called

element.getBoundingClientRect()

The method element.getBoundingClientRect() provides the element’s position and its relative position to the viewport.

So now with JS function, we could get the element position and check whether it’s within the viewport or not

What this function do, it will check whether the element within the boundaries of the viewport or not based on the position of the element compare with the boundaries of the viewport, if it’s within it will return true else return false. We return the Boolean and wrap it again as ExpectedCondition, so that we can use this function on the Selenium wait.until() or Serenity waitFor().

Now for our other condition, we will used a function called

document.elementFromPoint(param x, param y);

This function will returns the topmost Element at the specified coordinates (relative to the viewport).

Now if we put this in our code it will looks like this

First using the getBoundingClientRect() we will get the position and calculate the center of the element position to get the coordinate, then we use the elementFromPoint() to get topmost element and also we check with a loop. First the element directly return by the elementFromPoint() function then it’s parent to see whether it’s match our element or not.

Finally after both function is created we could use the functions on our Selenium wait.until() or Serenity waitFor()

Actions actions = new Actions(getDriver());

try {
actions.moveToElement(myButton).perform();
} catch (MoveTargetOutOfBoundsException e) {

}

waitFor(ExpectedConditionUtils.isVisibleInViewport(myButton));
waitFor(ExpectedConditionUtils.isNotObstructed(myButton));

myButton.click();

So after we scroll to the element, we could wait for both condition to be fulfilled before we actually trigger the click action on the element.

This way we could prevent the element to be click before it’s completely appear and prevent the ElementClickInterceptedException error to be thrown.

Lastly we could also combine both condition, here is the full class containing all of the functions.

Thanks for reading, hope this could help with your automation!

I also wanna thanks the original JavaScript explanation, references and original thread for the code:

--

--

Dennis Sandjaya
Blibli.com Tech Blog

Just a passing QA engineer who interest in code and test