mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: make handle beforeunload when reusing the context (#18357)
Fixes: https://github.com/microsoft/playwright/issues/17903
This commit is contained in:
parent
d4bab139b2
commit
1505a952fe
@ -180,10 +180,13 @@ export abstract class BrowserContext extends SdkObject {
|
||||
page = undefined;
|
||||
}
|
||||
|
||||
// Unless I do this early, setting extra http headers below does not respond.
|
||||
// Unless dialogs are dismissed, setting extra http headers below does not respond.
|
||||
page?._frameManager.setCloseAllOpeningDialogs(true);
|
||||
await page?._frameManager.closeOpenDialogs();
|
||||
// Navigate to about:blank first to ensure no page scripts are running after this point.
|
||||
await page?.mainFrame().goto(metadata, 'about:blank', { timeout: 0 });
|
||||
page?._frameManager.setCloseAllOpeningDialogs(false);
|
||||
|
||||
await this._resetStorage();
|
||||
await this._removeExposedBindings();
|
||||
await this._removeInitScripts();
|
||||
|
@ -25,13 +25,13 @@ export type DialogType = 'alert' | 'beforeunload' | 'confirm' | 'prompt';
|
||||
|
||||
export class Dialog extends SdkObject {
|
||||
private _page: Page;
|
||||
private _type: string;
|
||||
private _type: DialogType;
|
||||
private _message: string;
|
||||
private _onHandle: OnHandle;
|
||||
private _handled = false;
|
||||
private _defaultValue: string;
|
||||
|
||||
constructor(page: Page, type: string, message: string, onHandle: OnHandle, defaultValue?: string) {
|
||||
constructor(page: Page, type: DialogType, message: string, onHandle: OnHandle, defaultValue?: string) {
|
||||
super(page, 'dialog');
|
||||
this._page = page;
|
||||
this._type = type;
|
||||
@ -53,7 +53,7 @@ export class Dialog extends SdkObject {
|
||||
return this._defaultValue;
|
||||
}
|
||||
|
||||
async accept(promptText: string | undefined) {
|
||||
async accept(promptText?: string) {
|
||||
assert(!this._handled, 'Cannot accept dialog which is already handled!');
|
||||
this._handled = true;
|
||||
this._page._frameManager.dialogWillClose(this);
|
||||
@ -66,4 +66,11 @@ export class Dialog extends SdkObject {
|
||||
this._page._frameManager.dialogWillClose(this);
|
||||
await this._onHandle(false);
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this._type === 'beforeunload')
|
||||
await this.accept();
|
||||
else
|
||||
await this.dismiss();
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +108,7 @@ export class FrameManager {
|
||||
readonly _signalBarriers = new Set<SignalBarrier>();
|
||||
private _webSockets = new Map<string, network.WebSocket>();
|
||||
_openedDialogs: Set<Dialog> = new Set();
|
||||
private _closeAllOpeningDialogs = false;
|
||||
|
||||
constructor(page: Page) {
|
||||
this._page = page;
|
||||
@ -352,7 +353,10 @@ export class FrameManager {
|
||||
// Any ongoing evaluations will be stalled until the dialog is closed.
|
||||
for (const frame of this._frames.values())
|
||||
frame._invalidateNonStallingEvaluations('JavaScript dialog interrupted evaluation');
|
||||
this._openedDialogs.add(dialog);
|
||||
if (this._closeAllOpeningDialogs)
|
||||
dialog.close().then(() => {});
|
||||
else
|
||||
this._openedDialogs.add(dialog);
|
||||
}
|
||||
|
||||
dialogWillClose(dialog: Dialog) {
|
||||
@ -360,10 +364,14 @@ export class FrameManager {
|
||||
}
|
||||
|
||||
async closeOpenDialogs() {
|
||||
await Promise.all([...this._openedDialogs].map(dialog => dialog.dismiss())).catch(() => {});
|
||||
await Promise.all([...this._openedDialogs].map(dialog => dialog.close())).catch(() => {});
|
||||
this._openedDialogs.clear();
|
||||
}
|
||||
|
||||
setCloseAllOpeningDialogs(closeDialogs: boolean) {
|
||||
this._closeAllOpeningDialogs = closeDialogs;
|
||||
}
|
||||
|
||||
removeChildFramesRecursively(frame: Frame) {
|
||||
for (const child of frame.childFrames())
|
||||
this._removeFramesRecursively(child);
|
||||
|
@ -349,3 +349,28 @@ test('should restore cookies', async ({ runInlineTest }) => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(3);
|
||||
});
|
||||
|
||||
test('should reuse context with beforeunload', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'src/reuse.test.ts': `
|
||||
const { test } = pwt;
|
||||
let lastContextGuid;
|
||||
test('one', async ({ page, context }) => {
|
||||
lastContextGuid = context._guid;
|
||||
await page.evaluate(() => {
|
||||
window.addEventListener('beforeunload', event => {
|
||||
event.preventDefault();
|
||||
return event.returnValue = "Are you sure you want to exit?";
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('two', async ({ context }) => {
|
||||
expect(context._guid).toBe(lastContextGuid);
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 }, { PW_TEST_REUSE_CONTEXT: '1' });
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(2);
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user