我正在使用 Puppeteer 在网站上测试一些表单。当我运行测试时,我注意到尝试在页面之间导航时执行会卡住。我自己手动进行了一次试运行,并意识到该页面正在发出一个对话框,因为某些表单输入已更改而未提交表单。
这条消息说:
Leave site?
Changes you made may not be saved.
对此有一些明显的解决方法,例如我可以确保每次导航到下一页之前都提交表单。但是,理想情况下,我希望能够完全忽略此对话框,因为我只是在运行测试,并且我不在乎更改是否会被保存。
有办法禁用这些消息吗?如果没有,有没有办法检查是否有一个对话框打开然后将其关闭?
尝试通过 puppeteer 设置 window.onbeforeunload = null
await page.evaluate(() => {
window.onbeforeunload = null;
});
为了详细说明现有答案,您尝试处理的
beforeunload
事件会导致出现对话框提示。该对话框的处理方式与 prompt
和 alert
相同,使用 page.on("dialog", dialog => ...)
。
dialog
对象的 "beforeunload"
type,然后您可以根据您想要的行为调用 dismiss()
或 accept()
。 dismiss()
留在当前页面,中止导航操作,而 accept()
同意离开网站。
您可能的解决方案是同意离开网站
accept()
:
import puppeteer from "puppeteer"; // ^23.6.0
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
方法似乎有助于避免中止抛出以及删除解雇处理程序,如本例所示:
import puppeteer from "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());