Selenium-webdriver JS - 如何等待元素可见

时间:2016-03-30 12:55:14

标签: javascript selenium selenium-webdriver xpath webdriver

使用selenium-webdriverapi docs here),您如何等待元素可见?

我有以下功能,一组自制的测试帮助器,第一个工作但第二个工作失败(例如,即使它存在,它也会超时并且元素可见 - 如已确认通过第一个有效的功能 - 并且可见 - 由所有可以想象的测试和页面html / css / js的检查确认。

他们是:

/**
 * Wait for an element to exist
 * 
 * @param  {object} locator
 * @param  {int} timeout (ms)
 * 
 * @return {Promise<element>}
 */
// !! THIS WORKS OK
exports.waitForElement = function (locator, timeout) {
  var waitTimeout = timeout || DEFAULT_TIMEOUT;

  return this.wait(until.elementLocated(locator), waitTimeout)
    .then(() => {

        return this.findElement(locator);
      });
};


/**
 * Wait for an element to exist and then wait for it to be visible
 *
 * IMPORTANT: this is probable what you want to use instead of
 *   waitForVisibleElement most of the time.
 * 
 * @param  {hash} locator
 * @param  {number} timeout
 * 
 * @return {Promise<element>}
 */
// !! THIS FAILS TO WORK AS EXPECTED
exports.waitForVisibleElement = function (locator, timeout) {
  var waitTimeout = timeout || DEFAULT_TIMEOUT;

  return this.waitForElement(locator, waitTimeout) 
    .then(el => {
      console.log('--- element found:', el);
      return this.wait(until.elementIsVisible(el), waitTimeout)

        .then(() => {
          console.log('--- element visible!');
          // this is to make sure we are returning the same kind of
          // promise as waitForElement
          return this.findElement(locator);
        });

    });
};

...我在多个环境中进行了测试,因此waitForVisibleElement内部的代码没有其他原因导致问题,但我似乎找不到任何原因导致其无效工作!

作为澄清,在this方法monkeypatches给定的webdriver对象后,该代码的new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build()最终成为webdriver实例(augment的结果...)可能是一个有问题的设计模式,但这里没有我的问题的原因:)

UPDATE:显然这只发生在XPath定位器上,例如{ xpath: '//*[contains(text(), "first name")]' } ...而不是它现在更有意义了。此外,它与Firefox相同,所以它不是一个奇怪的chrome-webdriver thingy ...

1 个答案:

答案 0 :(得分:3)

很可能是承诺问题。 试试这个:

exports.waitForElement = function (locator, timeout) {
  var timeout = timeout || DEFAULT_TIMEOUT;
  return this.wait(until.elementLocated(locator), timeout);
};

exports.waitForVisibleElement = function (locator, timeout) {
  var timeout = timeout || DEFAULT_TIMEOUT;
  var element = this.wait(until.elementLocated(locator), timeout);
  return this.wait(new until.WebElementCondition('for element to be visible ' + locator, function() {
    return element.isDisplayed().then(v => v ? element : null);
  }), timeout);
};

用法:

driver.get("...");

driver.waitForElement(By.id("..."), 2000).getText().then(function(text){
  console.log(text);
});

driver.waitForVisibleElement(By.id("..."), 2000).getText().then(function(text){
  console.log(text);
});