1

I have a button: when I click on it, it sends an ajax request and after, the javascript code adds the class "hide" to this button when it is finished.

How can I wait the end of ajax request ? After sending the click command, I think Selenium should detect when the "hide" class is added to the button but I don't know how.

Can you help me please ?

It doesn't work (I have a timeout):

driver.find_element(By.ID, "saveButton").click()
wait = WebDriverWait(driver, 20)
wait.until(driver.find_element_by_xpath("//button[@id='saveButton' and contains(@class, 'hide')]"))
Yannick Funk
  • 1,319
  • 10
  • 23
ipStack
  • 381
  • 1
  • 12
  • provide url if it's possible, to help you – Vova Mar 16 '21 at 12:43
  • you can use a proxy (browsermob provides a common one) to track the request fired. otherwise you can wait for the element to not be visible. – DMart Mar 16 '21 at 14:49

4 Answers4

2

Use expected conditions either presence_of_element_located() or visibility_of_element_located()

 wait = WebDriverWait(driver, 20)
 wait.until(EC.presence_of_element_located((By.XPATH, "//button[@id='saveButton' and contains(@class, 'hide')]")))

OR

wait = WebDriverWait(driver, 20)
wait.until(EC.visibility_of_element_located((By.XPATH, "//button[@id='saveButton' and contains(@class, 'hide')]")))

You need to import below libraries.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
KunduK
  • 32,888
  • 5
  • 17
  • 41
1

You can wait for element to NOT be visisble:

driver.find_element(By.ID, "saveButton").click()
wait = WebDriverWait(driver, 20)
wait.until(EC.invisibility_of_element_located((By.ID, "saveButton"))) 

But if you want to know more about that AJAX call you should look into using a proxy: https://stackoverflow.com/a/40628176/1387701

DMart
  • 2,401
  • 1
  • 14
  • 19
0

I don't know if there is another answer but how about waiting for this in the loop?

while True:
    time.sleep(0.25)
    try:
        #try to get button
        break
    except:
        continue

Or you can check if the button is available with the if condition.

while True:
    time.sleep(0.25)
    if button:
        break

I hope you understand what I mean. it can also have another method ...

Ahmet Bilgin
  • 154
  • 9
0

You can also try this:

wait = WebDriverWait(driver, 10)
        wait.until(lambda driver: driver.execute_script("return jQuery.active == 0"))

But, I would go with the option of waiting for the next element you want to interact with. For example, next you need to click button with some_id. So, just wait for it:

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

element = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "#some_id")))
element.click()
vitaliis
  • 4,082
  • 5
  • 18
  • 40