【问题标题】:AngularJS testing with Protractor - chaining promises- How to wait for animation to complete?AngularJS 使用 Protractor 进行测试 - 链接承诺 - 如何等待动画完成?
【发布时间】:2018-04-20 00:53:09
【问题描述】:

我目前正在为我公司开发的 AngularJS 应用程序开发一个自动化测试套件。我已经设计和开发了许多测试用例,它们按预期运行&通过/失败。

但是,对于我目前正在开发的测试,我似乎在链接 Promise 时遇到了问题,并且无法解决它......目前的测试脚本是:

it('should navigate to the browser page', function() {
    console.log("Start browser page test");
    browser.waitForAngularEnabled(false);
    browser.wait(EC.visibilityOf(pagesMenuBtn), 10000).then(
        browser.actions().mouseMove(pagesMenuBtn).perform().then(
            //expect(pageBrowserBtn.isDisplayed()).toBeTruthy();
            browser.wait(EC.visibilityOf(pageBrowserBtn), 12000).then(
                pageBrowserBtn.click().then(
                    function() {
                        console.log("Browser menu button clicked");
                        //browser.pause();
                    }).then(
                        browser.wait(EC.visibilityOf(browserPageTagsLink), 20000).then(
                            function(){
                                console.log("End browser page test (then call)");
                                expect(browser.getCurrentUrl()).toBe(VM + '/#/pages/browser');
                            }
                        )
                    )
                )
            )
    );
});

当我运行我的测试脚本时(我有许多其他测试在此之前运行),前几个运行并成功通过,然后当这个测试开始执行时,控制台显示:

开始

....开始浏览器页面测试

点击浏览器菜单按钮

F

失败:

1) 应用应该导航到浏览器页面

消息:

失败:20010 毫秒后等待超时

堆栈:

TimeoutError: 20010ms 后等待超时 在 WebDriverError (C:\Users\path\selenium-webdriver\lib\error.js:27:5)

所以从控制台显示的输出来看,很明显测试执行正确,直到console.log("Browser menu button clicked);语句,这表明在菜单按钮上执行了我想要的点击(即点击的菜单按钮是显示在仅当光标悬停在 pagesMenuBtn 元素上时才会显示的弹出菜单上,因此表示该行

browser.wait(EC.visibilityOf(pageBrowserBtn), 12000).then(

正确执行)。

由于console.log("Browser menu button clicked");语句也显示在控制台中,这表明

pageBrowserBtn.click().then(

也被正确执行了。

但由于某种原因,测试会在等待显示 browserPageTagsLink 元素的 20 秒后超时。

这个browserPageTagsLink 元素只是显示在“浏览器”页面上的一个超链接元素,我的测试试图导航到它——我正在等待它可见,以便在我检查之前知道页面已经加载网址是正确的...

但是,当我观察运行这些测试的浏览器窗口中发生的情况以及我的测试运行时控制台中显示的内容时,脚本似乎“卡住”/暂停/“挂起”一段时间后Browser menu button clicked 消息显示在控制台中,我可以从浏览器窗口中看到该按钮实际上从未被单击过 - 显示此按钮的弹出菜单非常简短地显示:browser.actions().mouseMove(pagesMenuBtn).perform() 行导致光标将鼠标悬停在显示子菜单所需的按钮上,但似乎在子菜单元素完全加载完成之前执行了单击(元素上有一些动画 - 它似乎“淡入视图”),但是我认为点击是在元素完全加载完成之前发生的,所以它可能没有正确注册?

如何让我的测试在尝试单击子菜单菜单项之前等待动画完成,以便单击正确地注册到元素?

我试着用这条线来做这个:

browser.wait(EC.visibilityOf(pageBrowserBtn), 12000).then(

似乎只要元素开始变得可见,EC.visibilityOf(...) 条件就满足了,而不是等到它完全不透明,但是

pageTagBrowserBtn.click().then(

线,一旦条件为真就被调用,此时实际上不能执行 - 大概是因为元素在单击时不是“完全”可见的?

如何让我的测试在尝试点击元素之前等待动画(已使用 CSS 实现)完成?

我在 Protractor API 上查看了有关动画的任何信息,但它似乎只提供了函数 allowAnimations()...

编辑

该元素的动画在 CSS 中设置:

/* Animation for moving lists in configuration */
.list-fade.ng-enter,
.list-fade-leave.ng-leave {
    -webkit-transition: all linear 0.5s;
    transition: all linear 0.5s;
}

即当光标悬停在其父元素上时,该元素应该需要 0.5 秒才能显示出来。

我尝试添加对browser.wait() 的调用,以便我的测试在尝试单击之前等待元素完全显示 - 我更新了发送点击到的测试部分:

browser.actions().mouseMove(pagesMenuBtn).perform().then(
    //expect(pageTagBrowserBtn.isDisplayed()).toBeTruthy();
    browser.wait(EC.visibilityOf(pageTagBrowserBtn), 12000).then(
        browser.wait(10000).then(
            pageTagBrowserBtn.click().then(
                function() {
                    console.log("Tag Browser menu button clicked");

此时我告诉它等待 10 秒,以确保它确实给了元素足够的时间来加载(根据 CSS,它应该只需要 0.5 秒即可显示),但出于某种原因,我的测试由于同样的超时问题,仍然失败。

有人有什么建议吗?

【问题讨论】:

    标签: angularjs protractor css-animations visibility wait


    【解决方案1】:

    看着你的测试,我想知道为什么你必须这样链接你的承诺。在一个完全角度的页面上,Protractor 应该自动链接承诺,即当我编写这样的测试时

    driver.get(“http://www.google.com”);
    driver.findElement(webdriver.By.name('q')).sendKeys('webdriver');
    driver.findElement(webdriver.By.name('btnG')).click();
    driver.getTitle().then(function(title) {
      console.log(title);
    });
    

    它实际上是以这样的同步方式执行的:

    driver.get(“http://www.google.com”).
    then(function() {
      return driver.findElement(webdriver.By.name('q'));
    }).
    then(function(q) {
      return q.sendKeys('webdriver');
    }).
    then(function() {
      return driver.findElement(webdriver.By.name('btnG'));
    }).
    then(function(btnG) {
      return btnG.click();
    }).
    then(function() {
      return driver.getTitle();
    }).
    then(function(title) {
      console.log(title);
    });
    

    如果您的页面完全是 Angular 的,那么您编写的大部分内容都不需要 promise,并且我会导致您的测试出现时间问题。您是否尝试过在不链接承诺的情况下编写测试?

    也就是说,如果您还没有等待EC.visibilityOf(),您也可以尝试EC.elementToBeClickable(yourElement)

    【讨论】:

      猜你喜欢
      • 2021-02-20
      • 2021-01-23
      • 2013-12-23
      • 2017-06-17
      • 1970-01-01
      • 2018-03-05
      • 2016-10-16
      相关资源
      最近更新 更多