【问题标题】:Angular JS- testing with Protractor: how to get an element when element doesn't have a tag-name?Angular JS-使用量角器进行测试:当元素没有标签名时如何获取元素?
【发布时间】:2017-09-28 12:57:00
【问题描述】:

我正在为我的 AngularJS 应用程序开发一个测试套件,使用 Protractor 作为我的测试框架。

应用程序的菜单显示在网站所有页面的固定位置 - 当用户将光标悬停在菜单上的任何按钮上时,光标会变为指针,表示可以单击该按钮。菜单中的每个按钮代表应用程序的特定页面 - 如果当用户将光标悬停在该页面的菜单按钮上时存在属于页面的子页面,则会显示一个子菜单,每个子菜单都有文本按钮的子页面。

我目前正在进行一项测试,该测试将测试菜单的功能 - 将光标悬停在菜单上的一个按钮上,检查子菜单是否已显示,然后在光标不再显示时再次隐藏将鼠标悬停在该菜单按钮上,检查单击任何菜单按钮/子菜单按钮是否会将您带到正确的页面等。

菜单的 HTML 编写如下:

<ul id="nav"
    class="nav"
    data-slim-scroll
    data-collapse-nav
    data-highlight-active>
    <li data-ng-mouseenter="setMenuTop($event)" ng-show="menu.pages.length > 0 || menu.upages.length > 0 || canCreatePage">
        <a href="#/pages" id="pagesMenuBtn" target="_self"><i class="ti-layers"></i><span data-i18n="Pages"></span></a>
        <ul class="text-capitalize">
            <li ng-repeat="page in menu.pages"><a href="#/{{page.location}}" target="_self"><i class="ti-angle-right"></i><span data-i18n="{{page.title}}"></span></a></li>
            <li ng-repeat="upage in menu.upages">
                <div class="nav-menu-divider" data-ng-if="$index === 0"></div>
                <a href="#/{{upage.location}}" target="_self">
                    <i class="ti-angle-right"></i><span data-i18n="{{upage.title}}"></span>
                </a>
            </li>
            <li data-ng-show="canCreatePage">
                <div class="nav-menu-divider"></div>
                <a href="#/pages/create" target="_self">
                    <i class="ti-angle-right"></i><span data-i18n="Create Page"></span>
                </a>
            </li>
        </ul>
    </li>
    <li>...</li>
    <li>...</li>
    <li>...</li>
    <li>...</li>
    <li data-ng-mouseenter="setMenuTop($event)">
        <a href="#/config" target="_self"><i class="ti-settings"></i><span data-i18n="Config"></span></a>
        <ul>
            <li ng-repeat="page in menu.config"><a href="#/{{page.location}}" target="_self"><i class="ti-angle-right"></i><span data-i18n="{{page.title}}"></span></a></li>
            <li ng-show="platform._id"><a ng-href="#/config/platform/{{platform._id}}" target="_self"><i class="ti-angle-right"></i><span data-i18n="Platform"></span></a></li>
            <li ng-show="system._id"><a ng-href="#/config/system/{{system._id}}" target="_self"><i class="ti-angle-right"></i><span data-i18n="System"></span></a></li>
            <li><a href="#/config/user" target="_self"><i class="ti-angle-right"></i><span data-i18n="Users"></span></a></li>
            <li><a href="#/config/backup" target="_self"><i class="ti-angle-right"></i><span data-i18n="Backup / Restore"></span></a></li>
            <li ng-show="systemActions.dateTime"><a href="#/config/systemtime" target="_self"><i class="ti-angle-right"></i><span data-i18n="Date / Time"></span></a></li>
        </ul>
    </li>
    <li class="nav-footer">
        <span>{{currentTime.localTDZFormat}}</span>
    </li>
</ul>

如图所示,有两个菜单项具有与之关联的“子菜单”。

我想测试当用户将光标悬停在具有关联子菜单的菜单项之一上时,子菜单正确显示,当光标离开菜单项时,子菜单菜单不再显示:我尝试通过以下测试来做到这一点:

it('should display the Pages menu', function() {
    browser.waitForAngularEnabled(false);
    browser.actions().mouseMove(pagesMenuBtn).perform();
    expect(pageVarBrowserBtn.isDisplayed()).toBeTruthy();
    browser.actions().mouseMove(userCircle).perform();
    expect(pageVarBrowserBtn.isDisplayed()).toBeFalsy();
    browser.waitForAngularEnabled(true);
});

此测试中使用的变量定义为:

var pagesMenuBtn = element(by.id('pagesMenuBtn'));
var pageVarBrowserBtn = element.all(by.id('menu.pages')).get(0);
var userCircle = element(by.id('icon-user-circle'));

pageVarBrowserBtn 是用户将光标悬停在pagesMenuBtn 上时显示的子菜单中的第一个菜单项。

目前,当我运行测试时,浏览器打开,导航到我的应用程序的根页面,并将光标悬停在 pagesMenuBtn 元素上,以便显示子菜单(我可以看到它显示在测试打开的浏览器窗口)。

但是,然后我在控制台中收到一条错误消息:

失败:索引超出范围。试图访问 index: 0 处的元素,但只有 0 个元素匹配定位器 By(CSS selector, *[id="menu.pages"])

我不明白为什么会出现此错误...?如何从正在显示的子菜单中获取单个元素,以检查它是否是正确的项目,并且单击它会将用户带到正确的位置?我无法指定确切的元素 ID,因为它是由 ng-repeat 创建的,所以我试图通过它的位置/数组索引 - 0 来获取它。

【问题讨论】:

    标签: angularjs protractor automated-tests element


    【解决方案1】:

    首先,您收到上述错误可能有两个原因。

    1. Either the locator you are using is wrong.
    2. Your script is not waiting until the element is displayed in DOM.
    

    在您的情况下,您提到了错误的定位器 element.all(by.id('menu.pages')),因为您的 HTML 中不存在 ID 为 menu.pages 的元素。

    不要使用element.all(by.id('menu.pages')),而是将其更改为element.all(by.repeater('page in menu.pages')).get(0) 以从菜单列表中获取第一个元素。也请参考Element locators in Protractor 以查找量角器支持的所有可用定位策略的列表。

    希望这可能有助于解决您的问题!

    【讨论】:

    • 太棒了,使用element.all(by.repeater('page in menu.pages')).get(0); 工作 - 知道by.repeater 是如何访问由ng-repeat 创建的元素非常有用。
    【解决方案2】:

    您是否尝试使用 element.all(locator).first() 从选择器中获取第一个元素

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-13
      • 2015-11-30
      • 2017-04-16
      • 2017-12-30
      • 1970-01-01
      相关资源
      最近更新 更多