问题描述
我正在使用Puppeteer在网站上测试某些表格。在运行测试时,我发现尝试在页面之间导航时执行被卡住了。我自己进行了一次试运行,意识到由于某些表单输入已更改,而表单没有提交,因此页面正在发出对话框。
该消息显示:
Leave site?
Changes you made may not be saved.
有一些明显的解决方法,例如,我可以确保在导航到下一页之前每次都提交表单。但是,理想情况下,我只希望能够完全忽略此对话框,因为我只是在运行测试,并且我不在乎更改不会被保存。
是否可以禁用这些消息?如果没有,是否有办法检查是否打开了一个对话框,然后将其关闭?
解决方法
尝试由puppeteer设置window.onbeforeunload = null
await page.evaluate(() => {
window.onbeforeunload = null;
});
,
为了详细说明 existing answer,您尝试处理的 beforeunload
事件会导致出现一个对话框提示。此对话框的处理方式与 prompt
和 alert
相同,使用 page.on("dialog",dialog => ...)
。
可以检查传递给处理程序的 dialog
对象是否存在 "beforeunload"
type,然后您可以根据您的行为调用 dismiss()
或 accept()
想。 dismiss()
停留在当前页面,中止导航操作,而 accept()
同意离开网站。
您可能的解决方案是同意与 accept()
一起离开网站:
const puppeteer = require("puppeteer");
let browser;
(async () => {
const html = `
<h1>a page that prompts before unload</h1>
<script>
window.addEventListener("beforeunload",function (e) {
e.preventDefault();
(e || window.event).returnValue = "";
return "";
});
</script>
`;
browser = await puppeteer.launch({headless: false});
const [page] = await browser.pages();
const acceptBeforeUnload = dialog =>
dialog.type() === "beforeunload" && dialog.accept()
;
page.on("dialog",acceptBeforeUnload);
await page.setContent(html);
await page.goto("https://www.example.com");
console.log(page.url()); // => => https://www.example.com
})()
.catch(err => console.error(err))
.finally(() => browser.close())
;
请注意,使用现有答案中简单地在 window.beforeunload = null
回调中设置 evaluate
的方法不适用于此页面。您可以通过删除 page.on
并在 evaluate
上方添加 page.goto
调用来测试。
但是,对于更复杂的行为,例如动态启用和禁用卸载,evaluate
方法似乎有助于避免中止抛出以及删除关闭处理程序,如本示例所示:
const puppeteer = require("puppeteer");
let browser;
(async () => {
const html = `
<h1>a page that prompts before unload</h1>
<script>
window.addEventListener("beforeunload",function (e) {
e.preventDefault();
(e || window.event).returnValue = "";
return "";
});
</script>
`;
browser = await puppeteer.launch({headless: false});
const [page] = await browser.pages();
const dismissBeforeUnload = dialog =>
dialog.type() === "beforeunload" && dialog.dismiss()
;
page.on("dialog",dismissBeforeUnload);
await page.setContent(html);
// throws Error: net::ERR_ABORTED at https://www.example.com
await page.goto("https://www.example.com").catch(() => {});
console.log(page.url()); // => about:blank
// add to avoid Error: net::ERR_ABORTED when adding a new handler
await page.evaluate(() => {
window.onbeforeunload = null;
});
page.off("dialog",dismissBeforeUnload);
// next unload,we'll accept the dialog
page.on("dialog",dialog =>
dialog.type() === "beforeunload" && dialog.accept()
);
// this navigation will succeed
await page.goto("https://www.example.com");
console.log(page.url()); // => https://www.example.com
})()
.catch(err => console.error(err))
.finally(() => browser.close())
;