'How to detect a button.click() failure in Selenium?

I have a Selenium 3 Python script that is used to file FTC complaints for nuisance calls. Today a miscreant got through using the number "0" (literal 0). The FTC website rejected the number but my script failed to detect the failure.

Here is the relevant portion of my Python script that drives the complaint process. Here is a pastebin of the FTC page that is rejecting the number. According to the Selenium docs there is no return value from button_continue.click() (if I am parsing the docs correctly; see around the heading User Input - Filling In Forms).

# print("Clicking Continue")
button_continue = driver.find_element_by_id("StepTwoSubmitButton")
button_continue.click()

I also purchased the book Test-Driven Development with Python, but the Selenium hits I found when searching online turned out to be two pages in the book. (It was very disappointing; not recommended for this type of task, despite the title of the book).

My question is, how do I detect the failures using Selenium 3?


Here is the specific Javascript for the FTC page causing the trouble. It is from the pastebin:

<div class="s_form_verif_bttn_sl">
    <label for="StepTwoSubmitButton">
        <input type="submit" name="StepTwoSubmitButton" value="Submit" onclick="validateform();WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;StepTwoSubmitButton&quot;, &quot;&quot;, true, &quot;StepTwoEntry&quot;, &quot;&quot;, false, false))" id="StepTwoSubmitButton" accesskey="s" tabindex="17" class="th_s" />
    </label>&nbsp;&nbsp;
    <label for="StepTwoCancelButton"> 
        <input type="submit" name="StepTwoCancelButton" value="Cancel" id="StepTwoCancelButton" accesskey="s" tabindex="18" class="th_s" />
    </label>
</div>

I was able to reproduce the submit failure manually. Below is a screen capture of the result of submitting the form. When I watched the process in Developer Console I did not see anything out of the ordinary, like an uncaught exception.

enter image description here


Here are package versions.

$ apt-cache policy chromium-browser
chromium-browser:
  Installed: 73.0.3683.86-0ubuntu0.18.04.1
  Candidate: 73.0.3683.86-0ubuntu0.18.04.1

$ apt-cache policy python3-selenium
python3-selenium:
  Installed: 3.8.0+dfsg1-3
  Candidate: 3.8.0+dfsg1-3

$ apt-cache policy chromium-chromedriver
chromium-chromedriver:
  Installed: 73.0.3683.86-0ubuntu0.18.04.1
  Candidate: 73.0.3683.86-0ubuntu0.18.04.1

$ apt-cache policy python3
python3:
  Installed: 3.6.7-1~18.04
  Candidate: 3.6.7-1~18.04


Solution 1:[1]

click() should raise an exception if it fails, and all exceptions in the Python client bindings are derived from WebDriverException.

from selenium.common.exceptions import WebDriverException

button_continue = driver.find_element_by_id("StepTwoSubmitButton")
try:
    button_continue.click()
except WebDriverException as e:
    print('oops. click failed')
    print(e)

Solution 2:[2]

The element is a JavaScript enabled element, so invoke click() on it ideally you need to induce WebDriverWait for the element_to_be_clickable() and wrap it in a try-catch{} and you can use either of the Locator Strategies:

  • Using CSS_SELECTOR:

    try:
        WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[name='StepTwoSubmitButton']"))).click()
    except TimeoutException as e:
        print("Element click failed")
    
  • Using XPATH:

    try:
        WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@name='StepTwoSubmitButton')]"))).click()
    except TimeoutException as e:
        print("Element click failed")
    
  • Note : You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.common.exceptions import TimeoutException
    

Solution 3:[3]

First wait for the WebDriver to think the element is clickable. Doesn't seem to hurt to just always do this when attempting to click. Then attempt to click the element, and hook the exception if it doesn't click. In the exception action, push a new-line directly at the submit button.

Disclaimer: I'm a C programmer, this is my first time using Selenium, and I rarely mess with Python. However this fixed the issue for me.

#You'll need these dependencies:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import WebDriverException

# This code assumes you've already located your element and named it: "element"
#
    wait = WebDriverWait(driver, 10)
    wc_element = wait.until(EC.element_to_be_clickable(element))
    try: # If at first you can't click()...
        wc_element.click()
    except WebDriverException as e: # Hook the exception and send a newline instead.
        wc_element.send_keys('\n')

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 undetected Selenium
Solution 3 Matt Zweil