Summary of problem: I'm writing several test suites (using Jest and Puppeteer) to automate tests of my AngularJS app's home page. One of the tests I'd like to automate is clicking on an md-tab-item
. Sounds easy, right? Unforuntealy, this simple test has become a huge issue, and the only solution I have been able to come up with to fix it (adding a pause function to my test) makes my test extremely slow. I should also note that my md-tab-item
's are added dynamically, so the only way to select them is via an XPath selector that selects the target tab based on the text it contains. This makes clicking on the tab slightly harder as I first have to use Puppeteer's page.$x
method to convert the tab into a clickable ElementHandle
(the code below illustrates what I mean).
Background: I'm using Jest (v24.8.0) as my testing framework. I'm using Puppeteer (v1.19.0) to spin up and control a headless Chromium browser.
Disclaimer: In order to provide this community with a minimal, reproducible example I chose not to copy and paste my original code by instead wrote up a simpler example. So if you find a typo, I can assure you that is not the source of my problem because I have checked my original code very carefully for typos. I'm sorry in advance for any typos in the following code. I was vigilant but I am human so I make mistakes.
Broken code:
<!-- 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();
});
Questions:
- Do any of you Jest/Puppeteer experts have any idea why I have to wait before being able to click on my tab? If so, how can I improve my code so I no longer have to rely on
page.waitFor
to get the test to pass? - Is there perhaps a better way of clicking on an element specified by a XPath selector that I could try?