Chrome 当我使用Puppeteer浏览无头网站时,我可以忽略“离开网站?”对话框吗?

vshtjzan  于 2022-12-30  发布在  Go
关注(0)|答案(2)|浏览(192)

我正在使用Puppeteer测试一个网站上的一些表单。当我运行测试时,我注意到尝试在页面之间导航时执行受阻。我自己手动做了一次试运行,意识到页面正在发出一个对话框,因为一些表单输入在表单未提交的情况下发生了变化。
这条信息说:

Leave site?
Changes you made may not be saved.

有一些明显的解决方法,比如我可以确保每次在导航到下一页之前提交表单。但是,我最好能够完全忽略这个对话框,因为我只是在运行测试,我不在乎更改是否会被保存。
有没有办法关闭这些消息?如果没有,有没有办法检查是否有一个对话框打开,然后关闭它?

lztngnrs

lztngnrs1#

尝试设置窗口.onbeforeunload = null由puppeteer

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

xdnvmnnf2#

详细说明一下existing answer,您要处理的beforeunload事件会导致出现一个对话框提示符,该对话框的处理方式与prompt s和alert s相同,但使用page.on("dialog", dialog => ...)
可以检查传递给处理程序的dialog对象是否为"beforeunload"类型,然后可以根据需要的行为调用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())
;

请注意,使用现有的answer方法在evaluate回调中简单地设置window.beforeunload = null对本页不起作用。您可以通过删除page.on并在page.goto上添加evaluate调用来测试。
但是,对于更复杂的行为,如动态启用和禁用卸载,evaluate方法似乎有助于避免在删除dismiss处理程序时出现异常中止抛出,如以下示例所示:

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())
;

相关问题