microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
66.56k stars 3.64k forks source link

[BUG] Dismissing `beforeunload` prompt doesn't work in Chrome and Webkit #14431

Closed trotzig closed 1 year ago

trotzig commented 2 years ago

Context:

Code Snippet

import { chromium } from '@playwright/test';

const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
page.on('dialog', async dialog => {
  await dialog.dismiss();
  console.log('dialog dismissed');
});
await page.evaluate(() => {
  window.onbeforeunload = e => {
    return 'Confirm closing the page';
  };
});
console.log('before reload');
await page.evaluate(() => window.location.reload());
console.log('after reload');

await context.close();
await browser.close();

Describe the bug

We use Playwright at happo.io to take screenshots of web components/pages. One of our integration types is a Storybook runner that turns your Storybook stories into Happo screenshot tests. We iterate over all stories and render them one by one, taking a screenshot for each story. In rare cases, the Storybook story can trigger a navigation/change of location. This is bad for our test runner, so we try to disable them by adding a beforeunload listener and a page.on('dialog', ...) handler to auto-dismiss the dialog that appears when the page context is about to change/unload.

For some reason, calling dialog.dismiss() on the dialog that is triggered by a beforeunload event doesn't seem to dismiss the dialog. There's no error, and execution continues, but any communication with the Playwright page/context (e.g. calling page.evaluate) will stall.

The above code snippet will reproduce the bug. You'll see these terminal logs:

before reload
dialog dismissed

and nothing more. The expected output would be:

before reload
dialog dismissed
after reload

If you run the script in headful mode, you'll see that the "Reload site?" dialog remains visible even though the dialog.dismiss() call succeeds.

I can reproduce the bug using the repro script in Chrome and Webkit.

yury-s commented 2 years ago

I can reproduce it, after the dialog is dismissed await page.evaluate(() => window.location.reload()); is still hanging, the dialog seems to stay open too.

micahjon commented 2 years ago

Running into this issue as well. In my case await page.goBack() hangs forever if an onbeforeunload dialog is shown, even if I add an on('dialog') listener that dismisses it (dialog is not dismissed when I run in headless: false mode).

micahjon commented 2 years ago

@trotzig , @yury-s , was this working for either of you in a prior version of Playwright? I'd be happy to downgrade if it is. I tried installing some older versions yesterday but didn't have any luck.

I know this was working in Puppeteer (we noticed it when porting to Playwright).

trotzig commented 2 years ago

I don't know. I know it worked at some point in Puppeteer but I have no details really.

micahjon commented 2 years ago

Fortunately it does work in Firefox on Playwright. Using that for now.

LazyCompiler commented 2 years ago

I experience the same bug. In my case, I'm testing a Chrome Extension, and so the website I enter has this before-leaving-are-you-sure dialog.

Because both the dialog.dismiss() and the dialog.accept() functions didn't work, I decided to avoid this dialog by overriding the onbeforeunload event that caused it:

await page.evaluate(() => {
    window.onbeforeunload = null;
})
kspeers-r7 commented 1 year ago

I'm also seeing this issue - in my case, I'm injecting a beforeUnload handler to deliberately block navigation away and as such, need to dismiss the beforeunload dialog to block the navigation

marcusNumminen commented 1 year ago

I'm also facing this issue. I'm experimenting with some monkey testing with Gremilins.js and I'm trying to inject beforeunload to prevent navigation outside the current page.

aslushnikov commented 1 year ago

Merging this into https://github.com/microsoft/playwright/issues/21715