Skip to content

Commit ca08135

Browse files
authored
fix(browser): ignore synthetic pagehide events (#11582)
1 parent 14921e9 commit ca08135

2 files changed

Lines changed: 65 additions & 16 deletions

File tree

‎packages/browser/src/client/orchestrator.ts‎

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -358,22 +358,22 @@ export class IframeOrchestrator {
358358
// away during a test would keep the run waiting forever
359359
private watchUnload(iframe: HTMLIFrameElement, iframeId: string) {
360360
const loads = this.iframeLoads.get(iframe) ?? 0
361-
iframe.contentWindow?.addEventListener(
362-
'pagehide',
363-
() => {
364-
setTimeout(() => {
365-
if (
366-
this.iframes.get(iframeId) !== iframe ||
367-
!this.iframeEvents.get(iframe)?.size ||
368-
this.iframeLoads.get(iframe) !== loads
369-
) {
370-
return
371-
}
372-
this.dispatchIframeError(this.createConnectError(iframe, this.getIframeHref(iframe)))
373-
}, IFRAME_UNLOAD_TIMEOUT)
374-
},
375-
{ once: true },
376-
)
361+
iframe.contentWindow?.addEventListener('pagehide', (event) => {
362+
// tests can dispatch their own "pagehide"
363+
if (!event.isTrusted) {
364+
return
365+
}
366+
setTimeout(() => {
367+
if (
368+
this.iframes.get(iframeId) !== iframe ||
369+
!this.iframeEvents.get(iframe)?.size ||
370+
this.iframeLoads.get(iframe) !== loads
371+
) {
372+
return
373+
}
374+
this.dispatchIframeError(this.createConnectError(iframe, this.getIframeHref(iframe)))
375+
}, IFRAME_UNLOAD_TIMEOUT)
376+
})
377377
}
378378

379379
private createWarningMessage(iframeId: string, location: string) {

‎test/browser/specs/bail-out.test.ts‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,52 @@ test.runIf(
9090
)
9191
expect(stderr).toMatch(/Cannot connect to the iframe/)
9292
})
93+
94+
test.runIf(provider.name === 'playwright' && instances.some((i) => i.browser === 'firefox'))(
95+
'vitest bails out when the iframe navigates away after the test dispatched pagehide',
96+
async () => {
97+
const { stderr } = await runInlineBrowserTests(
98+
{
99+
'navigate.test.ts': `
100+
import { test } from 'vitest'
101+
102+
test('navigates away', async () => {
103+
window.dispatchEvent(new Event('pagehide'))
104+
location.href = 'http://127.0.0.1:1/'
105+
await new Promise(() => {})
106+
})
107+
`,
108+
},
109+
{
110+
browser: { instances: instances.filter((instance) => instance.browser === 'firefox') },
111+
},
112+
{ fails: true },
113+
)
114+
expect(stderr).toMatch(/Cannot connect to the iframe/)
115+
},
116+
)
117+
118+
test('pagehide dispatched by the test does not fail the running file', async () => {
119+
const { stderr, testTree } = await runInlineBrowserTests(
120+
{
121+
'pagehide.test.ts': `
122+
import { test } from 'vitest'
123+
124+
test('runs page lifecycle code', async () => {
125+
window.dispatchEvent(new Event('pagehide'))
126+
await new Promise((resolve) => setTimeout(resolve, 6_000))
127+
})
128+
`,
129+
},
130+
{ browser: { instances: [instances[0]] } },
131+
)
132+
133+
expect(stderr).toBe('')
134+
expect(testTree()).toMatchInlineSnapshot(`
135+
{
136+
"pagehide.test.ts": {
137+
"runs page lifecycle code": "passed",
138+
},
139+
}
140+
`)
141+
})

0 commit comments

Comments
 (0)