最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can I ignore the "Leave Site?" dialog when browsing headless using Puppeteer? - Stack Overflow

programmeradmin1浏览0评论

I am testing some forms on a website using Puppeteer. When I run the tests, I noticed the execution gets stuck when trying to navigate between pages. I did a dry run myself manually and realised that the page is issuing a dialog as some of the form inputs have changed without the form being submitted.

It's the message that says:

Leave site?
Changes you made may not be saved.

There are some obvious workarounds to this like I could ensure that the form is submitted each time before navigating to the next page. However, I'd ideally like to just be able to ignore this dialog altogether as I'm just running tests and I don't care that the changes won't be saved.

Is there a way to disable these messages? If not, is there a way to check if there's a dialog open and then dismiss it?

I am testing some forms on a website using Puppeteer. When I run the tests, I noticed the execution gets stuck when trying to navigate between pages. I did a dry run myself manually and realised that the page is issuing a dialog as some of the form inputs have changed without the form being submitted.

It's the message that says:

Leave site?
Changes you made may not be saved.

There are some obvious workarounds to this like I could ensure that the form is submitted each time before navigating to the next page. However, I'd ideally like to just be able to ignore this dialog altogether as I'm just running tests and I don't care that the changes won't be saved.

Is there a way to disable these messages? If not, is there a way to check if there's a dialog open and then dismiss it?

Share Improve this question asked Oct 28, 2020 at 8:57 dashingdovedashingdove 4451 gold badge8 silver badges18 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

Try to set window.onbeforeunload = null by puppeteer

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

To elaborate on the existing answer, the beforeunload event you're trying to deal with causes a dialog box prompt to appear. This dialog can be handled in the same manner as prompts and alerts, with page.on("dialog", dialog => ...).

The dialog object passed to the handler can be checked for the "beforeunload" type, then you can call dismiss() or accept() depending on the behavior you want. dismiss() stays on the current page, aborting the navigation action, while accept() agrees to leave the site.

Your likely solution is to agree to leave the site with 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.");
  console.log(page.url()); // => => https://www.example.
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

Note that using the existing answer's method of simply setting window.beforeunload = null in an evaluate callback doesn't work for this page. You can test that by removing the page.on and adding the evaluate call above page.goto.

However, for more plex behaviors, like enabling and disabling the unload dynamically, the evaluate approach seems to help avoid abort throws in conjunction with removing a dismiss handler, as this example illustrates:

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.
  await page.goto("https://www.example.").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.");
  console.log(page.url()); // => https://www.example.
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());
发布评论

评论列表(0)

  1. 暂无评论