Context:
Code Snippet
const { chromium } = require("playwright");
(async () => {
const context = await chromium.launchPersistentContext("./udd", {
headless: false,
acceptDownloads: true,
downloadsPath: "./",
});
context.on("page", (page) => {
page.on("download", (download) => {
console.log("download", download);
});
});
const newPage = await context.newPage();
await newPage.goto(
"https://support.spatialkey.com/spatialkey-sample-csv-data"
);
newPage.on("download", (download) => download.path().then(console.log));
})();
Describe the bug
Expectation:
Current behavior:
context based listenerIs there something wrong with my machine? I tried quitting existing chrome installation and reinstalling all packages to no avail. Any suggestion would be helpful, thanks!
The same bug is happening with playwright@next as well. Complete version info: "playwright": "^1.2.0-next.1595618348108". Assuming it's something with my setup since such a bug would have been caught by others/tests too.
Can reproduce it on Windows too.
I think you may be hitting this test case which is known to be failing on Chromium Headfull:
The download links on the page to which you are navigating (https://support.spatialkey.com/spatialkey-sample-csv-data) look like:
<a href="http://samplecsvs.s3.amazonaws.com/SalesJan2009.csv" target="_blank" rel="noopener">download .csv file</a>
Note the target="_blank" which matches the linked test case.
Good find @rwoll! I can understand how this is an issue.
Is there a way that download event can be captured at browser level. I am not sure how chrome shows up the global downloads page or even the bottom bar which shows downloaded files. If we could emit a download event at browser level, it should make it immune to this closing-download-page behavior.
Also, do you think a bad-patch for this could be to force keep that new download page open?
Thanks for the help!
Is there a way that download event can be captured at browser level. I am not sure how chrome shows up the global downloads page or even the bottom bar which shows downloaded files. If we could emit a download event at browser level, it should make it immune to this closing-download-page behavior.
I'll defer to the core team as I'm not sure of the exact issue that's going on creating this bug. Some amount of information about the download gets to Playwright (as you'll see in my (hopefully) temporary hack).
Also, do you think a bad-patch for this could be to force keep that new download page open?
I'm not sure how you would force the page to stay open, but maybe that could work. An alternative, which I've been using, works as follows:
After getting a download event, try to get the path info via download.path(), if that doesn't resolve within 3 seconds, compute the path from internal fields on the download event:
const { chromium } = require("playwright");
const fs = require("fs");
const path = require("path");
const FORCE_DOWNLOAD_PATH_TIMEOUT = 3_000; // 3 seconds
const test = async ({ userDataDir, downloadsDir }) => {
const context = await chromium.launchPersistentContext(userDataDir, {
headless: false,
acceptDownloads: true,
downloadsPath: downloadsDir,
});
context.on("page", (page) => {
page.on("download", async (download) => {
const dlPath = await new Promise(async (res, reject) => {
const tid = setTimeout(() => {
clearTimeout(tid);
console.info("timedout waiting for path; forcing path");
res(path.join(download._downloadsPath, download._uuid));
}, FORCE_DOWNLOAD_PATH_TIMEOUT);
res(await download.path());
clearTimeout(tid);
});
console.log("download path:", dlPath);
});
});
const newPage = await context.newPage();
await newPage.goto(
"https://support.spatialkey.com/spatialkey-sample-csv-data"
);
newPage.on("download", (_download) => {});
await newPage.click("text='download .csv file'");
};
(async (test) => {
const userDataDir = fs.mkdtempSync("playwright-user-data-");
const downloadsDir = fs.mkdtempSync("playwright-downloads-");
try {
await test({ userDataDir, downloadsDir });
} catch (error) {
console.error("error while executing test:", error);
} finally {
fs.rmdirSync(userDataDir, { recursive: true });
fs.rmdirSync(downloadsDir, { recursive: true });
}
})(test);
After running that script (and manually clicking on one of the download links) you should see output like:
$ node hacks.js
timedout waiting for path; forcing path
download path: playwright-downloads-cZ4U4l/a43fefeb-b97c-4c35-aeb0-6540efe2f898
timedout waiting for path; forcing path
download path: playwright-downloads-cZ4U4l/95917e0e-bdaa-49bb-80bb-dc9ab8d1305a
@VikramTiwari Let me know if the workaround helps you or if you have questions, and hopefully someone from the PW team can help resolve the underlying issue so this hack isn't needed.
Hey @rwoll, this helped. Thanks a ton! :)
I haven't tried to stop the page from closing but I will try it and update on the status.
Most helpful comment
Can reproduce it on Windows too.