我可以忽略“离开站点”吗?使用 Puppeteer 浏览无头时的对话框?

问题描述 投票:0回答:2

我正在使用 Puppeteer 在网站上测试一些表单。当我运行测试时,我注意到尝试在页面之间导航时执行会卡住。我自己手动进行了一次试运行,并意识到该页面正在发出一个对话框,因为某些表单输入已更改而未提交表单。

这条消息说:

Leave site?
Changes you made may not be saved.

对此有一些明显的解决方法,例如我可以确保每次导航到下一页之前都提交表单。但是,理想情况下,我希望能够完全忽略此对话框,因为我只是在运行测试,并且我不在乎更改是否会被保存。

有办法禁用这些消息吗?如果没有,有没有办法检查是否有一个对话框打开然后将其关闭?

javascript node.js google-chrome dialog puppeteer
2个回答
6
投票

尝试通过 puppeteer 设置 window.onbeforeunload = null

await page.evaluate(() => {
  window.onbeforeunload = null;
});

4
投票

为了详细说明现有答案,您尝试处理的

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());
© www.soinside.com 2019 - 2024. All rights reserved.