How to Combine Cypress Tests with Codecov
Instrument your app, collect Cypress coverage, and upload reports to Codecov from CI. Includes Vite and GitHub Actions setup, troubleshooting, and reporting tips.
To combine Cypress tests with Codecov, instrument your application before Cypress runs, collect the browser coverage with @cypress/code-coverage, generate a report, then upload that report from CI. Cypress does not instrument application code automatically; the bundler or build step must add coverage counters first. Codecov receives the resulting report in a separate upload step.
This guide uses JavaScript examples and GitHub Actions. Adapt the instrumentation step to your bundler and follow Codecov’s current upload guidance for your CI provider and repository visibility. See the Cypress coverage guide and Codecov quick start.
1. Instrument the application code
Coverage tooling measures instrumented source code by recording which statements, branches, functions, and lines execute. Cypress runs the app in a browser, but Cypress itself does not insert the counters. Use the instrumentation path that matches the app’s build system, and scope it to the application files you want measured rather than dependencies such as node_modules.
Vite projects
For Vite, Cypress documents vite-plugin-istanbul. Install it:
npm install --save-dev vite-plugin-istanbul
Then add it to vite.config.ts (or the equivalent JavaScript configuration). Adjust the include, exclude, and extension patterns to match your project:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import istanbul from 'vite-plugin-istanbul'
export default defineConfig({
plugins: [
vue(),
istanbul({
include: 'src/*',
exclude: ['node_modules', 'test/'],
extension: ['.js', '.ts', '.vue'],
requireEnv: true,
}),
],
})
With requireEnv: true, enable instrumentation in the process that starts the instrumented app by setting VITE_COVERAGE=true. For example, use a CI-specific start command or environment setting. Cypress must visit the instrumented build, not a separately started production build without counters. If the project uses React, Vue, or another framework on Vite, include all relevant source extensions, including framework component files where applicable.
Babel or other Istanbul setups
Cypress also documents Istanbul instrumentation through Babel or nyc-based build approaches. For a Babel project, configure babel-plugin-istanbul in a Cypress-only Babel environment so other tools such as unit-test runners do not unintentionally apply the same plugin. The exact configuration depends on how the app is bundled; consult the Cypress instrumentation examples for the matching stack.
Use source maps where supported so reports can map instrumented output back to original source files. Exclude generated files and third-party code from the measured scope where appropriate.
2. Install and configure the Cypress coverage plugin
Install the plugin as a development dependency. Cypress documents @cypress/code-coverage as the collector and report generator for coverage data exposed by the application.
npm install --save-dev @cypress/code-coverage
Import its support module from the support file used by the Cypress test mode. For E2E tests, that is commonly cypress/support/e2e.js:
// cypress/support/e2e.js
import '@cypress/code-coverage/support'
Register its Node task in setupNodeEvents and return the config object. Example for a CommonJS Cypress configuration:
// cypress.config.js
const { defineConfig } = require('cypress')
const registerCodeCoverageTasks = require('@cypress/code-coverage/task')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
registerCodeCoverageTasks(on, config)
return config
},
},
})
For an ESM TypeScript configuration, use imports instead:
// cypress.config.ts
import { defineConfig } from 'cypress'
import registerCodeCoverageTasks from '@cypress/code-coverage/task'
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
registerCodeCoverageTasks(on, config)
return config
},
},
})
If other plugins change the Cypress config or its environment values, preserve those changes and return the final config object. For component testing, register the task in the component configuration and import the support module from the component support file; importing it only from the E2E support file will not configure component tests.
The plugin listing in the supplied research dossier reports version 4.0.3 for Cypress 15.10.0 and newer. Check the plugin’s current README and release information against your installed Cypress version, especially if using an older project.
3. Run Cypress and inspect the report
Start the application using the instrumented configuration, then run Cypress. The following command names are examples; connect them to your actual start and test scripts:
# Example package.json scripts
{
"scripts": {
"start:coverage": "vite --host 0.0.0.0",
"cy:run": "cypress run",
"coverage:summary": "nyc report --reporter=text-summary"
}
}
Start the app with instrumentation enabled in one terminal and run the tests in another, or use your project’s existing CI orchestration:
VITE_COVERAGE=true npm run start:coverage
# In another process, once the app is ready:
npm run cy:run
npm run coverage:summary
When collection is configured and the app is instrumented, the plugin writes raw coverage data under .nyc_output and generates an HTML report under coverage. Open coverage/index.html locally to inspect files and uncovered lines. The terminal summary is useful for CI logs. Keep the generated report available as a CI artifact if you want to inspect it even when an upload fails.
Coverage percentages indicate execution, not whether assertions would detect defects or whether a user journey is adequately tested. Use uncovered branches and lines to identify meaningful test gaps; do not treat a high percentage alone as proof of test quality.
4. Upload the report to Codecov from GitHub Actions
Run Cypress and generate coverage before the Codecov step, in the same workspace so the uploader can find the report. A basic workflow outline is:
name: Cypress coverage
on:
push:
pull_request:
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- name: Run instrumented app and Cypress
run: npm run ci:e2e:coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
The ci:e2e:coverage command is deliberately project-specific: it must start or build the instrumented app, wait until it is ready, run Cypress, and leave the report in the job’s workspace. For example, if you already use a CI helper to start the server and wait for readiness, define that script in your project and call it here. Do not assume that simply running cypress run instruments or starts the application.
Store the Codecov upload token as a CI secret named CODECOV_TOKEN when your repository and provider require it. Codecov’s token requirements can vary by repository visibility and CI context, including fork pull requests; follow its current token guidance. The Codecov Action also documents options including files, directory, flags, name, fail_ci_if_error, and OIDC. Use explicit report paths or flags if your workflow produces multiple reports, and choose whether an upload failure should fail the CI job based on your release policy. See the Codecov Action documentation.
Using the Codecov CLI instead
Codecov’s quick start also documents its CLI. Use the CLI flow that matches the official current instructions for your CI provider, keep credentials in secrets, and upload the report produced in the prior step. Do not expose a token in committed workflow files or shell logs. The GitHub Action is usually the most direct GitHub Actions integration; the CLI is relevant where Codecov’s provider-specific setup calls for it.
5. Choose the coverage scope and reporting behavior
- Frontend only: Instrument the browser application and collect the coverage exposed in the page. Keep the report focused on source files that the team intends to track.
- Component tests: Configure the plugin for Cypress component testing and load the support import from that mode’s support file.
- Backend coverage: Instrument the server separately and expose its coverage data using the mechanism described by Cypress, such as the plugin’s backend coverage endpoint integration. Configure
env.codeCoverage.urlfor the endpoint so the plugin can fetch and merge it with frontend data. - Multiple reports: If separate jobs create separate coverage files, upload all relevant report files or configure Codecov flags to identify report groups. Ensure all reports correspond to the same commit and expected source revision.
- Thresholds: Generate a local summary or enforce thresholds with the reporting tool only after defining the intended scope. A changed include/exclude pattern can change percentages without any change in tests.
Cypress distinguishes source code coverage from UI Coverage: code coverage records which source lines ran, while UI Coverage concerns which interactive interface elements tests exercised. They answer different questions; this setup covers source execution reporting. See Cypress’s explanation of the distinction.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| No coverage object or report | The app bundle was not instrumented, or Cypress visited a different non-instrumented server/build. | Verify the instrumentation plugin is active in the app build and inspect the running page for window.__coverage__. Confirm the server Cypress visits is the instrumented one. |
| Plugin reports missing frontend coverage | The support import is missing, the app has no counters, or the test mode uses a different support file. | Import @cypress/code-coverage/support in the support file for the mode under test, and ensure instrumentation runs before tests. |
| Task or plugin setup error | The task was not registered in the relevant setupNodeEvents, or a modified config was not returned. |
Register @cypress/code-coverage/task in the correct E2E or component setup and return the resulting config. |
| Report exists locally but Codecov shows no upload | The upload step ran before tests, report files are outside its working directory, or the intended report path is not found. | Run upload after Cypress, check the job workspace and uploader logs, and configure files or directory when needed. |
| Codecov authentication failure | The token is absent, incorrect, unavailable to the event context, or tokenless upload is not enabled for this repository/provider. | Check Codecov’s current token policy, verify the CI secret name and value, and account for fork pull request restrictions. Never print the token in logs. |
| Paths appear missing or reports do not combine | Coverage files may come from different revisions, use incompatible source paths, or be uploaded as unrelated reports. | Generate and upload reports from the same checked-out commit, review source map and path configuration, and use consistent Codecov flags for separate components. |
| Unexpectedly low or inflated percentages | Instrumentation include/exclude patterns changed, generated files or dependencies are counted, or tests never exercise important branches. | Inspect file-level HTML output, constrain instrumentation to intended source, and add tests for uncovered behavior that matters. |
| Instrumentation breaks a normal build or duplicates another tool’s plugin | Instrumentation is enabled in every environment or a Babel plugin is applied twice. | Enable coverage only for Cypress/CI builds, such as through an environment variable or dedicated Babel environment, and keep tool-specific transforms scoped. |
Performance, reliability, and cost notes
- Runtime: Instrumentation adds counters to executed code and can affect build and browser-test runtime. Limit instrumentation to relevant application source, and avoid running coverage-instrumented builds for workflows that do not need coverage.
- Reliable collection: Start the app and wait for readiness before Cypress visits it. Ensure every test run produces coverage before the upload step, and retain the report artifact so upload failures do not erase the only diagnostic copy.
- Parallel jobs: If tests run in separate jobs or shards, ensure their coverage reports are all uploaded and associated with the same commit and suitable flags. A single job cannot upload reports that were never transferred into its workspace.
- CI policy: Decide whether an upload outage should fail the build. Codecov’s action exposes
fail_ci_if_error; apply it consistently with whether coverage upload is a required merge check. - Cost: Cypress and Codecov plans and terms can change; consult their current product information for pricing. The collection workflow itself creates local artifacts before the Codecov upload step.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. It does not collect Cypress source coverage or upload coverage reports to Codecov; it is an alternative for capturing rendered pages when you need screenshots alongside a testing or review workflow. Its one-request API can return PNG, JPEG, WebP, or PDF. See the ScreenshotNeo website and API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Does Codecov run Cypress tests?
No. Cypress runs the browser tests and produces coverage data; Codecov processes uploaded coverage reports.
Does a coverage percentage prove the tests are good?
No. It measures execution, not whether assertions catch incorrect behavior. Review uncovered code and test intent together.
Can I combine browser and server coverage?
Yes, when both sides are instrumented and the backend exposes coverage in a form the Cypress plugin can retrieve and merge, as described in Cypress’s full-stack coverage guidance.
Can I use this setup for visual screenshots?
Coverage collection and screenshot capture are separate tasks. Cypress can run visual checks with suitable tooling; ScreenshotNeo can capture a page through its API, but it does not replace Cypress coverage collection or Codecov uploads.


