Skip to content

digitalxero/cypress-marks

Repository files navigation

cypress-marks

CI npm version License: MIT

A Cypress plugin that filters tests using pytest-style expression parsing, providing --env tags (like pytest -m) and --env tests (like pytest -k) options with full boolean expression support.

Features

  • Tag filtering: --env tags='@smoke and not @slow'
  • Test name filtering: --env tests='login or logout'
  • Path filtering: --env spec='file.cy.ts::Suite::test' (pytest-style)
  • Boolean expressions: Full support for and, or, not, and parentheses
  • Hierarchical tags: Tags inherit through describe blocks
  • Underscore mapping: test_login matches "test login" in test names
  • TypeScript support: Full type definitions included

Installation

npm install cypress-marks --save-dev

Setup

1. Register in support file

Add to your cypress/support/e2e.ts:

import { register } from 'cypress-marks';

register();

2. Configure plugin (optional, enables spec pre-filtering)

Add to your cypress.config.ts:

import { defineConfig } from 'cypress';
import { plugin } from 'cypress-marks/plugin';

export default defineConfig({
  e2e: {
    // IMPORTANT: Must be async and await the plugin!
    async setupNodeEvents(on, config) {
      ...
      config = await plugin(on, config);

      return config
    },
  },
});

Common mistakes:

// WRONG - not async, not awaiting
setupNodeEvents(on, config) {
  return plugin(on, config);  // Returns Promise, not config!
}

// WRONG - not returning the config
setupNodeEvents(on, config) {
  plugin(on, config);  // Config modifications are lost!
}

Usage

Tag Filtering

Tags must start with @ prefix:

describe('User Authentication', { tags: ['@smoke'] }, () => {
  it('should login successfully', { tags: ['@critical'] }, () => {
    // Test implementation
  });

  it('should handle invalid credentials', { tags: ['@negative'] }, () => {
    // Test implementation
  });
});

Run with tag filters:

# Run only smoke tests
npx cypress run --env tags='@smoke'

# Run smoke tests except slow ones
npx cypress run --env tags='@smoke and not @slow'

# Run smoke or regression tests
npx cypress run --env tags='@smoke or @regression'

# Complex expressions with parentheses
npx cypress run --env tags='(@smoke or @regression) and not @flaky'

Test Name Filtering

Filter by test name (case-insensitive substring match):

# Run tests containing "login"
npx cypress run --env tests='login'

# Run tests containing "login" or "logout"
npx cypress run --env tests='login or logout'

# Exclude tests containing "slow"
npx cypress run --env tests='not slow'

Underscore-to-Space Mapping

Underscores in expressions match spaces in test names:

# Matches "user authentication" in test names
npx cypress run --env tests='user_authentication'

To match literal underscores, escape them:

# Matches "user_auth" literally
npx cypress run --env tests='user\_auth'

Path Filtering (Pytest-Style)

Select specific tests using pytest-style :: separated paths:

# Run all tests in a specific file
npx cypress run --env spec='login.cy.ts'

# Run all tests in a specific suite
npx cypress run --env spec='login.cy.ts::User Authentication'

# Run a specific test
npx cypress run --env spec='login.cy.ts::User Authentication::should login successfully'

# Nested suite hierarchy
npx cypress run --env spec='login.cy.ts::Auth::Login::validates credentials'

# Use glob patterns for files
npx cypress run --env spec='**/auth/*.cy.ts::smoke'

# Multiple files/tests (OR logic)
npx cypress run --env spec='login.cy.ts::login,logout.cy.ts::logout'

Path Syntax

Pattern Description
file.cy.ts Run all tests in the file
file.cy.ts::Suite Run all tests in the suite (case-insensitive substring match)
file.cy.ts::Suite::test Run specific test (case-insensitive substring match)
file.cy.ts::Outer::Inner::test Nested suite path
**/*.cy.ts::Suite Glob pattern with suite filter

Key behaviors:

  • File path component uses glob matching (supports * and **)
  • Suite/test names use case-insensitive substring matching
  • Literal spaces are supported directly in names
  • Multiple specs separated by commas use OR logic

Combined Filtering

Use both tag and name filters together:

npx cypress run --env tags='@smoke',tests='login'

Combine path filtering with tag filtering:

# Run smoke tests in auth files
npx cypress run --env spec='**/auth/*.cy.ts',tags='@smoke'

All specified conditions must match for a test to run (AND logic between filter types).

Filter Mode

By default, filtered tests appear as "skipped" in the Cypress reporter. To omit them entirely:

npx cypress run --env tags='@smoke',marksOmitFiltered=true

Expression Syntax

Operators

Operator Description Example
and Logical AND @smoke and @fast
or Logical OR @smoke or @regression
not Logical NOT not @slow
() Grouping (@smoke or @regression) and not @flaky

Precedence

From highest to lowest:

  1. not (unary)
  2. and (binary, left-associative)
  3. or (binary, left-associative)

Examples

# Simple tag
--env tags='@smoke'

# Negation
--env tags='not @slow'

# AND (both must match)
--env tags='@smoke and @critical'

# OR (either matches)
--env tags='@smoke or @regression'

# Combined with precedence
--env tags='@smoke and @critical or @regression'
# Equivalent to: (@smoke and @critical) or @regression

# Override precedence with parentheses
--env tags='@smoke and (@critical or @regression)'

Environment Variables

Variable Type Description
spec string Pytest-style path filter (file::suite::test)
tags string Tag filter expression
tests string Test name filter expression
marksOmitFiltered boolean Omit filtered tests vs skip (default: false)
marksFilterSpecs boolean Pre-filter spec files (default: false, auto-enabled when spec is set)
marksDebug boolean Enable debug logging (default: false)

Tag Requirements

Tags must start with the @ prefix:

// Correct
{ tags: ['@smoke', '@regression'] }

// Incorrect - will throw TagValidationError
{ tags: ['smoke', 'regression'] }

This requirement applies to:

  • Tags defined in test/describe config
  • Tag identifiers in filter expressions

Advanced Usage

Programmatic Expression Evaluation

import { compile, createTagMatcher } from 'cypress-marks';

const expr = compile('@smoke and not @slow');
const tags = new Set(['@smoke', '@fast']);
const matcher = createTagMatcher(tags);

const matches = expr.evaluate(matcher); // true

Custom Matchers

import { compile, createNameMatcher } from 'cypress-marks';

const expr = compile('login or logout');
const matcher = createNameMatcher('User can login successfully');

const matches = expr.evaluate(matcher); // true

Spec Pre-Filtering

When marksFilterSpecs=true, the plugin pre-scans spec files and excludes those with no matching tests. This prevents empty spec runs.

Required dependency:

npm install globby --save-dev

Usage:

npx cypress run --env tags='@smoke',marksFilterSpecs=true

How it works:

  1. Parses each spec file to extract test names and tags (including inherited suite tags)
  2. Evaluates the filter expression against each test
  3. Excludes spec files where no tests would match
  4. Updates config.specPattern with only the matching specs

Limitations:

  • Dynamic test generation (tests created at runtime) cannot be detected
  • The parser handles standard describe/context/it/specify syntax with { tags: [] } config

Comparison with pytest

Feature pytest cypress-marks
Tag filtering -m 'smoke and not slow' --env tags='@smoke and not @slow'
Name filtering -k 'login or logout' --env tests='login or logout'
Path selection file.py::Class::test --env spec='file.cy.ts::Suite::test'
Boolean ops and, or, not, () and, or, not, ()
Tag prefix No requirement Must start with @

Contributing

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Build
npm run build

# Lint
npm run lint

# Type check
npm run typecheck

Release Process

Releases are automated via GitHub Actions using Conventional Commits and svu for semantic versioning.

On Pull Request:

  • Builds, tests, and lints
  • Publishes a release candidate to npm (e.g., 1.0.0-rc.feature-branch.42)
  • Comments on the PR with the RC install command

On Merge to Main:

  • Automatically determines the next version based on commit messages:
    • fix: → patch bump (0.0.x)
    • feat: → minor bump (0.x.0)
    • feat!: or BREAKING CHANGE: → major bump (x.0.0)
  • Updates package.json, commits, and tags
  • Creates a GitHub Release with auto-generated notes
  • Publishes to npm

Commit Message Examples:

# Patch release (0.0.1 → 0.0.2)
git commit -m "fix: handle empty tag expressions correctly"

# Minor release (0.1.0 → 0.2.0)
git commit -m "feat: add support for regex patterns in test filter"

# Major release (1.0.0 → 2.0.0)
git commit -m "feat!: require @ prefix for all tags"
# or
git commit -m "feat: new API

BREAKING CHANGE: removed deprecated compile() options"

npm Trusted Publishing Setup

This project uses npm Trusted Publishing with GitHub Actions OIDC - no npm tokens required.

License

MIT

About

A Cypress plugin that filters tests using pytest-style expression parsing, providing `--env tags` (like pytest `-m`) and `--env tests` (like pytest `-k`) options with full boolean expression support.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors