This package is responsible for installing, building, and managing the Electron binary that powers Cypress. It enables development with an Electron shell that matches the final compiled Cypress binary 1:1 by using symlinks during development.
The package uses TypeScript to compile to CJS. ESM builds are not run by default, but can be enabled or tested with build:esm.
- CommonJS: Primary build used by the binary script and other packages
- ES Modules: Alternative build for modern Node.js applications
- Output: Compiled JavaScript in
dist/cjs/, and a binary indist/Cypress.
# Build both CommonJS and ES Module versions
yarn workspace @packages/electron build
# Build only CommonJS version
yarn workspace @packages/electron build:cjs
# Build only ES Module version
yarn workspace @packages/electron build:esm
# Clean build artifacts
yarn workspace @packages/electron clean-depsNote: The build process compiles TypeScript source to JavaScript. The --install command packages the actual Electron binary for your OS-specific platform.
The package provides a binary script cypress-electron with several commands:
# Install/build Electron binary for current platform
./bin/cypress-electron --install
# Show help and usage information
./bin/cypress-electron --help
# Launch an Electron app (development mode)
./bin/cypress-electron /path/to/your/app
# Launch with debugging enabled
./bin/cypress-electron /path/to/your/app --inspect-brkThese commands are parsed out from argv in the cli() function defined in ./lib/electron.ts
/**
* Checks if Electron binary exists and is up-to-date, installs if needed
*/
function installIfNeeded(): Promise<void>
/**
* Forces installation of Electron binary with optional arguments
*/
function install(...args: any[]): Promise<void>
/**
* Launches an Electron app with the specified path and arguments
* @param appPath - Path to the application to launch
* @param argv - Command line arguments to pass to the app
* @param callback - Optional callback when the app exits
* @returns Promise that resolves to the spawned Electron process
*/
function open(
appPath: string,
argv: string[],
callback?: (code: number) => void
): Promise<ChildProcess>
/**
* Returns the Electron version being used
* @returns String version (e.g., "36.4.0")
*/
function getElectronVersion(): string
/**
* Returns the Node.js version bundled with Electron
* @returns Promise that resolves to Node.js version string
*/
function getElectronNodeVersion(): Promise<string>
/**
* Returns the icons package for platform-specific icon paths
* @returns Icons package object
*/
function icons(): any
/**
* CLI entry point for command-line operations
* @param argv - Command line arguments array
*/
function cli(argv: string[]): void# Run unit tests
yarn workspace @packages/electron test
# Run tests with debugger
yarn workspace @packages/electron test-debug
# Run tests in watch mode
yarn workspace @packages/electron test-watchpackages/electron/
├── bin/ # Binary scripts
│ └── cypress-electron # Main CLI script
├── lib/ # TypeScript source
│ ├── electron.ts # Main entry point and CLI logic
│ ├── install.ts # Installation and packaging logic
│ ├── paths.ts # Platform-specific path resolution
│ └── print-node-version.ts
├── dist/ # Compiled output
│ ├── cjs/ # CommonJS build
│ ├── esm/ # ES Module build
│ └── Cypress/ # Electron app binary (created by --install)
├── app/ # App template for packaging
└── test/ # Test files
The version of electron that is bundled with Cypress should be kept as up-to-date as possible with the stable Electron releases. Many users expect the bundled Chromium and Node.js to be relatively recent. Also, historically, it has been extremely difficult to upgrade over multiple major versions of Electron at once, because of all the breaking changes in Electron and Node.js that impact Cypress.
Upgrading electron involves more than just bumping this package's package.json. Here are additional tasks to check off when upgrading Electron:
-
Write accurate changelog items. The "User-facing changelog" for an Electron upgrade should mention the new Node.js and Chromium versions bundled. If this is a patch version of
electron, a changelog entry might not be needed.- For example:
- Upgraded
electronfrom21.0.0to25.8.4. - Upgraded bundled Node.js version from
16.16.0to18.15.0. - Upgraded bundled Chromium version from
106.0.5249.51to114.0.5735.289.
- Upgraded
- For example:
-
Determine if the Electron upgrade is a breaking change. Electron upgrades constitute "breaking changes" in Cypress if:
- the major version number of Node.js changes, since users rely on the bundled Node.js to load plugins and
.jsfixtures, or - there are changes to Electron that require new shared libraries to be installed on Linux, breaking existing CI setups, or
- there is some other change that would break existing usage of Cypress (for example, a Web API feature being removed/added to the bundled Chromium)
- the major version number of Node.js changes, since users rely on the bundled Node.js to load plugins and
-
Create and publish Docker
base-internalfamily images matching the Node.js and Chromium versions in Electron. These images live inside thecypress-docker-imagesrepository. Thebase-internalimages will be used inside our CI pipelines. For general use of Cypress in Docker, we encourage the use of the Cypress Docker Factory. This works great for using Cypress as an end user, but doesn't fully suit the needs for developing Cypress, as we require:- The installation of packages, such as
curl,xauth, andbuild-essential/makeneeded for ourcirclecijobs/pipelines. - Specific images targeted to test Cypress on various node versions and distributions of linux, such as different versions of
ubuntu.
These images are currently created on an 'as-needed' basis and are published manually to the cypress docker repository. When creating these images, make sure:
- The Ubuntu images in base-internal are updated to be used in the system binary tests if any of the following are true for the images used inside the system binary tests:
- The last two major Ubuntu LTS Releases are out-of-date.
- The NodeJS version is not the active LTS.
- The installation of packages, such as
-
Update
src/@workflows.yml- Ensure it references the new
base-internalDocker images
- Ensure it references the new
-
Ensure that a matching Node.js version is enforced in the monorepo for local development and CI. When Electron is upgraded, oftentimes, the bundled Node.js version that comes with Electron is updated as well. Because all unit and integration tests run in normal Node.js (not Electron's Node.js), it's important for this Node.js version to be synced with the monorepo. There are a few places where this needs to be done:
-
/.node-version- used by some Node version managers -
/.nvmrc- used bynvm -
@types/nodeused throughout the monorepo to determine compatible node types. The major version of this package must reflect the node version set in/.node-version. - github workflows - used for repository templates, vulnerability detection, and V8 snapshots. If the node version for Snyk needs to be updated, then the required pull request check into
developmust also be updated. A repository administrator will need to accomplish this. -
/package.json- updateengines -
docker-compose.yml- update Docker image to the new matchinginternalimage -
/system-tests/test-binary/*- update binary system tests to use the newly published Ubuntu and Node images mentioned above, if applicable - Do a global search for the old Node.js version to identify any new areas that may need updating/unification, and update those locations (and this document!)
-
-
Update
better-sqlite3version if needed Look through the commit history ofbetter-sqlite3and find the first version that supports the proper version ofelectron's prebuilds. Update/packages/server/package.jsonand/packages/types/package.jsonto the appropriate version. -
Update
cypress-publish-binaryFor binary publishing, make sure theelectronversion that we updated in/package.jsonmatches theelectronversion inside the publish binary project. This is to make sure add-on tests inside the publish-binary repository work locally, but are not required to install the correct version ofelectronin CI when publishing the binary. Ensure theelectrontarget in this project's.circleciconfiguration is updated as well. Set the Remove this before merging, and ensure that branch is merged as well.- Create a new branch in
cypress-publish-binary - Update
electronversion inpackage.json - Update the target
electronversion in the circle configuration - Update the docker image to the new browsers-internal image made in the previous step
- Add your branch name to the
&full-workflow-filtersanchor in@pipeline.yml - Trigger the pipeline in CircleCI's UI, and set the
publish-binary-branchparameter to the branch you created in thecypress-publish-binaryrepository.
- Create a new branch in
-
Manually smoke test
cypress open. Upgrading Electron can break thedesktop-guiin unexpected ways. Since testing in this area is weak, double-check that things like launchingcypress open, signing into Cypress Cloud, and launching Electron tests still work. -
Manually smoke test
cypress runin record mode Upgrading Electron can causebetter-sqlite3to SIGSEGV the Electron process. -
Fix failing tests. Usually, these are due to breaking changes in either Node.js or Electron. Check the changelogs of both to find relevant changes.
-
If needed, update the V8 Snapshot Cache by running the GitHub workflow. Make sure to use the branch that contains the electron updates to populate the
'workflow from'and'branch to update'arguments. Select'Generate from scratch'and'commit directly to branch'. This will usually take 6-8 hours to complete and is best to not be actively developing on the branch when this workflow runs.
- Build the package:
yarn build:cjs(oryarn buildfor both formats) - Test the binary:
./bin/cypress-electron --install - Run tests:
yarn test
Enable debug logging by setting the DEBUG environment variable:
DEBUG=cypress:electron* ./bin/cypress-electron --install
DEBUG=cypress:electron:install* ./bin/cypress-electron --install- TypeScript compilation errors: Check that all dependencies are installed and TypeScript config is correct
- Missing dependencies: Ensure
@electron/packagerand other dev dependencies are available
- Path resolution issues: Verify that the compiled output structure matches the expected paths
- Binary not found: Run
./bin/cypress-electron --installto create the Electron binary - Permission errors: On Linux, ensure proper permissions for the binary directory
- macOS: ARM64 vs x64 architecture detection may need updates
- Linux: Sandbox issues when running as root (automatically handled)
- Windows: Junction vs directory symlink handling (automatically handled)
When contributing to this package:
- Follow the existing patterns for error handling and logging
- Test on multiple platforms if making platform-specific changes
- Update tests for any new functionality
- Rebuild after changes using
yarn build:cjs - Test the binary with
./bin/cypress-electron --install
For more detailed information about the build system, see BUILD.md.
Solution: Update the string representation of fs.readFileSync in scripts/binary/binary-integrity-check-source.js to match the string generated by the new version of electron. To do this, create a throw-away script that runs console.log(fs.readFileSync.toString()). Execute this with Electron rather than Node (ie. npm i -g electron@x.y.z && electron throwaway-script.js).
Solution: This error is benign. From time to time, the error message we match against in order to swallow the error changes. Update the necessary support files with the new error message.
Solution: This is often due to a mismatched prebuild of better-sqlite3. Ensure your repository is clear of untracked files with git clean -xfd, and run yarn again. If the issue persists, ensure you are running the latest version of your operating system. Electron prebuilds key to darwin/linux/windows, and do not differentiate between versions of the same.
If you run into an error like below, please try some of the strategies below.
Could not detect abi for version X.X.X and runtime electron. Updating "node-abi" might help solve this issue if it is a new release of electronSolution: See if there's a new version of @electron/rebuild with a newer version of node-abi within it. If there is not a newer version, find the latest release of node-abi that has an updated ABI registry with an abi entry matching the major version of Electron that you're updating to. Set this node-abi version in the resolutions of our package.json file and rerun yarn.