【问题标题】:How can I target elements outside the angular app with protractor?如何使用量角器定位角度应用程序之外的元素?
【发布时间】:2017-11-22 06:33:03
【问题描述】:

我有一个在 Angular 应用引导之前播放的介绍元素。

<!-- need to target div below -->
<div id="intro"></div>
<!-- still bootstraping -->
<app-root></app-root>

我正在使用 Angular-cli 中提供的以下量角器规范

describe('my App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage(); // default from angular cli
  });

  it(`should provide an intro div`, () => {
    page.navigateTo();
    const introDiv = element(by.id('intro'));
    expect(introDiv.isPresent()).toBe(true); // reports as false in protractor test
  });
});

我能够使用上面相同的“it”函数来定位 Angular 应用程序内的元素,为什么这不能在 Angular 应用程序之外工作,我如何定位 index.html 中的元素?

更新:

我已经进行了进一步的测试,并想将其记录在问题中仅供参考:

上面没有提到,我实际上有角度删除了介绍 div,因为它是全屏覆盖。

感谢 Ernst Zwingli 提供的 Protractor 文档的参考,它告诉我 Protractor 在每个 WebDriver 操作之前自动应用browser.waitForAngular() 命令。

因此,上面试图针对 intro div 的测试在 angular bootstraped 并删除了 div 之后找不到它。

我在 index.html 中创建了一个没有任何内容的临时 div。 element(by.id('find-me')) 可以简单地使用它,即使它在 Angular 的应用程序之外。

<div id="find-me"></div>

it(`is available after angular bootstraps and can be targeted with element()`, () => {
    const findMeDiv = element(by.id('find-me'));
    expect(findMeDiv.isPresent()).toBe(true);
  });

我终于能够使用 browser.waitForAngularEnabled(false) 来定位 intro div,因为它在 Angular 引导之前可用。虽然这只等待 $http 和 $timeouts 似乎足以在引导之前定位 div 。我不确定它是否完全抵消了browser.waitForAngular()

(与waitForAngular()的区别在于等待渲染、http、超时,而waitForAngularEnabled()只关心http超时 - 虽然名称相似性可能表明 waitForAngularEnabled(false) 完全取消了 waitForAngular() 例如还包括 rendering 并且未在文档中指定)。

<div id="intro"></div>

// Works
  it(`Found to be available if I use browser.waitForAngularEnabled(false) since div is removed when Angular is ready`, () => {
    browser.waitForAngularEnabled(false);
    const introDiv = element(by.id('intro'));
    expect(introDiv.isPresent()).toBe(true);
  });

所以基本上 Ernst Zwingli 和 Xotabu4 都提供了很好的洞察力,因为我需要 browser.waitForAngularEnabled(false); 并且可以使用 element() 函数来访问 div。

【问题讨论】:

    标签: angular protractor e2e-testing


    【解决方案1】:

    您基本上应该将该部分视为non-angular 并使用Selenium WebDriver-methods 查找元素。

    因此,使用 browser.driver.findElement(by.id('intro')) 代替 element(by.id('intro')),因为 browser.driver 使用 JavaScript/Vanilla browser 而不是量角器 browser,因此可以在任何角度范围之外工作。

    但是,您需要放弃您的expect() 语句,因为量角器element(locator) 代表ElementArrayFinder,而像findElement()getWebElement() 和类似的WebDriver 方法直接代表WebElement(所以他们立即执行元素搜索,而不是等到代码需要真正的 WebElement)。 Read about here

    因此,在您的情况下,使用 findElement 您会收到 WebDriver-Error,因为该元素不存在,或者您会收到 WebElement,因为它存在(无需进一步检查存在)。

    Here the Selenium-Documentationhere a GitHub, that explains the use of Protractor in Non-Angular

    顺便说一句

    如果整个页面是非 Angular 的,您需要使用 browser.waitForAngularEnabled(false) 关闭 Protractor ControlFlow(这是之前的 ignoreSynchronization = true,但不要再使用它了)。

    如果页面只有一部分是非 Angular 的,您可能不需要关闭 Protractor,但您可能需要显式处理同步执行(用于尝试和错误)

    更新

    由于收到的评论,我很想链接到一些进一步的信息,这进一步证明了我的观点(因为 Protractor Vanilla):

    【讨论】:

    • element(by.id('intro')), use browser.driver.findElement(by.id('intro')) 元素的搜索将是完全一样的,除了在第一种情况下'waitForAngular()'会被做,检查源代码。我相信我们只需要稍等片刻
    • @Xotabu4 :我认为你错了。我更新了我的答案,以更好地区分香草和量角器
    • 感谢 cmets 并回答了你们两个给我的问题,我可以使用 element() 定位 div 并使用 browser.waitForAngularEnabled(false) 在角度引导之前定位它。 :)
    猜你喜欢
    • 1970-01-01
    • 2016-01-22
    • 2020-07-03
    • 2015-09-12
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    相关资源
    最近更新 更多