在Protractor中,browser.isElementPresent与element.isPresent和element.isElementPresent有何区别?

26

在 Protractor 中,基本上有三种方法来检查一个元素是否存在:

var elm = element(by.id("myid"));

browser.isElementPresent(elm);
elm.isPresent();
elm.isElementPresent();

这些选项是否等效和可互换,通常应该选择哪个?

3个回答

37

所有的函数都有类似的工作方式,但存在微小的差异。以下是我发现的几个差异 -

elm.isPresent() -

  1. ElementFinder的扩展,因此在执行任何操作之前等待Angular在页面上安定下来。
  2. elmelement(locator)ElementFinder而不是ElementArrayFinder时才有效。如果使用指定的locator返回多个元素,则首先检查第一个元素是否在DOM中isEnabled()。不接受任何参数作为输入。
  3. 在Angular页面和Angular元素上最有效。
  4. 每当需要查找元素是否存在时,首选使用。

elm.isElementPresent(subLoc) - (当有子定位器subLoc时)

  1. ElementFinder的扩展,因此在执行任何操作之前等待Angular在页面上稳定。
  2. 用于检查父级的子元素是否存在。它将父级elmsub locator作为参数。(与elm.isPresent()之间的唯一区别)
  3. 最适合使用Angular页面和Angular元素。
  4. 每当需要检查父级的子元素是否存在时,首选使用。

browser.isElementPresent(element || Locator) -

  1. 它是webdriver的一种实现,因此不会等待Angular稳定。
  2. 定位器元素作为参数,并使用第一个结果,如果使用相同的定位器定位到多个元素,则只使用第一个。
  3. 最适用于非Angular页面。
  4. 在测试非Angular页面时首选使用。

以上所有内容都检查DOM中元素的存在并返回一个布尔结果。虽然angular和非angular特性不影响这些方法的使用,但默认情况下该方法等待angular稳定,可以帮助避免出现类似于未找到元素或状态元素引用异常等angular问题而导致的错误。


这就是我希望得到的答案。非常感谢!我发现这三种存在检查方式相当令人困惑,因为实际上这些方法之间存在差异,而仅仅通过方法名称来看并不清楚这些差异是什么。此外,这些差异也没有得到适当的记录。希望这个答案填补了空白,并能帮助未来的其他人。 - alecxe

5

我不确定哪个更受欢迎,但我能够找到源代码并检查它。

根据文档,elm.isPresent()elm.isElementPresent() 是等效的。希望这能够帮助你。

Protractor API 文档

在标题右侧有一个名为 View code 的链接。

browser.isElementPresent(elm);

https://angular.github.io/protractor/#/api?view=webdriver.WebElement.prototype.isElementPresent

/**
 * Schedules a command to test if there is at least one descendant of this
 * element that matches the given search criteria.
 *
 * @param {!(webdriver.Locator|webdriver.By.Hash|Function)} locator The
 *     locator strategy to use when searching for the element.
 * @return {!webdriver.promise.Promise.<boolean>} A promise that will be
 *     resolved with whether an element could be located on the page.
 */
webdriver.WebElement.prototype.isElementPresent = function(locator) {
  return this.findElements(locator).then(function(result) {
    return !!result.length;
  });
};

elm.isPresent();

https://angular.github.io/protractor/#/api?view=ElementFinder.prototype.isPresent

/**
 * Determine whether the element is present on the page.
 *
 * @view
 * <span>{{person.name}}</span>
 *
 * @example
 * // Element exists.
 * expect(element(by.binding('person.name')).isPresent()).toBe(true);
 *
 * // Element not present.
 * expect(element(by.binding('notPresent')).isPresent()).toBe(false);
 *
 * @return {ElementFinder} which resolves to whether
 *     the element is present on the page.
 */
ElementFinder.prototype.isPresent = function() {
  return this.parentElementArrayFinder.getWebElements().then(function(arr) {
    if (arr.length === 0) {
      return false;
    }
    return arr[0].isEnabled().then(function() {
      return true; // is present, whether it is enabled or not
    }, function(err) {
      if (err.code == webdriver.error.ErrorCode.STALE_ELEMENT_REFERENCE) {
        return false;
      } else {
        throw err;
      }
    });
  }, function(err) {
    if (err.code == webdriver.error.ErrorCode.NO_SUCH_ELEMENT) {
      return false;
    } else {
      throw err;
    }
  });
};

elm.isElementPresent();

https://angular.github.io/protractor/#/api?view=ElementFinder.prototype.isElementPresent

/**
 * Same as ElementFinder.isPresent(), except this checks whether the element
 * identified by the subLocator is present, rather than the current element 
 * finder. i.e. `element(by.css('#abc')).element(by.css('#def')).isPresent()` is
 * identical to `element(by.css('#abc')).isElementPresent(by.css('#def'))`.
 *
 * @see ElementFinder.isPresent
 *
 * @param {webdriver.Locator} subLocator Locator for element to look for.
 * @return {ElementFinder} which resolves to whether
 *     the subelement is present on the page.
 */
ElementFinder.prototype.isElementPresent = function(subLocator) {
  if (!subLocator) {
    throw new Error('SubLocator is not supplied as a parameter to ' + 
      '`isElementPresent(subLocator)`. You are probably looking for the ' + 
      'function `isPresent()`.');
  }
  return this.element(subLocator).isPresent();
};

1
谁给这个回答下了踩,请告诉我们原因,我觉得这个回答很好啊。 - Ardesco
4
我认为,downvote 应该是针对那些只是复制粘贴源代码而没有做出任何解释的人。 - Michael Radionov
1
我既没有点踩也没有点赞。我认为迈克尔关于点踩的原因肯定是正确的。无论如何,感谢您的参与和关注! - alecxe
我已经解释过这两个是等价的... 其余的我认为从源代码中很容易理解。这些函数只有2到3行,不包括 elm.isPresent() 中的错误代码。 耸肩 - JeffC

-3
你可以使用isPresent函数来检查元素是否存在。
因此,您的代码将类似于:
var myElement = element(by.css('.elementClass'));
expect(myElement.isPresent()).toBeFalsy();

这里是关于isPresent函数的protractor文档。


3
谢谢!这就是问题所在——实际上在protractor中有三种方法可以做到这一点,这就是问题所在。 - alecxe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接