diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 1d708bf0da..ef8356ca63 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -277,8 +277,11 @@ export class FrameManager { frameDetached(frameId: string) { const frame = this._frames.get(frameId); - if (frame) + if (frame) { this._removeFramesRecursively(frame); + // Recalculate subtree lifecycle for the whole tree - it should not be that big. + this._page.mainFrame()._recalculateLifecycle(); + } } frameStoppedLoading(frameId: string) { @@ -590,7 +593,7 @@ export class Frame extends SdkObject { }); } - private _recalculateLifecycle() { + _recalculateLifecycle() { const events = new Set(this._firedLifecycleEvents); for (const child of this._childFrames) { child._recalculateLifecycle(); diff --git a/tests/page/page-goto.spec.ts b/tests/page/page-goto.spec.ts index bfb2493e0e..d7673be7c1 100644 --- a/tests/page/page-goto.spec.ts +++ b/tests/page/page-goto.spec.ts @@ -663,3 +663,35 @@ it('should return when navigation is committed if commit is specified', async ({ const response = await page.goto(server.EMPTY_PAGE, { waitUntil: 'commit' }); expect(response.status()).toBe(200); }); + +it('should wait for load when iframe attaches and detaches', async ({ page, server }) => { + server.setRoute('/empty.html', (req, res) => { + res.writeHead(200, { 'content-type': 'text/html' }); + res.end(` + + + + `); + }); + + server.setRoute('/iframe.html', (req, res) => { + res.writeHead(200, { 'content-type': 'text/html' }); + res.end(` + + `); + }); + + // Stall the css so that 'load' does not fire. + server.setRoute('/style2.css', () => {}); + + const frameDetached = page.waitForEvent('framedetached'); + const done = page.goto(server.EMPTY_PAGE, { waitUntil: 'load' }); + await frameDetached; // Make sure that iframe is gone. + await done; + expect(await page.$('iframe')).toBe(null); +}); diff --git a/tests/page/page-network-idle.spec.ts b/tests/page/page-network-idle.spec.ts index a93d7ba3e9..1447d156e0 100644 --- a/tests/page/page-network-idle.spec.ts +++ b/tests/page/page-network-idle.spec.ts @@ -157,3 +157,18 @@ it('should wait for networkidle from the popup', async ({ page, server, isAndroi await popup.waitForLoadState('networkidle'); } }); + +it('should wait for networkidle when iframe attaches and detaches', async ({ page }) => { + await page.setContent(` + + + + `, { waitUntil: 'networkidle' }); + expect(await page.$('iframe')).toBe(null); +});