mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-05 19:04:43 +03:00
fix(lifecycle): recalculate lifecycle on iframe detach (#15812)
It could be that iframe was blocking some event, like load or networkidle, and we never updated the lifecycle after the iframe was detached. This lead to goto and other navigation commands to never resolve.
This commit is contained in:
parent
fd21852b01
commit
4bec6309df
@ -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<types.LifecycleEvent>(this._firedLifecycleEvents);
|
||||
for (const child of this._childFrames) {
|
||||
child._recalculateLifecycle();
|
||||
|
@ -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(`
|
||||
<body>
|
||||
<script>
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = './iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
setTimeout(() => iframe.remove(), 1000);
|
||||
</script>
|
||||
</body>
|
||||
`);
|
||||
});
|
||||
|
||||
server.setRoute('/iframe.html', (req, res) => {
|
||||
res.writeHead(200, { 'content-type': 'text/html' });
|
||||
res.end(`
|
||||
<link rel="stylesheet" href="./style2.css">
|
||||
`);
|
||||
});
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
@ -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(`
|
||||
<body>
|
||||
<script>
|
||||
setTimeout(() => {
|
||||
const iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
setTimeout(() => iframe.remove(), 400);
|
||||
}, 400);
|
||||
</script>
|
||||
</body>
|
||||
`, { waitUntil: 'networkidle' });
|
||||
expect(await page.$('iframe')).toBe(null);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user