Search code examples
pythonangularseleniumpaypal-sandboxwebdriverwait

Explicit waits doesn't work on PayPal sandbox which based on Angular


I have a problem with the automation of PayPal sandbox by Selenium Python. Generally, I wrote explicit waits for each action method like send_keys(), or click() into the button, but they just don't work. I tried almost all explicit waits that are available.

I tried to adapt method which will be waiting until Angular script will be fully loaded, but it totally doesn't work because of this app based on Angular v.1., by executing javascript. For example:

while self.context.browser.execute_script(
"return angular.element(document).injector().get('$http').pendingRequests.length === 0"):
             sleep(0.5)

The only method which works are static python sleep, which is totally inappropriate! But when I add 2 seconds of sleep between every first action on the page, the test passing without any problems, while I trying to replace sleep by for example WebDriverWait(self.context.browser, timeout=15).until(EC.visibility_of_all_elements_located) , the test stop when all elements are visible on the page. Can someone handle this? My code witch sleeps between each page objects:

context.pages.base_page.asert_if_url_contain_text("sandbox.paypal.com")
context.pages.paypal_login_page.login_to_pp_as(**testPP)
sleep(2)
context.pages.choose_payment_page.pp_payment_method("paypal")
sleep(2)
context.pages.pay_now_page.click_pay_now()
sleep(2)
context.pages.finish_payment_page.click_return_to_seller()
sleep(5)
context.pages.base_page.open()

Example method witch explicit wait:

def click_pay_now(self):
    WebDriverWait(self.context.browser, timeout=15).until(EC.visibility_of_all_elements_located)
    self.pay_now_button.is_element_visible()
    self.pay_now_button.click()

Solution

  • visibility_of_all_elements_located() will return a list, instead you need to use visibility_of_element_located() which will return a WebElement.

    Ideally, if your usecase is to invoke click() then you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:

    • Using CSS_SELECTOR:

      WebDriverWait(self.context.browser, timeout=15).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "element_css"))).click()
      
    • Using XPATH:

      WebDriverWait(self.context.browser, timeout=15).until(EC.element_to_be_clickable((By.XPATH, "element_xpath"))).click()
      
    • 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
      

    Reference

    You can find a relevant detailed discussion in: