使用量角器测试AngularJS-测试失败,因为尽管等待ElementToEclickable,但元素不可单击。。。?

使用量角器测试AngularJS-测试失败,因为尽管等待ElementToEclickable,但元素不可单击。。。?,angularjs,protractor,automated-tests,wait,Angularjs,Protractor,Automated Tests,Wait,我在使用量角器为AngularJS应用程序开发的测试套件中编写一个测试时遇到了一个奇怪的问题 在最初开发测试时,我使用了对browser.pause()的调用,以确保在运行测试脚本时手动告诉测试执行每一行。我现在很高兴,到目前为止,我编写的测试正在正确执行&所有通过/失败都取决于它们的标准 现在我想删除对browser.pause()的调用,这样脚本就可以自动运行每个测试,而无需任何用户交互。但是,由于应用程序是角度的,因此在执行引用元素的测试步骤之前,这样做会导致一些计时/等待元素加载的问题-

我在使用量角器为AngularJS应用程序开发的测试套件中编写一个测试时遇到了一个奇怪的问题

在最初开发测试时,我使用了对
browser.pause()
的调用,以确保在运行测试脚本时手动告诉测试执行每一行。我现在很高兴,到目前为止,我编写的测试正在正确执行&所有通过/失败都取决于它们的标准

现在我想删除对
browser.pause()
的调用,这样脚本就可以自动运行每个测试,而无需任何用户交互。但是,由于应用程序是角度的,因此在执行引用元素的测试步骤之前,这样做会导致一些计时/等待元素加载的问题-因此我目前正在进行每个测试,并尝试确保在与元素交互之前,允许元素加载/等待元素所需的时间,等等

当我现在运行测试脚本时,第二个测试(导航到导出页面)失败,我编写了如下内容:

it('should navigate to the Export page', function() {
    browser.waitForAngularEnabled(false);
    browser.wait(EC.elementToBeClickable(exportMenuBtn), 25000).then(
        browser.actions().mouseMove(exportMenuBtn).perform().then(
            exportMenuBtn.click().then(
                function() {
                    console.log("Export page test completed ");
                    expect(browser.getCurrentUrl()).toBe(VM + '/#/export');
                }
            )
        )
    );
});
我在运行脚本的命令行中收到的错误消息显示:

失败:未知错误:元素。。。在点(40301)处不可单击。其他元素将收到单击:

然后将测试脚本更新为:

it('should navigate to the Export page', function() {
    browser.waitForAngularEnabled(false);
    browser.wait(pageLoaded, 5000);
    exportMenuBtn.click();
    browser.wait(pageLoaded, 5000);
    browser.wait(EC.urlIs(VM + '/#/export'), 5000);
});
但我的测试脚本仍然失败,并给出相同的错误消息:

失败:未知错误:元素

似乎导致问题的对话框在dialog/service.js中定义为:

function wait(msg, progress, title) {
    // Create a wait dialog
    var dlg = dialogs.wait(
        title,
        msg,
        progress,
        {
            // Disable keyboard ESC to close dialogue instances
            keyboard: false,

            // lock the background window
            backdrop: "static",
            size: "sm",
            windowClass: "ult-loading modal-message",
            animation: false
        }
    );

    // Push the dialog into the pool
    dlgs.push(dlg);

    // Return the created dialog
    return dlg;
}
当手动运行测试/浏览页面时,此对话框实际上不可见,因此它似乎是在浏览/加载新页面时运行的某种“后台任务”。我还应该注意,此对话框是在
工厂中定义的

.factory('DialogMgr', function($rootScope, $document, dialogs) {
    ...
    function wait(...) {
        ...
    }
});
我想知道这是否可能与对话框中设置的“淡入淡出”动画有关?我将如何解决此问题?

这是一个问题

怎么不满足你的问题

我添加了(尽管有注释)行
browser.wait(EC.invisibilityOf(blockingElement),5000)作为问题的答案

此时,元素
isClickable
并不自动意味着它也在前面,并且没有其他对象覆盖它。这只是意味着,对象可能会收到一个
单击()
,因为

元素可见并已启用,以便您可以单击它

。您甚至可以检查源代码

更新

在加载页面时,如果您有评论,将出现一个阻止输入的对话框弹出窗口。因此,您可以创建自己的
ExpectedConditions
-函数,该函数将始终等待该阻塞对话框消失

以下是要构建的可重用函数,基于以下假设,即此拦截器元素将出现在许多地方:

var loaded = function(){
    var EC = protractor.ExpectedConditions;
    var blockerElm = $('div[window-class="ult-loading"');
    return EC.invisibilityOf(blockerElm);
}
module.exports = new loaded();
以下是如何在测试用例中调用它:

var loaded = require(pathToLoaded.js);
it('should navigate to the Charts page', function() {
    console.log("Start Charts page test");
    browser.waitForAngularEnabled(false);
    browser.wait(loaded, 5000);
    chartsMenuBtn.click(); //works, if the element is defined as you said
    browser.wait(EC.urlIs(site + '/#/charts'), 5000);
})

虽然我知道这不被认为是“最佳实践”,但我真正能够解决这一问题的唯一方法是在调用
浏览器之前插入
browser.sleep()
行。单击()

使用Ernst Zwingli在回答中提供的
pageLoaded()
函数:

var pageLoaded = function() {
    var blockingElement = $('div[window-class="ult-loading modal-message"');
    //console.log("blockingElement: ", blockingElement);
    return EC.invisibilityOf(blockingElement);
}
module.exports = new pageLoaded();

无需调用
browser.sleep(500),页面没有时间在加载页面时在后台打开和关闭的对话框上完成动画-这意味着对话框收到的是单击,而不是我想要的菜单按钮。

从哪里获得
blockingElement
?控制台中的错误似乎表明这是一个此时将接收单击的对话框,但在测试执行期间没有显示任何对话框(即,执行的所有行都不会导航到显示对话框的页面)。错误显示:
其他元素将接收单击:…
,但是这些页面上没有显示任何对话框…只是意识到错误消息中显示的代码部分在我的OP中没有正确显示-因此我重新格式化了它。您提供的指向量角器API的链接正是我在另一个问题上编写代码所遵循的,您在这里发布了您引用的答案,显示了一个对话框-我还没有找到你的答案,但是在我解决了这个测试的问题后,我会重新访问它。正如我在这个问题中提到的,最初编写测试时,我有一个
browser.pause()行已启用,当我手动运行测试时(必须告诉脚本在执行每行时继续),它们都正确通过。自从删除对
browser.pause()的调用后,我才遇到这个问题-所以这似乎是一个时间问题。。。
function wait(msg, progress, title) {
    // Create a wait dialog
    var dlg = dialogs.wait(
        title,
        msg,
        progress,
        {
            // Disable keyboard ESC to close dialogue instances
            keyboard: false,

            // lock the background window
            backdrop: "static",
            size: "sm",
            windowClass: "ult-loading modal-message",
            animation: false
        }
    );

    // Push the dialog into the pool
    dlgs.push(dlg);

    // Return the created dialog
    return dlg;
}
.factory('DialogMgr', function($rootScope, $document, dialogs) {
    ...
    function wait(...) {
        ...
    }
});
var loaded = function(){
    var EC = protractor.ExpectedConditions;
    var blockerElm = $('div[window-class="ult-loading"');
    return EC.invisibilityOf(blockerElm);
}
module.exports = new loaded();
var loaded = require(pathToLoaded.js);
it('should navigate to the Charts page', function() {
    console.log("Start Charts page test");
    browser.waitForAngularEnabled(false);
    browser.wait(loaded, 5000);
    chartsMenuBtn.click(); //works, if the element is defined as you said
    browser.wait(EC.urlIs(site + '/#/charts'), 5000);
})
it('should navigate to the Export page', function() {
    browser.waitForAngularEnabled(false);
    browser.wait(pageLoaded, 5000);
    browser.sleep(500);
    exportMenuBtn.click();
    browser.wait(EC.urlIs(site + '/#/export'), 5000);
});
var pageLoaded = function() {
    var blockingElement = $('div[window-class="ult-loading modal-message"');
    //console.log("blockingElement: ", blockingElement);
    return EC.invisibilityOf(blockingElement);
}
module.exports = new pageLoaded();