playwright: [BUG] Playwright-core - Timeout while waiting for event \"download\"\nNote:

Context:

  • Playwright Version: 1.3.0
  • Operating System: AWS Lambda
  • Node.js version: 12
  • Browser: [Chromium]
  • Extra: playwright-aws-lambda

Hi Team,

I am testing playwright-core with AWS lambda.

there is problem with page.waitForEvent(“download”) in playwright-code 1.3.0.

page.waitForEvent(“download”) works fine with playwright-code 1.0.2 but with playwright-code 1.3.0 does not.

Error:

“TimeoutError: page.waitForEvent: Timeout 30000ms exceeded.”, “Note: use DEBUG=pw:api environment variable and rerun to capture Playwright logs.”, " at ProgressController.run (/opt/node_modules/playwright-core/lib/progress.js:71:30)“, " at Page.waitForEvent (/opt/node_modules/playwright-core/lib/page.js:243:35)”, " at Page.waitForEvent (/opt/node_modules/playwright-core/lib/helper.js:80:31)",

Code Snippet

 await page.goto(
    "https://file-examples.com/index.php/sample-documents-download/sample-xls-download/"
  );

  const handles = await page.$$("#table-files .file-link");

  for (let num of handles) {
    const [download] = await Promise.all([
      page.waitForEvent("download"), // wait for download to start
      num.click("a.btn"),
    ]);
    const path = await download.path();
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 21 (7 by maintainers)

Most upvoted comments

@dgozman Yeah, I suspected that as well. My playwright-core version is 1.8.0.

@osmenia You are legend! Thanks man. I just downgraded to 1.0.2 and it worked both locally and on lambda. I’ve been stuck at it for days, so glad it worked. I’ll try the solution provided on that issuecomment as well, but I’ll have to look a bit deeper into docker-lambda thing.

Now the only issue with downgrade approach is that the suggestedFilename function is not in 1.0.2. Is there any workaround for that at the moment?

@dgozman I tried enabling the logs as you suggested above and turns out, the event is not firing up in lambda. I can see the download logs and network activity logs as below: image

The download was completed but I did not receive the completion callback. I used two approaches:

  • 1st Approach:
  const [download] = await Promise.all([
    page.waitForEvent('download'),
    page.click(`#${BTN_ID}`),
  ]);
  const downloadStream = await download.createReadStream();

Received timeout error

  • 2nd Approach:
const downloadFile = async (page, element) => {
  return new Promise((resolve, reject) => {
    page.on('download', (download) => {
      console.log('File downloaded!');
      resolve(download);
    });
    return page.click(element);
  });
};
const download = await downloadFile(page, `#${BTN_ID}`);

Did not receive any timeout error and the lambda function kept running, and ultimately, timed out.

I came up with the second approach to check if the on download event is emitted, which isn’t. So something’s up with the events on lambda. I have a project due, very soon, so any urgent help would be really appreciated.


This is the package I am using for chrome on lambda: https://github.com/JupiterOne/playwright-aws-lambda I guess this is the only difference between local and lambda execution. Locally, we use local installation of chrome and on lambda, we use this package. So Is it possible that this chrome is not emitting the on-download event? (but I can see the download completion in network logs)

Since num is a ElementHandle, the click method does not accept a new selector. You have to use $ to get the new element to click on it.

Example:

// @ts-check
const playwright = require("playwright");

(async () => {
  const browser = await playwright.chromium.launch()
  const context = await browser.newContext({
    acceptDownloads: true
  })
  const page = await context.newPage()
  await page.goto(
    "https://file-examples.com/index.php/sample-documents-download/sample-xls-download/"
  );

  const handles = await page.$$("#table-files .file-link");

  for (let num of handles) {
    const [download] = await Promise.all([
      page.waitForEvent("download"), // wait for download to start
      (await num.$("a.btn")).click(),
    ]);
    const path = await download.path();
    console.log(path)
  }
  await browser.close();
})();

Interactive: https://try.playwright.tech/?s=gd4r9