Selenium - after bootstrap modal test, subsequent test fail with error ElementClickInterceptedError Selenium - after bootstrap modal test, subsequent test fail with error ElementClickInterceptedError selenium selenium

Selenium - after bootstrap modal test, subsequent test fail with error ElementClickInterceptedError


You don't need to use the implicitwait everytime. What you need to wait for is the visibility of the elements before doing the click operations.

There is a elementIsVisible method available in the wait condition. I've modified the code to check for the presence of the element and then the visibility of the element before doing the click.

(async function uitest() {    let driver = await new Builder().forBrowser('chrome').build();    let element    try {        await driver.get(fileName)        //Launch Modal 1 and close        await driver.findElement(By.id('launchModalButton')).click()        let closeButton1 = await driver.wait(until.elementLocated(By.id('closeButton')))        closeButton1 = await driver.wait(until.elementIsVisible(closeButton1))        await closeButton1.click()        // middle button click         await driver.findElement(By.id('button')).click()        //Launch Modal 2 and close        await driver.findElement(By.id('launchModalButton_2')).click()        let closeButton2 = await driver.wait(until.elementLocated(By.id('closeButton_2')))        closeButton2 = await driver.wait(until.elementIsVisible(closeButton2))        await closeButton2.click()    } catch (err) {        console.log(err)    } finally {        await driver.quit();    }})()


This error message...

[13108:12832:0501/100716.495:ERROR:browser_switcher_service.cc(238)] XXX Init() ElementClickInterceptedError: element click intercepted: Element ... is not clickable at po int (233, 67). Other element would receive the click: ... (Session info: chrome=81.0.4044.129)

...implies that the desired element wasn't clickable when you invoked click() on it.


As you mentioned test which launch a modal and close it, will pass, but subsequent test fails with ElementClickInterceptedError essentially means that when you invoked click() on the second element Button at that point of time the Modal Dialog Box containing the element with text as Launch modal was still obsecuring the desired element. Hence the click on the desired element failed.

Details

To start with implicit wait may not be effective with modern application built using JavaScript, Angular, ReactJS, jQuery, AJAX, Vue.js, Ember.js, etc.

Effectively you need to replace implicit wait with explicit wait.


selenium-webdriver/lib/until

  • elementLocated: Creates a condition that will loop until an element is found with the given locator.

    /** * Creates a condition that will loop until an element is * {@link ./webdriver.WebDriver#findElement found} with the given locator. * * @param {!(By|Function)} locator The locator to use. * @return {!WebElementCondition} The new condition. */exports.elementLocated = function elementLocated(locator) {  locator = by.checkedLocator(locator);  let locatorStr =      typeof locator === 'function' ? 'by function()' : locator + '';  return new WebElementCondition('for element to be located ' + locatorStr,      function(driver) {    return driver.findElements(locator).then(function(elements) {      return elements[0];    });      });};
  • elementIsVisible: Creates a condition that will wait for the given element to become visible.

    /** * Creates a condition that will wait for the given element to become visible. * * @param {!./webdriver.WebElement} element The element to test. * @return {!WebElementCondition} The new condition. * @see ./webdriver.WebDriver#isDisplayed */exports.elementIsVisible = function elementIsVisible(element) {  return new WebElementCondition('until element is visible', function() {    return element.isDisplayed().then(v => v ? element : null);  });};

Solution

So your effective code block replacing implicit wait with explicit wait will be:

(async function uitest() {    let driver = await new Builder().forBrowser('chrome').build();    let  element    try {        await driver.get(fileName)        //Click Launch Modal        let launchModal = await driver.wait(until.elementLocated(By.id('launchModalButton')))        launchModal = await driver.wait(until.elementIsVisible(launchModal))        await launchModal.click()        //Close Launch Modal        let closeModal = await driver.wait(until.elementLocated(By.id('closeButton')))        closeModal = await driver.wait(until.elementIsVisible(closeModal))        await closeModal.click()        //Click Button        let button = await driver.wait(until.elementLocated(By.id('button')))        button = await driver.wait(until.elementIsVisible(button))        await button.click()        //Click Launch Modal 2 and close        let launchModal2 = await driver.wait(until.elementLocated(By.id('launchModalButton_2')))        launchModal2 = await driver.wait(until.elementIsVisible(launchModal2))        await launchModal2.click()        //Close Launch Modal 2        let closeButton2 = await driver.wait(until.elementLocated(By.id('closeButton_2')))        closeButton2 = await driver.wait(until.elementIsVisible(closeButton2))        await closeButton2.click()              } catch (err) {        console.log(err)    } finally {        await driver.quit();    }    })()

References

You can find a couple of related discussions in:


To bypass ElementNotClickable (this is web-driver logic), you can just use JavaScript click.

var element = await driver.findElement(By.id('button'))driver.executeScript('arguments[0].click();', element)