Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

webdriver wait for ajax request in python

Currently I am writing webdriver test for search which uses ajax for suggestions. Test works well if I add explicit wait after typing the search content and before pressing enter.

wd.find_element_by_xpath("//div[@class='searchbox']/input").send_keys("obama")
time.sleep(2)
wd.find_element_by_xpath("//div[@class='searchbox']/input").send_keys(Keys.RETURN)

but

wd.find_element_by_xpath("//div[@class='searchbox']/input").send_keys("obama")
wd.find_element_by_xpath("//div[@class='searchbox']/input").send_keys(Keys.RETURN)

fails. I am running tests on ec2 with 1 virtual cpu. I am suspecting, I pressed enter even before GET requests related to search are sent and if I press enter before suggestions, it fails.

Is there any better way that adding explicit waits?

like image 751
raju Avatar asked Jun 05 '14 07:06

raju


People also ask

How wait for AJAX call in Selenium?

Moreover, the JavaScript Executor can be used to wait for an Ajax call. The executeScript method is used to run a JavaScript command in Selenium. The waiting is done till jQuery. active command yields 0.

Which wait mechanism is used for AJAX controls?

Implicit Wait() This method tells webdriver to wait if the element is not available immediately, but this wait will be in place for the entire time the browser is open.

Does Selenium wait for page to load python?

For Python, you will have to implement Selenium Wait for page to load in order to ensure that tests are performed with the necessary WebElements in the DOM. Certain websites have some components or elements hidden, or not visible at an initial stage.

Can we handle AJAX controls using Selenium?

AJAX sends HTTP requests from the client to server and then process the server's response without reloading the entire page. To handle AJAX controls, wait commands may not work. It's just because the actual page is not going to refresh.


2 Answers

Add this method, where I ensure the API responses are back from server

def wait_for_ajax(driver):
    wait = WebDriverWait(driver, 15)
    try:
        wait.until(lambda driver: driver.execute_script('return jQuery.active') == 0)
        wait.until(lambda driver: driver.execute_script('return document.readyState') == 'complete')
    except Exception as e:
        pass
like image 75
Prashanth Sams Avatar answered Oct 02 '22 23:10

Prashanth Sams


You indeed can add an explicit wait for the presence of an element like

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0

ff = webdriver.Firefox()
ff.get("http://somedomain/url_that_delays_loading")
ff.find_element_by_xpath("//div[@class='searchbox']/input").send_keys("obama")

try:
    element = WebDriverWait(ff, 10).until(EC.presence_of_element_located((By.ID, "keywordSuggestion")))
finally:
    ff.find_element_by_xpath("//div[@class='searchbox']/input").send_keys(Keys.RETURN)
    ff.quit()

See: http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-and-implicit-waits

like image 37
Fabricator Avatar answered Oct 03 '22 00:10

Fabricator