Playwright: [Question] Timeout Error

Created on 29 Apr 2020  路  10Comments  路  Source: microsoft/playwright

I just tried this piece of code:

const playwright = require('playwright');
try {
  await page.waitForSelector('.foo');
} catch (e) {
  if (e instanceof playwright.errors.TimeoutError) {
    // Do something if this is a timeout.
  }
  } else {
    console.log(err);
  }
}

I am running this with Jest however, so unsure if this affects it, but for me it ends up in the else branch. I assume that is not supposed to happen.

This does work:

if (err.name === 'TimeoutError')

Most helpful comment

I think the issue could be with TimeoutError class being a different instance in the test (executed in vm script) vs jest-playwright environment (executed in top-level Node context). We had a similar issue with instanceof RegExp.

All 10 comments

What is the exact error you are getting logged? Is it the Playwright timeout error?

TimeoutError: waiting for selector ".foo" failed: timeout exceeded
    at new RerunnableTask
    at Frame._scheduleRerunnableTask
    at Frame.waitForSelector
    at Frame.<anonymous>
    at Page.waitForSelector
    at Page.<anonymous>
    at test.js:12:17
name: 'TimeoutError'

Running this example seems to provide the expected output.

import playwright from 'playwright';

(async () => {
  const browser = await playwright.chromium.launch({
    headless: false
  });
  const context1 = await browser.newContext();
  const page1 = await context1.newPage();
  await page1.goto('https://google.com');
  try {
    await page1.waitForSelector('.nothing');
  } catch (err) {
    if (err instanceof playwright.errors.TimeoutError) {
      console.log('timeout error');
    } else {
      console.log('not timeout error');
    }
  }

  await context1.close();
  browser.close();
})();

This might be due to that it's running inside a Jest env then, which launches a new Node.js vm, or something along those lines. This is the output:

    TimeoutError: waiting for selector "[hidden] v0-dialog[show]" failed: timeout exceeded
        at new RerunnableTask (/home/userA/code/projA/node_modules/playwright-core/lib/frames.js:722:30)
        at Frame._scheduleRerunnableTask (/home/userA/code/projA/node_modules/playwright-core/lib/frames.js:660:32)
        at Frame.waitForSelector (/home/userA/code/projA/node_modules/playwright-core/lib/frames.js:367:35)
        at Frame.<anonymous> (/home/userA/code/projA/node_modules/playwright-core/lib/helper.js:64:31)
        at Page.waitForSelector (/home/userA/code/projA/node_modules/playwright-core/lib/page.js:132:33)
        at Page.waitForSelector (/home/userA/code/projA/node_modules/playwright-core/lib/helper.js:64:31)
        at checkAndCloseUnexpectedDialog (/home/userA/code/projA/tests/e2e/suite/util.js:43:16)
        at Object.<anonymous> (/home/userA/code/projA/tests/e2e/suite/healthCheckProfile/cdaProfile.e2e.test.js:29:11)
        at Promise.then.completed (/home/userA/code/projA/node_modules/jest-circus/build/utils.js:198:28)
        at new Promise (<anonymous>)
      -- ASYNC --
        at Frame.<anonymous> (/home/userA/code/projA/node_modules/playwright-core/lib/helper.js:63:23)
        at Page.waitForSelector (/home/userA/code/projA/node_modules/playwright-core/lib/page.js:132:33)
        at Page.waitForSelector (/home/userA/code/projA/node_modules/playwright-core/lib/helper.js:64:31)
        at checkAndCloseUnexpectedDialog (/home/userA/code/projA/tests/e2e/suite/util.js:43:16)
        at Object.<anonymous> (/home/userA/code/projA/tests/e2e/suite/healthCheckProfile/cdaProfile.e2e.test.js:29:11)
        at Promise.then.completed (/home/userA/code/projA/node_modules/jest-circus/build/utils.js:198:28)
        at new Promise (<anonymous>)
        at callAsyncCircusFn (/home/userA/code/projA/node_modules/jest-circus/build/utils.js:162:10)
        at _callCircusHook (/home/userA/code/projA/node_modules/jest-circus/build/run.js:168:40)
        at _runTest (/home/userA/code/projA/node_modules/jest-circus/build/run.js:145:5)
      -- ASYNC --
        at Page.waitForSelector (/home/userA/code/projA/node_modules/playwright-core/lib/helper.js:63:23)
        at checkAndCloseUnexpectedDialog (/home/userA/code/projA/tests/e2e/suite/util.js:43:16)
        at Object.<anonymous> (/home/userA/code/projA/tests/e2e/suite/healthCheckProfile/cdaProfile.e2e.test.js:29:11)
        at Promise.then.completed (/home/userA/code/projA/node_modules/jest-circus/build/utils.js:198:28)
        at new Promise (<anonymous>)
        at callAsyncCircusFn (/home/userA/code/projA/node_modules/jest-circus/build/utils.js:162:10)
        at _callCircusHook (/home/userA/code/projA/node_modules/jest-circus/build/run.js:168:40)
        at _runTest (/home/userA/code/projA/node_modules/jest-circus/build/run.js:145:5)
        at _runTestsForDescribeBlock (/home/userA/code/projA/node_modules/jest-circus/build/run.js:56:5)
        at _runTestsForDescribeBlock (/home/userA/code/projA/node_modules/jest-circus/build/run.js:82:5) {
      name: 'TimeoutError'
    }

Running it inside of a simple test seems to work for me as well. I did have to add some timeouts for jest, so that it didn't give an error about jest not closing with an async test still running.
Clearly, your test are a lot more involved than this example.

I ran my test with npx jest or npm test where test is defined as jest in my npm script. I do not have any other jest config options.

const playwright = require('playwright');
test('it should catch a timeout error', async () => {
  const browser = await playwright.chromium.launch({
    headless: false
  });
  const context1 = await browser.newContext();
  const page1 = await context1.newPage();
  await page1.goto('https://google.com');
  try {
    await page1.waitForSelector('.nothing', { timeout: 1500 });
  } catch (err) {
    if (err instanceof playwright.errors.TimeoutError) {
      console.log('timeout error');
    } else {
      console.log('not timeout error');
    }
  }

  await context1.close();
  browser.close();
}, 15000);

Probably the issue for that is that the Jest timeout is smaller an the Playwright timeout. So either increasing the Jest one to 30+ seconds or drecreasing the Playwright one should maybe fix it.

No, that is not the issue. I just copy&pasted the simple case above, but my case looks more like this:

try {
  await page.waitForSelector('dialog', {
    waitFor: 'detached',
    timeout: 500,
  });
} catch (err) {
  if (err instanceof playwright.errors.TimeoutError) {
    await page.click('dialog button.cancel');
  } else {
    // Unknown error occurred
    throw err;
  }
}

i.e. I do expect a timeout in some cases after 500ms for the above, and that is where the error occurs.

@mxschmitt Could it have any relation to running this in jest-playwright and that I have to have const playwright = require('playwright'); as an import to be able to use playwright.errors.TimeoutError?

I think the issue could be with TimeoutError class being a different instance in the test (executed in vm script) vs jest-playwright environment (executed in top-level Node context). We had a similar issue with instanceof RegExp.

@mxschmitt Yeah, so it was as I expected, it had to do with that the Jest tests run in a vm context. Do you have any recommendation how to solve this with jest-playwright, is there any patch made to jest-playwright that could fix this. Possibly exposing the playwright object somehow? (I believe you refrained from doing this, but if that is not an option a nice workaround for this would be cool).

Probably the easiest way is with checking against the actual class name as you did (if (err.name === 'TimeoutError')). Thats the upstream issue: https://github.com/facebook/jest/issues/2549. Seems like there is no other easy possible solution.

I assume https://jestjs.io/docs/en/configuration#extraglobals-arraystring will not work since I suspect it only work on built-in globals?

Even so, if you expose playwright (such as that you do with page) in the environment's setup(), would that not work? Or is there a reason jest-playwright does not want to do this?

(For reference I will close this issue soon, just keeping adding the questions here for @mxschmitt so others can read in the future befure I close.)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shirshak55 picture shirshak55  路  3Comments

juliomatcom picture juliomatcom  路  3Comments

jperl picture jperl  路  3Comments

jperl picture jperl  路  4Comments

andyricchuiti picture andyricchuiti  路  4Comments