mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-04 14:19:55 -06:00
fix: preserve navigation functionality when unload event is deprecated (#29525)
* chore: Force deprecation of unload event * empty commit * use pagehide instead of unload event * tslint * bump cache * some debugging * rm debug * comment out forced deprecation of unload - tbd how to enable * rm more unnecessary debug * changelog * rename event callback from onUnload -> onPageHide * comment on discrepency of event naming for end of page lifecycle events * use pagehide in chrome, unload elsewhere * comment on chromium-specific pagehide behavior * changelog --------- Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
# Bump this version to force CI to re-create the cache from scratch.
|
||||
|
||||
05-10-24
|
||||
05-09-24
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
|
||||
## 13.10.1
|
||||
|
||||
_Released 5/28/2024 (PENDING)_
|
||||
|
||||
**Bugfixes:**
|
||||
|
||||
- Pre-emptively fix behavior with Chrome for when `unload` events are forcefully deprecated by using `pagehide` as a proxy. Fixes [#29241](https://github.com/cypress-io/cypress/issues/29241).
|
||||
|
||||
## 13.10.0
|
||||
|
||||
_Released 5/21/2024_
|
||||
|
||||
@@ -344,7 +344,12 @@ export class EventManager {
|
||||
// when we actually unload then
|
||||
// nuke all of the cookies again
|
||||
// so we clear out unload
|
||||
$window.on('unload', () => {
|
||||
// While we must move to pagehide for Chromium, it does not work for our
|
||||
// needs in Firefox. Until that is addressed, only Chromium uses the pagehide
|
||||
// event as a proxy for AUT unloads.
|
||||
const unloadEvent = this.isBrowser({ family: 'chromium' }) ? 'pagehide' : 'unload'
|
||||
|
||||
$window.on(unloadEvent, (e) => {
|
||||
this._clearAllCookies()
|
||||
})
|
||||
|
||||
|
||||
@@ -97,13 +97,15 @@ describe('src/cy/commands/navigation', () => {
|
||||
})
|
||||
|
||||
it('removes listeners', () => {
|
||||
cy.log(Cypress.browser)
|
||||
const unloadEvent = Cypress.browser.family === 'chromium' ? 'pagehide' : 'unload'
|
||||
const win = cy.state('window')
|
||||
|
||||
const rel = cy.stub(win, 'removeEventListener')
|
||||
|
||||
cy.reload().then(() => {
|
||||
expect(rel).to.be.calledWith('beforeunload')
|
||||
expect(rel).to.be.calledWith('unload')
|
||||
expect(rel).to.be.calledWith(unloadEvent)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -411,8 +413,10 @@ describe('src/cy/commands/navigation', () => {
|
||||
const rel = cy.stub(win, 'removeEventListener')
|
||||
|
||||
cy.go('back').then(() => {
|
||||
const unloadEvent = cy.browser.family === 'chromium' ? 'pagehide' : 'unload'
|
||||
|
||||
expect(rel).to.be.calledWith('beforeunload')
|
||||
expect(rel).to.be.calledWith('unload')
|
||||
expect(rel).to.be.calledWith(unloadEvent)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -218,10 +218,13 @@ const attachToWindow = (autWindow: Window) => {
|
||||
Cypress.specBridgeCommunicator.toPrimary('window:load', { url: remoteLocation.href })
|
||||
cy.isStable(true, 'load')
|
||||
},
|
||||
onUnload (e) {
|
||||
onPageHide (e) {
|
||||
cy.state('window', undefined)
|
||||
cy.state('document', undefined)
|
||||
|
||||
// unload is being actively deprecated/removed by chrome, so for
|
||||
// compatibility, we are using `window`'s `pagehide` event as a proxy
|
||||
// for the `window:unload` event that we emit. See: https://github.com/cypress-io/cypress/pull/29525
|
||||
return Cypress.action('app:window:unload', e)
|
||||
},
|
||||
onNavigation (...args) {
|
||||
|
||||
@@ -2,16 +2,20 @@ import type { $Cy } from '../../cypress/cy'
|
||||
import { handleErrorEvent } from './errors'
|
||||
|
||||
export const handleSpecWindowEvents = (cy: $Cy) => {
|
||||
// While we must move to pagehide for Chromium, it does not work for our
|
||||
// needs in Firefox. Until that is addressed, only Chromium uses the pagehide
|
||||
// event as a proxy for AUT unloads.
|
||||
const unloadEvent = cy.Cypress.browser.family === 'chromium' ? 'pagehide' : 'unload'
|
||||
const handleWindowErrorEvent = handleErrorEvent(cy, 'spec')('error')
|
||||
const handleWindowUnhandledRejectionEvent = handleErrorEvent(cy, 'spec')('unhandledrejection')
|
||||
|
||||
const handleUnload = () => {
|
||||
window.removeEventListener('unload', handleUnload)
|
||||
window.removeEventListener(unloadEvent, handleUnload)
|
||||
window.removeEventListener('error', handleWindowErrorEvent)
|
||||
window.removeEventListener('unhandledrejection', handleWindowUnhandledRejectionEvent)
|
||||
}
|
||||
|
||||
window.addEventListener('unload', handleUnload)
|
||||
window.addEventListener(unloadEvent, handleUnload)
|
||||
window.addEventListener('error', handleWindowErrorEvent)
|
||||
window.addEventListener('unhandledrejection', handleWindowUnhandledRejectionEvent)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ type BoundCallbacks = {
|
||||
onSubmit: (e) => any
|
||||
onLoad: (e) => any
|
||||
onBeforeUnload: (e) => undefined | Promise<undefined>
|
||||
onUnload: (e) => any
|
||||
onPageHide: (e: PageTransitionEvent) => any
|
||||
onNavigation: (...args) => any
|
||||
onAlert: (str) => any
|
||||
onConfirm: (str) => boolean
|
||||
@@ -93,12 +93,18 @@ export const bindToListeners = (contentWindow, callbacks: BoundCallbacks) => {
|
||||
callbacks.onBeforeUnload(e)
|
||||
})
|
||||
|
||||
addListener(contentWindow, 'unload', (e) => {
|
||||
// While we must move to pagehide for Chromium, it does not work for our
|
||||
// needs in Firefox. Until that is addressed, only Chromium uses the pagehide
|
||||
// event as a proxy for AUT unloads.
|
||||
|
||||
const unloadEvent = Cypress.browser.family === 'chromium' ? 'pagehide' : 'unload'
|
||||
|
||||
addListener(contentWindow, unloadEvent, (e) => {
|
||||
// when we unload we need to remove all of the event listeners
|
||||
removeAllListeners()
|
||||
|
||||
// else we know to proceed onwards!
|
||||
callbacks.onUnload(e)
|
||||
callbacks.onPageHide(e)
|
||||
})
|
||||
|
||||
addListener(contentWindow, 'hashchange', (e) => {
|
||||
|
||||
@@ -117,6 +117,8 @@ class $Cypress {
|
||||
log: any
|
||||
isBrowser: any
|
||||
browserMajorVersion: any
|
||||
// This is NodeEventEmitter['emit'], but typescript cannot determine that it is
|
||||
// definitively initialized due to being initialized with $Events.extend(this)
|
||||
emit: any
|
||||
emitThen: any
|
||||
emitMap: any
|
||||
|
||||
@@ -1125,7 +1125,10 @@ export class $Cy extends EventEmitter2 implements ITimeouts, IStability, IAssert
|
||||
// doesn't trigger a confirmation dialog
|
||||
return undefined
|
||||
},
|
||||
onUnload (e) {
|
||||
onPageHide (e) {
|
||||
// unload is being actively deprecated/removed by chrome, so for
|
||||
// compatibility, we are using `window`'s `pagehide` event as a proxy
|
||||
// for the `window:unload` event that we emit. See: https://github.com/cypress-io/cypress/pull/29525
|
||||
return cy.Cypress.action('app:window:unload', e)
|
||||
},
|
||||
onNavigation (...args) {
|
||||
|
||||
@@ -5,6 +5,8 @@ const disabledFeatures = [
|
||||
// Disables "Enhanced ad privacy in Chrome" dialog
|
||||
// https://github.com/cypress-io/cypress/issues/29199
|
||||
'PrivacySandboxSettings4',
|
||||
// Uncomment to force the deprecation of unload events
|
||||
// 'DeprecateUnloadByUserAndOrigin',
|
||||
]
|
||||
|
||||
// Common Chrome Flags for Automation
|
||||
@@ -91,6 +93,9 @@ const DEFAULT_FLAGS = [
|
||||
|
||||
// enable precise memory info so performance.memory returns more accurate values
|
||||
'enable-precise-memory-info',
|
||||
|
||||
// Uncomment to force the deprecation of upload events
|
||||
//`--enable-features=PermissionsPolicyUnload,DeprecateUnload`,
|
||||
]
|
||||
|
||||
// prepend -- to each flag and concatenate them together
|
||||
|
||||
Reference in New Issue
Block a user