Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Puppeteer failing simple tests with: "waiting for function failed: timeout 500ms exceeded"?

While trying to set up some simple end-to-end tests with Jest and Puppeteer, I've found that any test I write will inexplicably fail with a timeout.

Here's a simple example test file, which deviates only slightly from Puppeteer's own example:

import puppeteer from 'puppeteer';

describe('Load Google Puppeteer Test', () => {
  test('Load Google', async () => {
    const browser = await puppeteer.launch({
      headless: false
    });

    const page = await browser.newPage();
    await page.goto('https://google.co.uk');
    await expect(page).toMatch("I'm Feeling Lucky");
    await browser.close();
  });
});

And the response it produces:

TimeoutError: Text not found "I'm Feeling Lucky"
      waiting for function failed: timeout 500ms exceeded

I have tried adding in custom timeouts to the goto line, the test clause, amongst other things, all with no effect. Any ideas on what might be causing this? Thanks.

like image 733
Aaron C Avatar asked Sep 14 '25 01:09

Aaron C


2 Answers

What I would say is happening here is that using toMatch expects text to be displayed. However, in your case, the text you want to verify is text associated with a button.

You should try something like this:

await expect(page).toMatchElement('input[value="I\'m Feeling Lucky"]');

Update 1:

Another possibility (and it's one you've raised yourself) is that the verification is timing out before the page has a chance to load. This is a common issue, from my experience, with executing code in headless mode. It's very fast. Sometimes too fast. Statements can be executed before everything in the UI is ready.

In this case you're better off adding some waitForSelector statements throughout your code as follows:

await page.waitForSelector('input[value="I\'m Feeling Lucky"]');

This will ensure that the selector you want is displayed before carrying on with the next step in your code. By doing this you will make your scripts much more robust while maintaining efficiency - these waits won't slow down your code. They'll simply pause until puppeteer registers the selector you want to interact with / verify as being displayed. Most of the time you won't even notice the pause as it will be so short (I'm talking milliseconds).

But this will make your scripts rock solid while also ensuring that things won't break if the web page is slower to respond for any reason during test execution.

like image 195
AJC24 Avatar answered Sep 15 '25 14:09

AJC24


You're probably using 'expect-puppeteer' package which does the toMatch expect. This is not a small deviation. The weird thing is that your default timeout isn't 30 seconds as the package's default, check that.

However, to fix your issue:

await expect(page).toMatch("I'm Feeling Lucky", { timeout: 6000 });

Or set the default timeout explicitly using:

page.setDefaultTimeout(timeout)

See here.

like image 23
Moshisho Avatar answered Sep 15 '25 14:09

Moshisho