强制Selenium等待AngularJS

6

我该如何强制使用python Selenium等待一秒钟,直到AngularJS完成页面解析并加载它所需的某些内容。

或者,我该如何强制Selenium在单击按钮后等待1秒钟,该按钮会导致由AngularJS处理的向服务器发出的ajax请求。在导航到其他页面之前,我需要服务器端操作发生。

3个回答

4
如果您的应用程序中有一些异步行为非常重要,以至于真正的用户需要等待它完成,那么您应该告诉他们。同样,您的脚本可以在继续之前等待相同的指示。
例如,如果用户单击按钮触发API调用以创建记录,并且用户需要等待该记录被创建,则应显示指示何时成功完成的消息,例如“记录已成功创建”。然后,您的脚本可以等待相同的文本出现,就像用户一样。
重要的是,您的应用程序实现方式不应该有影响。重要的是您的用户可以使用您的应用程序,而不是调用某些AngularJS API或React API等等。
1. 使用Selenium
Selenium包括WebDriverWait和expected_conditions模块,以帮助您等待特定条件得到满足:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

TIMEOUT = 5

# ...

WebDriverWait(driver, TIMEOUT).until(
    EC.text_to_be_present_in_element(
        [By.CLASS_NAME, "alert"],
        "Record created successfully"))

2. 使用 Capybara(使用 Selenium)

如上所述,裸的 Selenium 很复杂而且很棘手。capybara-py 将其大部分抽象化了:

from capybara.dsl import page

# ...

page.assert_text("Record created successfully")

3

通过Selenium访问AngularJS作用域 - 很可能状态已经保存在Scope / IsolatedScope中。

我构建了一些扩展来帮助解决这个问题,可以转换为Python。

webDriver.NgWaitFor(productDiv, "scope.Data.Id != 0");
webDriver.NgWaitFor(partialElement, "scope.IsBusyLoadingTemplate == false");

https://github.com/leblancmeneses/RobustHaven.IntegrationTests/blob/master/NgExtensions/NgWebDriverExtensions.cs

当您同时使用AngularJS $http和jQuery处理ajax请求时,可以使用以下方法:

webDriver.WaitFor("window.isBrowserBusy() == false");

需要你在AngularJS和jQuery中设置拦截器来管理XHR请求的计数。

以下是我们项目中使用的框架:(您可能需要从中提取更多内容)

https://github.com/leblancmeneses/RobustHaven.IntegrationTests


2
我遇到了同样的问题,这是我解决问题的方法。
from datetime import datetime, timedelta
from time import sleep

from selenium import webdriver
from selenium.common.exceptions import WebDriverException


class MyDriver(webdriver.Chrome):
    def __init__(self, executable_path="chromedriver", port=0,
                 chrome_options=None, service_args=None,
                 desired_capabilities=None, service_log_path=None):
        super().__init__(executable_path, port, chrome_options, service_args,
                         desired_capabilities, service_log_path)

    def wait_until_angular(self, seconds: int = 10) -> None:
        java_script_to_load_angular = "var injector = window.angular.element('body').injector(); " \
                                      "var $http = injector.get('$http');" \
                                      "return ($http.pendingRequests.length === 0);"
        end_time = datetime.utcnow() + timedelta(seconds=seconds)
        print("wait for Angular Elements....")
        while datetime.utcnow() < end_time:
            try:
                if self.execute_script(java_script_to_load_angular):
                    return
            except WebDriverException:
                continue
            sleep(1)
        raise TimeoutError("waiting for angular elements for too long")

这对我很有用 希望能帮到你!!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接