Skip to content

Commit c225524

Browse files
authored
fix: don't error on navigating to a download link (microsoft#328)
1 parent 950d0d1 commit c225524

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

src/tab.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,26 @@ export class Tab {
6666
}
6767

6868
async navigate(url: string) {
69-
await this.page.goto(url, { waitUntil: 'domcontentloaded' });
69+
const downloadEvent = this.page.waitForEvent('download').catch(() => {});
70+
try {
71+
await this.page.goto(url, { waitUntil: 'domcontentloaded' });
72+
} catch (_e: unknown) {
73+
const e = _e as Error;
74+
const mightBeDownload =
75+
e.message.includes('net::ERR_ABORTED') // chromium
76+
|| e.message.includes('Download is starting'); // firefox + webkit
77+
if (!mightBeDownload)
78+
throw e;
79+
80+
// on chromium, the download event is fired *after* page.goto rejects, so we wait a lil bit
81+
const download = await Promise.race([
82+
downloadEvent,
83+
new Promise(resolve => setTimeout(resolve, 500)),
84+
]);
85+
if (!download)
86+
throw e;
87+
}
88+
7089
// Cap load event to 5 seconds, the page is operational at this point.
7190
await this.page.waitForLoadState('load', { timeout: 5000 }).catch(() => {});
7291
}

tests/files.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,21 @@ test('clicking on download link emits download', async ({ startClient }, testInf
119119
### Downloads
120120
- Downloaded file test.txt to ${path.join(outputDir, 'test.txt')}`);
121121
});
122+
123+
test('navigating to download link emits download', async ({ client, server, mcpBrowser }) => {
124+
test.skip(mcpBrowser === 'webkit' && process.platform === 'linux', 'https://github.com/microsoft/playwright/blob/8e08fdb52c27bb75de9bf87627bf740fadab2122/tests/library/download.spec.ts#L436');
125+
server.route('/download', (req, res) => {
126+
res.writeHead(200, {
127+
'Content-Type': 'text/plain',
128+
'Content-Disposition': 'attachment; filename=test.txt',
129+
});
130+
res.end('Hello world!');
131+
});
132+
133+
expect(await client.callTool({
134+
name: 'browser_navigate',
135+
arguments: {
136+
url: server.PREFIX + '/download',
137+
},
138+
})).toContainTextContent('### Downloads');
139+
});

0 commit comments

Comments
 (0)