1

I am trying to do web automation. I am defining a pop-up menu containing a button defined with either xpath or css respectively as

  • XPath:-->: //button[contains(text(), 'Open Door')

  • CSS:-->: div.device-item.content.view-content > div.detail > div > button.btn.btn-primary.ng-star-inserted

While all is well, it throws

org.openqa.selenium.ElementClickInterceptedException: element click intercepted:

when I am debugging the test one step at a time, it runs successfully by clicking the button, with out any problem. But when I am running the test, it fails. I hope it is not a wait issue, as we apply check waiting for the presence of the button and verify it exists and clickable.

I believe many would advice to use JavaScriptExecutor approach, but our framework has a problem of returning any web element as a custom object called "Element" which is neither Web Element nor sub class of it, but extends Object and implements an interface called IElement, so we can't use JavaScriptExecutor method since it needs Web Element form of the button which we want to click on.

Guy
  • 46,488
  • 10
  • 44
  • 88
PraNuta
  • 629
  • 3
  • 12
  • 33
  • You can just pass the xpath / css to JavaScriptExecutor and select it in js. – pguardiario Nov 11 '19 at 03:05
  • @pguardiario Is there an example you can suggest ? I checked the JavaScriptExecutor page at https://selenium.dev/selenium/docs/api/java/index.html but could not find any method which takes the xpath or css. – PraNuta Nov 11 '19 at 03:37
  • which language selenium library you are using for your script development? (so that we can provide the sample JS executor) and do you have multiple tabs with Open Door button by any change in your application? – supputuri Nov 11 '19 at 04:18
  • Are you running this on internet explorer browser? – Pankaj Devrani Nov 11 '19 at 06:21
  • I am running on Chrome browser. I am using Java bindings. No other tabs with 'Open Door' button. Just one tab and only one DDO door entitty, which when clicked will open a menu having 'Open Door' and 'Details' menu items in it. – PraNuta Nov 11 '19 at 15:21
  • this means that another object will retrieve the click. (meaning it will process the click event first...) Click that object (id="device-card-6712"). What happens at that point? – pcalkins Nov 11 '19 at 21:16

5 Answers5

2

If it works in debug it means the overlay disappear automatically. You can wait for it to vanish

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("[id^='device-card']")));

And in any case you can wait for the button to be clickable

button = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//button[contains(text(), 'Open Door')")));
button.click();
Guy
  • 46,488
  • 10
  • 44
  • 88
  • I tried this approach, it still did threw me the same error. org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element is not clickable at point (487, 656). Other element would receive the click:
    ...
    (Session info: chrome=78.0.3904.87) Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03' I gave a waiting period of 50 sec.
    – PraNuta Nov 11 '19 at 20:00
  • ``` private void buttonClick(String action){ WebDriverWait wait = new WebDriverWait(WebDriverSingleton.getWebDriver(), 50); if(action.equalsIgnoreCase("OPEN")) { wait.until(ExpectedConditions.elementToBeClickable(By.xpath(OPEN_DOOR_XPATH))); openDoorBtn.click(); }else if(action.equalsIgnoreCase("CLOSE")) { wait.until(ExpectedConditions.elementToBeClickable(By.xpath(CLOSE_DOOR_XPATH))); closeDoorBtn.click(); } } ``` – PraNuta Nov 11 '19 at 20:14
  • @PraNuta Did you try waiting for the the other element to disappear? you should also click the element returned from `wait.until`, see updated answer. – Guy Nov 12 '19 at 08:40
  • Let me try this more carefully tomorrow. – PraNuta Nov 13 '19 at 04:05
0

It will look something like:

driver.executeScript("document.querySelector('button.btn').click()")

Just adjust the css

pguardiario
  • 53,827
  • 19
  • 119
  • 159
0

There are a couple of things you need to take care:

  • XPath //button[contains(text(), 'Open Door'): This xpath can be optimized further in either of the formats:
    • //button[text()='Open Door']
    • //button[contains(., 'Open Door')]
  • CSS: div.device-item.content.view-content > div.detail > div > button.btn.btn-primary.ng-star-inserted looks good however I strongly believe button.btn.btn-primary.ng-star-inserted would also work.
  • "...Executes successfully in debug mode...": As the browser client gets ample time to settle the webpage dynamics and the desired WebElement gets enough time to get interactive.
  • "...we amply check waiting for the presence of the button and verify it exists and clickable...": Is a myth as:
    • presenceOfElementLocated(): Is the expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
  • where as:
    • elementToBeClickable(): Is the expectation for checking an element is visible and enabled such that you can click it.
  • As your usecase is to invoke click() on the element you need to use the ExpectedConditions as elementToBeClickable().
  • Example:

    new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("css_element"))).click();
    

You can find a detailed discussion in What is the most efficient way to wait for a page element (xpath) to show up in Selenium Webdriver?


Update

As you are still seeing the error ...ElementClickInterceptedException: element click intercepted..., you can add an additional step to induce WebDriverWait for the invisibility and you can use either of the following options:

  • invisibilityOf(WebElement element):

    new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOf(overlapping_webelement));
    new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("css_clickable_element"))).click();
    
  • invisibilityOfElementLocated(By locator):

    new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("css_overlapping_element")));
    new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("css_clickable_element"))).click();
    

You can find a relevant detailed discussion in Selenium invisibilityOf(element) method throwing NoSuchElementException + WebDriverWait.ignoring(NoSuchElementException.class) is not working

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thanks for great explanation. Couple of things. The element is visible and clickable too. As I print out to the console. I am able to printout it's button text. ```OpenDoor Button is present=true; OpenDoor Button Text-Open Door ``` Only problem is **ElementClickInterceptedException: element click intercepted**. How to overcome that "click intercepted" problem. – PraNuta Nov 11 '19 at 20:45
  • Updated the answer. Please let me know the status. – undetected Selenium Nov 12 '19 at 07:48
  • Sure. Will try and let you know DebanjanB – PraNuta Nov 13 '19 at 04:13
  • From the exception stack trace... ```org.openqa.selenium.ElementClickInterceptedException: element click intercepted: Element
    ...
    is not clickable at point (487, 623). Other element would receive the click:
    ...
    ``` I thought the last (**div.group-btn-container**)is overlapping element which a container.
    – PraNuta Nov 13 '19 at 04:30
  • **Then I used...** ```new WebDriverWait(driver, 30).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("div.group-btn-container"))); new WebDriverWait(driver, 5).until(ExpectedConditions.elementToBeClickable(By.cssSelector("div.device-item.content.view-content > div.detail > div > button.btn.btn-primary.ng-star-inserted"))).click(); closeDoorBtn.click();``` Now, I got this exception. **TimeoutException: Expected condition failed: waiting for element to no longer be visible: By.cssSelector: div.group-btn-container (tried for 30 second(s)** – PraNuta Nov 13 '19 at 04:35
  • @PraNuta In the first error stack trace you are seeing `
    ...
    is not clickable` but within second error stack trace there are two back to back clicks, one on `By.cssSelector("div.device-item.content.view-content > div.detail > div > button.btn.btn-primary.ng-star-inserted")` and the next on `closeDoorBtn`. Possibly your locators are a bit off.
    – undetected Selenium Nov 13 '19 at 06:36
  • I spoke with our Angular Developer. We identified that – PraNuta Nov 13 '19 at 16:57
  • I spoke with our Angular Developer. We identified that -- When the Device area is not clicked yet, the xpath/css locator for the 'Open/Close Door' button is identifying the bottom located div Container element. -- When the Device area is clicked, and when you see 'Open/Close Door' button is visible, the xpath/css locator is correctly identifying them, instead of the bottom div Container element. -- So during the Run mode instead of Debug mode testing the div Container is receiving the click instead of the button. -- This was the problem.The Developer is going to find a solution for this. – PraNuta Nov 13 '19 at 17:03
  • @PraNuta Well, if you can share the actual webpage I think we can make it work now as well :) – undetected Selenium Nov 13 '19 at 18:16
0
  1. you can move the mouse to that element and then click on it, even I was facing this issue and this solution solved it

    Actions clickOnBtn = new Actions(driver);
    clickOnBtn .moveToElement("//button[contains(text(), 'Open Door')").click().build().perform;
    
  2. this happens even when the element is not visible completely onscreen, in this case you can scroll to that element and then use the above code as shown below

    JavascriptExecutor jse2 = (JavascriptExecutor)driver;
    jse2.executeScript("arguments[0].scrollIntoView()", ele); 
    Actions clickOnBtn = new Actions(driver);
    clickOnBtn .moveToElement("//button[contains(text(), 'Open Door')").click().build().perform;
    
  3. click element using javascriptExecutor

    JavascriptExecutor executor = (JavascriptExecutor)driver;
    executor.executeScript("arguments[0].click();", ele);
    
  4. This even happens sometimes with the way we selected the element, the xpath can be changed, we can try to use a parent tag rather than the button and try

Suhail Ahmed
  • 504
  • 1
  • 9
  • 19
  • Suhail; I tried this approach also. Same result. When I run step by step via debug option, it works, but when I run straight, it throws the same exception **org.openqa.selenium.ElementClickInterceptedException: element click intercepted:** – PraNuta Nov 12 '19 at 04:54
  • I have updated my answer with 2 more solutions can you have a look into it and check, this happens even when the element is not visible completely onscreen, in this case you can scroll to that element and the click on that element, else can you try once click on element using javascriptexecutor – Suhail Ahmed Nov 13 '19 at 09:22
  • This even happens sometimes with the way we selected the element, the xpath can be changed, we can try to use a parent tag rather than the button and try – Suhail Ahmed Nov 13 '19 at 10:08
0

you can define your own ExpectedCondition with click action:

public class SuccessfulClick implements ExpectedCondition<Boolean> {
    private WebElement element;

    public SuccessfulClick(WebElement element) { //WebElement element
        this.element = element;
    }

    @Override
    public Boolean apply(WebDriver driver) {
        try {
            element.click();
            return true;
        } catch (ElementClickInterceptedException | StaleElementReferenceException | NoSuchElementException e) {
            return false;
        }
    }
}

and then use it:

wait10.until(elementToBeClickable(btn));
wait10.until(new SuccessfulClick(btn));
Adam Silenko
  • 3,025
  • 1
  • 14
  • 30