Transactions - resolving "Element is not clickable at point (X, Y)" error condition

Last updated: Fri Jul 19 22:57:27 GMT 2019

When a transaction test (sporadically) reports an obscure Element <A> is not clickable at point (<X>, <Y>). Other element would receive the click: <B> error message, who are you gonna call?

Table of contents

Problem analysis

Let's start with an assumption that your transaction is properly constructed and leverages waitForCondition statements in all the appropriate places, yet still reports the following error:

Transaction test reporting the error
Transaction test reporting "Element is not clickable..." error - review the example here.

Let's display the error message in a more readable manner:

Element <A> is not clickable at point (<X>, <Y>).
Other element would receive the click: <B>.

Before delving into the details of this error, let's review what this transaction test is trying to achieve.

Transaction scenario used in this article

Our transaction here is testing a Salesforce instance. The initial steps that deal with login-related tasks are absent from the table below, as we will only be focusing on the relevant part of the transaction - the part where the error condition occurs, which is step #17. In the table below, however, some additional (earlier) steps are included as well, to provide sufficient context for understanding the issue:

Step numberDescriptionScreenshot indicating exact transaction flow
#8 - #10Wait for and click the Edit buttonTransaction flow - steps #8 - #10
#11 - #14First, wait for text Edit S-CS-0100299 to appear.
Then wait for and click the Cancel button
Transaction flow - steps #11 - #14
#15 - #17Wait for and click the Change Owner buttonTransaction flow - steps #15 - #17

The entire transaction script looks like this:

Entire transaction script

This script, despite being constructed as per recommendations for proper usage of waitForCondition steps, still produces an unexpected error at step #17. Time to investigate further.

Dissecting the error message

The error message from step #17 comprises of two parts. The first part (slightly abbreviated) says this:

Element <div ...>Change Owner</div> is not clickable at point (594, 171).

The target element is not clickable - that is... weird? We used proper waiting conditions right before this step, meaning the target element is definitely present and visible.

The second part of the error message reveals the first clue:

Other element would receive the click: <div class="slds-form-element slds-form-element_readonly slds-grow slds-hint-parent override--slds-form-element" data-aura-rendered-by="1154:0">...</div>

How can an element be visible, but when clicked on, some other element would receive the click event?

Screenshot analysis

A much clearer clue is revealed in the screenshot of the error:

Screenshot at the time of error
Screenshot of the target web page around the moment when error condition occurred

In the figure above, the Change Owner button is already visible, but only partially - the editing dialog and the semi-transparent overlay element from the previous step have not yet disappeared entirely, due to a gradual transition from fully visible to invisible. This explains how a visible element is unable to receive a click event.

Analytical conclusion

Any matching and fully or partially visible element will satisfy the selenium.isVisible() condition. An element is partially visible when it is covered by another element and the covering element is semi-transparent.

Solving the issue

Solving the issue at hand is often not an exact science, especially not for users who are not intimately familiar with the internal structure of the tested application. A certain amount of creativity and trial-and-error experimentation can be expected.

Theory

A theoretical solution that works around the Element A is not clickable at point (X, Y). Other element would receive the click: B issue is rather simple and consists of two steps:

  1. Finding the XPath locator of the element obstructing the click
  2. Making the transaction wait until the offending element is either gone or becomes invisible

The theory is simple, right? Well, determining what exactly these two steps should be might prove a bit more challenging.

Locating the offending overlay element

The basic information about the offending overlay element is already given in the second part of the error message:

Other element would receive the click: <div class="slds-form-element slds-form-element_readonly slds-grow slds-hint-parent override--slds-form-element" data-aura-rendered-by="1154:0">...</div>

There is a good chance that the following <div> element locator (created by just adjusting the content of the error message above) is what we're looking for:

//div[@class="slds-form-element slds-form-element_readonly slds-grow slds-hint-parent override--slds-form-element"]

Such element locator is a good start. However, at this point, it is often beneficial to leverage web development tools integrated into your web browser to inspect the relevant overlay elements manually.

Waiting for the overlay element to disappear

When the offending overlay element is implemented in a way that makes it completely disappear from the DOM structure before further interactions with the tested application are possible, the following transaction step will make sure the overlay element is gone before the transaction is allowed to continue:

#Step nameCommandTargetValue (timeout in ms)
17Wait for the overlay to disappearwaitForCondition!selenium.isElementPresent('<OVERLAY-LOCATOR>')10000

Notice the ! character in front of the selenium.isElementPresent in the target column above - this is a negation operator. Instead of waiting for the presence of the specified element, the command above makes the transaction wait for the absence of said element.

Waiting for the overlay element to become invisible

When the offending overlay element is constructed in a manner that makes it always be present in the DOM structure but only visible when needed, the following transaction step can provide the necessary waiting condition:

#Step nameCommandTargetValue (timeout in ms)
17Wait for the overlay to become invisiblewaitForCondition!selenium.isVisible('<OVERLAY-LOCATOR>')10000

Waiting for the overlay element to either disappear or become invisible

Yet another approach is to wait for any of the events that may happen to the offending overlay element - either to have it disappear from the DOM entirely or to wait until it becomes invisible:

#Step nameCommandTargetValue 
17Wait for the overlay to disappearwaitForCondition!selenium.isElementPresent('<OVERLAY-LOCATOR>') || !selenium.isVisible('<OVERLAY-LOCATOR>')10000

Using sleep

Potentially 100% successful yet a rather rudimentary approach to solving the issue at hand is to simply make the transaction stall for a fixed amount of time. This can be achieved using the sleep command like this:

#Step nameCommandTargetValue (sleep in milliseconds)
17Sleepsleep 2000

The sleep command can certainly make the transaction wait long enough for the offending overlay element to disappear. The downside is the fixed amount of time your transaction will spend doing nothing. While the transaction itself is not doing anything during sleep, the induced delay does contribute to either Enterprise Agent utilization or Cloud Agent unit consumption (or both). Additionally, such an artificial delay makes the transaction time metric less precise.

Other approaches

The approaches above are not the only available and be-all-end-all solutions. Because there are many ways of manipulating DOM content to create overlay elements, there are many methods for finding them and waiting for their disappearance. As stated in the initial paragraph of this section, a certain level of creativity can be expected.

Making our example work

While working on the example used in this guide, three iterations had to be performed and each revealed a new element that needed to be waited out. Eventually, the right waitForCondition step was constructed and the transaction has been running smoothly ever since:

Successfully-completing and stable transaction
Stable and successfully-completing transaction in the end. Review the working example here.

In our case, the step that successfully made the transaction stall until the overlay element disappears was this one:

#Step nameCommandTargetValue (timeout in ms)
17Wait for the overlay to disappearwaitForCondition!selenium.isElementPresent('//div[@class="slds-form-element slds-form-element_readonly slds-grow slds-hint-parent override--slds-form-element"]')10000

Related information

The following resources provide further information on related subjects: