Puppeteer无法单击DOM中XPath指定的元素

时间:2019-08-12 20:42:33

标签: javascript angularjs xpath jestjs puppeteer

问题摘要::我正在编写几个测试套件(使用Jest和Puppeteer)以自动化对AngularJS应用首页的测试。我要自动化的测试之一是单击md-tab-item。听起来很简单,对吧?不幸的是,这个简单的测试已成为一个巨大的问题,而我唯一能够解决该问题的解决方案(在测试中添加了暂停功能)使我的测试非常慢。我还要注意,我的md-tab-item是动态添加的,因此选择它们的唯一方法是通过XPath选择器,该选择器根据包含的文本选择目标选项卡。这使单击选项卡有点困难,因为我首先必须使用Puppeteer的page.$x方法将选项卡转换为可点击的ElementHandle(下面的代码说明了我的意思)。

背景:我正在使用Jest(v24.8.0)作为测试框架。我正在使用Puppeteer(v1.19.0)启动并控制无头的Chromium浏览器。

免责声明: 为了向该社区提供minimal, reproducible example,我选择不复制并粘贴原始代码,而是写了一个简单的例子。因此,如果您发现了错字,我可以向您保证,这不是问题的根源,因为我已经非常仔细地检查了原始代码中的错字。对于以下代码中的任何拼写错误,我们深表歉意。我保持警惕,但我是人,所以我会犯错。

破损的代码:

<!-- index.html -->
<html>
  <body ng-app="myApp" ng-controller="myCtrl">
    <md-content>
      <md-toolbar>
        <div class='md-toolbar-tools'>
          <h2>My Toolbar</h2>
        </div>
      </md-toolbar>
      <md-progress-linear></md-progress-linear>
      <md-tabs>
        <md-tabs-canvas>
          <md-pagination-wrapper>
            <md-tab-item>Tab 1</md-tab-item>
            <md-tab-item>Tab 2</md-tab-item>
            <md-tab-item>Tab 3</md-tab-item>
          </md-pagination-wrapper>
        </md-tabs-canvas>
      </md-tabs>
      <div><!-- Displays tab content based on which tab is clicked --></div>
    </md-content>
  </body>
</html>
// index.spec.js
test('click on second tab', async() => {

  // check if tab exists: this ALWAYS passes
  tabXPath = '//md-tab-item[contains(text(), "Tab 2")]|//md-tab-item[contains(text(), "tab 2")]';
  const tabExists = await page.waitForXPath(tabXPath, {timeout: 3000}) ? true : false;
  expect(tabExists).toBe(true);

  // use tab's XPath to create a clickable ElementHandle
  let clickableTab = await page.$x(tabXPath);

  // bug: tab cannot be clicked unless I wait - increases test time by 1s :(
  await page.waitFor(1000);

  // click on this ElementHandle
  await clickableTab[0].click();

}); 

问题:

  1. 您是否对Jest / Puppeteer专家有任何想法,为什么我必须等待才能单击选项卡?如果是这样,如何改善我的代码,以使我不再依靠page.waitFor来通过测试?
  2. 也许可以尝试单击XPath选择器指定的元素的更好方法吗?

1 个答案:

答案 0 :(得分:0)

  1. 使用Puppeteer,您需要等待,否则代码的其他部分将在加载所需网页元素之前执行。但是,与其尝试执行waitFor,不如尝试使用waitForSelector(此处为CSS选择器)或waitForNavigation-然后,您只需要等待特定的位加载即可。

  2. 这几乎是Puppeteer支持根据其文档进行操作的唯一方法,this可能会有所帮助。