【问题标题】:Wait for multiple elements to be visible in selenium webdriver JavaScript bindings等待多个元素在 selenium webdriver JavaScript 绑定中可见
【发布时间】:2016-06-09 01:54:11
【问题描述】:

JavaScript 的 selenium webdriver 绑定允许通过组合两个等待命令来等待元素可见,如下例所示:

const timeout = 1000;
const locator = webdriver.By.id('test');
driver.wait(webdriver.until.elementLocated(locator, timeout).then(function() {
   that.findElement(locator).then(function(element) {
      driver.wait(webdriver.until.elementIsVisible(element), timeout).then(function() {
         // element is visible!
      });
   });
});

当我们需要等待一组元素一起可见时,是否有更简单的方法以及如何做到这一点?

【问题讨论】:

    标签: javascript node.js selenium selenium-webdriver webdriver


    【解决方案1】:

    Promises 的一大优点是您可以保持异步代码线性而不是嵌套(来自延续传递风格的回调地狱)。

    Promise 为您提供 return 语句和错误抛出,而您会因延续传递风格而失去这些。

    在您的情况下,您需要从您的承诺返回函数中返回承诺,以便您可以链接您的承诺。

    示例:Promise.all 接受一个 promise 数组,并在所有 promise 解析后解析,如果有任何一个被拒绝,则该数组被拒绝。

    this.waitForElementsToBecomeVisible = function() {
        return Promise.all([
            driver.wait(webdriver.until.elementIsVisible(usernameTextField), 500),
            driver.wait(webdriver.until.elementIsVisible(firstNameTextField), 500),
            driver.wait(webdriver.until.elementIsVisible(lastNameTextField), 500),
            driver.wait(webdriver.until.elementIsVisible(createEmployeeButton), 500)
        ]);
    }
    

    然后你可以链接你的承诺。

    driver.get('https://website.com/login').then(function () {
        loginPage = new LoginPage(driver);
        return loginPage.login('company.admin', 'password')
    }).then(function () {
        employeePage = new EmployeePage(driver);
        return employeePage.clickAddEmployee()
    }).then(function () {
        addEmployeeForm = new AddEmployeeForm(driver);
       /**
        *
        * Wait for elements to become visible
        */
        return addEmployeeForm.waitForElementsToBecomeVisible();
    }).then(function() {
        return addEmployeeForm.completeForm(employee);
    }).then(function() {
        return addEmployeeForm.clickCreateEmployee();
    }).then(function() {
        return employeePage.searchEmployee(employee);
    });
    

    您可以看到上面的示例没有嵌套并且更易于维护。您返回一个承诺并继续链接而不是嵌套。我希望这对您有所帮助,并且不会让您感到困惑。

    【讨论】:

    • 感谢您的反馈!我完全同意您的建议,即等待多个 Promise 解决并链式 Promise 而不是嵌套它们。在我的示例中,当存在依赖项时,我专门寻找最佳解决方案(我需要首先等待元素被定位,并且只有当承诺返回元素检查它的可见性时)并且另外一次对多个元素执行此操作.另外我想知道,是否允许在使用它自己的自定义承诺的 selenium webdriver 环境中使用 es2015 风格的承诺?
    • 我在使用 es2015 功能方面还没有遇到任何问题。你可以使用 new Promise(promise);在 selenium-webdriver 中。
    • 如果您查看 selenium-webdriver node_module 并查看 lib 文件夹中的一些 javascript 文件,您会看到 es2015 语法。
    • 当 promise 返回时,您可以通过执行 .then(function(elements) { //access such as elements[0] }); 获得结果如果你需要一个例子,我明天会更新我的答案。
    【解决方案2】:

    简单 - 编写一个通用/全局函数。如果需要改变它,可以将单个或多个 Webdriver 元素作为输入和条件。循环直到元素结束并执行相同的操作 等待每个元素可见。

    这就是我在我的职能中经常这样做的方式。在 Ruby 中我会这样做

    for each element in [array of elements], Condition
       [Below is same as your code if working well]
       Driver - Element wait until (Condition satisfied)
       element perform function
    end
    

    如果您甚至需要处理多个条件,则可以使用 switch case 语句。 如果您只需要执行一次功能,请将功能保留在外面

    element perform function
    

    【讨论】:

    • 感谢您的反馈,但我真的不明白这如何转化为 nodejs 中的异步执行模型?等待元素不会停止程序执行,而只会返回一个承诺。我最感兴趣的是看看这是如何在 nodejs 环境中正确完成的。
    • 你到底想异步做什么。您没有测试您的应用程序吗?我想说的是,很难想象用户使用 Web UI 会同时做一些事情。
    • 我想说的是,当使用 JavaScript 绑定时,没有什么可以阻止程序执行,而是必须使用级联承诺解决方案来完成所有事情。
    • 我假设您正在测试而不是开发。如果是这样,我的建议是保持简单,编写一个函数来验证元素和属性,并在有限的时间内保持循环,直到属性良好。对数组重复。这将有助于其他人理解/增加测试的可读性。如果您不进行测试,请修改您的问题。
    猜你喜欢
    • 1970-01-01
    • 2017-08-07
    • 2015-11-30
    • 1970-01-01
    • 2017-08-14
    • 2019-10-21
    • 2018-09-18
    • 2016-12-25
    • 2013-08-06
    相关资源
    最近更新 更多