如何使用WebDriver验证WebElement是否显示在视口中?

时间:2013-08-16 09:17:02

标签: java selenium webdriver scrollbar visibility

考虑以下情况,

  1. 网页与垂直滚动条一起显示
  2. 滚动条位于底部
  3. WebElement“Test”出现在页面顶部,现在在当前视图端口中不可见。
  4. 要验证的功能:

    单击页面底部的“转到顶部”链接应滚动页面,以便在视图端口中显示WebElement“Test”。

    请告诉我如何使用WebDriver验证元素是否显示在当前视口中。

    注意:的 在上述情况下,element.isDisplayed将始终为true,因为该函数检查整个页面而不是仅检查当前视图端口。

3 个答案:

答案 0 :(得分:1)

嗯,作为我想到的最后一件事,我会选择这样的事情:

  1. 点击底部的链接后获取截图(确保它只为您提供了查看端口截图)
  2. 使用Webdriver的window.scrollTo转到顶部(见下文)
  3. 重复第1步
  4. 比较第1.和第3步的结果
  5. 使用webdriver滚动的位置应该如下:

    JavascriptExecutor js = (JavascriptExecutor)driver;
    js.executeScript("window.scrollTo(0,0)");
    

    这似乎是一种绝望的解决方法,但如果没有建议其他解决方案,可能值得努力。

答案 1 :(得分:1)

@Vel Ganesh - 我不知道这是否可以使用硒进行验证。但绝对可以使用Sikuli完成。您可以查看sikuli.org了解详情。 Sikuli有一个Java API,因此也可以与WebDriver代码集成。

答案 2 :(得分:0)

   * This function determines if the YOffset ot top of the element falls between the top of the
   * client window and the bottom of the client window to determine if it's in the viewport.
   * @param selector
   * @return bool
   */
  async isElementInViewPort(selector) {
    // Get the needed  element dimensions using webdriver
    const elemLocation = await selector.getLocation();
    const elemTopBoundY = await elemLocation.y;
    // Get the needed client dimensions using javascript
    const winUpperBound = await this.driver.executeScript('return window.pageYOffset');
    const winHeight = await this.driver.executeScript('return document.documentElement.clientHeight');
    const winLowerBound = winUpperBound + winHeight;
    if (winUpperBound <= elemTopBoundY
      && winLowerBound >= elemTopBoundY) {
      return true;
    } return false;
  }

  /* waitForElementisinViewPort
   * This function determines if the YOffset ot top of the element falls between the top of the
   * client window and the bottom of the client window after an action such as a scroll.
   * The wait avoids trying to do anything before the element is in the viewport.
   * @param selector
   * @state selector
   * @param timeout
   * @return bool
   */
  async waitForElementToBeinViewPort(selector, state, timeout) {
    try {
      let isInViewpPort;
      await this.driver.wait(async () => {
        const bool = await this.isElementInViewPort(selector);
        isInViewpPort = bool;
        return bool === state;
      }, timeout);
      return isInViewpPort;
    } catch (err) {
      console.log(`Function: waitForElementToBeinViewPort failed ${err} `);
      return null;
    }
  }

Example test

  const links = [{ link: 'All Web hosting deals', selector: coupons.selector.COUPON_DEALS_WEB },
    { link: 'Domain name deals', selector: coupons.selector.COUPON_DEALS_DOMAIN },
    { link: 'How do you redeem these coupons', selector: common.baseselector.FOOTER_CTA }];

  describe('Coupons Page Extra Links section', () => {
    links.forEach(async (link, i) => {
      it('Click each Extra Links section link and verify an expected element is scrolled to', async () => {
        await coupons.visit(page = '/coupons');
        const nav = await driver.findElement(common.baseselector.mainNav);
        // Need a scroll to top so that other tests don't leave the element under test off the page initially.
        await driver.executeScript('arguments[0].scrollIntoView()', nav);
        const linksToClick = await coupons.getExtraPlanLinks();
        const element = await driver.findElement(links[i].selector);
        await assert.isFalse(await coupons.waitForElementToBeinViewPort(element, false, timeout),
          `element ${link.selector} should not be in the viewport`);
        await linksToClick[i].click();
        const bool = await coupons.waitForElementToBeinViewPort(element, true, timeout);
        assert.isTrue(bool, ` element ${link.selector} should be in the viewport`);
      });
    });
  });