CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-cypress

Cypress is a next generation front end testing tool built for the modern web

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

custom-frameworks.mddocs/

Custom Component Frameworks

System for defining custom component testing frameworks beyond the built-in React, Vue, and Angular support. This allows you to create component testing support for any JavaScript framework or custom component system.

Capabilities

Define Component Framework

Creates a definition for a custom third-party component framework that can be used with Cypress component testing.

/**
 * Provides automatic code completion for Component Frameworks Definitions
 * @param config - Component framework definition configuration
 * @returns The configuration passed in parameter (for type safety)
 */
function defineComponentFramework(
  config: ThirdPartyComponentFrameworkDefinition
): ThirdPartyComponentFrameworkDefinition;

interface ThirdPartyComponentFrameworkDefinition {
  /** Unique identifier for the framework */
  type: string;
  /** Human-readable name of the framework */
  name: string;
  /** List of supported bundlers (webpack, vite, etc.) */
  supportedBundlers: string[];
  /** Functions to detect if this framework is being used in a project */
  detectors: FrameworkDetector[];
  /** Function to determine required dependencies for this framework */
  dependencies: (installer: DependencyInstaller) => PackageManagerType[];
}

Usage Examples:

// cypress.config.js
const { defineConfig, defineComponentFramework } = require('cypress');

const solidJsFramework = defineComponentFramework({
  type: 'cypress-ct-solid-js',
  name: 'Solid.js',
  supportedBundlers: ['vite', 'webpack'],
  detectors: [
    {
      file: 'package.json',
      matcher: /solid-js/
    }
  ],
  dependencies: (installer) => [
    installer.packageJson({
      dependency: 'solid-js',
      minVersion: '^1.0.0'
    }),
    installer.packageJson({
      dependency: 'vite-plugin-solid',
      minVersion: '^2.0.0'
    })
  ]
});

module.exports = defineConfig({
  component: {
    devServer: solidJsFramework,
    specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}'
  }
});

Framework Detection

Define how Cypress should detect when your custom framework is being used in a project.

interface FrameworkDetector {
  /** File to check for framework presence */
  file: string;
  /** Pattern to match in the file content */
  matcher: RegExp | string;
}

// Alternative detector interface for package.json dependencies
interface PackageJsonDetector {
  file: 'package.json';
  matcher: RegExp;
}

// Alternative detector interface for config files
interface ConfigFileDetector {
  file: string;
  matcher: (content: string) => boolean;
}

Framework Detection Examples:

// Detect Svelte framework
const svelteDetectors = [
  {
    file: 'package.json',
    matcher: /svelte/
  },
  {
    file: 'svelte.config.js',
    matcher: /export.*svelte/
  }
];

// Detect Lit framework
const litDetectors = [
  {
    file: 'package.json',
    matcher: /lit|@lit/
  }
];

// Detect Stencil framework
const stencilDetectors = [
  {
    file: 'stencil.config.ts',
    matcher: /stencil/
  },
  {
    file: 'package.json',
    matcher: /@stencil\/core/
  }
];

Dependency Management

Define the dependencies required for your custom framework to work with Cypress component testing.

interface DependencyInstaller {
  /** Specify a package.json dependency requirement */
  packageJson(requirement: PackageRequirement): PackageManagerType;
  /** Specify a custom installation script */
  custom(script: string): PackageManagerType;
}

interface PackageRequirement {
  /** Package name */
  dependency: string;
  /** Minimum version required */
  minVersion?: string;
  /** Whether this is a dev dependency */
  dev?: boolean;
}

interface PackageManagerType {
  /** Package manager type */
  type: 'npm' | 'yarn' | 'pnpm';
  /** Installation command */
  command: string;
}

Dependency Examples:

// Solid.js framework dependencies
const solidDependencies = (installer) => [
  installer.packageJson({
    dependency: 'solid-js',
    minVersion: '^1.6.0'
  }),
  installer.packageJson({
    dependency: 'vite-plugin-solid',
    minVersion: '^2.5.0',
    dev: true
  }),
  installer.packageJson({
    dependency: '@cypress/mount-utils',
    minVersion: '^1.0.0',
    dev: true
  })
];

// Lit framework dependencies
const litDependencies = (installer) => [
  installer.packageJson({
    dependency: 'lit',
    minVersion: '^2.0.0'
  }),
  installer.packageJson({
    dependency: '@web/dev-server-esbuild',
    minVersion: '^0.3.0',
    dev: true
  })
];

Complete Custom Framework Example

Here's a complete example of defining a custom framework for Solid.js:

// frameworks/solid.js
const { defineComponentFramework } = require('cypress');

module.exports = defineComponentFramework({
  type: 'cypress-ct-solid-js',
  name: 'Solid.js',
  supportedBundlers: ['vite', 'webpack'],
  
  detectors: [
    {
      file: 'package.json',
      matcher: /solid-js/
    },
    {
      file: 'vite.config.js',
      matcher: /solidPlugin|vite-plugin-solid/
    },
    {
      file: 'vite.config.ts',
      matcher: /solidPlugin|vite-plugin-solid/
    }
  ],
  
  dependencies: (installer) => [
    installer.packageJson({
      dependency: 'solid-js',
      minVersion: '^1.6.0'
    }),
    installer.packageJson({
      dependency: 'vite-plugin-solid',
      minVersion: '^2.5.0',
      dev: true
    }),
    installer.packageJson({
      dependency: '@cypress/mount-utils',
      minVersion: '^1.0.0',
      dev: true
    })
  ]
});

Mount Function Implementation

When creating a custom framework, you'll also need to implement a mount function:

// cypress/support/solid-mount.js
import { render } from 'solid-js/web';
import { getContainerEl, setupHooks } from '@cypress/mount-utils';

let dispose;

function cleanup() {
  if (dispose) {
    dispose();
    dispose = null;
  }
}

export function mount(component, options = {}) {
  return cy.then(() => {
    // Clean up previous mount
    cleanup();
    
    // Get the container element
    const root = getContainerEl();
    
    // Render the Solid component
    dispose = render(() => component, root);
    
    // Log the mount operation
    if (options.log !== false) {
      Cypress.log({
        name: 'mount',
        message: 'Solid.js component'
      });
    }
    
    return cy.wrap({ component }).then(() => ({ component }));
  });
}

// Set up cleanup hooks
setupHooks(cleanup);

Usage in Tests

Once your custom framework is defined and the mount function is implemented:

// cypress/component/SolidButton.cy.js
import { mount } from '../support/solid-mount';
import Button from './Button'; // Solid.js component

describe('Solid Button', () => {
  it('renders and responds to clicks', () => {
    let clicked = false;
    const handleClick = () => { clicked = true; };
    
    mount(() => <Button onClick={handleClick}>Click me</Button>);
    
    cy.contains('Click me').should('be.visible');
    cy.contains('Click me').click().then(() => {
      expect(clicked).to.be.true;
    });
  });
});

Framework Configuration Integration

Integrate your custom framework with Cypress configuration:

// cypress.config.js
const { defineConfig } = require('cypress');
const solidFramework = require('./frameworks/solid');

module.exports = defineConfig({
  component: {
    devServer: {
      framework: solidFramework.type,
      bundler: 'vite',
      viteConfig: {
        plugins: [solidPlugin()]
      }
    },
    specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
    supportFile: 'cypress/support/component.js'
  }
});

Advanced Framework Features

For more sophisticated frameworks, you can implement additional features:

Custom Assertions

// cypress/support/solid-commands.js
Cypress.Commands.add('solidComponent', { prevSubject: true }, (subject) => {
  // Custom assertions for Solid.js components
  return cy.wrap(subject).should('exist');
});

// Usage
cy.get('[data-cy=my-component]').solidComponent();

Framework-Specific Utilities

// cypress/support/solid-utils.js
export function createSignal(initialValue) {
  // Utility functions specific to your framework
  return { value: initialValue };
}

export function waitForReactivity() {
  // Wait for framework's reactivity system to update
  return cy.wait(0); // or more sophisticated waiting logic
}

Testing the Custom Framework

Test your custom framework implementation:

// cypress/component/framework-test.cy.js
import { mount } from '../support/solid-mount';

describe('Custom Framework Integration', () => {
  it('mounts components correctly', () => {
    const TestComponent = () => <div data-cy="test">Framework works!</div>;
    
    mount(TestComponent);
    cy.get('[data-cy=test]').should('contain', 'Framework works!');
  });
  
  it('handles props and state', () => {
    const Counter = (props) => {
      const [count, setCount] = createSignal(props.initial || 0);
      return (
        <div>
          <span data-cy="count">{count()}</span>
          <button data-cy="increment" onClick={() => setCount(c => c + 1)}>
            +1
          </button>
        </div>
      );
    };
    
    mount(() => <Counter initial={5} />);
    cy.get('[data-cy=count]').should('contain', '5');
    cy.get('[data-cy=increment]').click();
    cy.get('[data-cy=count]').should('contain', '6');
  });
});

This custom framework system allows you to extend Cypress component testing to any JavaScript framework, providing the same powerful testing capabilities that are available for React, Vue, and Angular components.

Install with Tessl CLI

npx tessl i tessl/npm-cypress

docs

angular-testing.md

cli-integration.md

configuration.md

custom-frameworks.md

index.md

interactive-testing.md

programmatic-execution.md

react-testing.md

vue-testing.md

tile.json