---
url: https://huldoser.github.io/test-inventory/frameworks/cypress.md
description: >-
  Scan Cypress tests without running them, interpret the inventory, and check
  Cypress syntax and limitations.
---

# Cypress

This guide covers **Cypress 13.0 or newer**. You need Node.js 22.12 or newer to run test-inventory and an
existing JavaScript or TypeScript test suite. The scanner reads your source without executing your tests or starting
a browser. These are minimum supported versions; [CI comparisons](/guide/runners#checked-in-ci) list tested versions.

[Choose another framework](/frameworks/) · [Use an AI client](/guide/agents)

## Install

```sh
npm install --save-dev test-inventory
```

## Scan your suite

Run from the folder containing your project's `package.json`:

```sh
npx test-inventory --framework cypress --pretty --output inventory.json
```

To select files explicitly, use quoted globs. This example matches the `trading-ui-cypress` fixture used below;
adjust the globs to your suite's layout:

```sh
npx test-inventory "cypress/e2e/**/*.cy.js" --framework cypress --output inventory.json
```

The command replaces `inventory.json` once the new output is complete. It does not change your test files.

## Check the result

Print the counts and diagnostics from the saved file:

```sh
node -e "const i = require('./inventory.json'); console.log(i.summary); console.log(i.diagnostics)"
```

For matching tests, `summary.fileCount` and `summary.testCount` should be greater than zero. Review diagnostics
even when the command exits with 0: errors can mean tests are missing. If the result is empty or unexpected,
use [troubleshooting](/guide/troubleshooting).

The inventory describes source declarations, not execution results. Conditional skips are not proof that a run
skipped the test. Loops and tables are one record by default; supported cases can be expanded with `--expand-cases`.
Expected-to-fail tests execute and check for failure; they are not disabled tests.

Tests created by unreadable helpers can be missing without a diagnostic. A dependency hash does not prove complete
coverage of runtime dependencies. Read the [shared limits](/guide/limits) before using scans to make CI decisions.

## Find skipped tests

```sh
npx test-inventory --framework cypress --state skip --fields fullName,state,condition,reason --pretty
```

This uses the same file selection as the first scan. If you supplied globs, `--root` or `--framework-version`,
repeat those options here.

This selects source declarations marked skip; it is not a report of a test run.
See [query recipes](/guide/recipes) for other inventory queries.

## Example

`trading-ui-cypress` checks order tickets with Cypress. Tests take Cypress's test config before their function:
retries, tags for `@cypress/grep`, and the browsers they run in.

```js excerpt
// cypress/e2e/orders/ticket.cy.js
describe('order ticket', { tags: '@orders', retries: { runMode: 2, openMode: 0 } }, () => {
  // ...
  it('accepts an order within the limits', { tags: ['@smoke'] }, () => {
  // ...
  it('opens the ticket from the watchlist', { browser: '!electron' }, () => {
```

```sh
npx test-inventory "cypress/e2e/**/*.cy.js" --framework cypress --output inventory.json
```

Without the glob and `--framework`, the scan finds the same files from Cypress's default `specPattern`, and Cypress from
`package.json`. A test takes its describe's tags and retries, `runMode` of them, and `browser` is a condition:

```json
{
  "fullName": "order ticket > opens the ticket from the watchlist",
  "state": "skip",
  "isConditional": true,
  "condition": "browser: '!electron'",
  "retries": 2,
  "tags": ["@orders"]
}
```

## Cypress component and end-to-end tests

`trading-components-cypress` models a project with E2E specs in `cypress/e2e/` and React component specs next to
components in `src/`. Its config gives each testing type its own file pattern and support file:

```js
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  retries: { runMode: 1, openMode: 0 },
  e2e: {
    baseUrl: 'http://localhost:4173',
    specPattern: 'cypress/e2e/**/*.cy.js',
    supportFile: 'cypress/support/e2e.js',
  },
  component: {
    devServer: { framework: 'react', bundler: 'vite' },
    specPattern: 'src/**/*.cy.tsx',
    supportFile: 'cypress/support/component.js',
  },
});
```

The component spec imports a component from the same folder:

```tsx excerpt
// src/OrderTicket.cy.tsx
import { mount } from 'cypress/react';
import { OrderTicket } from './OrderTicket';

// ...
it('blocks orders without buying power', () => {
  mount(<OrderTicket symbol="AAPL" buyingPower={0} />);
  cy.contains('button', 'Buy AAPL').should('be.disabled');
});
```

Scan both sets of files from the project root:

```sh
npx test-inventory "cypress/e2e/**/*.cy.js" "src/**/*.cy.tsx" --framework cypress --pretty
```

Omitting the globs finds the same files from this config. These are excerpts of two output records:

```json
{
  "fullName": "order entry > opens the order ticket from the watchlist",
  "relativeFilePath": "cypress/e2e/orders.cy.js",
  "projects": ["e2e"]
}
```

```json
{
  "fullName": "OrderTicket > blocks orders without buying power",
  "relativeFilePath": "src/OrderTicket.cy.tsx",
  "projects": ["component"],
  "dependencies": [
    "cypress.config.js",
    "cypress/support/component.js",
    "cypress/support/e2e.js",
    "src/OrderTicket.cy.tsx",
    "src/OrderTicket.tsx"
  ]
}
```

The scan includes both configured support files in dependency hashes; it does not execute them, start the dev
server or mount the component. `projects` identifies the testing type. Explicit globs do not override its
`specPattern`: a selected file outside both patterns can appear with `projects: []` and state `not-loaded`.
Use your project's patterns when adapting the command.

## Configuration and limits

The scan reads the first `cypress.config.*` in the root. Its `e2e` and configured `component` testing types
become projects. Explicit scan globs still need to match the testing type's `specPattern` for the file to count
as run, as with `cypress run --spec`. Component selection also excludes the e2e `specPattern` matches.

The testing type's `retries`, otherwise the config's, applies; an object uses `runMode`. Support files,
including the default support file, enter dependency hashes but are not executed. Browser-dependent skips
describe conditions in source, not proof that a browser skipped the test.

::: details Exact file selection

For Cypress: its testing types are the projects, `e2e` and, when the config sets up
component testing, `component`; each runs the files under the config's folder that its `specPattern` matches, by default
`cypress/e2e/**/*.cy.{js,jsx,ts,tsx}` and `**/*.cy.{js,jsx,ts,tsx}`, without dot files, those its `excludeSpecPattern`
matches, and those in `node_modules` unless a `specPattern` names it. As in `cypress run`, each pattern is matched
against the whole path from the config's folder, so `*.draft.cy.js` leaves out only files in that folder. As globby,
which Cypress uses, reads them, a `specPattern` that starts with `!` leaves files out, an `excludeSpecPattern` drops its
`!`, and a folder in either stands for every file below it. Component testing also leaves out the files e2e's
`specPattern` matches. Scanned with globs, a file counts as run only where its
testing type's `specPattern` takes it too, as `cypress run --spec` does. The testing type's `retries`, else the
config's, applies to every test, its `runMode` when it is an object, as `cypress run` takes.

:::

## Supported syntax

Cypress 13.0 and newer.

### Where test comes from

| Form               | Example                                                                                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Globals            | Mocha's BDD globals, `describe`, `context`, `it`, `specify`, their `x` forms and the hooks, which Cypress sets in every spec                           |
| Kept in a variable | `const later = it.skip`: only what both branches of a choice share applies, also of one written in place, as `(process.env.CI ? it.skip : it)(...)`    |
| Local helpers file | `import { it } from './helpers'` or `require('./helpers')`, followed through local imports, and helper functions that declare tests, read at each call |

### Calls

Cypress reads tests and describes as Mocha does, with these differences:

| Call                                                                      | Read as                                                                                                                                                                                           |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `it(title, config, fn)`, `describe(title, config, fn)`                    | A test or describe with Cypress's test config, before its function. `it(title, config)` without a function is a test that runs and fails, as Cypress then gives Mocha the config as its function. |
| `retries` in a test config                                                | `retries`; for `{ runMode, openMode }`, `runMode`, which `cypress run` uses. A describe's passes to its tests. `null` sets none.                                                                  |
| `browser` in a test config                                                | The test, or a describe's tests, skipped under a condition, `browser: '!firefox'` as written: Cypress runs them only in the browsers it names.                                                    |
| `tags` in a test config                                                   | `tags`, a string or a list, as `@cypress/grep` reads them. A describe's pass to its tests.                                                                                                        |
| `env` in a test config                                                    | From Cypress 16, a `removed-api` error: Cypress 16 fails each test it applies to when the test runs.                                                                                              |
| `this.retries()` in a describe, `.retries()` after `it()` or `describe()` | A `describe-throws` or `invalid-chain` error: Cypress throws while it loads the spec. In a test or hook, `this.retries()` fails only that test or hook, when it runs, and is not reported.        |
| `this.timeout()`, `it(...).timeout()`                                     | Not read: Cypress has no test timeout, only command timeouts.                                                                                                                                     |

A call Cypress refuses, as `it.concurrent()` or a describe without a function, fails its spec, and every test in the
file is `notLoaded`; the other specs run.

The [shared syntax rules](/reference/syntax#in-every-runner) also apply.

## Next

* [Shared limits](/guide/limits): imports, generated tests, conditions and dependency coverage.
* [Key concepts](/guide/concepts): counts, states, IDs and hashes.
* [Output reference](/reference/output) and [diagnostics](/reference/diagnostics): interpret every field and warning.
* [CLI](/guide/cli), [library](/guide/library) and [MCP](/guide/agents): use the same inventory through each interface.
* [Compare with Cypress](/guide/runners#cypress-s-list): differences from runner collection and execution reports.
