mirror of
https://github.com/cypress-io/cypress.git
synced 2026-04-29 11:32:15 -05:00
fix: workaround for the electron animation bug (#31391)
* fix: workaround for the electron animation bug * fix bug * Update packages/server/test/unit/browsers/electron_spec.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * try something * try something * try something * try something * fix * fix * fix * refactor and ensure still broken * and the fix * Update packages/server/test/unit/browsers/electron_spec.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/server/lib/browsers/electron.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update CHANGELOG.md * refactor * Update cli/CHANGELOG.md * Update cli/CHANGELOG.md Co-authored-by: Matt Schile <mschile@cypress.io> * fix build * Update packages/server/test/unit/browsers/electron_spec.js --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jennifer Shehane <jennifer@cypress.io> Co-authored-by: Matt Schile <mschile@cypress.io>
This commit is contained in:
@@ -7,6 +7,7 @@ _Released 4/8/2025 (PENDING)_
|
||||
|
||||
- Allows for `babel-loader` version 10 to be a peer dependency of `@cypress/webpack-preprocessor`. Fixed in [#31218](https://github.com/cypress-io/cypress/pull/31218).
|
||||
- Fixed an issue where Firefox BiDi was prematurely removing prerequests on pending requests. Fixes [#31376](https://github.com/cypress-io/cypress/issues/31376).
|
||||
- Fixed an [issue](https://github.com/electron/electron/issues/45398) with Electron causing slow animations and increased test times by starting a CDP screencast with a noop configuration. Fixes [#30980](https://github.com/cypress-io/cypress/issues/30980).
|
||||
|
||||
**Misc:**
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { CDPSocketServer } from '@packages/socket/lib/cdp-socket'
|
||||
import memory from './memory'
|
||||
import { BrowserCriClient } from './browser-cri-client'
|
||||
import { getRemoteDebuggingPort } from '../util/electron-app'
|
||||
import type { CriClient } from './cri-client'
|
||||
|
||||
// TODO: unmix these two types
|
||||
type ElectronOpts = Windows.WindowOptions & BrowserLaunchOpts
|
||||
@@ -131,6 +132,25 @@ async function recordVideo (cdpAutomation: CdpAutomation, videoApi: RunModeVideo
|
||||
await cdpAutomation.startVideoRecording(writeVideoFrame, screencastOpts())
|
||||
}
|
||||
|
||||
// Start video legitimately if we have a video api. Otherwise, if we're in run mode, start a dummy screencast to prevent:
|
||||
// https://github.com/electron/electron/issues/45398
|
||||
async function handleVideo (handleVideoOptions: { pageCriClient: CriClient, cdpAutomation: CdpAutomation, videoApi?: RunModeVideoApi, options: BrowserLaunchOpts }) {
|
||||
const { pageCriClient, cdpAutomation, videoApi, options } = handleVideoOptions
|
||||
|
||||
if (videoApi) {
|
||||
await recordVideo(cdpAutomation, videoApi)
|
||||
} else if (options.isTextTerminal) {
|
||||
// To prevent https://github.com/electron/electron/issues/45398, we start a dummy screen cast with a quality of 0
|
||||
// and only capture every 2^32 - 1 frames without listening to any frames. This is effectively a no-op, but it
|
||||
// prevents the issue from occurring.
|
||||
await pageCriClient.send('Page.startScreencast', {
|
||||
format: 'jpeg',
|
||||
everyNthFrame: 2 ** 31 - 1,
|
||||
quality: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export = {
|
||||
_defaultOptions (projectRoot: string | undefined, state: Preferences, options: BrowserLaunchOpts, automation: Automation): ElectronOpts {
|
||||
const _this = this
|
||||
@@ -317,7 +337,7 @@ export = {
|
||||
pageCriClient.send('ServiceWorker.enable'),
|
||||
this.connectProtocolToBrowser({ protocolManager }),
|
||||
cdpSocketServer?.attachCDPClient(cdpAutomation),
|
||||
videoApi && recordVideo(cdpAutomation, videoApi),
|
||||
handleVideo({ pageCriClient, cdpAutomation, videoApi, options }),
|
||||
this._handleDownloads(win, options.downloadsFolder, automation),
|
||||
utils.initializeCDP(pageCriClient, automation),
|
||||
// Ensure to clear browser state in between runs. This is handled differently in browsers when we launch new tabs, but we don't have that concept in electron
|
||||
|
||||
@@ -14,6 +14,7 @@ const { Automation } = require(`../../../lib/automation`)
|
||||
const { BrowserCriClient } = require('../../../lib/browsers/browser-cri-client')
|
||||
const electronApp = require('../../../lib/util/electron-app')
|
||||
const utils = require('../../../lib/browsers/utils')
|
||||
const { screencastOpts } = require('../../../lib/browsers/cdp_automation')
|
||||
|
||||
const ELECTRON_PID = 10001
|
||||
|
||||
@@ -476,6 +477,41 @@ describe('lib/browsers/electron', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('expects the video to be fully enabled if specified in the config', async function () {
|
||||
const mockWriteVideoFrame = sinon.stub()
|
||||
const mockVideoApi = {
|
||||
useFfmpegVideoController: sinon.stub().resolves({
|
||||
writeVideoFrame: mockWriteVideoFrame,
|
||||
}),
|
||||
}
|
||||
|
||||
await electron._launch(this.win, this.url, this.automation, this.options, mockVideoApi, undefined, { attachCDPClient: sinon.stub() })
|
||||
|
||||
expect(mockVideoApi.useFfmpegVideoController).to.be.called
|
||||
expect(this.pageCriClient.on).to.be.calledWith('Page.screencastFrame', sinon.match.func)
|
||||
expect(this.pageCriClient.send).to.be.calledWith('Page.startScreencast', screencastOpts())
|
||||
})
|
||||
|
||||
it('starts the screencast but does not capture the frames if video is not enabled but the app is in run mode', async function () {
|
||||
this.options.isTextTerminal = true
|
||||
|
||||
await electron._launch(this.win, this.url, this.automation, this.options, undefined, undefined, { attachCDPClient: sinon.stub() })
|
||||
|
||||
expect(this.pageCriClient.on).not.to.be.calledWith('Page.screencastFrame', sinon.match.func)
|
||||
expect(this.pageCriClient.send).to.be.calledWith('Page.startScreencast', {
|
||||
format: 'jpeg',
|
||||
everyNthFrame: 2 ** 31 - 1,
|
||||
quality: 0,
|
||||
})
|
||||
})
|
||||
|
||||
it('does not start the screencast if video is not enabled and the app is not in run mode', async function () {
|
||||
await electron._launch(this.win, this.url, this.automation, this.options, undefined, undefined, { attachCDPClient: sinon.stub() })
|
||||
|
||||
expect(this.pageCriClient.on).not.to.be.calledWith('Page.screencastFrame', sinon.match.func)
|
||||
expect(this.pageCriClient.send).not.to.be.calledWith('Page.startScreencast', sinon.match.any)
|
||||
})
|
||||
|
||||
it('registers onRequest automation middleware and calls show when requesting to be focused', function () {
|
||||
sinon.spy(this.automation, 'use')
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
describe('electron animation bug', () => {
|
||||
it('loads in less than .3 seconds', { defaultCommandTimeout: 750 }, () => {
|
||||
cy.visit('/electron_animation_bug.html')
|
||||
|
||||
cy.get('#app').should('exist')
|
||||
cy.get('#remove').click()
|
||||
cy.get('#app').should('not.exist')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<div>hello</div>
|
||||
<div>world</div>
|
||||
</div>
|
||||
<button id="remove">remove</button>
|
||||
<script>
|
||||
const remove = document.getElementById('remove')
|
||||
remove.addEventListener('click', () => {
|
||||
const app = document.getElementById('app')
|
||||
app.animate([
|
||||
{ transform: 'translate(5px, 10px)', opacity: 0 }
|
||||
], {
|
||||
duration: 500,
|
||||
easing: 'cubic-bezier(0.4, 0, 1, 1)'
|
||||
}).finished.then(() => {
|
||||
app.remove()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,9 @@
|
||||
import { default as systemTests } from '../lib/system-tests'
|
||||
|
||||
describe('e2e electron animation bug', () => {
|
||||
systemTests.it('executes a test that demonstrates the electron animation bug and ensures that we have worked around it', {
|
||||
browser: 'electron',
|
||||
project: 'e2e',
|
||||
spec: 'electron_animation_bug.cy.ts',
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user